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."