diff --git a/code/__DEFINES/dcs/signals/signals_object.dm b/code/__DEFINES/dcs/signals/signals_object.dm index 2b6c1b32206..8b5778602e0 100644 --- a/code/__DEFINES/dcs/signals/signals_object.dm +++ b/code/__DEFINES/dcs/signals/signals_object.dm @@ -539,3 +539,9 @@ #define COMSIG_ITEM_WEIGHT_CLASS_CHANGED "item_weight_class_changed" /// Sent from /obj/item/update_weight_class(), to its loc. (obj/item/changed_item, old_w_class, new_w_class) #define COMSIG_ATOM_CONTENTS_WEIGHT_CLASS_CHANGED "atom_contents_weight_class_changed" + +///Sent from /obj/item/skillchip/on_implant() +#define COMSIG_SKILLCHIP_IMPLANTED "skillchip_implanted" + +///Sent from /obj/item/skillchip/on_remove() +#define COMSIG_SKILLCHIP_REMOVED "skillchip_removed" diff --git a/code/datums/quirks/positive_quirks/chipped.dm b/code/datums/quirks/positive_quirks/chipped.dm index 7f43fc07b5b..474e8a4adcd 100644 --- a/code/datums/quirks/positive_quirks/chipped.dm +++ b/code/datums/quirks/positive_quirks/chipped.dm @@ -5,7 +5,7 @@ value = 2 gain_text = span_notice("The chip in your head itches a bit.") lose_text = span_danger("You don't feel so chipped anymore..") - medical_record_text = "Patient explained how they got caught up in 'the skillchip chase' recently, and now the chip in they head itches every so often. Dumbass." + medical_record_text = "Patient explained how they got caught up in 'the skillchip chase' recently, and now the chip in their head itches every so often. Dumbass." mail_goodies = list( /obj/item/skillchip/matrix_taunt, /obj/item/skillchip/big_pointer, @@ -14,44 +14,70 @@ ) /// Variable that holds the chip, used on removal. var/obj/item/skillchip/installed_chip - var/datum/callback/itchy_timer + ///itchy status effect we give our owner + var/datum/itchy_effect /datum/quirk_constant_data/chipped associated_typepath = /datum/quirk/chipped customization_options = list(/datum/preference/choiced/chipped) /datum/quirk/chipped/add_to_holder(mob/living/new_holder, quirk_transfer, client/client_source) - var/obj/item/skillchip/chip_pref = GLOB.quirk_chipped_choice[client_source?.prefs?.read_preference(/datum/preference/choiced/chipped)] + var/chip_pref = client_source?.prefs?.read_preference(/datum/preference/choiced/chipped) - if(!chip_pref) + if(isnull(chip_pref)) return ..() - - gain_text = span_notice("The [chip_pref] in your head itches a bit.") + installed_chip = GLOB.quirk_chipped_choice[chip_pref] || GLOB.quirk_chipped_choice[pick(GLOB.quirk_chipped_choice)] + gain_text = span_notice("The [installed_chip::name] in your head itches a bit.") lose_text = span_notice("Your head stops itching so much.") return ..() /datum/quirk/chipped/add_unique(client/client_source) - - var/preferred_chip = GLOB.quirk_chipped_choice[client_source?.prefs?.read_preference(/datum/preference/choiced/chipped)] - if(isnull(preferred_chip)) //Client is gone or they chose a random chip - preferred_chip = GLOB.quirk_chipped_choice[pick(GLOB.quirk_chipped_choice)] + if(!iscarbon(quirk_holder)) + return var/mob/living/carbon/quirk_holder_carbon = quirk_holder - if(iscarbon(quirk_holder)) - installed_chip = new preferred_chip() - quirk_holder_carbon.implant_skillchip(installed_chip, force = TRUE) + installed_chip = new installed_chip() + + RegisterSignals(installed_chip, list(COMSIG_QDELETING, COMSIG_SKILLCHIP_REMOVED), PROC_REF(remove_effect)) + RegisterSignal(installed_chip, COMSIG_SKILLCHIP_IMPLANTED, PROC_REF(apply_effect)) + + quirk_holder_carbon.implant_skillchip(installed_chip, force = TRUE) installed_chip.try_activate_skillchip(silent = FALSE, force = TRUE) - var/obj/item/organ/brain/itchy_brain = quirk_holder.get_organ_by_type(ORGAN_SLOT_BRAIN) - itchy_timer = addtimer(CALLBACK(src, PROC_REF(cause_itchy), itchy_brain), rand(5 SECONDS, 10 MINUTES)) // they get The Itch from a poor quality install every so often +/datum/quirk/chipped/proc/apply_effect(datum/source, obj/item/brain_applied) + SIGNAL_HANDLER + var/mob/living/carbon/quirk_holder_carbon = quirk_holder + if(brain_applied == quirk_holder_carbon.get_organ_slot(ORGAN_SLOT_BRAIN)) + itchy_effect = quirk_holder.apply_status_effect(/datum/status_effect/itchy_skillchip_quirk) + +/datum/quirk/chipped/proc/remove_effect(datum/source, obj/item/brain_removed) + SIGNAL_HANDLER + var/mob/living/carbon/quirk_holder_carbon = quirk_holder + if(QDELING(source) || brain_removed == quirk_holder_carbon.get_organ_slot(ORGAN_SLOT_BRAIN)) + quirk_holder.remove_status_effect(itchy_effect) + itchy_effect = null /datum/quirk/chipped/remove() - qdel(installed_chip) - deltimer(itchy_timer) - . = ..() + QDEL_NULL(installed_chip) + if(itchy_effect) + quirk_holder.remove_status_effect(itchy_effect) + itchy_effect = null + return ..() -/datum/quirk/chipped/proc/cause_itchy(obj/item/organ/brain/itchy_brain) +/datum/status_effect/itchy_skillchip_quirk + id = "itchy skillchip" + tick_interval_lowerbound = 5 SECONDS + tick_interval_upperbound = 10 MINUTES + ///lower damage we apply to our itchy owner + var/minimum_damage = 1 + ///upper damage we apply to our itchy owner + var/maximum_damage = 5 - itchy_brain.apply_organ_damage(rand(1, 5), maximum = itchy_brain.maxHealth * 0.3) - to_chat(itchy_brain.owner, span_warning("Your [itchy_brain] itches.")) - itchy_timer = addtimer(CALLBACK(itchy_brain, PROC_REF(cause_itchy)), rand(5 SECONDS, 10 MINUTES)) // it will never end +/datum/status_effect/itchy_skillchip_quirk/tick(seconds_between_ticks) + var/mob/living/carbon/carbon_owner = owner + var/obj/item/organ/brain/itchy_brain = carbon_owner.get_organ_slot(ORGAN_SLOT_BRAIN) + if(isnull(itchy_brain)) + return + itchy_brain.apply_organ_damage(rand(minimum_damage, maximum_damage), maximum = itchy_brain.maxHealth * 0.3) + if(owner.stat == CONSCIOUS && !owner.incapacitated && owner.get_empty_held_indexes()) + to_chat(owner, span_warning("You scratch the itch in your head.")) diff --git a/code/datums/status_effects/_status_effect.dm b/code/datums/status_effects/_status_effect.dm index df525fa8c81..9f3e3a54904 100644 --- a/code/datums/status_effects/_status_effect.dm +++ b/code/datums/status_effects/_status_effect.dm @@ -12,6 +12,10 @@ /// While processing, this becomes the world.time when the next tick will occur. /// -1 = will prevent ticks, and if duration is also unlimited (-1), stop processing wholesale. var/tick_interval = 1 SECONDS + ///If our tick intervals are set to be a dynamic value within a range, the lowerbound of said range + var/tick_interval_lowerbound + ///If our tick intervals are set to be a dynamic value within a range, the upperbound of said range + var/tick_interval_upperbound /// The mob affected by the status effect. VAR_FINAL/mob/living/owner /// How many of the effect can be on one mob, and/or what happens when you try to add a duplicate. @@ -112,7 +116,7 @@ return if(tick_interval != STATUS_EFFECT_NO_TICK && tick_interval < world.time) - var/tick_length = initial(tick_interval) + var/tick_length = (tick_interval_upperbound && tick_interval_lowerbound) ? rand(tick_interval_lowerbound, tick_interval_upperbound) : initial(tick_interval) tick(tick_length / (1 SECONDS)) tick_interval = world.time + tick_length if(QDELING(src)) diff --git a/code/modules/library/skill_learning/skillchip.dm b/code/modules/library/skill_learning/skillchip.dm index 5ca3f784ecb..f534e391bcb 100644 --- a/code/modules/library/skill_learning/skillchip.dm +++ b/code/modules/library/skill_learning/skillchip.dm @@ -132,10 +132,12 @@ * * owner_brain - The brain that this skillchip was implanted in to. */ /obj/item/skillchip/proc/on_implant(obj/item/organ/brain/owner_brain) + SHOULD_CALL_PARENT(TRUE) if(holding_brain) CRASH("Skillchip is trying to be implanted into [owner_brain], but it's already implanted in [holding_brain]") holding_brain = owner_brain + SEND_SIGNAL(src, COMSIG_SKILLCHIP_IMPLANTED, holding_brain) /** * Called when a skillchip is activated. @@ -172,7 +174,7 @@ try_deactivate_skillchip(silent, TRUE) COOLDOWN_RESET(src, chip_cooldown) - + SEND_SIGNAL(src, COMSIG_SKILLCHIP_REMOVED, holding_brain) holding_brain = null /**