You can fix up a deconstructed nuclear bomb (#95104)

## About The Pull Request

Allows reconstruction of a deconstructed nuclear bomb, including placing
the core back in. You can put the core back in with either a raw
core(which is still unobtainable afaik) or the box. The box remains
usable afterwards.

The beer nuke's deconstruction has been slightly modified such that it
no longer shows a glowing core inside of it, and is instead empty. The
beer nuke can also now be given a transplant core, and will blow up like
a real bomb if given a real core.

Additionally, provides a message making explicit that you can't take out
the nuke core bare.

This also fixes a runtime in the beer nuke's deconstruction due to
attempting to start processing a null core.

This also fixes that nuke cores processing inside the bomb would not
irradiate their surrounding area

## Why It's Good For The Game

It makes sense. If you catch the guy what broke your nuke, you should be
able to fix your nuke. I also think making the beer bomb into a real
bomb is pretty funny.

Probably closes #95101, because I assume not being able to take out the
raw core is very intentional.

## Changelog
🆑

add: You can now put a deconstructed nuclear bomb back together again
fix: Nuclear bombs with exposed cores will again irradiate their
surrounding area

/🆑
This commit is contained in:
Leland Kemble
2026-02-08 22:42:21 +01:00
committed by GitHub
parent 6f9af69045
commit 218534473c
3 changed files with 94 additions and 34 deletions
@@ -124,10 +124,22 @@ GLOBAL_VAR(station_nuke_source)
if(NUKESTATE_INTACT)
if(istype(weapon, /obj/item/screwdriver/nuke))
to_chat(user, span_notice("You start removing [src]'s front panel's screws..."))
if(weapon.use_tool(src, user, 6 SECONDS, volume = 100))
deconstruction_state = NUKESTATE_UNSCREWED
to_chat(user, span_notice("You remove the screws from [src]'s front panel."))
update_appearance()
if(!weapon.use_tool(src, user, 6 SECONDS, volume = 100))
return TRUE
deconstruction_state = NUKESTATE_UNSCREWED
to_chat(user, span_notice("You remove the screws from [src]'s front panel."))
update_appearance()
return TRUE
if(NUKESTATE_UNSCREWED)
if(istype(weapon, /obj/item/screwdriver/nuke))
to_chat(user, span_notice("You start screwing [src]'s front panel back in..."))
if(!weapon.use_tool(src, user, 8 SECONDS, volume = 100))
return TRUE
deconstruction_state = NUKESTATE_INTACT
to_chat(user, span_notice("You screw [src]'s front panel back into place."))
deconstruction_state = NUKESTATE_INTACT
update_appearance()
return TRUE
if(NUKESTATE_PANEL_REMOVED)
@@ -135,24 +147,26 @@ GLOBAL_VAR(station_nuke_source)
if(!weapon.tool_start_check(user, amount = 1))
return TRUE
to_chat(user, span_notice("You start cutting [src]'s inner plate..."))
if(weapon.use_tool(src, user, 8 SECONDS, volume=100))
to_chat(user, span_notice("You cut [src]'s inner plate."))
deconstruction_state = NUKESTATE_WELDED
update_appearance()
if(!weapon.use_tool(src, user, 8 SECONDS, volume=100))
return TRUE
to_chat(user, span_notice("You cut [src]'s inner plate."))
deconstruction_state = NUKESTATE_WELDED
update_appearance()
return TRUE
if(NUKESTATE_CORE_EXPOSED)
if(istype(weapon, /obj/item/nuke_core_container))
var/obj/item/nuke_core_container/core_box = weapon
to_chat(user, span_notice("You start loading the plutonium core into [core_box]..."))
if(do_after(user, 5 SECONDS, target = src, hidden = TRUE))
if(core_box.load(core, user))
to_chat(user, span_notice("You load the plutonium core into [core_box]."))
deconstruction_state = NUKESTATE_CORE_REMOVED
update_appearance()
core = null
else
to_chat(user, span_warning("You fail to load the plutonium core into [core_box]. [core_box] has already been used!"))
if(!do_after(user, 5 SECONDS, target = src, hidden = TRUE))
return TRUE
if(core_box.load(core, user))
to_chat(user, span_notice("You load the plutonium core into [core_box]."))
deconstruction_state = NUKESTATE_CORE_REMOVED
update_appearance()
core = null
else
to_chat(user, span_warning("You fail to load the plutonium core into [core_box]. [core_box] has already been used!"))
return TRUE
if(istype(weapon, /obj/item/stack/sheet/iron))
@@ -160,11 +174,37 @@ GLOBAL_VAR(station_nuke_source)
return TRUE
to_chat(user, span_notice("You begin repairing [src]'s inner metal plate..."))
if(weapon.use_tool(src, user, 10 SECONDS, amount = 20))
to_chat(user, span_notice("You repair [src]'s inner metal plate. The radiation is contained."))
deconstruction_state = NUKESTATE_PANEL_REMOVED
STOP_PROCESSING(SSobj, core)
update_appearance()
if(!weapon.use_tool(src, user, 10 SECONDS, amount = 20))
return TRUE
to_chat(user, span_notice("You repair [src]'s inner metal plate. The radiation is contained."))
deconstruction_state = NUKESTATE_PANEL_REMOVED
STOP_PROCESSING(SSobj, core)
update_appearance()
return TRUE
if(NUKESTATE_CORE_REMOVED)
if(astype(weapon, /obj/item/nuke_core_container)?.core && !istype(weapon, /obj/item/nuke_core_container/supermatter))
var/obj/item/nuke_core_container/core_box = weapon
to_chat(user, span_notice("You pry open [core_box] and begin placing [core_box.core] into [src]'s inner chamber..."))
if(!do_after(user, 15 SECONDS, src))
return TRUE
core_box.core.forceMove(src)
core = core_box.core
to_chat(user, span_notice("You place [core_box.core] into [src]'s inner chamber."))
deconstruction_state = NUKESTATE_CORE_EXPOSED
update_appearance()
core_box.icon_state = core_box::icon_state
core_box.core = null
return TRUE
if(istype(weapon, /obj/item/nuke_core) && !istype(weapon, /obj/item/nuke_core/supermatter_sliver))
to_chat(user, span_notice("You begin placing [weapon] into [src]'s inner chamber..."))
if(!do_after(user, 6 SECONDS, src))
return TRUE
weapon.forceMove(src)
core = weapon
to_chat(user, span_notice("You place [weapon] into [src]'s inner chamber."))
deconstruction_state = NUKESTATE_CORE_EXPOSED
update_appearance()
return TRUE
return ..()
@@ -173,22 +213,42 @@ GLOBAL_VAR(station_nuke_source)
switch(deconstruction_state)
if(NUKESTATE_UNSCREWED)
to_chat(user, span_notice("You start removing [src]'s front panel..."))
if(tool.use_tool(src, user, 30, volume=100))
to_chat(user, span_notice("You remove [src]'s front panel."))
deconstruction_state = NUKESTATE_PANEL_REMOVED
update_appearance()
if(!tool.use_tool(src, user, 30, volume=100))
return TRUE
to_chat(user, span_notice("You remove [src]'s front panel."))
deconstruction_state = NUKESTATE_PANEL_REMOVED
update_appearance()
return TRUE
if(NUKESTATE_WELDED)
to_chat(user, span_notice("You start prying off [src]'s inner plate..."))
if(tool.use_tool(src, user, 30, volume=100))
if(!tool.use_tool(src, user, 30, volume=100))
return TRUE
if(core)
to_chat(user, span_notice("You pry off [src]'s inner plate. You can see the core's green glow!"))
deconstruction_state = NUKESTATE_CORE_EXPOSED
update_appearance()
START_PROCESSING(SSobj, core)
else
to_chat(user, span_notice("You pry off [src]'s inner plate. The inner chamber is empty, save for some beer stains."))
deconstruction_state = NUKESTATE_CORE_REMOVED
update_appearance()
new /obj/item/stack/sheet/iron(loc, 15)
return TRUE
if(NUKESTATE_PANEL_REMOVED)
to_chat(user, span_notice("You start levering [src]'s inner panel back into place..."))
if(!tool.use_tool(src, user, 30, volume = 100))
return TRUE
to_chat(user, span_notice("You lever [src]'s inner panel back into place."))
deconstruction_state = NUKESTATE_UNSCREWED
update_appearance()
return TRUE
return FALSE
/obj/machinery/nuclearbomb/attack_hand_secondary(mob/user, list/modifiers)
if(deconstruction_state != NUKESTATE_CORE_EXPOSED)
return ..()
to_chat(user, span_danger("You can't hold [core] with your bare hands!"))
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
/obj/machinery/nuclearbomb/can_interact(mob/user)
if(HAS_TRAIT(user, TRAIT_CAN_USE_NUKE))
return TRUE
@@ -32,13 +32,11 @@
weapon.interact_with_atom(keg, user) // redirect refillable containers to the keg, allowing them to be filled
return TRUE // pretend we handled the attack, too.
if(istype(weapon, /obj/item/nuke_core_container))
to_chat(user, span_notice("[src] has had its plutonium core removed as a part of being decommissioned."))
return TRUE
return ..()
/obj/machinery/nuclearbomb/beer/actually_explode()
if(core)
return ..()
//Unblock roundend, we're not actually exploding.
SSticker.roundend_check_paused = FALSE
var/turf/bomb_location = get_turf(src)
@@ -61,6 +59,8 @@
disarm_nuke()
/obj/machinery/nuclearbomb/beer/really_actually_explode(detonation_status)
if(core)
return ..()
//if it's always hooked in it'll override admin choices
RegisterSignal(overflow_control, COMSIG_CREATED_ROUND_EVENT, PROC_REF(on_created_round_event))
disarm_nuke()