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