diff --git a/code/__DEFINES/gamemode.dm b/code/__DEFINES/gamemode.dm
index 7e8d241c920..ad2680e10aa 100644
--- a/code/__DEFINES/gamemode.dm
+++ b/code/__DEFINES/gamemode.dm
@@ -52,3 +52,15 @@
#define SPECIAL_ROLE_XENOMORPH_SENTINEL "Xenomorph Sentinel"
#define SPECIAL_ROLE_XENOMORPH_LARVA "Xenomorph Larva"
#define SPECIAL_ROLE_EVENTMISC "Event Role"
+
+// Constants used by code which checks the status of nuclear blasts during a
+// round, regardless of original game mode, e.g. setting the ending cinematic.
+
+/// The bomb is on-station.
+#define NUKE_SITE_ON_STATION 0
+/// The bomb is on station z-level, but not a station tile.
+#define NUKE_SITE_ON_STATION_ZLEVEL 1
+/// The bomb is off station z-level.
+#define NUKE_SITE_OFF_STATION_ZLEVEL 2
+/// The bomb's location cannot be found.
+#define NUKE_SITE_INVALID 3
diff --git a/code/controllers/subsystem/SSticker.dm b/code/controllers/subsystem/SSticker.dm
index daca4f6b2cc..6cd840b0828 100644
--- a/code/controllers/subsystem/SSticker.dm
+++ b/code/controllers/subsystem/SSticker.dm
@@ -340,7 +340,7 @@ SUBSYSTEM_DEF(ticker)
return TRUE
-/datum/controller/subsystem/ticker/proc/station_explosion_cinematic(station_missed = 0, override = null)
+/datum/controller/subsystem/ticker/proc/station_explosion_cinematic(nuke_site = NUKE_SITE_ON_STATION, override = null)
if(cinematic)
return //already a cinematic in progress!
@@ -353,11 +353,9 @@ SUBSYSTEM_DEF(ticker)
cinematic.mouse_opacity = MOUSE_OPACITY_TRANSPARENT
cinematic.screen_loc = "1,1"
- if(station_missed)
- for(var/mob/M in GLOB.mob_list)
- if(M.client)
- M.client.screen += cinematic //show every client the cinematic
- else //nuke kills everyone on z-level 1 to prevent "hurr-durr I survived"
+ if(nuke_site == NUKE_SITE_ON_STATION)
+ // Kill everyone on z-level 1 except for mobs in freezers and
+ // malfunctioning AIs.
for(var/mob/M in GLOB.mob_list)
if(M.stat != DEAD)
var/turf/T = get_turf(M)
@@ -370,34 +368,15 @@ SUBSYSTEM_DEF(ticker)
CHECK_TICK
if(M && M.client) //Play the survivors a cinematic.
M.client.screen += cinematic
+ else
+ for(var/mob/M in GLOB.mob_list)
+ if(M.client)
+ M.client.screen += cinematic //show every client the cinematic
- //Now animate the cinematic
- switch(station_missed)
- if(1) //nuke was nearby but (mostly) missed
- if(mode && !override)
- override = mode.name
- switch(override)
- if("nuclear emergency") //Nuke wasn't on station when it blew up
- flick("intro_nuke", cinematic)
- sleep(35)
- SEND_SOUND(world, sound('sound/effects/explosion_distant.ogg'))
- flick("station_intact_fade_red", cinematic)
- cinematic.icon_state = "summary_nukefail"
- if("fake") //The round isn't over, we're just freaking people out for fun
- flick("intro_nuke", cinematic)
- sleep(35)
- SEND_SOUND(world, sound('sound/items/bikehorn.ogg'))
- flick("summary_selfdes", cinematic)
- else
- flick("intro_nuke", cinematic)
- sleep(35)
- SEND_SOUND(world, sound('sound/effects/explosion_distant.ogg'))
-
-
- if(2) //nuke was nowhere nearby //TODO: a really distant explosion animation
- sleep(50)
- SEND_SOUND(world, sound('sound/effects/explosion_distant.ogg'))
- else //station was destroyed
+ switch(nuke_site)
+ //Now animate the cinematic
+ if(NUKE_SITE_ON_STATION)
+ // station was destroyed
if(mode && !override)
override = mode.name
switch(override)
@@ -420,6 +399,31 @@ SUBSYSTEM_DEF(ticker)
SEND_SOUND(world, sound('sound/effects/explosion_distant.ogg'))
cinematic.icon_state = "summary_selfdes"
stop_delta_alarm()
+ if(NUKE_SITE_ON_STATION_ZLEVEL)
+ // nuke was nearby but (mostly) missed
+ if(mode && !override)
+ override = mode.name
+ switch(override)
+ if("nuclear emergency") //Nuke wasn't on station when it blew up
+ flick("intro_nuke", cinematic)
+ sleep(35)
+ SEND_SOUND(world, sound('sound/effects/explosion_distant.ogg'))
+ flick("station_intact_fade_red", cinematic)
+ cinematic.icon_state = "summary_nukefail"
+ if("fake") //The round isn't over, we're just freaking people out for fun
+ flick("intro_nuke", cinematic)
+ sleep(35)
+ SEND_SOUND(world, sound('sound/items/bikehorn.ogg'))
+ flick("summary_selfdes", cinematic)
+ else
+ flick("intro_nuke", cinematic)
+ sleep(35)
+ SEND_SOUND(world, sound('sound/effects/explosion_distant.ogg'))
+ if(NUKE_SITE_OFF_STATION_ZLEVEL, NUKE_SITE_INVALID)
+ // nuke was nowhere nearby
+ // TODO: a really distant explosion animation
+ sleep(50)
+ SEND_SOUND(world, sound('sound/effects/explosion_distant.ogg'))
//If its actually the end of the round, wait for it to end.
//Otherwise if its a verb it will continue on afterwards.
diff --git a/code/game/gamemodes/malfunction/Malf_Modules.dm b/code/game/gamemodes/malfunction/Malf_Modules.dm
index 91670058037..389699b921a 100644
--- a/code/game/gamemodes/malfunction/Malf_Modules.dm
+++ b/code/game/gamemodes/malfunction/Malf_Modules.dm
@@ -314,7 +314,7 @@
for(var/explodee in GLOB.player_list)
SEND_SOUND(explodee, doomsday_alarm)
sleep(100)
- SSticker.station_explosion_cinematic(null, "AI malfunction")
+ SSticker.station_explosion_cinematic(NUKE_SITE_ON_STATION, "AI malfunction")
to_chat(world, "The AI cleansed the station of life with the doomsday device!")
SSticker.mode.station_was_nuked = TRUE
diff --git a/code/game/gamemodes/nuclear/nuclearbomb.dm b/code/game/gamemodes/nuclear/nuclearbomb.dm
index 40a23f1d45d..f61991e65b2 100644
--- a/code/game/gamemodes/nuclear/nuclearbomb.dm
+++ b/code/game/gamemodes/nuclear/nuclearbomb.dm
@@ -531,7 +531,23 @@ GLOBAL_VAR(bomb_set)
if(zap_flags & ZAP_MACHINE_EXPLOSIVE)
qdel(src)//like the singulo, tesla deletes it. stops it from exploding over and over
-#define NUKERANGE 80
+/// Determine the location of the nuke with respect to the station. Used for,
+/// among other things, calculating win conditions for nukies and choosing which
+/// round-end cinematic to play.
+/obj/machinery/nuclearbomb/proc/get_nuke_site()
+ var/turf/bomb_turf = get_turf(src)
+ if(!bomb_turf)
+ return NUKE_SITE_INVALID
+
+ if(!is_station_level(bomb_turf.z))
+ return NUKE_SITE_OFF_STATION_ZLEVEL
+
+ if(get_area(src) in SSmapping.existing_station_areas)
+ return NUKE_SITE_ON_STATION
+
+ return NUKE_SITE_ON_STATION_ZLEVEL
+
+
/obj/machinery/nuclearbomb/proc/explode()
if(safety)
timing = FALSE
@@ -549,35 +565,34 @@ GLOBAL_VAR(bomb_set)
GLOB.enter_allowed = 0
- var/off_station = 0
- var/turf/bomb_location = get_turf(src)
- var/area/A = get_area(src)
- if( bomb_location && is_station_level(bomb_location.z) )
- if( (bomb_location.x < (128 - NUKERANGE)) || (bomb_location.x > (128 + NUKERANGE)) || (bomb_location.y < (128 - NUKERANGE)) || (bomb_location.y > (128 + NUKERANGE)) && (!(A in GLOB.the_station_areas)))
- off_station = 1
- else
- off_station = 2
+ var/nuke_site = get_nuke_site()
if(SSticker)
if(SSticker.mode && SSticker.mode.name == "nuclear emergency")
var/obj/docking_port/mobile/syndie_shuttle = SSshuttle.getShuttle("syndicate")
if(syndie_shuttle)
SSticker.mode:syndies_didnt_escape = is_station_level(syndie_shuttle.z)
- SSticker.mode:nuke_off_station = off_station
- SSticker.station_explosion_cinematic(off_station,null)
+ SSticker.mode:nuke_off_station = nuke_site
+ SSticker.station_explosion_cinematic(nuke_site, null)
if(SSticker.mode)
SSticker.mode.explosion_in_progress = FALSE
if(SSticker.mode.name == "nuclear emergency")
SSticker.mode:nukes_left --
- else if(off_station == 1)
+ else if(nuke_site == NUKE_SITE_ON_STATION_ZLEVEL)
to_chat(world, "A nuclear device was set off, but the explosion was out of reach of the station!")
- else if(off_station == 2)
- to_chat(world, "A nuclear device was set off, but the device was not on the station!")
+ else if(nuke_site == NUKE_SITE_OFF_STATION_ZLEVEL)
+ to_chat(world, "A nuclear device was set off, but the device nowhere near the station!")
+ else if(nuke_site == NUKE_SITE_INVALID)
+ to_chat(world, "A nuclear device was set off in an unknown location!")
+ log_admin("The nuclear device [src] detonated but was not located on a valid turf.")
else
to_chat(world, "The station was destroyed by the nuclear blast!")
- SSticker.mode.station_was_nuked = (off_station < 2) //offstation==1 is a draw. the station becomes irradiated and needs to be evacuated.
- //kinda shit but I couldn't get permission to do what I wanted to do.
+ // NUKE_SITE_ON_STATION_ZLEVEL still counts as nuked for the
+ // purposes of /datum/game_mode/nuclear/declare_completion() and its
+ // weird logic of specifying whether the nuke blew up "something
+ // that wasn't" the station.
+ SSticker.mode.station_was_nuked = nuke_site == NUKE_SITE_ON_STATION || nuke_site == NUKE_SITE_ON_STATION_ZLEVEL
if(!SSticker.mode.check_finished())//If the mode does not deal with the nuke going off so just reboot because everyone is stuck as is
SSticker.reboot_helper("Station destroyed by Nuclear Device.", "nuke - unhandled ending")