From faf405b0837b6e5db8d426fdd8933ea759fe0d87 Mon Sep 17 00:00:00 2001 From: CRITAWAKETS Date: Tue, 8 Aug 2023 11:17:33 -0400 Subject: [PATCH] Adds in the Tactical Deniability Implant for nukeops. (#77214) ## About The Pull Request This PR adds in the Tactical Deniability Implant to the nuclear operative uplink for 6 TC. It's new version of the minibomb, implanted directly into your brain. It disables softcrit and hardcrit, making it extremely powerful... For about 10.7 seconds (without stacked minibombs), before you realize what the increasing beeping is for, and proceed to explode. Even atropine can't save you from this one. There is kind of a buff in that the delay of mini/macrobombs can no longer reach 30 seconds, since it just makes things a lot more interesting with a time cap (and also you'd need like 4 macrobombs to reach it so it mostly only impacts this new feature) ## Why It's Good For The Game It's an interesting tradeoff where you can survive for a bit after critical condition, but whenever it triggers you've effectively sealed your own fate. Even if a helpful operative comes along to heal you, you WILL explode. ## Changelog :cl: add: The Syndicate has begun rolling out new Tactical Deniability Implants for their Nuclear Operative teams. It seems these implants are designed to make teams "fight harder" by "giving incentives for fighting to the bitter end", whatever they're talking about. /:cl: --- .../items/implants/implant_explosive.dm | 113 ++++++++++++++---- .../game/objects/items/storage/uplink_kits.dm | 6 + code/modules/uplink/uplink_items/nukeops.dm | 7 ++ 3 files changed, 100 insertions(+), 26 deletions(-) diff --git a/code/game/objects/items/implants/implant_explosive.dm b/code/game/objects/items/implants/implant_explosive.dm index abe487a0166..70471a8e99a 100644 --- a/code/game/objects/items/implants/implant_explosive.dm +++ b/code/game/objects/items/implants/implant_explosive.dm @@ -27,6 +27,12 @@ var/explosion_devastate = MICROBOMB_EXPLOSION_DEVASTATE ///Whether the confirmation UI popup is active or not var/popup = FALSE + ///Do we rapidly increase the beeping speed as it gets closer to detonating? + var/panic_beep_sound = FALSE + ///Do we disable paralysis upon activation + var/no_paralyze = FALSE + ///Do we override other explosive implants? + var/master_implant = FALSE /obj/item/implant/explosive/proc/on_death(datum/source, gibbed) @@ -64,34 +70,28 @@ return FALSE if(cause == "death" && HAS_TRAIT(imp_in, TRAIT_PREVENT_IMPLANT_AUTO_EXPLOSION)) return FALSE - explosion_devastate = round(explosion_devastate) - explosion_heavy = round(explosion_heavy) - explosion_light = round(explosion_light) to_chat(imp_in, span_notice("You activate your [name].")) active = TRUE var/turf/boomturf = get_turf(imp_in) message_admins("[ADMIN_LOOKUPFLW(imp_in)] has activated their [name] at [ADMIN_VERBOSEJMP(boomturf)], with cause of [cause].") //If the delay is shorter or equal to the default delay, just blow up already jeez if(delay <= MICROBOMB_DELAY) - explosion(src, devastation_range = explosion_devastate, heavy_impact_range = explosion_heavy, light_impact_range = explosion_light, flame_range = explosion_light, flash_range = explosion_light, explosion_cause = src) - if(imp_in) - imp_in.investigate_log("has been gibbed by an explosive implant.", INVESTIGATE_DEATHS) - imp_in.gib(TRUE) - qdel(src) + explode() return timed_explosion() /obj/item/implant/explosive/implant(mob/living/target, mob/user, silent = FALSE, force = FALSE) for(var/target_implant in target.implants) if(istype(target_implant, /obj/item/implant/explosive)) //we don't use our own type here, because macrobombs inherit this proc and need to be able to upgrade microbombs - //We merge the two implants into a single bigger, badder one by adding the injected implant's values into the already present implant - var/obj/item/implant/explosive/implant_to_upgrade = target_implant - implant_to_upgrade.explosion_devastate += explosion_devastate - implant_to_upgrade.explosion_heavy += explosion_heavy - implant_to_upgrade.explosion_light += explosion_light - implant_to_upgrade.delay += delay - qdel(src) - return TRUE + var/obj/item/implant/explosive/other_implant = target_implant + if(other_implant.master_implant && master_implant) //we cant have two master implants at once + target.balloon_alert(target, "cannot fit implant!") + return FALSE + if(master_implant) + merge_implants(src, other_implant) + else + merge_implants(other_implant, src) + return TRUE . = ..() if(.) @@ -102,6 +102,18 @@ if(.) UnregisterSignal(target, COMSIG_LIVING_DEATH) +/** + * Merges two explosive implants together, adding the stats of the latter to the former before qdeling the latter implant. + * kept_implant = the implant that is kept + * stat_implant = the implant which has it's stats added to kept_implant, before being deleted. + */ +/obj/item/implant/explosive/proc/merge_implants(obj/item/implant/explosive/kept_implant, obj/item/implant/explosive/stat_implant) + kept_implant.explosion_devastate += stat_implant.explosion_devastate + kept_implant.explosion_heavy += stat_implant.explosion_heavy + kept_implant.explosion_light += stat_implant.explosion_light + kept_implant.delay = min(kept_implant.delay + stat_implant.delay, 30 SECONDS) + qdel(stat_implant) + /** * Explosive activation sequence for implants with a delay longer than 0.7 seconds. * Make the implantee beep a few times, keel over and explode. Usually to a devastating effect. @@ -120,26 +132,44 @@ ) playsound(loc, 'sound/items/timer.ogg', 30, FALSE) - sleep(delay * 0.25) - if(imp_in && !imp_in.stat) + if(!panic_beep_sound) + sleep(delay * 0.25) + if(imp_in && !imp_in.stat && !no_paralyze) imp_in.visible_message(span_warning("[imp_in] doubles over in pain!")) imp_in.Paralyze(14 SECONDS) //total of 4 bomb beeps, and we've already beeped once var/bomb_beeps_until_boom = 3 - while(bomb_beeps_until_boom > 0) - //for extra spice - var/beep_volume = 35 - playsound(loc, 'sound/items/timer.ogg', beep_volume, FALSE) - sleep(delay * 0.25) - bomb_beeps_until_boom-- - beep_volume += 5 + if(!panic_beep_sound) + while(bomb_beeps_until_boom > 0) + //for extra spice + var/beep_volume = 35 + playsound(loc, 'sound/items/timer.ogg', beep_volume, vary = FALSE) + sleep(delay * 0.25) + bomb_beeps_until_boom-- + beep_volume += 5 + explode() + else + addtimer(CALLBACK(src, PROC_REF(explode)), delay) + while(delay > 1) //so we dont accidentally enter an infinite sleep + var/beep_volume = 35 + playsound(loc, 'sound/items/timer.ogg', beep_volume, vary = FALSE) + sleep(delay * 0.2) + delay -= delay * 0.2 + beep_volume += 5 + + +///When called, just explodes +/obj/item/implant/explosive/proc/explode() + explosion_devastate = round(explosion_devastate) + explosion_heavy = round(explosion_heavy) + explosion_light = round(explosion_light) explosion(src, devastation_range = explosion_devastate, heavy_impact_range = explosion_heavy, light_impact_range = explosion_light, flame_range = explosion_light, flash_range = explosion_light, explosion_cause = src) if(imp_in) imp_in.investigate_log("has been gibbed by an explosive implant.", INVESTIGATE_DEATHS) imp_in.gib(TRUE) qdel(src) -//Macrobomb has the strength and delay of 10 microbombs +///Macrobomb has the strength and delay of 10 microbombs /obj/item/implant/explosive/macro name = "macrobomb implant" desc = "And boom goes the weasel. And everything else nearby." @@ -149,6 +179,33 @@ explosion_heavy = 10 * MICROBOMB_EXPLOSION_HEAVY explosion_devastate = 10 * MICROBOMB_EXPLOSION_DEVASTATE +///Microbomb which prevents you from going into critical condition but also explodes after a timer when you reach critical condition in the first place. +/obj/item/implant/explosive/deniability + name = "tactical deniability implant" + desc = "An enhanced version of the microbomb that directly plugs into the brain. No downsides, promise!" + delay = 10 SECONDS + panic_beep_sound = TRUE + no_paralyze = TRUE + master_implant = TRUE + +/obj/item/implant/explosive/deniability/implant(mob/living/target, mob/user, silent = FALSE, force = FALSE) + . = ..() + if(.) + RegisterSignal(target, COMSIG_LIVING_HEALTH_UPDATE, PROC_REF(check_health)) + target.add_traits(list(TRAIT_NOSOFTCRIT, TRAIT_NOHARDCRIT), IMPLANT_TRAIT) + +/obj/item/implant/explosive/deniability/removed(mob/target, silent = FALSE, special = FALSE) + . = ..() + if(.) + UnregisterSignal(target, COMSIG_LIVING_HEALTH_UPDATE) + target.remove_traits(list(TRAIT_NOSOFTCRIT, TRAIT_NOHARDCRIT), IMPLANT_TRAIT) + +/obj/item/implant/explosive/deniability/proc/check_health(mob/living/source) + SIGNAL_HANDLER + + if(source.health < source.crit_threshold) + INVOKE_ASYNC(src, PROC_REF(activate), "deniability") + /obj/item/implanter/explosive name = "implanter (microbomb)" imp_type = /obj/item/implant/explosive @@ -162,6 +219,10 @@ name = "implanter (macrobomb)" imp_type = /obj/item/implant/explosive/macro +/obj/item/implanter/tactical_deniability + name = "implanter (tactical deniability)" + imp_type = /obj/item/implant/explosive/deniability + /datum/action/item_action/explosive_implant check_flags = NONE name = "Activate Explosive Implant" diff --git a/code/game/objects/items/storage/uplink_kits.dm b/code/game/objects/items/storage/uplink_kits.dm index 4d300204bb3..4c2eb4a3978 100644 --- a/code/game/objects/items/storage/uplink_kits.dm +++ b/code/game/objects/items/storage/uplink_kits.dm @@ -366,6 +366,12 @@ /obj/item/storage/box/syndie_kit/imp_macrobomb/PopulateContents() new /obj/item/implanter/explosive_macro(src) +/obj/item/storage/box/syndie_kit/imp_deniability + name = "tactical deniability implant box" + +/obj/item/storage/box/syndie_kit/imp_deniability/PopulateContents() + new /obj/item/implanter/tactical_deniability(src) + /obj/item/storage/box/syndie_kit/imp_uplink name = "uplink implant box" diff --git a/code/modules/uplink/uplink_items/nukeops.dm b/code/modules/uplink/uplink_items/nukeops.dm index 42bc0f56069..d92eb241d45 100644 --- a/code/modules/uplink/uplink_items/nukeops.dm +++ b/code/modules/uplink/uplink_items/nukeops.dm @@ -683,6 +683,13 @@ cost = 20 restricted = TRUE +/datum/uplink_item/implants/nuclear/deniability + name = "Tactical Deniability Implant" + desc = "An implant injected into the brain, and later activated either manually or automatically upon entering critical condition. \ + Prevents collapsing from critical condition, but explodes after a while." + item = /obj/item/storage/box/syndie_kit/imp_deniability + cost = 6 + /datum/uplink_item/implants/nuclear/reviverplus name = "Reviver Implant" desc = "This implant will attempt to revive and heal you if you lose consciousness. Comes with an autosurgeon."