diff --git a/code/datums/quirks/_quirk.dm b/code/datums/quirks/_quirk.dm index 12396387e9e1c4..712adb4a78634c 100644 --- a/code/datums/quirks/_quirk.dm +++ b/code/datums/quirks/_quirk.dm @@ -33,11 +33,23 @@ /// The base weight for the each quirk's mail goodies list to be selected is 5 /// then the item selected is determined by pick(selected_quirk.mail_goodies) var/list/mail_goodies + /// The minimum stat where this quirk can process (if it has QUIRK_PROCESSES) + /// If null, then it will process regardless of stat. + var/minimum_process_stat = HARD_CRIT + /// A list of additional signals to register with update_process() + var/list/process_update_signals + /// A list of traits that should stop this quirk from processing. + /// Signals for adding and removing this trait will automatically be added to `process_update_signals`. + var/list/no_process_traits + +/datum/quirk/New() + . = ..() + for(var/trait in no_process_traits) + LAZYADD(process_update_signals, list(SIGNAL_ADDTRAIT(trait), SIGNAL_REMOVETRAIT(trait))) /datum/quirk/Destroy() if(quirk_holder) remove_from_current_holder() - return ..() /// Called when quirk_holder is qdeleting. Simply qdels this datum and lets Destroy() handle the rest. @@ -78,7 +90,12 @@ add(client_source) if(quirk_flags & QUIRK_PROCESSES) - START_PROCESSING(SSquirks, src) + if(!isnull(minimum_process_stat)) + RegisterSignal(quirk_holder, COMSIG_MOB_STATCHANGE, PROC_REF(on_stat_changed)) + if(process_update_signals) + RegisterSignals(quirk_holder, process_update_signals, PROC_REF(update_process)) + if(should_process()) + START_PROCESSING(SSquirks, src) if(!quirk_transfer) if(gain_text) @@ -99,7 +116,9 @@ if(!quirk_holder) CRASH("Attempted to remove quirk from the current holder when it has no current holder.") - UnregisterSignal(quirk_holder, list(COMSIG_MOB_LOGIN, COMSIG_QDELETING)) + UnregisterSignal(quirk_holder, list(COMSIG_MOB_STATCHANGE, COMSIG_MOB_LOGIN, COMSIG_QDELETING)) + if(process_update_signals) + UnregisterSignal(quirk_holder, process_update_signals) quirk_holder.quirks -= src @@ -148,6 +167,35 @@ /datum/quirk/proc/post_add() return +/// Returns if the quirk holder should process currently or not. +/datum/quirk/proc/should_process() + SHOULD_CALL_PARENT(TRUE) + SHOULD_BE_PURE(TRUE) + if(QDELETED(quirk_holder)) + return FALSE + if(!(quirk_flags & QUIRK_PROCESSES)) + return FALSE + if(!isnull(minimum_process_stat) && quirk_holder.stat <= minimum_process_stat) + return FALSE + for(var/trait in no_process_traits) + if(HAS_TRAIT(quirk_holder, trait)) + return FALSE + return TRUE + +/// Checks to see if the quirk should be processing, and starts/stops it. +/datum/quirk/proc/update_process() + SIGNAL_HANDLER + SHOULD_NOT_OVERRIDE(TRUE) + if(should_process()) + START_PROCESSING(SSquirks, src) + else + STOP_PROCESSING(SSquirks, src) + +/// Updates processing status whenever the mob's stat changes. +/datum/quirk/proc/on_stat_changed(mob/living/source, new_stat) + SIGNAL_HANDLER + update_process() + /// Subtype quirk that has some bonus logic to spawn items for the player. /datum/quirk/item_quirk /// Lazylist of strings describing where all the quirk items have been spawned. @@ -204,7 +252,7 @@ /mob/living/proc/get_quirk_string(medical = FALSE, category = CAT_QUIRK_ALL, from_scan = FALSE) var/list/dat = list() for(var/datum/quirk/candidate as anything in quirks) - if(from_scan & candidate.quirk_flags & QUIRK_HIDE_FROM_SCAN) + if(from_scan && (candidate.quirk_flags & QUIRK_HIDE_FROM_SCAN)) continue switch(category) if(CAT_QUIRK_MAJOR_DISABILITY) @@ -218,7 +266,7 @@ continue dat += medical ? candidate.medical_record_text : candidate.name - if(!dat.len) + if(!length(dat)) return medical ? "No issues have been declared." : "None" return medical ? dat.Join("
") : dat.Join(", ") diff --git a/code/datums/quirks/negative_quirks/addict.dm b/code/datums/quirks/negative_quirks/addict.dm index 2ab7b8641274b0..8574c6060d6b8c 100644 --- a/code/datums/quirks/negative_quirks/addict.dm +++ b/code/datums/quirks/negative_quirks/addict.dm @@ -5,15 +5,16 @@ medical_record_text = "Patient has a history with SOMETHING but he refuses to tell us what it is." abstract_parent_type = /datum/quirk/item_quirk/addict quirk_flags = QUIRK_HUMAN_ONLY|QUIRK_PROCESSES + no_process_traits = list(TRAIT_LIVERLESS_METABOLISM) var/datum/reagent/reagent_type //!If this is defined, reagent_id will be unused and the defined reagent type will be instead. var/datum/reagent/reagent_instance //! actual instanced version of the reagent var/where_drug //! Where the drug spawned var/obj/item/drug_container_type //! If this is defined before pill generation, pill generation will be skipped. This is the type of the pill bottle. var/where_accessory //! where the accessory spawned var/obj/item/accessory_type //! If this is null, an accessory won't be spawned. - var/process_interval = 30 SECONDS //! how frequently the quirk processes - var/next_process = 0 //! ticker for processing var/drug_flavour_text = "Better hope you don't run out... of what, exactly? You don't know." + var/process_interval = 30 SECONDS //! how frequently the quirk processes + COOLDOWN_DECLARE(next_process) //! ticker for processing /datum/quirk/item_quirk/addict/add_unique(client/client_source) var/mob/living/carbon/human/human_holder = quirk_holder @@ -62,22 +63,21 @@ ) /datum/quirk/item_quirk/addict/process(seconds_per_tick) - if(HAS_TRAIT(quirk_holder, TRAIT_LIVERLESS_METABOLISM)) + if(!COOLDOWN_FINISHED(src, next_process)) return + COOLDOWN_START(src, next_process, process_interval) var/mob/living/carbon/human/human_holder = quirk_holder - if(world.time > next_process) - next_process = world.time + process_interval - var/deleted = QDELETED(reagent_instance) - var/missing_addiction = FALSE - for(var/addiction_type in reagent_instance.addiction_types) - if(!LAZYACCESS(human_holder.last_mind?.active_addictions, addiction_type)) - missing_addiction = TRUE - if(deleted || missing_addiction) - if(deleted) - reagent_instance = new reagent_type() - to_chat(quirk_holder, span_danger("You thought you kicked it, but you feel like you're falling back onto bad habits..")) - for(var/addiction in reagent_instance.addiction_types) - human_holder.last_mind?.add_addiction_points(addiction, 1000) ///Max that shit out + var/deleted = QDELETED(reagent_instance) + var/missing_addiction = FALSE + for(var/addiction_type in reagent_instance.addiction_types) + if(!LAZYACCESS(human_holder.last_mind?.active_addictions, addiction_type)) + missing_addiction = TRUE + if(deleted || missing_addiction) + if(deleted) + reagent_instance = new reagent_type() + to_chat(quirk_holder, span_danger("You thought you kicked it, but you feel like you're falling back onto bad habits..")) + for(var/addiction in reagent_instance.addiction_types) + human_holder.last_mind?.add_addiction_points(addiction, 1000) ///Max that shit out /datum/quirk/item_quirk/addict/junkie name = "Junkie" diff --git a/code/datums/quirks/negative_quirks/allergic.dm b/code/datums/quirks/negative_quirks/allergic.dm index 8588b95e6e33ca..43bee117c4061d 100644 --- a/code/datums/quirks/negative_quirks/allergic.dm +++ b/code/datums/quirks/negative_quirks/allergic.dm @@ -9,6 +9,7 @@ hardcore_value = 3 quirk_flags = QUIRK_HUMAN_ONLY|QUIRK_PROCESSES mail_goodies = list(/obj/item/reagent_containers/hypospray/medipen) // epinephrine medipen stops allergic reactions + no_process_traits = list(TRAIT_STASIS) var/list/allergies = list() var/list/blacklist = list( /datum/reagent/medicine/c2, @@ -45,15 +46,6 @@ to_chat(quirk_holder, span_boldnotice("You are allergic to [allergy_string], make sure not to consume any of these!")) /datum/quirk/item_quirk/allergic/process(seconds_per_tick) - if(!iscarbon(quirk_holder)) - return - - if(HAS_TRAIT(quirk_holder, TRAIT_STASIS)) - return - - if(quirk_holder.stat == DEAD) - return - var/mob/living/carbon/carbon_quirk_holder = quirk_holder //Just halts the progression, I'd suggest you run to medbay asap to get it fixed if(carbon_quirk_holder.reagents.has_reagent(/datum/reagent/medicine/epinephrine)) diff --git a/code/datums/quirks/negative_quirks/brain_problems.dm b/code/datums/quirks/negative_quirks/brain_problems.dm index 15cc0128020cf4..448835009cd343 100644 --- a/code/datums/quirks/negative_quirks/brain_problems.dm +++ b/code/datums/quirks/negative_quirks/brain_problems.dm @@ -14,6 +14,7 @@ hardcore_value = 12 quirk_flags = QUIRK_HUMAN_ONLY|QUIRK_PROCESSES mail_goodies = list(/obj/item/storage/pill_bottle/mannitol/braintumor) + no_process_traits = list(TRAIT_TUMOR_SUPPRESSED) /datum/quirk/item_quirk/brainproblems/add_unique(client/client_source) give_item_to_holder( @@ -28,10 +29,4 @@ ) /datum/quirk/item_quirk/brainproblems/process(seconds_per_tick) - if(quirk_holder.stat == DEAD) - return - - if(HAS_TRAIT(quirk_holder, TRAIT_TUMOR_SUPPRESSED)) - return - quirk_holder.adjustOrganLoss(ORGAN_SLOT_BRAIN, 0.2 * seconds_per_tick) diff --git a/code/datums/quirks/negative_quirks/claustrophobia.dm b/code/datums/quirks/negative_quirks/claustrophobia.dm index 226c9b65ef8496..8f0cb0186e4e41 100644 --- a/code/datums/quirks/negative_quirks/claustrophobia.dm +++ b/code/datums/quirks/negative_quirks/claustrophobia.dm @@ -7,17 +7,13 @@ hardcore_value = 5 quirk_flags = QUIRK_HUMAN_ONLY|QUIRK_PROCESSES mail_goodies = list(/obj/item/reagent_containers/syringe/convermol) // to help breathing + minimum_process_stat = CONSCIOUS + no_process_traits = list(TRAIT_MIND_TEMPORARILY_GONE, TRAIT_FEARLESS, TRAIT_KNOCKEDOUT) /datum/quirk/claustrophobia/remove() quirk_holder.clear_mood_event("claustrophobia") /datum/quirk/claustrophobia/process(seconds_per_tick) - if(quirk_holder.stat != CONSCIOUS || quirk_holder.IsSleeping() || quirk_holder.IsUnconscious()) - return - - if(HAS_TRAIT(quirk_holder, TRAIT_MIND_TEMPORARILY_GONE) || HAS_TRAIT(quirk_holder, TRAIT_FEARLESS)) - return - var/nick_spotted = FALSE for(var/mob/living/carbon/human/possible_claus in view(5, quirk_holder)) diff --git a/code/datums/quirks/negative_quirks/family_heirloom.dm b/code/datums/quirks/negative_quirks/family_heirloom.dm index 235913120a3fb1..d7b2755088ab21 100644 --- a/code/datums/quirks/negative_quirks/family_heirloom.dm +++ b/code/datums/quirks/negative_quirks/family_heirloom.dm @@ -55,9 +55,6 @@ return ..() /datum/quirk/item_quirk/family_heirloom/process() - if(quirk_holder.stat == DEAD) - return - var/obj/family_heirloom = heirloom?.resolve() if(family_heirloom && (family_heirloom in quirk_holder.get_all_contents()))