mirror of
https://github.com/yogstation13/Yogstation.git
synced 2025-02-26 09:04:50 +00:00
[Port] Explosions Subsystem Test 1 (#10202)
* Explosions Subsystem Test 1 * Fucking linter * Fucking TG Are Dents * SCREW OFF LINTER
This commit is contained in:
@@ -1,11 +1,16 @@
|
|||||||
|
/// Percentage of tick to leave for master controller to run
|
||||||
|
#define MAPTICK_MC_MIN_RESERVE 70
|
||||||
|
/// internal_tick_usage is updated every tick by extools
|
||||||
|
#define MAPTICK_LAST_INTERNAL_TICK_USAGE ((GLOB.internal_tick_usage / world.tick_lag) * 100)
|
||||||
/// Tick limit while running normally
|
/// Tick limit while running normally
|
||||||
#define TICK_LIMIT_RUNNING 80
|
#define TICK_BYOND_RESERVE 2
|
||||||
|
#define TICK_LIMIT_RUNNING (max(100 - TICK_BYOND_RESERVE - MAPTICK_LAST_INTERNAL_TICK_USAGE, MAPTICK_MC_MIN_RESERVE))
|
||||||
/// Tick limit used to resume things in stoplag
|
/// Tick limit used to resume things in stoplag
|
||||||
#define TICK_LIMIT_TO_RUN 70
|
#define TICK_LIMIT_TO_RUN 70
|
||||||
/// Tick limit for MC while running
|
/// Tick limit for MC while running
|
||||||
#define TICK_LIMIT_MC 70
|
#define TICK_LIMIT_MC 70
|
||||||
/// Tick limit while initializing
|
/// Tick limit while initializing
|
||||||
#define TICK_LIMIT_MC_INIT_DEFAULT 98
|
#define TICK_LIMIT_MC_INIT_DEFAULT (100 - TICK_BYOND_RESERVE)
|
||||||
|
|
||||||
/// for general usage of tick_usage
|
/// for general usage of tick_usage
|
||||||
#define TICK_USAGE world.tick_usage
|
#define TICK_USAGE world.tick_usage
|
||||||
|
|||||||
@@ -38,7 +38,8 @@
|
|||||||
#define COMSIG_GLOB_MOB_DEATH "!mob_death"
|
#define COMSIG_GLOB_MOB_DEATH "!mob_death"
|
||||||
/// global living say plug - use sparingly: (mob/speaker , message)
|
/// global living say plug - use sparingly: (mob/speaker , message)
|
||||||
#define COMSIG_GLOB_LIVING_SAY_SPECIAL "!say_special"
|
#define COMSIG_GLOB_LIVING_SAY_SPECIAL "!say_special"
|
||||||
|
/// called after an explosion happened : (epicenter, devastation_range, heavy_impact_range, light_impact_range, took, orig_dev_range, orig_heavy_range, orig_light_range)
|
||||||
|
#define COMSIG_GLOB_EXPLOSION "!explosion"
|
||||||
// signals from globally accessible objects
|
// signals from globally accessible objects
|
||||||
/// from SSsun when the sun changes position : (azimuth)
|
/// from SSsun when the sun changes position : (azimuth)
|
||||||
#define COMSIG_SUN_MOVED "sun_moved"
|
#define COMSIG_SUN_MOVED "sun_moved"
|
||||||
|
|||||||
@@ -43,6 +43,8 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204
|
|||||||
#define INITIALIZED_1 (1<<14)
|
#define INITIALIZED_1 (1<<14)
|
||||||
/// was this spawned by an admin? used for stat tracking stuff.
|
/// was this spawned by an admin? used for stat tracking stuff.
|
||||||
#define ADMIN_SPAWNED_1 (1<<15)
|
#define ADMIN_SPAWNED_1 (1<<15)
|
||||||
|
/// should not get harmed if this gets caught by an explosion?
|
||||||
|
#define PREVENT_CONTENTS_EXPLOSION_1 (1<<16)
|
||||||
|
|
||||||
//turf-only flags
|
//turf-only flags
|
||||||
#define NOJAUNT_1 (1<<0)
|
#define NOJAUNT_1 (1<<0)
|
||||||
|
|||||||
@@ -135,6 +135,7 @@
|
|||||||
#define INIT_ORDER_MINOR_MAPPING -40
|
#define INIT_ORDER_MINOR_MAPPING -40
|
||||||
#define INIT_ORDER_PATH -50
|
#define INIT_ORDER_PATH -50
|
||||||
#define INIT_ORDER_DISCORD -60
|
#define INIT_ORDER_DISCORD -60
|
||||||
|
#define INIT_ORDER_EXPLOSIONS -69
|
||||||
#define INIT_ORDER_PERSISTENCE -95
|
#define INIT_ORDER_PERSISTENCE -95
|
||||||
#define INIT_ORDER_DEMO -99 // To avoid a bunch of changes related to initialization being written, do this last
|
#define INIT_ORDER_DEMO -99 // To avoid a bunch of changes related to initialization being written, do this last
|
||||||
#define INIT_ORDER_CHAT -100 //Should be last to ensure chat remains smooth during init.
|
#define INIT_ORDER_CHAT -100 //Should be last to ensure chat remains smooth during init.
|
||||||
@@ -169,6 +170,7 @@
|
|||||||
#define FIRE_PRIORITY_ATMOS_ADJACENCY 300
|
#define FIRE_PRIORITY_ATMOS_ADJACENCY 300
|
||||||
#define FIRE_PRIORITY_CHAT 400
|
#define FIRE_PRIORITY_CHAT 400
|
||||||
#define FIRE_PRIORITY_OVERLAYS 500
|
#define FIRE_PRIORITY_OVERLAYS 500
|
||||||
|
#define FIRE_PRIORITY_EXPLOSIONS 666
|
||||||
#define FIRE_PRIORITY_INPUT 1000 // This must always always be the max highest priority. Player input must never be lost.
|
#define FIRE_PRIORITY_INPUT 1000 // This must always always be the max highest priority. Player input must never be lost.
|
||||||
|
|
||||||
// SS runlevels
|
// SS runlevels
|
||||||
@@ -212,3 +214,21 @@
|
|||||||
if(isturf(A)){SSdemo.mark_turf(A);}\
|
if(isturf(A)){SSdemo.mark_turf(A);}\
|
||||||
if(isobj(A) || ismob(A)){SSdemo.mark_dirty(A);}\
|
if(isobj(A) || ismob(A)){SSdemo.mark_dirty(A);}\
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Air subsystem subtasks
|
||||||
|
#define SSAIR_PIPENETS 1
|
||||||
|
#define SSAIR_ATMOSMACHINERY 2
|
||||||
|
#define SSAIR_EQUALIZE 3
|
||||||
|
#define SSAIR_ACTIVETURFS 4
|
||||||
|
#define SSAIR_EXCITEDGROUPS 5
|
||||||
|
#define SSAIR_HIGHPRESSURE 6
|
||||||
|
#define SSAIR_HOTSPOTS 7
|
||||||
|
#define SSAIR_SUPERCONDUCTIVITY 8
|
||||||
|
#define SSAIR_REBUILD_PIPENETS 9
|
||||||
|
|
||||||
|
|
||||||
|
// Explosion Subsystem subtasks
|
||||||
|
#define SSEXPLOSIONS_MOVABLES 1
|
||||||
|
#define SSEXPLOSIONS_TURFS 2
|
||||||
|
#define SSEXPLOSIONS_THROWS 3
|
||||||
@@ -18,3 +18,5 @@ GLOBAL_LIST_EMPTY(powernets)
|
|||||||
GLOBAL_VAR_INIT(bsa_unlock, FALSE) //BSA unlocked by head ID swipes
|
GLOBAL_VAR_INIT(bsa_unlock, FALSE) //BSA unlocked by head ID swipes
|
||||||
|
|
||||||
GLOBAL_LIST_EMPTY(player_details) // ckey -> /datum/player_details
|
GLOBAL_LIST_EMPTY(player_details) // ckey -> /datum/player_details
|
||||||
|
|
||||||
|
GLOBAL_VAR_INIT(internal_tick_usage, 0.2 * world.tick_lag)
|
||||||
|
|||||||
@@ -36,6 +36,9 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
|
|||||||
|
|
||||||
var/sleep_delta = 1
|
var/sleep_delta = 1
|
||||||
|
|
||||||
|
///Only run ticker subsystems for the next n ticks.
|
||||||
|
var/skip_ticks = 0
|
||||||
|
|
||||||
var/make_runtime = 0
|
var/make_runtime = 0
|
||||||
|
|
||||||
var/initializations_finished_with_no_players_logged_in //I wonder what this could be?
|
var/initializations_finished_with_no_players_logged_in //I wonder what this could be?
|
||||||
@@ -342,7 +345,7 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
|
|||||||
new/datum/controller/failsafe() // (re)Start the failsafe.
|
new/datum/controller/failsafe() // (re)Start the failsafe.
|
||||||
|
|
||||||
//now do the actual stuff
|
//now do the actual stuff
|
||||||
if (!queue_head || !(iteration % 3))
|
if (!skip_ticks)
|
||||||
var/checking_runlevel = current_runlevel
|
var/checking_runlevel = current_runlevel
|
||||||
if(cached_runlevel != checking_runlevel)
|
if(cached_runlevel != checking_runlevel)
|
||||||
//resechedule subsystems
|
//resechedule subsystems
|
||||||
@@ -388,6 +391,8 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
|
|||||||
|
|
||||||
iteration++
|
iteration++
|
||||||
last_run = world.time
|
last_run = world.time
|
||||||
|
if (skip_ticks)
|
||||||
|
skip_ticks--
|
||||||
src.sleep_delta = MC_AVERAGE_FAST(src.sleep_delta, sleep_delta)
|
src.sleep_delta = MC_AVERAGE_FAST(src.sleep_delta, sleep_delta)
|
||||||
current_ticklimit = TICK_LIMIT_RUNNING
|
current_ticklimit = TICK_LIMIT_RUNNING
|
||||||
if (processing * sleep_delta <= world.tick_lag)
|
if (processing * sleep_delta <= world.tick_lag)
|
||||||
@@ -455,6 +460,10 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
|
|||||||
queue_node_flags = queue_node.flags
|
queue_node_flags = queue_node.flags
|
||||||
queue_node_priority = queue_node.queued_priority
|
queue_node_priority = queue_node.queued_priority
|
||||||
|
|
||||||
|
if (!(queue_node_flags & SS_TICKER) && skip_ticks)
|
||||||
|
queue_node = queue_node.queue_next
|
||||||
|
continue
|
||||||
|
|
||||||
//super special case, subsystems where we can't make them pause mid way through
|
//super special case, subsystems where we can't make them pause mid way through
|
||||||
//if we can't run them this tick (without going over a tick)
|
//if we can't run them this tick (without going over a tick)
|
||||||
//we bump up their priority and attempt to run them next tick
|
//we bump up their priority and attempt to run them next tick
|
||||||
@@ -590,14 +599,16 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
|
|||||||
log_world("MC: SoftReset: Finished.")
|
log_world("MC: SoftReset: Finished.")
|
||||||
. = 1
|
. = 1
|
||||||
|
|
||||||
|
/datum/controller/master/proc/laggy_byond_map_update_incoming()
|
||||||
|
if (!skip_ticks)
|
||||||
|
skip_ticks = 1
|
||||||
|
|
||||||
/datum/controller/master/stat_entry()
|
/datum/controller/master/stat_entry()
|
||||||
if(!statclick)
|
if(!statclick)
|
||||||
statclick = new/obj/effect/statclick/debug(null, "Initializing...", src)
|
statclick = new/obj/effect/statclick/debug(null, "Initializing...", src)
|
||||||
|
|
||||||
stat("Byond:", "(FPS:[world.fps]) (TickCount:[world.time/world.tick_lag]) (TickDrift:[round(Master.tickdrift,1)]([round((Master.tickdrift/(world.time/world.tick_lag))*100,0.1)]%))")
|
stat("Byond:", "(FPS:[world.fps]) (TickCount:[world.time/world.tick_lag]) (TickDrift:[round(Master.tickdrift,1)]([round((Master.tickdrift/(world.time/world.tick_lag))*100,0.1)]%)) (Internal Tick Usage: [round(MAPTICK_LAST_INTERNAL_TICK_USAGE,0.1)]%)")
|
||||||
stat("Master Controller:", statclick.update("(TickRate:[Master.processing]) (Iteration:[Master.iteration])"))
|
stat("Master Controller:", statclick.update("(TickRate:[Master.processing]) (Iteration:[Master.iteration]) (TickLimit: [round(Master.current_ticklimit, 0.1)])"))
|
||||||
|
|
||||||
/datum/controller/master/StartLoadingMap()
|
/datum/controller/master/StartLoadingMap()
|
||||||
//disallow more than one map to load at once, multithreading it will just cause race conditions
|
//disallow more than one map to load at once, multithreading it will just cause race conditions
|
||||||
|
|||||||
@@ -1,12 +1,3 @@
|
|||||||
#define SSAIR_PIPENETS 1
|
|
||||||
#define SSAIR_ATMOSMACHINERY 2
|
|
||||||
#define SSAIR_EQUALIZE 3
|
|
||||||
#define SSAIR_ACTIVETURFS 4
|
|
||||||
#define SSAIR_EXCITEDGROUPS 5
|
|
||||||
#define SSAIR_HIGHPRESSURE 6
|
|
||||||
#define SSAIR_HOTSPOTS 7
|
|
||||||
#define SSAIR_SUPERCONDUCTIVITY 8
|
|
||||||
|
|
||||||
SUBSYSTEM_DEF(air)
|
SUBSYSTEM_DEF(air)
|
||||||
name = "Atmospherics"
|
name = "Atmospherics"
|
||||||
init_order = INIT_ORDER_AIR
|
init_order = INIT_ORDER_AIR
|
||||||
@@ -21,12 +12,14 @@ SUBSYSTEM_DEF(air)
|
|||||||
var/cost_hotspots = 0
|
var/cost_hotspots = 0
|
||||||
var/cost_superconductivity = 0
|
var/cost_superconductivity = 0
|
||||||
var/cost_pipenets = 0
|
var/cost_pipenets = 0
|
||||||
|
var/cost_rebuilds = 0
|
||||||
var/cost_atmos_machinery = 0
|
var/cost_atmos_machinery = 0
|
||||||
var/cost_equalize = 0
|
var/cost_equalize = 0
|
||||||
|
|
||||||
var/list/active_turfs = list()
|
var/list/active_turfs = list()
|
||||||
var/list/hotspots = list()
|
var/list/hotspots = list()
|
||||||
var/list/networks = list()
|
var/list/networks = list()
|
||||||
|
var/list/pipenets_needing_rebuilt = list()
|
||||||
var/list/obj/machinery/atmos_machinery = list()
|
var/list/obj/machinery/atmos_machinery = list()
|
||||||
var/list/pipe_init_dirs_cache = list()
|
var/list/pipe_init_dirs_cache = list()
|
||||||
|
|
||||||
@@ -39,7 +32,7 @@ SUBSYSTEM_DEF(air)
|
|||||||
|
|
||||||
|
|
||||||
var/list/currentrun = list()
|
var/list/currentrun = list()
|
||||||
var/currentpart = SSAIR_PIPENETS
|
var/currentpart = SSAIR_REBUILD_PIPENETS
|
||||||
|
|
||||||
var/map_loading = TRUE
|
var/map_loading = TRUE
|
||||||
var/list/queued_for_activation
|
var/list/queued_for_activation
|
||||||
@@ -55,6 +48,7 @@ SUBSYSTEM_DEF(air)
|
|||||||
msg += "HS:[round(cost_hotspots,1)]|"
|
msg += "HS:[round(cost_hotspots,1)]|"
|
||||||
msg += "SC:[round(cost_superconductivity,1)]|"
|
msg += "SC:[round(cost_superconductivity,1)]|"
|
||||||
msg += "PN:[round(cost_pipenets,1)]|"
|
msg += "PN:[round(cost_pipenets,1)]|"
|
||||||
|
msg += "RB:[round(cost_rebuilds,1)]|"
|
||||||
msg += "AM:[round(cost_atmos_machinery,1)]"
|
msg += "AM:[round(cost_atmos_machinery,1)]"
|
||||||
msg += "} "
|
msg += "} "
|
||||||
msg += "AT:[active_turfs.len]|"
|
msg += "AT:[active_turfs.len]|"
|
||||||
@@ -79,7 +73,17 @@ SUBSYSTEM_DEF(air)
|
|||||||
|
|
||||||
/datum/controller/subsystem/air/fire(resumed = 0)
|
/datum/controller/subsystem/air/fire(resumed = 0)
|
||||||
var/timer = TICK_USAGE_REAL
|
var/timer = TICK_USAGE_REAL
|
||||||
|
if(currentpart == SSAIR_REBUILD_PIPENETS)
|
||||||
|
var/list/pipenet_rebuilds = pipenets_needing_rebuilt
|
||||||
|
for(var/thing in pipenet_rebuilds)
|
||||||
|
var/obj/machinery/atmospherics/AT = thing
|
||||||
|
AT.build_network()
|
||||||
|
cost_rebuilds = MC_AVERAGE(cost_rebuilds, TICK_DELTA_TO_MS(TICK_USAGE_REAL - timer))
|
||||||
|
pipenets_needing_rebuilt.Cut()
|
||||||
|
if(state != SS_RUNNING)
|
||||||
|
return
|
||||||
|
resumed = FALSE
|
||||||
|
currentpart = SSAIR_PIPENETS
|
||||||
if(currentpart == SSAIR_PIPENETS || !resumed)
|
if(currentpart == SSAIR_PIPENETS || !resumed)
|
||||||
process_pipenets(resumed)
|
process_pipenets(resumed)
|
||||||
cost_pipenets = MC_AVERAGE(cost_pipenets, TICK_DELTA_TO_MS(TICK_USAGE_REAL - timer))
|
cost_pipenets = MC_AVERAGE(cost_pipenets, TICK_DELTA_TO_MS(TICK_USAGE_REAL - timer))
|
||||||
@@ -149,7 +153,7 @@ SUBSYSTEM_DEF(air)
|
|||||||
if(state != SS_RUNNING)
|
if(state != SS_RUNNING)
|
||||||
return
|
return
|
||||||
resumed = 0
|
resumed = 0
|
||||||
currentpart = SSAIR_PIPENETS
|
currentpart = SSAIR_REBUILD_PIPENETS
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -168,6 +172,9 @@ SUBSYSTEM_DEF(air)
|
|||||||
if(MC_TICK_CHECK)
|
if(MC_TICK_CHECK)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
/datum/controller/subsystem/air/proc/add_to_rebuild_queue(atmos_machine)
|
||||||
|
if(istype(atmos_machine, /obj/machinery/atmospherics))
|
||||||
|
pipenets_needing_rebuilt += atmos_machine
|
||||||
|
|
||||||
/datum/controller/subsystem/air/proc/process_atmos_machinery(resumed = 0)
|
/datum/controller/subsystem/air/proc/process_atmos_machinery(resumed = 0)
|
||||||
var/seconds = wait * 0.1
|
var/seconds = wait * 0.1
|
||||||
@@ -430,12 +437,4 @@ SUBSYSTEM_DEF(air)
|
|||||||
pipe_init_dirs_cache[type]["[dir]"] = temp.GetInitDirections()
|
pipe_init_dirs_cache[type]["[dir]"] = temp.GetInitDirections()
|
||||||
qdel(temp)
|
qdel(temp)
|
||||||
|
|
||||||
return pipe_init_dirs_cache[type]["[dir]"]
|
return pipe_init_dirs_cache[type]["[dir]"]
|
||||||
|
|
||||||
#undef SSAIR_PIPENETS
|
|
||||||
#undef SSAIR_ATMOSMACHINERY
|
|
||||||
#undef SSAIR_ACTIVETURFS
|
|
||||||
#undef SSAIR_EXCITEDGROUPS
|
|
||||||
#undef SSAIR_HIGHPRESSURE
|
|
||||||
#undef SSAIR_HOTSPOTS
|
|
||||||
#undef SSAIR_SUPERCONDUCTIVITY
|
|
||||||
564
code/controllers/subsystem/explosions.dm
Normal file
564
code/controllers/subsystem/explosions.dm
Normal file
@@ -0,0 +1,564 @@
|
|||||||
|
#define EXPLOSION_THROW_SPEED 4
|
||||||
|
GLOBAL_LIST_EMPTY(explosions)
|
||||||
|
|
||||||
|
SUBSYSTEM_DEF(explosions)
|
||||||
|
name = "Explosions"
|
||||||
|
init_order = INIT_ORDER_EXPLOSIONS
|
||||||
|
priority = FIRE_PRIORITY_EXPLOSIONS
|
||||||
|
wait = 1
|
||||||
|
flags = SS_TICKER|SS_NO_INIT
|
||||||
|
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
|
||||||
|
|
||||||
|
var/cost_lowturf = 0
|
||||||
|
var/cost_medturf = 0
|
||||||
|
var/cost_highturf = 0
|
||||||
|
var/cost_flameturf = 0
|
||||||
|
|
||||||
|
var/cost_throwturf = 0
|
||||||
|
|
||||||
|
var/cost_low_mov_atom = 0
|
||||||
|
var/cost_med_mov_atom = 0
|
||||||
|
var/cost_high_mov_atom = 0
|
||||||
|
|
||||||
|
var/list/lowturf = list()
|
||||||
|
var/list/medturf = list()
|
||||||
|
var/list/highturf = list()
|
||||||
|
var/list/flameturf = list()
|
||||||
|
|
||||||
|
var/list/throwturf = list()
|
||||||
|
|
||||||
|
var/list/low_mov_atom = list()
|
||||||
|
var/list/med_mov_atom = list()
|
||||||
|
var/list/high_mov_atom = list()
|
||||||
|
|
||||||
|
var/list/explosions = list()
|
||||||
|
|
||||||
|
var/currentpart = SSAIR_PIPENETS
|
||||||
|
|
||||||
|
|
||||||
|
/datum/controller/subsystem/explosions/stat_entry(msg)
|
||||||
|
msg += "C:{"
|
||||||
|
msg += "LT:[round(cost_lowturf,1)]|"
|
||||||
|
msg += "MT:[round(cost_medturf,1)]|"
|
||||||
|
msg += "HT:[round(cost_highturf,1)]|"
|
||||||
|
msg += "FT:[round(cost_flameturf,1)]||"
|
||||||
|
|
||||||
|
msg += "LO:[round(cost_low_mov_atom,1)]|"
|
||||||
|
msg += "MO:[round(cost_med_mov_atom,1)]|"
|
||||||
|
msg += "HO:[round(cost_high_mov_atom,1)]|"
|
||||||
|
|
||||||
|
msg += "TO:[round(cost_throwturf,1)]"
|
||||||
|
|
||||||
|
msg += "} "
|
||||||
|
|
||||||
|
msg += "AMT:{"
|
||||||
|
msg += "LT:[lowturf.len]|"
|
||||||
|
msg += "MT:[medturf.len]|"
|
||||||
|
msg += "HT:[highturf.len]|"
|
||||||
|
msg += "FT:[flameturf.len]||"
|
||||||
|
|
||||||
|
msg += "LO:[low_mov_atom.len]|"
|
||||||
|
msg += "MO:[med_mov_atom.len]|"
|
||||||
|
msg += "HO:[high_mov_atom.len]|"
|
||||||
|
|
||||||
|
msg += "TO:[throwturf.len]"
|
||||||
|
|
||||||
|
msg += "} "
|
||||||
|
return ..()
|
||||||
|
|
||||||
|
|
||||||
|
#define SSEX_TURF "turf"
|
||||||
|
#define SSEX_OBJ "obj"
|
||||||
|
|
||||||
|
/datum/controller/subsystem/explosions/proc/is_exploding()
|
||||||
|
return (lowturf.len || medturf.len || highturf.len || flameturf.len || throwturf.len || low_mov_atom.len || med_mov_atom.len || high_mov_atom.len)
|
||||||
|
|
||||||
|
/datum/controller/subsystem/explosions/proc/wipe_turf(turf/T)
|
||||||
|
lowturf -= T
|
||||||
|
medturf -= T
|
||||||
|
highturf -= T
|
||||||
|
flameturf -= T
|
||||||
|
throwturf -= T
|
||||||
|
|
||||||
|
/client/proc/check_bomb_impacts()
|
||||||
|
set name = "Check Bomb Impact"
|
||||||
|
set category = "Debug"
|
||||||
|
|
||||||
|
var/newmode = alert("Use reactionary explosions?","Check Bomb Impact", "Yes", "No")
|
||||||
|
var/turf/epicenter = get_turf(mob)
|
||||||
|
if(!epicenter)
|
||||||
|
return
|
||||||
|
|
||||||
|
var/dev = 0
|
||||||
|
var/heavy = 0
|
||||||
|
var/light = 0
|
||||||
|
var/list/choices = list("Small Bomb","Medium Bomb","Big Bomb","Custom Bomb")
|
||||||
|
var/choice = input("Bomb Size?") in choices
|
||||||
|
switch(choice)
|
||||||
|
if(null)
|
||||||
|
return 0
|
||||||
|
if("Small Bomb")
|
||||||
|
dev = 1
|
||||||
|
heavy = 2
|
||||||
|
light = 3
|
||||||
|
if("Medium Bomb")
|
||||||
|
dev = 2
|
||||||
|
heavy = 3
|
||||||
|
light = 4
|
||||||
|
if("Big Bomb")
|
||||||
|
dev = 3
|
||||||
|
heavy = 5
|
||||||
|
light = 7
|
||||||
|
if("Custom Bomb")
|
||||||
|
dev = input("Devastation range (Tiles):") as num
|
||||||
|
heavy = input("Heavy impact range (Tiles):") as num
|
||||||
|
light = input("Light impact range (Tiles):") as num
|
||||||
|
|
||||||
|
var/max_range = max(dev, heavy, light)
|
||||||
|
var/x0 = epicenter.x
|
||||||
|
var/y0 = epicenter.y
|
||||||
|
var/list/wipe_colours = list()
|
||||||
|
for(var/turf/T in spiral_range_turfs(max_range, epicenter))
|
||||||
|
wipe_colours += T
|
||||||
|
var/dist = cheap_hypotenuse(T.x, T.y, x0, y0)
|
||||||
|
|
||||||
|
if(newmode == "Yes")
|
||||||
|
var/turf/TT = T
|
||||||
|
while(TT != epicenter)
|
||||||
|
TT = get_step_towards(TT,epicenter)
|
||||||
|
if(TT.density)
|
||||||
|
dist += TT.explosion_block
|
||||||
|
|
||||||
|
for(var/obj/O in T)
|
||||||
|
var/the_block = O.explosion_block
|
||||||
|
dist += the_block == EXPLOSION_BLOCK_PROC ? O.GetExplosionBlock() : the_block
|
||||||
|
|
||||||
|
if(dist < dev)
|
||||||
|
T.color = "red"
|
||||||
|
T.maptext = "Dev"
|
||||||
|
else if (dist < heavy)
|
||||||
|
T.color = "yellow"
|
||||||
|
T.maptext = "Heavy"
|
||||||
|
else if (dist < light)
|
||||||
|
T.color = "blue"
|
||||||
|
T.maptext = "Light"
|
||||||
|
else
|
||||||
|
continue
|
||||||
|
|
||||||
|
addtimer(CALLBACK(GLOBAL_PROC, .proc/wipe_color_and_text, wipe_colours), 100)
|
||||||
|
|
||||||
|
/proc/wipe_color_and_text(list/atom/wiping)
|
||||||
|
for(var/i in wiping)
|
||||||
|
var/atom/A = i
|
||||||
|
A.color = null
|
||||||
|
A.maptext = ""
|
||||||
|
|
||||||
|
/proc/dyn_explosion(turf/epicenter, power, flash_range, adminlog = TRUE, ignorecap = TRUE, flame_range = 0, silent = FALSE, smoke = TRUE)
|
||||||
|
if(!power)
|
||||||
|
return
|
||||||
|
var/range = 0
|
||||||
|
range = round((2 * power)**GLOB.DYN_EX_SCALE)
|
||||||
|
explosion(epicenter, round(range * 0.25), round(range * 0.5), round(range), flash_range*range, adminlog, ignorecap, flame_range*range, silent, smoke)
|
||||||
|
|
||||||
|
// Using default dyn_ex scale:
|
||||||
|
// 100 explosion power is a (5, 10, 20) explosion.
|
||||||
|
// 75 explosion power is a (4, 8, 17) explosion.
|
||||||
|
// 50 explosion power is a (3, 7, 14) explosion.
|
||||||
|
// 25 explosion power is a (2, 5, 10) explosion.
|
||||||
|
// 10 explosion power is a (1, 3, 6) explosion.
|
||||||
|
// 5 explosion power is a (0, 1, 3) explosion.
|
||||||
|
// 1 explosion power is a (0, 0, 1) explosion.
|
||||||
|
|
||||||
|
/proc/explosion(atom/epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range, adminlog = TRUE, ignorecap = FALSE, flame_range = 0, silent = FALSE, smoke = FALSE)
|
||||||
|
. = SSexplosions.explode(arglist(args))
|
||||||
|
|
||||||
|
#define CREAK_DELAY 5 SECONDS //Time taken for the creak to play after explosion, if applicable.
|
||||||
|
#define DEVASTATION_PROB 30 //The probability modifier for devistation, maths!
|
||||||
|
#define HEAVY_IMPACT_PROB 5 //ditto
|
||||||
|
#define FAR_UPPER 60 //Upper limit for the far_volume, distance, clamped.
|
||||||
|
#define FAR_LOWER 40 //lower limit for the far_volume, distance, clamped.
|
||||||
|
#define PROB_SOUND 75 //The probability modifier for a sound to be an echo, or a far sound. (0-100)
|
||||||
|
#define SHAKE_CLAMP 2.5 //The limit for how much the camera can shake for out of view booms.
|
||||||
|
#define FREQ_UPPER 40 //The upper limit for the randomly selected frequency.
|
||||||
|
#define FREQ_LOWER 25 //The lower of the above.
|
||||||
|
|
||||||
|
/datum/controller/subsystem/explosions/proc/explode(atom/epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range, adminlog, ignorecap, flame_range, silent, smoke)
|
||||||
|
epicenter = get_turf(epicenter)
|
||||||
|
if(!epicenter)
|
||||||
|
return
|
||||||
|
|
||||||
|
if(isnull(flame_range))
|
||||||
|
flame_range = light_impact_range
|
||||||
|
if(isnull(flash_range))
|
||||||
|
flash_range = devastation_range
|
||||||
|
|
||||||
|
// Archive the uncapped explosion for the doppler array
|
||||||
|
var/orig_dev_range = devastation_range
|
||||||
|
var/orig_heavy_range = heavy_impact_range
|
||||||
|
var/orig_light_range = light_impact_range
|
||||||
|
|
||||||
|
var/orig_max_distance = max(devastation_range, heavy_impact_range, light_impact_range, flash_range, flame_range)
|
||||||
|
|
||||||
|
//Zlevel specific bomb cap multiplier
|
||||||
|
var/cap_multiplier = SSmapping.level_trait(epicenter.z, ZTRAIT_BOMBCAP_MULTIPLIER)
|
||||||
|
if (isnull(cap_multiplier))
|
||||||
|
cap_multiplier = 1
|
||||||
|
|
||||||
|
if(!ignorecap)
|
||||||
|
devastation_range = min(GLOB.MAX_EX_DEVESTATION_RANGE * cap_multiplier, devastation_range)
|
||||||
|
heavy_impact_range = min(GLOB.MAX_EX_HEAVY_RANGE * cap_multiplier, heavy_impact_range)
|
||||||
|
light_impact_range = min(GLOB.MAX_EX_LIGHT_RANGE * cap_multiplier, light_impact_range)
|
||||||
|
flash_range = min(GLOB.MAX_EX_FLASH_RANGE * cap_multiplier, flash_range)
|
||||||
|
flame_range = min(GLOB.MAX_EX_FLAME_RANGE * cap_multiplier, flame_range)
|
||||||
|
|
||||||
|
var/max_range = max(devastation_range, heavy_impact_range, light_impact_range, flame_range)
|
||||||
|
var/started_at = REALTIMEOFDAY
|
||||||
|
if(adminlog)
|
||||||
|
message_admins("Explosion with size ([devastation_range], [heavy_impact_range], [light_impact_range], [flame_range]) in [ADMIN_VERBOSEJMP(epicenter)]")
|
||||||
|
log_game("Explosion with size ([devastation_range], [heavy_impact_range], [light_impact_range], [flame_range]) in [loc_name(epicenter)]")
|
||||||
|
|
||||||
|
var/x0 = epicenter.x
|
||||||
|
var/y0 = epicenter.y
|
||||||
|
var/z0 = epicenter.z
|
||||||
|
var/area/areatype = get_area(epicenter)
|
||||||
|
SSblackbox.record_feedback("associative", "explosion", 1, list("dev" = devastation_range, "heavy" = heavy_impact_range, "light" = light_impact_range, "flash" = flash_range, "flame" = flame_range, "orig_dev" = orig_dev_range, "orig_heavy" = orig_heavy_range, "orig_light" = orig_light_range, "x" = x0, "y" = y0, "z" = z0, "area" = areatype.type, "time" = time_stamp("YYYY-MM-DD hh:mm:ss", 1)))
|
||||||
|
|
||||||
|
// Play sounds; we want sounds to be different depending on distance so we will manually do it ourselves.
|
||||||
|
// Stereo users will also hear the direction of the explosion!
|
||||||
|
|
||||||
|
// Calculate far explosion sound range. Only allow the sound effect for heavy/devastating explosions.
|
||||||
|
// 3/7/14 will calculate to 80 + 35
|
||||||
|
|
||||||
|
var/far_dist = 0
|
||||||
|
far_dist += heavy_impact_range * 15
|
||||||
|
far_dist += devastation_range * 20
|
||||||
|
|
||||||
|
if(!silent)
|
||||||
|
var/frequency = get_rand_frequency()
|
||||||
|
var/sound/explosion_sound = sound(get_sfx("explosion"))
|
||||||
|
var/sound/far_explosion_sound = sound('sound/effects/explosionfar.ogg')
|
||||||
|
var/sound/creaking_explosion_sound = sound(get_sfx("explosion_creaking"))
|
||||||
|
var/sound/hull_creaking_sound = sound(get_sfx("hull_creaking"))
|
||||||
|
var/sound/explosion_echo_sound = sound('sound/effects/explosion_distant.ogg')
|
||||||
|
var/on_station = SSmapping.level_trait(epicenter.z, ZTRAIT_STATION)
|
||||||
|
var/creaking_explosion = FALSE
|
||||||
|
|
||||||
|
if(prob(devastation_range*DEVASTATION_PROB+heavy_impact_range*HEAVY_IMPACT_PROB) && on_station) // Huge explosions are near guaranteed to make the station creak and whine, smaller ones might.
|
||||||
|
creaking_explosion = TRUE // prob over 100 always returns true
|
||||||
|
|
||||||
|
for(var/MN in GLOB.player_list)
|
||||||
|
var/mob/M = MN
|
||||||
|
// Double check for client
|
||||||
|
var/turf/M_turf = get_turf(M)
|
||||||
|
if(M_turf && M_turf.z == z0)
|
||||||
|
var/dist = get_dist(M_turf, epicenter)
|
||||||
|
var/baseshakeamount
|
||||||
|
if(orig_max_distance - dist > 0)
|
||||||
|
baseshakeamount = sqrt((orig_max_distance - dist)*0.1)
|
||||||
|
// If inside the blast radius + world.view - 2
|
||||||
|
if(dist <= round(max_range + world.view - 2, 1))
|
||||||
|
M.playsound_local(epicenter, null, 100, 1, frequency, S = explosion_sound)
|
||||||
|
if(baseshakeamount > 0)
|
||||||
|
shake_camera(M, 25, clamp(baseshakeamount, 0, 10))
|
||||||
|
// You hear a far explosion if you're outside the blast radius. Small bombs shouldn't be heard all over the station.
|
||||||
|
else if(dist <= far_dist)
|
||||||
|
var/far_volume = clamp(far_dist/2, FAR_LOWER, FAR_UPPER) // Volume is based on explosion size and dist
|
||||||
|
if(creaking_explosion)
|
||||||
|
M.playsound_local(epicenter, null, far_volume, 1, frequency, S = creaking_explosion_sound, distance_multiplier = 0)
|
||||||
|
else if(prob(PROB_SOUND)) // Sound variety during meteor storm/tesloose/other bad event
|
||||||
|
M.playsound_local(epicenter, null, far_volume, 1, frequency, S = far_explosion_sound, distance_multiplier = 0) // Far sound
|
||||||
|
else
|
||||||
|
M.playsound_local(epicenter, null, far_volume, 1, frequency, S = explosion_echo_sound, distance_multiplier = 0) // Echo sound
|
||||||
|
|
||||||
|
if(baseshakeamount > 0 || devastation_range)
|
||||||
|
if(!baseshakeamount) // Devastating explosions rock the station and ground
|
||||||
|
baseshakeamount = devastation_range*3
|
||||||
|
shake_camera(M, 10, clamp(baseshakeamount*0.25, 0, SHAKE_CLAMP))
|
||||||
|
else if(!isspaceturf(get_turf(M)) && heavy_impact_range) // Big enough explosions echo throughout the hull
|
||||||
|
var/echo_volume = 40
|
||||||
|
if(devastation_range)
|
||||||
|
baseshakeamount = devastation_range
|
||||||
|
shake_camera(M, 10, clamp(baseshakeamount*0.25, 0, SHAKE_CLAMP))
|
||||||
|
echo_volume = 60
|
||||||
|
M.playsound_local(epicenter, null, echo_volume, 1, frequency, S = explosion_echo_sound, distance_multiplier = 0)
|
||||||
|
|
||||||
|
if(creaking_explosion) // 5 seconds after the bang, the station begins to creak
|
||||||
|
addtimer(CALLBACK(M, /mob/proc/playsound_local, epicenter, null, rand(FREQ_LOWER, FREQ_UPPER), 1, frequency, null, null, FALSE, hull_creaking_sound, 0), CREAK_DELAY)
|
||||||
|
|
||||||
|
if(heavy_impact_range > 1)
|
||||||
|
var/datum/effect_system/explosion/E
|
||||||
|
if(smoke)
|
||||||
|
E = new /datum/effect_system/explosion/smoke
|
||||||
|
else
|
||||||
|
E = new
|
||||||
|
E.set_up(epicenter)
|
||||||
|
E.start()
|
||||||
|
|
||||||
|
//flash mobs
|
||||||
|
if(flash_range)
|
||||||
|
for(var/mob/living/L in viewers(flash_range, epicenter))
|
||||||
|
L.flash_act()
|
||||||
|
|
||||||
|
var/list/affected_turfs = GatherSpiralTurfs(max_range, epicenter)
|
||||||
|
|
||||||
|
var/reactionary = CONFIG_GET(flag/reactionary_explosions)
|
||||||
|
var/list/cached_exp_block
|
||||||
|
|
||||||
|
if(reactionary)
|
||||||
|
cached_exp_block = CaculateExplosionBlock(affected_turfs)
|
||||||
|
|
||||||
|
//lists are guaranteed to contain at least 1 turf at this point
|
||||||
|
|
||||||
|
for(var/TI in affected_turfs)
|
||||||
|
var/turf/T = TI
|
||||||
|
var/init_dist = cheap_hypotenuse(T.x, T.y, x0, y0)
|
||||||
|
var/dist = init_dist
|
||||||
|
|
||||||
|
if(reactionary)
|
||||||
|
var/turf/Trajectory = T
|
||||||
|
while(Trajectory != epicenter)
|
||||||
|
Trajectory = get_step_towards(Trajectory, epicenter)
|
||||||
|
dist += cached_exp_block[Trajectory]
|
||||||
|
|
||||||
|
var/flame_dist = dist < flame_range
|
||||||
|
var/throw_dist = dist
|
||||||
|
|
||||||
|
if(dist < devastation_range)
|
||||||
|
dist = EXPLODE_DEVASTATE
|
||||||
|
else if(dist < heavy_impact_range)
|
||||||
|
dist = EXPLODE_HEAVY
|
||||||
|
else if(dist < light_impact_range)
|
||||||
|
dist = EXPLODE_LIGHT
|
||||||
|
else
|
||||||
|
dist = EXPLODE_NONE
|
||||||
|
|
||||||
|
if(T == epicenter) // Ensures explosives detonating from bags trigger other explosives in that bag
|
||||||
|
var/list/items = list()
|
||||||
|
for(var/I in T)
|
||||||
|
var/atom/A = I
|
||||||
|
if (length(A.contents) && !(A.flags_1 & PREVENT_CONTENTS_EXPLOSION_1)) //The atom/contents_explosion() proc returns null if the contents ex_acting has been handled by the atom, and TRUE if it hasn't.
|
||||||
|
items += A.GetAllContents()
|
||||||
|
for(var/thing in items)
|
||||||
|
var/atom/movable/movable_thing = thing
|
||||||
|
if(QDELETED(movable_thing))
|
||||||
|
continue
|
||||||
|
switch(dist)
|
||||||
|
if(EXPLODE_DEVASTATE)
|
||||||
|
SSexplosions.high_mov_atom += movable_thing
|
||||||
|
if(EXPLODE_HEAVY)
|
||||||
|
SSexplosions.med_mov_atom += movable_thing
|
||||||
|
if(EXPLODE_LIGHT)
|
||||||
|
SSexplosions.low_mov_atom += movable_thing
|
||||||
|
switch(dist)
|
||||||
|
if(EXPLODE_DEVASTATE)
|
||||||
|
SSexplosions.highturf += T
|
||||||
|
if(EXPLODE_HEAVY)
|
||||||
|
SSexplosions.medturf += T
|
||||||
|
if(EXPLODE_LIGHT)
|
||||||
|
SSexplosions.lowturf += T
|
||||||
|
|
||||||
|
|
||||||
|
if(flame_dist && prob(40) && !isspaceturf(T) && !T.density)
|
||||||
|
flameturf += T
|
||||||
|
|
||||||
|
//--- THROW ITEMS AROUND ---
|
||||||
|
var/throw_dir = get_dir(epicenter,T)
|
||||||
|
var/throw_range = max_range-throw_dist
|
||||||
|
var/list/throwingturf = T.explosion_throw_details
|
||||||
|
if (throwingturf)
|
||||||
|
if (throwingturf[1] < throw_range)
|
||||||
|
throwingturf[1] = throw_range
|
||||||
|
throwingturf[2] = throw_dir
|
||||||
|
throwingturf[3] = max_range
|
||||||
|
else
|
||||||
|
T.explosion_throw_details = list(throw_range, throw_dir, max_range)
|
||||||
|
throwturf += T
|
||||||
|
|
||||||
|
|
||||||
|
var/took = (REALTIMEOFDAY - started_at) / 10
|
||||||
|
|
||||||
|
//You need to press the DebugGame verb to see these now....they were getting annoying and we've collected a fair bit of data. Just -test- changes to explosion code using this please so we can compare
|
||||||
|
if(GLOB.Debug2)
|
||||||
|
log_world("## DEBUG: Explosion([x0],[y0],[z0])(d[devastation_range],h[heavy_impact_range],l[light_impact_range]): Took [took] seconds.")
|
||||||
|
|
||||||
|
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_EXPLOSION, epicenter, devastation_range, heavy_impact_range, light_impact_range, took, orig_dev_range, orig_heavy_range, orig_light_range)
|
||||||
|
|
||||||
|
#undef CREAK_DELAY
|
||||||
|
#undef DEVASTATION_PROB
|
||||||
|
#undef HEAVY_IMPACT_PROB
|
||||||
|
#undef FAR_UPPER
|
||||||
|
#undef FAR_LOWER
|
||||||
|
#undef PROB_SOUND
|
||||||
|
#undef SHAKE_CLAMP
|
||||||
|
#undef FREQ_UPPER
|
||||||
|
#undef FREQ_LOWER
|
||||||
|
|
||||||
|
/datum/controller/subsystem/explosions/proc/GatherSpiralTurfs(range, turf/epicenter)
|
||||||
|
var/list/outlist = list()
|
||||||
|
var/center = epicenter
|
||||||
|
var/dist = range
|
||||||
|
if(!dist)
|
||||||
|
outlist += center
|
||||||
|
return outlist
|
||||||
|
|
||||||
|
var/turf/t_center = get_turf(center)
|
||||||
|
if(!t_center)
|
||||||
|
return outlist
|
||||||
|
|
||||||
|
var/list/L = outlist
|
||||||
|
var/turf/T
|
||||||
|
var/y
|
||||||
|
var/x
|
||||||
|
var/c_dist = 1
|
||||||
|
L += t_center
|
||||||
|
|
||||||
|
while( c_dist <= dist )
|
||||||
|
y = t_center.y + c_dist
|
||||||
|
x = t_center.x - c_dist + 1
|
||||||
|
for(x in x to t_center.x+c_dist)
|
||||||
|
T = locate(x,y,t_center.z)
|
||||||
|
if(T)
|
||||||
|
L += T
|
||||||
|
|
||||||
|
y = t_center.y + c_dist - 1
|
||||||
|
x = t_center.x + c_dist
|
||||||
|
for(y in t_center.y-c_dist to y)
|
||||||
|
T = locate(x,y,t_center.z)
|
||||||
|
if(T)
|
||||||
|
L += T
|
||||||
|
|
||||||
|
y = t_center.y - c_dist
|
||||||
|
x = t_center.x + c_dist - 1
|
||||||
|
for(x in t_center.x-c_dist to x)
|
||||||
|
T = locate(x,y,t_center.z)
|
||||||
|
if(T)
|
||||||
|
L += T
|
||||||
|
|
||||||
|
y = t_center.y - c_dist + 1
|
||||||
|
x = t_center.x - c_dist
|
||||||
|
for(y in y to t_center.y+c_dist)
|
||||||
|
T = locate(x,y,t_center.z)
|
||||||
|
if(T)
|
||||||
|
L += T
|
||||||
|
c_dist++
|
||||||
|
. = L
|
||||||
|
|
||||||
|
/datum/controller/subsystem/explosions/proc/CaculateExplosionBlock(list/affected_turfs)
|
||||||
|
. = list()
|
||||||
|
var/I
|
||||||
|
for(I in 1 to affected_turfs.len) // we cache the explosion block rating of every turf in the explosion area
|
||||||
|
var/turf/T = affected_turfs[I]
|
||||||
|
var/current_exp_block = T.density ? T.explosion_block : 0
|
||||||
|
|
||||||
|
for(var/obj/O in T)
|
||||||
|
var/the_block = O.explosion_block
|
||||||
|
current_exp_block += the_block == EXPLOSION_BLOCK_PROC ? O.GetExplosionBlock() : the_block
|
||||||
|
|
||||||
|
.[T] = current_exp_block
|
||||||
|
|
||||||
|
/datum/controller/subsystem/explosions/fire(resumed = 0)
|
||||||
|
if (!is_exploding())
|
||||||
|
return
|
||||||
|
var/timer
|
||||||
|
Master.current_ticklimit = TICK_LIMIT_RUNNING //force using the entire tick if we need it.
|
||||||
|
|
||||||
|
if(currentpart == SSEXPLOSIONS_TURFS)
|
||||||
|
currentpart = SSEXPLOSIONS_MOVABLES
|
||||||
|
|
||||||
|
timer = TICK_USAGE_REAL
|
||||||
|
var/list/low_turf = lowturf
|
||||||
|
lowturf = list()
|
||||||
|
for(var/thing in low_turf)
|
||||||
|
var/turf/turf_thing = thing
|
||||||
|
turf_thing.explosion_level = max(turf_thing.explosion_level, EXPLODE_LIGHT)
|
||||||
|
turf_thing.ex_act(EXPLODE_LIGHT)
|
||||||
|
cost_lowturf = MC_AVERAGE(cost_lowturf, TICK_DELTA_TO_MS(TICK_USAGE_REAL - timer))
|
||||||
|
|
||||||
|
timer = TICK_USAGE_REAL
|
||||||
|
var/list/med_turf = medturf
|
||||||
|
medturf = list()
|
||||||
|
for(var/thing in med_turf)
|
||||||
|
var/turf/turf_thing = thing
|
||||||
|
turf_thing.explosion_level = max(turf_thing.explosion_level, EXPLODE_HEAVY)
|
||||||
|
turf_thing.ex_act(EXPLODE_HEAVY)
|
||||||
|
cost_medturf = MC_AVERAGE(cost_medturf, TICK_DELTA_TO_MS(TICK_USAGE_REAL - timer))
|
||||||
|
|
||||||
|
timer = TICK_USAGE_REAL
|
||||||
|
var/list/high_turf = highturf
|
||||||
|
highturf = list()
|
||||||
|
for(var/thing in high_turf)
|
||||||
|
var/turf/turf_thing = thing
|
||||||
|
turf_thing.explosion_level = max(turf_thing.explosion_level, EXPLODE_DEVASTATE)
|
||||||
|
turf_thing.ex_act(EXPLODE_DEVASTATE)
|
||||||
|
cost_highturf = MC_AVERAGE(cost_highturf, TICK_DELTA_TO_MS(TICK_USAGE_REAL - timer))
|
||||||
|
|
||||||
|
timer = TICK_USAGE_REAL
|
||||||
|
var/list/flame_turf = flameturf
|
||||||
|
flameturf = list()
|
||||||
|
for(var/thing in flame_turf)
|
||||||
|
if(thing)
|
||||||
|
var/turf/T = thing
|
||||||
|
new /obj/effect/hotspot(T) //Mostly for ambience!
|
||||||
|
cost_flameturf = MC_AVERAGE(cost_flameturf, TICK_DELTA_TO_MS(TICK_USAGE_REAL - timer))
|
||||||
|
|
||||||
|
if (low_turf.len || med_turf.len || high_turf.len)
|
||||||
|
Master.laggy_byond_map_update_incoming()
|
||||||
|
|
||||||
|
if(currentpart == SSEXPLOSIONS_MOVABLES)
|
||||||
|
currentpart = SSEXPLOSIONS_THROWS
|
||||||
|
|
||||||
|
timer = TICK_USAGE_REAL
|
||||||
|
var/list/local_high_mov_atom = high_mov_atom
|
||||||
|
high_mov_atom = list()
|
||||||
|
for(var/thing in local_high_mov_atom)
|
||||||
|
var/atom/movable/movable_thing = thing
|
||||||
|
if(QDELETED(movable_thing))
|
||||||
|
continue
|
||||||
|
movable_thing.ex_act(EXPLODE_DEVASTATE)
|
||||||
|
cost_high_mov_atom = MC_AVERAGE(cost_high_mov_atom, TICK_DELTA_TO_MS(TICK_USAGE_REAL - timer))
|
||||||
|
|
||||||
|
timer = TICK_USAGE_REAL
|
||||||
|
var/list/local_med_mov_atom = med_mov_atom
|
||||||
|
med_mov_atom = list()
|
||||||
|
for(var/thing in local_med_mov_atom)
|
||||||
|
var/atom/movable/movable_thing = thing
|
||||||
|
if(QDELETED(movable_thing))
|
||||||
|
continue
|
||||||
|
movable_thing.ex_act(EXPLODE_HEAVY)
|
||||||
|
cost_med_mov_atom = MC_AVERAGE(cost_med_mov_atom, TICK_DELTA_TO_MS(TICK_USAGE_REAL - timer))
|
||||||
|
|
||||||
|
timer = TICK_USAGE_REAL
|
||||||
|
var/list/local_low_mov_atom = low_mov_atom
|
||||||
|
low_mov_atom = list()
|
||||||
|
for(var/thing in local_low_mov_atom)
|
||||||
|
var/atom/movable/movable_thing = thing
|
||||||
|
if(QDELETED(movable_thing))
|
||||||
|
continue
|
||||||
|
movable_thing.ex_act(EXPLODE_LIGHT)
|
||||||
|
cost_low_mov_atom = MC_AVERAGE(cost_low_mov_atom, TICK_DELTA_TO_MS(TICK_USAGE_REAL - timer))
|
||||||
|
|
||||||
|
|
||||||
|
if (currentpart == SSEXPLOSIONS_THROWS)
|
||||||
|
currentpart = SSEXPLOSIONS_TURFS
|
||||||
|
timer = TICK_USAGE_REAL
|
||||||
|
var/list/throw_turf = throwturf
|
||||||
|
throwturf = list()
|
||||||
|
for (var/thing in throw_turf)
|
||||||
|
if (!thing)
|
||||||
|
continue
|
||||||
|
var/turf/T = thing
|
||||||
|
var/list/L = T.explosion_throw_details
|
||||||
|
T.explosion_throw_details = null
|
||||||
|
if (length(L) != 3)
|
||||||
|
continue
|
||||||
|
var/throw_range = L[1]
|
||||||
|
var/throw_dir = L[2]
|
||||||
|
var/max_range = L[3]
|
||||||
|
for(var/atom/movable/A in T)
|
||||||
|
if(!A.anchored && A.move_resist != INFINITY)
|
||||||
|
var/atom_throw_range = rand(throw_range, max_range)
|
||||||
|
var/turf/throw_at = get_ranged_target_turf(A, throw_dir, atom_throw_range)
|
||||||
|
A.throw_at(throw_at, atom_throw_range, EXPLOSION_THROW_SPEED, quickstart = FALSE)
|
||||||
|
cost_throwturf = MC_AVERAGE(cost_throwturf, TICK_DELTA_TO_MS(TICK_USAGE_REAL - timer))
|
||||||
|
|
||||||
|
currentpart = SSEXPLOSIONS_TURFS
|
||||||
@@ -341,10 +341,12 @@ SUBSYSTEM_DEF(ticker)
|
|||||||
|
|
||||||
/datum/controller/subsystem/ticker/proc/station_explosion_detonation(atom/bomb)
|
/datum/controller/subsystem/ticker/proc/station_explosion_detonation(atom/bomb)
|
||||||
if(bomb) //BOOM
|
if(bomb) //BOOM
|
||||||
var/turf/epi = bomb.loc
|
|
||||||
qdel(bomb)
|
qdel(bomb)
|
||||||
if(epi)
|
for(var/T in GLOB.station_turfs)
|
||||||
explosion(epi, 0, 256, 512, 0, TRUE, TRUE, 0, TRUE)
|
if(prob(33))
|
||||||
|
SSexplosions.highturf += T
|
||||||
|
else
|
||||||
|
SSexplosions.medturf += T
|
||||||
|
|
||||||
/datum/controller/subsystem/ticker/proc/create_characters()
|
/datum/controller/subsystem/ticker/proc/create_characters()
|
||||||
for(var/mob/dead/new_player/player in GLOB.player_list)
|
for(var/mob/dead/new_player/player in GLOB.player_list)
|
||||||
|
|||||||
@@ -1,419 +0,0 @@
|
|||||||
#define EXPLOSION_THROW_SPEED 4
|
|
||||||
|
|
||||||
GLOBAL_LIST_EMPTY(explosions)
|
|
||||||
//Against my better judgement, I will return the explosion datum
|
|
||||||
//If I see any GC errors for it I will find you
|
|
||||||
//and I will gib you
|
|
||||||
/proc/explosion(atom/epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range, adminlog = TRUE, ignorecap = FALSE, flame_range = 0, silent = FALSE, smoke = FALSE)
|
|
||||||
return new /datum/explosion(epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range, adminlog, ignorecap, flame_range, silent, smoke)
|
|
||||||
|
|
||||||
//This datum creates 3 async tasks
|
|
||||||
//1 GatherSpiralTurfsProc runs spiral_range_turfs(tick_checked = TRUE) to populate the affected_turfs list
|
|
||||||
//2 CaculateExplosionBlock adds the blockings to the cached_exp_block list
|
|
||||||
//3 The main thread explodes the prepared turfs
|
|
||||||
|
|
||||||
/datum/explosion
|
|
||||||
var/explosion_id
|
|
||||||
var/atom/explosion_source
|
|
||||||
var/started_at
|
|
||||||
var/running = TRUE
|
|
||||||
var/stopped = 0 //This is the number of threads stopped !DOESN'T COUNT THREAD 2!
|
|
||||||
var/static/id_counter = 0
|
|
||||||
|
|
||||||
#define EX_PREPROCESS_EXIT_CHECK \
|
|
||||||
if(!running) {\
|
|
||||||
stopped = 2;\
|
|
||||||
qdel(src);\
|
|
||||||
return;\
|
|
||||||
}
|
|
||||||
|
|
||||||
#define EX_PREPROCESS_CHECK_TICK \
|
|
||||||
if(TICK_CHECK) {\
|
|
||||||
stoplag();\
|
|
||||||
EX_PREPROCESS_EXIT_CHECK\
|
|
||||||
}
|
|
||||||
|
|
||||||
/datum/explosion/New(atom/epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range, adminlog, ignorecap, flame_range, silent, smoke)
|
|
||||||
set waitfor = FALSE
|
|
||||||
|
|
||||||
var/id = ++id_counter
|
|
||||||
explosion_id = id
|
|
||||||
explosion_source = epicenter
|
|
||||||
|
|
||||||
epicenter = get_turf(epicenter)
|
|
||||||
if(!epicenter)
|
|
||||||
return
|
|
||||||
|
|
||||||
GLOB.explosions += src
|
|
||||||
if(isnull(flame_range))
|
|
||||||
flame_range = light_impact_range
|
|
||||||
if(isnull(flash_range))
|
|
||||||
flash_range = devastation_range
|
|
||||||
|
|
||||||
// Archive the uncapped explosion for the doppler array
|
|
||||||
var/orig_dev_range = devastation_range
|
|
||||||
var/orig_heavy_range = heavy_impact_range
|
|
||||||
var/orig_light_range = light_impact_range
|
|
||||||
|
|
||||||
var/orig_max_distance = max(devastation_range, heavy_impact_range, light_impact_range, flash_range, flame_range)
|
|
||||||
|
|
||||||
//Zlevel specific bomb cap multiplier
|
|
||||||
var/cap_multiplier = SSmapping.level_trait(epicenter.z, ZTRAIT_BOMBCAP_MULTIPLIER)
|
|
||||||
if (isnull(cap_multiplier))
|
|
||||||
cap_multiplier = 1
|
|
||||||
|
|
||||||
if(!ignorecap)
|
|
||||||
devastation_range = min(GLOB.MAX_EX_DEVESTATION_RANGE * cap_multiplier, devastation_range)
|
|
||||||
heavy_impact_range = min(GLOB.MAX_EX_HEAVY_RANGE * cap_multiplier, heavy_impact_range)
|
|
||||||
light_impact_range = min(GLOB.MAX_EX_LIGHT_RANGE * cap_multiplier, light_impact_range)
|
|
||||||
flash_range = min(GLOB.MAX_EX_FLASH_RANGE * cap_multiplier, flash_range)
|
|
||||||
flame_range = min(GLOB.MAX_EX_FLAME_RANGE * cap_multiplier, flame_range)
|
|
||||||
|
|
||||||
//DO NOT REMOVE THIS STOPLAG, IT BREAKS THINGS
|
|
||||||
//not sleeping causes us to ex_act() the thing that triggered the explosion
|
|
||||||
//doing that might cause it to trigger another explosion
|
|
||||||
//this is bad
|
|
||||||
//I would make this not ex_act the thing that triggered the explosion,
|
|
||||||
//but everything that explodes gives us their loc or a get_turf()
|
|
||||||
//and somethings expect us to ex_act them so they can qdel()
|
|
||||||
stoplag() //tldr, let the calling proc call qdel(src) before we explode
|
|
||||||
|
|
||||||
EX_PREPROCESS_EXIT_CHECK
|
|
||||||
|
|
||||||
started_at = REALTIMEOFDAY
|
|
||||||
|
|
||||||
var/max_range = max(devastation_range, heavy_impact_range, light_impact_range, flame_range)
|
|
||||||
|
|
||||||
if(adminlog)
|
|
||||||
if(SSticker.current_state != GAME_STATE_FINISHED) //don't bother alerting admins after the game has ended, but we still log it in the game log
|
|
||||||
message_admins("Explosion with size ([devastation_range], [heavy_impact_range], [light_impact_range], [flame_range]) in [ADMIN_VERBOSEJMP(epicenter)]")
|
|
||||||
log_game("Explosion with size ([devastation_range], [heavy_impact_range], [light_impact_range], [flame_range]) in [loc_name(epicenter)]")
|
|
||||||
|
|
||||||
var/x0 = epicenter.x
|
|
||||||
var/y0 = epicenter.y
|
|
||||||
var/z0 = epicenter.z
|
|
||||||
var/area/areatype = get_area(epicenter)
|
|
||||||
SSblackbox.record_feedback("associative", "explosion", 1, list("dev" = devastation_range, "heavy" = heavy_impact_range, "light" = light_impact_range, "flash" = flash_range, "flame" = flame_range, "orig_dev" = orig_dev_range, "orig_heavy" = orig_heavy_range, "orig_light" = orig_light_range, "x" = x0, "y" = y0, "z" = z0, "area" = areatype.type, "time" = time_stamp("YYYY-MM-DD hh:mm:ss", 1)))
|
|
||||||
|
|
||||||
// Play sounds; we want sounds to be different depending on distance so we will manually do it ourselves.
|
|
||||||
// Stereo users will also hear the direction of the explosion!
|
|
||||||
|
|
||||||
// Calculate far explosion sound range. Only allow the sound effect for heavy/devastating explosions.
|
|
||||||
// 3/7/14 will calculate to 80 + 35
|
|
||||||
|
|
||||||
var/far_dist = 0
|
|
||||||
far_dist += heavy_impact_range * 5
|
|
||||||
far_dist += devastation_range * 20
|
|
||||||
|
|
||||||
if(!silent)
|
|
||||||
var/frequency = get_rand_frequency()
|
|
||||||
var/sound/explosion_sound = sound(get_sfx("explosion"))
|
|
||||||
var/sound/far_explosion_sound = sound('sound/effects/explosionfar.ogg')
|
|
||||||
|
|
||||||
for(var/mob/M in GLOB.player_list)
|
|
||||||
// Double check for client
|
|
||||||
var/turf/M_turf = get_turf(M)
|
|
||||||
if(M_turf && M_turf.z == z0)
|
|
||||||
var/dist = get_dist(M_turf, epicenter)
|
|
||||||
var/baseshakeamount
|
|
||||||
if(orig_max_distance - dist > 0)
|
|
||||||
baseshakeamount = sqrt((orig_max_distance - dist)*0.1)
|
|
||||||
// If inside the blast radius + world.view - 2
|
|
||||||
if(dist <= round(max_range + world.view - 2, 1))
|
|
||||||
M.playsound_local(epicenter, null, 100, 1, frequency, falloff = 5, S = explosion_sound)
|
|
||||||
if(baseshakeamount > 0)
|
|
||||||
shake_camera(M, 25, clamp(baseshakeamount, 0, 10))
|
|
||||||
// You hear a far explosion if you're outside the blast radius. Small bombs shouldn't be heard all over the station.
|
|
||||||
else if(dist <= far_dist)
|
|
||||||
var/far_volume = clamp(far_dist, 30, 50) // Volume is based on explosion size and dist
|
|
||||||
far_volume += (dist <= far_dist * 0.5 ? 50 : 0) // add 50 volume if the mob is pretty close to the explosion
|
|
||||||
M.playsound_local(epicenter, null, far_volume, 1, frequency, falloff = 5, S = far_explosion_sound)
|
|
||||||
if(baseshakeamount > 0)
|
|
||||||
shake_camera(M, 10, clamp(baseshakeamount*0.25, 0, 2.5))
|
|
||||||
EX_PREPROCESS_CHECK_TICK
|
|
||||||
|
|
||||||
//postpone processing for a bit
|
|
||||||
var/postponeCycles = max(round(devastation_range/8),1)
|
|
||||||
SSlighting.postpone(postponeCycles)
|
|
||||||
SSmachines.postpone(postponeCycles)
|
|
||||||
|
|
||||||
if(heavy_impact_range > 1)
|
|
||||||
var/datum/effect_system/explosion/E
|
|
||||||
if(smoke)
|
|
||||||
E = new /datum/effect_system/explosion/smoke
|
|
||||||
else
|
|
||||||
E = new
|
|
||||||
E.set_up(epicenter)
|
|
||||||
E.start()
|
|
||||||
|
|
||||||
EX_PREPROCESS_CHECK_TICK
|
|
||||||
|
|
||||||
//flash mobs
|
|
||||||
if(flash_range)
|
|
||||||
for(var/mob/living/L in viewers(flash_range, epicenter))
|
|
||||||
L.flash_act()
|
|
||||||
|
|
||||||
EX_PREPROCESS_CHECK_TICK
|
|
||||||
|
|
||||||
var/list/exploded_this_tick = list() //open turfs that need to be blocked off while we sleep
|
|
||||||
var/list/affected_turfs = GatherSpiralTurfs(max_range, epicenter)
|
|
||||||
|
|
||||||
var/reactionary = CONFIG_GET(flag/reactionary_explosions)
|
|
||||||
var/list/cached_exp_block = list()
|
|
||||||
|
|
||||||
if(reactionary)
|
|
||||||
cached_exp_block = CaculateExplosionBlock(affected_turfs)
|
|
||||||
|
|
||||||
//lists are guaranteed to contain at least 1 turf at this point
|
|
||||||
|
|
||||||
var/iteration = 0
|
|
||||||
var/affTurfLen = affected_turfs.len
|
|
||||||
var/expBlockLen = cached_exp_block.len
|
|
||||||
for(var/TI in affected_turfs)
|
|
||||||
var/turf/T = TI
|
|
||||||
++iteration
|
|
||||||
var/init_dist = cheap_hypotenuse(T.x, T.y, x0, y0)
|
|
||||||
var/dist = init_dist
|
|
||||||
|
|
||||||
if(reactionary)
|
|
||||||
var/turf/Trajectory = T
|
|
||||||
while(Trajectory != epicenter)
|
|
||||||
Trajectory = get_step_towards(Trajectory, epicenter)
|
|
||||||
dist += cached_exp_block[Trajectory]
|
|
||||||
|
|
||||||
var/flame_dist = dist < flame_range
|
|
||||||
var/throw_dist = dist
|
|
||||||
|
|
||||||
if(dist < devastation_range)
|
|
||||||
dist = EXPLODE_DEVASTATE
|
|
||||||
else if(dist < heavy_impact_range)
|
|
||||||
dist = EXPLODE_HEAVY
|
|
||||||
else if(dist < light_impact_range)
|
|
||||||
dist = EXPLODE_LIGHT
|
|
||||||
else
|
|
||||||
dist = EXPLODE_NONE
|
|
||||||
|
|
||||||
//------- EX_ACT AND TURF FIRES -------
|
|
||||||
|
|
||||||
if(T == epicenter) // Ensures explosives detonating from bags trigger other explosives in that bag
|
|
||||||
var/list/items = list()
|
|
||||||
for(var/I in T)
|
|
||||||
var/atom/A = I
|
|
||||||
if (!A.prevent_content_explosion()) //The atom/contents_explosion() proc returns null if the contents ex_acting has been handled by the atom, and TRUE if it hasn't.
|
|
||||||
items += A.GetAllContents()
|
|
||||||
for(var/O in items)
|
|
||||||
var/atom/A = O
|
|
||||||
if(!QDELETED(A))
|
|
||||||
A.ex_act(dist)
|
|
||||||
|
|
||||||
if(flame_dist && prob(40) && !isspaceturf(T) && !T.density)
|
|
||||||
new /obj/effect/hotspot(T) //Mostly for ambience!
|
|
||||||
|
|
||||||
if(dist > EXPLODE_NONE)
|
|
||||||
T.explosion_level = max(T.explosion_level, dist) //let the bigger one have it
|
|
||||||
T.explosion_id = id
|
|
||||||
T.ex_act(dist)
|
|
||||||
exploded_this_tick += T
|
|
||||||
|
|
||||||
//--- THROW ITEMS AROUND ---
|
|
||||||
|
|
||||||
var/throw_dir = get_dir(epicenter,T)
|
|
||||||
for(var/obj/item/I in T)
|
|
||||||
if(!I.anchored)
|
|
||||||
var/throw_range = rand(throw_dist, max_range)
|
|
||||||
var/turf/throw_at = get_ranged_target_turf(I, throw_dir, throw_range)
|
|
||||||
I.throw_at(throw_at, throw_range, EXPLOSION_THROW_SPEED)
|
|
||||||
|
|
||||||
//wait for the lists to repop
|
|
||||||
var/break_condition
|
|
||||||
if(reactionary)
|
|
||||||
//If we've caught up to the density checker thread and there are no more turfs to process
|
|
||||||
break_condition = iteration == expBlockLen && iteration < affTurfLen
|
|
||||||
else
|
|
||||||
//If we've caught up to the turf gathering thread and it's still running
|
|
||||||
break_condition = iteration == affTurfLen && !stopped
|
|
||||||
|
|
||||||
if(break_condition || TICK_CHECK)
|
|
||||||
stoplag()
|
|
||||||
|
|
||||||
if(!running)
|
|
||||||
break
|
|
||||||
|
|
||||||
//update the trackers
|
|
||||||
affTurfLen = affected_turfs.len
|
|
||||||
expBlockLen = cached_exp_block.len
|
|
||||||
|
|
||||||
if(break_condition)
|
|
||||||
if(reactionary)
|
|
||||||
//until there are more block checked turfs than what we are currently at
|
|
||||||
//or the explosion has stopped
|
|
||||||
UNTIL(iteration < affTurfLen || !running)
|
|
||||||
else
|
|
||||||
//until there are more gathered turfs than what we are currently at
|
|
||||||
//or there are no more turfs to gather/the explosion has stopped
|
|
||||||
UNTIL(iteration < expBlockLen || stopped)
|
|
||||||
|
|
||||||
if(!running)
|
|
||||||
break
|
|
||||||
|
|
||||||
//update the trackers
|
|
||||||
affTurfLen = affected_turfs.len
|
|
||||||
expBlockLen = cached_exp_block.len
|
|
||||||
|
|
||||||
var/circumference = (PI * (init_dist + 4) * 2) //+4 to radius to prevent shit gaps
|
|
||||||
if(exploded_this_tick.len > circumference) //only do this every revolution
|
|
||||||
for(var/Unexplode in exploded_this_tick)
|
|
||||||
var/turf/UnexplodeT = Unexplode
|
|
||||||
UnexplodeT.explosion_level = 0
|
|
||||||
exploded_this_tick.Cut()
|
|
||||||
|
|
||||||
//unfuck the shit
|
|
||||||
for(var/Unexplode in exploded_this_tick)
|
|
||||||
var/turf/UnexplodeT = Unexplode
|
|
||||||
UnexplodeT.explosion_level = 0
|
|
||||||
exploded_this_tick.Cut()
|
|
||||||
|
|
||||||
var/took = (REALTIMEOFDAY - started_at) / 10
|
|
||||||
|
|
||||||
//You need to press the DebugGame verb to see these now....they were getting annoying and we've collected a fair bit of data. Just -test- changes to explosion code using this please so we can compare
|
|
||||||
if(GLOB.Debug2)
|
|
||||||
log_world("## DEBUG: Explosion([x0],[y0],[z0])(d[devastation_range],h[heavy_impact_range],l[light_impact_range]): Took [took] seconds.")
|
|
||||||
|
|
||||||
if(running) //if we aren't in a hurry
|
|
||||||
//Machines which report explosions.
|
|
||||||
for(var/array in GLOB.doppler_arrays)
|
|
||||||
var/obj/machinery/doppler_array/A = array
|
|
||||||
A.sense_explosion(epicenter, devastation_range, heavy_impact_range, light_impact_range, took,orig_dev_range, orig_heavy_range, orig_light_range)
|
|
||||||
|
|
||||||
++stopped
|
|
||||||
qdel(src)
|
|
||||||
|
|
||||||
#undef EX_PREPROCESS_EXIT_CHECK
|
|
||||||
#undef EX_PREPROCESS_CHECK_TICK
|
|
||||||
|
|
||||||
//asyncly populate the affected_turfs list
|
|
||||||
/datum/explosion/proc/GatherSpiralTurfs(range, turf/epicenter)
|
|
||||||
set waitfor = FALSE
|
|
||||||
. = list()
|
|
||||||
spiral_range_turfs(range, epicenter, outlist = ., tick_checked = TRUE)
|
|
||||||
++stopped
|
|
||||||
|
|
||||||
/datum/explosion/proc/CaculateExplosionBlock(list/affected_turfs)
|
|
||||||
set waitfor = FALSE
|
|
||||||
|
|
||||||
. = list()
|
|
||||||
var/processed = 0
|
|
||||||
while(running)
|
|
||||||
var/I
|
|
||||||
for(I in (processed + 1) to affected_turfs.len) // we cache the explosion block rating of every turf in the explosion area
|
|
||||||
var/turf/T = affected_turfs[I]
|
|
||||||
var/current_exp_block = T.density ? T.explosion_block : 0
|
|
||||||
|
|
||||||
for(var/obj/O in T)
|
|
||||||
var/the_block = O.explosion_block
|
|
||||||
current_exp_block += the_block == EXPLOSION_BLOCK_PROC ? O.GetExplosionBlock() : the_block
|
|
||||||
|
|
||||||
.[T] = current_exp_block
|
|
||||||
|
|
||||||
if(TICK_CHECK)
|
|
||||||
break
|
|
||||||
|
|
||||||
processed = I
|
|
||||||
stoplag()
|
|
||||||
|
|
||||||
/datum/explosion/Destroy()
|
|
||||||
running = FALSE
|
|
||||||
if(stopped < 2) //wait for main thread and spiral_range thread
|
|
||||||
return QDEL_HINT_IWILLGC
|
|
||||||
GLOB.explosions -= src
|
|
||||||
explosion_source = null
|
|
||||||
return ..()
|
|
||||||
|
|
||||||
/client/proc/check_bomb_impacts()
|
|
||||||
set name = "Check Bomb Impact"
|
|
||||||
set category = "Debug"
|
|
||||||
|
|
||||||
var/newmode = alert("Use reactionary explosions?","Check Bomb Impact", "Yes", "No")
|
|
||||||
var/turf/epicenter = get_turf(mob)
|
|
||||||
if(!epicenter)
|
|
||||||
return
|
|
||||||
|
|
||||||
var/dev = 0
|
|
||||||
var/heavy = 0
|
|
||||||
var/light = 0
|
|
||||||
var/list/choices = list("Small Bomb","Medium Bomb","Big Bomb","Custom Bomb")
|
|
||||||
var/choice = input("Bomb Size?") in choices
|
|
||||||
switch(choice)
|
|
||||||
if(null)
|
|
||||||
return 0
|
|
||||||
if("Small Bomb")
|
|
||||||
dev = 1
|
|
||||||
heavy = 2
|
|
||||||
light = 3
|
|
||||||
if("Medium Bomb")
|
|
||||||
dev = 2
|
|
||||||
heavy = 3
|
|
||||||
light = 4
|
|
||||||
if("Big Bomb")
|
|
||||||
dev = 3
|
|
||||||
heavy = 5
|
|
||||||
light = 7
|
|
||||||
if("Custom Bomb")
|
|
||||||
dev = input("Devastation range (Tiles):") as num
|
|
||||||
heavy = input("Heavy impact range (Tiles):") as num
|
|
||||||
light = input("Light impact range (Tiles):") as num
|
|
||||||
|
|
||||||
var/max_range = max(dev, heavy, light)
|
|
||||||
var/x0 = epicenter.x
|
|
||||||
var/y0 = epicenter.y
|
|
||||||
var/list/wipe_colours = list()
|
|
||||||
for(var/turf/T in spiral_range_turfs(max_range, epicenter))
|
|
||||||
wipe_colours += T
|
|
||||||
var/dist = cheap_hypotenuse(T.x, T.y, x0, y0)
|
|
||||||
|
|
||||||
if(newmode == "Yes")
|
|
||||||
var/turf/TT = T
|
|
||||||
while(TT != epicenter)
|
|
||||||
TT = get_step_towards(TT,epicenter)
|
|
||||||
if(TT.density)
|
|
||||||
dist += TT.explosion_block
|
|
||||||
|
|
||||||
for(var/obj/O in T)
|
|
||||||
var/the_block = O.explosion_block
|
|
||||||
dist += the_block == EXPLOSION_BLOCK_PROC ? O.GetExplosionBlock() : the_block
|
|
||||||
|
|
||||||
if(dist < dev)
|
|
||||||
T.color = "red"
|
|
||||||
T.maptext = "Dev"
|
|
||||||
else if (dist < heavy)
|
|
||||||
T.color = "yellow"
|
|
||||||
T.maptext = "Heavy"
|
|
||||||
else if (dist < light)
|
|
||||||
T.color = "blue"
|
|
||||||
T.maptext = "Light"
|
|
||||||
else
|
|
||||||
continue
|
|
||||||
|
|
||||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/wipe_color_and_text, wipe_colours), 100)
|
|
||||||
|
|
||||||
/proc/wipe_color_and_text(list/atom/wiping)
|
|
||||||
for(var/i in wiping)
|
|
||||||
var/atom/A = i
|
|
||||||
A.color = null
|
|
||||||
A.maptext = ""
|
|
||||||
|
|
||||||
/proc/dyn_explosion(turf/epicenter, power, flash_range, adminlog = TRUE, ignorecap = TRUE, flame_range = 0, silent = FALSE, smoke = TRUE)
|
|
||||||
if(!power)
|
|
||||||
return
|
|
||||||
var/range = 0
|
|
||||||
range = round((2 * power)**GLOB.DYN_EX_SCALE)
|
|
||||||
explosion(epicenter, round(range * 0.25), round(range * 0.5), round(range), flash_range*range, adminlog, ignorecap, flame_range*range, silent, smoke)
|
|
||||||
|
|
||||||
// Using default dyn_ex scale:
|
|
||||||
// 100 explosion power is a (5, 10, 20) explosion.
|
|
||||||
// 75 explosion power is a (4, 8, 17) explosion.
|
|
||||||
// 50 explosion power is a (3, 7, 14) explosion.
|
|
||||||
// 25 explosion power is a (2, 5, 10) explosion.
|
|
||||||
// 10 explosion power is a (1, 3, 6) explosion.
|
|
||||||
// 5 explosion power is a (0, 1, 3) explosion.
|
|
||||||
// 1 explosion power is a (0, 0, 1) explosion.
|
|
||||||
@@ -501,10 +501,6 @@
|
|||||||
to_chat(user, "<span class='warning'>You can't move while buckled to [src]!</span>")
|
to_chat(user, "<span class='warning'>You can't move while buckled to [src]!</span>")
|
||||||
return
|
return
|
||||||
|
|
||||||
/// Return true if this atoms contents should not have ex_act called on ex_act
|
|
||||||
/atom/proc/prevent_content_explosion()
|
|
||||||
return FALSE
|
|
||||||
|
|
||||||
/// Handle what happens when your contents are exploded by a bomb
|
/// Handle what happens when your contents are exploded by a bomb
|
||||||
/atom/proc/contents_explosion(severity, target)
|
/atom/proc/contents_explosion(severity, target)
|
||||||
return //For handling the effects of explosions on contents that would not normally be effected
|
return //For handling the effects of explosions on contents that would not normally be effected
|
||||||
|
|||||||
@@ -597,12 +597,12 @@
|
|||||||
step(src, AM.dir)
|
step(src, AM.dir)
|
||||||
..()
|
..()
|
||||||
|
|
||||||
/atom/movable/proc/safe_throw_at(atom/target, range, speed, mob/thrower, spin = TRUE, diagonals_first = FALSE, datum/callback/callback, force = MOVE_FORCE_STRONG)
|
/atom/movable/proc/safe_throw_at(atom/target, range, speed, mob/thrower, spin = TRUE, diagonals_first = FALSE, datum/callback/callback, force = MOVE_FORCE_STRONG, quickstart = TRUE)
|
||||||
if((force < (move_resist * MOVE_FORCE_THROW_RATIO)) || (move_resist == INFINITY))
|
if((force < (move_resist * MOVE_FORCE_THROW_RATIO)) || (move_resist == INFINITY))
|
||||||
return
|
return
|
||||||
return throw_at(target, range, speed, thrower, spin, diagonals_first, callback, force)
|
return throw_at(target, range, speed, thrower, spin, diagonals_first, callback, force)
|
||||||
|
|
||||||
/atom/movable/proc/throw_at(atom/target, range, speed, mob/thrower, spin = TRUE, diagonals_first = FALSE, datum/callback/callback, force = MOVE_FORCE_STRONG) //If this returns FALSE then callback will not be called.
|
/atom/movable/proc/throw_at(atom/target, range, speed, mob/thrower, spin = TRUE, diagonals_first = FALSE, datum/callback/callback, force = MOVE_FORCE_STRONG, quickstart = TRUE) //If this returns FALSE then callback will not be called.
|
||||||
. = FALSE
|
. = FALSE
|
||||||
if (!target || speed <= 0)
|
if (!target || speed <= 0)
|
||||||
return
|
return
|
||||||
@@ -684,7 +684,8 @@
|
|||||||
SSthrowing.processing[src] = TT
|
SSthrowing.processing[src] = TT
|
||||||
if (SSthrowing.state == SS_PAUSED && length(SSthrowing.currentrun))
|
if (SSthrowing.state == SS_PAUSED && length(SSthrowing.currentrun))
|
||||||
SSthrowing.currentrun[src] = TT
|
SSthrowing.currentrun[src] = TT
|
||||||
TT.tick()
|
if (quickstart)
|
||||||
|
TT.tick()
|
||||||
|
|
||||||
/atom/movable/proc/handle_buckled_mob_movement(newloc, direct, glide_size_override)
|
/atom/movable/proc/handle_buckled_mob_movement(newloc, direct, glide_size_override)
|
||||||
for(var/m in buckled_mobs)
|
for(var/m in buckled_mobs)
|
||||||
|
|||||||
@@ -138,7 +138,7 @@
|
|||||||
var/datum/component/slippery/slipper = GetComponent(/datum/component/slippery)
|
var/datum/component/slippery/slipper = GetComponent(/datum/component/slippery)
|
||||||
slipper.signal_enabled = active
|
slipper.signal_enabled = active
|
||||||
|
|
||||||
/obj/item/shield/energy/bananium/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback, force)
|
/obj/item/shield/energy/bananium/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback, force, quickstart = TRUE)
|
||||||
if(active)
|
if(active)
|
||||||
if(iscarbon(thrower))
|
if(iscarbon(thrower))
|
||||||
var/mob/living/carbon/C = thrower
|
var/mob/living/carbon/C = thrower
|
||||||
|
|||||||
@@ -143,15 +143,29 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event
|
|||||||
|
|
||||||
/obj/effect/meteor/proc/ram_turf(turf/T)
|
/obj/effect/meteor/proc/ram_turf(turf/T)
|
||||||
//first bust whatever is in the turf
|
//first bust whatever is in the turf
|
||||||
for(var/atom/A in T)
|
for(var/thing in T)
|
||||||
if(A != src)
|
if(thing == src)
|
||||||
if(isliving(A))
|
continue
|
||||||
A.visible_message("<span class='warning'>[src] slams into [A].</span>", "<span class='userdanger'>[src] slams into you!.</span>")
|
if(isliving(thing))
|
||||||
A.ex_act(hitpwr)
|
var/mob/living/living_thing = thing
|
||||||
|
living_thing.visible_message("<span class='warning'>[src] slams into [living_thing].</span>", "<span class='userdanger'>[src] slams into you!.</span>")
|
||||||
|
switch(hitpwr)
|
||||||
|
if(EXPLODE_DEVASTATE)
|
||||||
|
SSexplosions.high_mov_atom += thing
|
||||||
|
if(EXPLODE_HEAVY)
|
||||||
|
SSexplosions.med_mov_atom += thing
|
||||||
|
if(EXPLODE_LIGHT)
|
||||||
|
SSexplosions.low_mov_atom += thing
|
||||||
|
|
||||||
//then, ram the turf if it still exists
|
//then, ram the turf if it still exists
|
||||||
if(T)
|
if(T)
|
||||||
T.ex_act(hitpwr)
|
switch(hitpwr)
|
||||||
|
if(EXPLODE_DEVASTATE)
|
||||||
|
SSexplosions.highturf += T
|
||||||
|
if(EXPLODE_HEAVY)
|
||||||
|
SSexplosions.medturf += T
|
||||||
|
if(EXPLODE_LIGHT)
|
||||||
|
SSexplosions.lowturf += T
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1311,7 +1311,7 @@
|
|||||||
|
|
||||||
var/obj/structure/window/killthis = (locate(/obj/structure/window) in get_turf(src))
|
var/obj/structure/window/killthis = (locate(/obj/structure/window) in get_turf(src))
|
||||||
if(killthis)
|
if(killthis)
|
||||||
killthis.ex_act(EXPLODE_HEAVY)//Smashin windows
|
SSexplosions.med_mov_atom += killthis
|
||||||
|
|
||||||
operating = TRUE
|
operating = TRUE
|
||||||
update_icon(AIRLOCK_CLOSING, 1)
|
update_icon(AIRLOCK_CLOSING, 1)
|
||||||
|
|||||||
@@ -14,15 +14,11 @@ GLOBAL_LIST_EMPTY(doppler_arrays)
|
|||||||
|
|
||||||
/obj/machinery/doppler_array/Initialize()
|
/obj/machinery/doppler_array/Initialize()
|
||||||
. = ..()
|
. = ..()
|
||||||
GLOB.doppler_arrays += src
|
RegisterSignal(SSdcs, COMSIG_GLOB_EXPLOSION, .proc/sense_explosion)
|
||||||
|
|
||||||
/obj/machinery/doppler_array/ComponentInitialize()
|
/obj/machinery/doppler_array/ComponentInitialize()
|
||||||
AddComponent(/datum/component/simple_rotation,ROTATION_ALTCLICK | ROTATION_CLOCKWISE,null,null,CALLBACK(src,.proc/rot_message))
|
AddComponent(/datum/component/simple_rotation,ROTATION_ALTCLICK | ROTATION_CLOCKWISE,null,null,CALLBACK(src,.proc/rot_message))
|
||||||
|
|
||||||
/obj/machinery/doppler_array/Destroy()
|
|
||||||
GLOB.doppler_arrays -= src
|
|
||||||
return ..()
|
|
||||||
|
|
||||||
/obj/machinery/doppler_array/examine(mob/user)
|
/obj/machinery/doppler_array/examine(mob/user)
|
||||||
..()
|
..()
|
||||||
to_chat(user, "<span class='notice'>Its dish is facing to the [dir2text(dir)].</span>")
|
to_chat(user, "<span class='notice'>Its dish is facing to the [dir2text(dir)].</span>")
|
||||||
@@ -48,8 +44,8 @@ GLOBAL_LIST_EMPTY(doppler_arrays)
|
|||||||
to_chat(user, "<span class='notice'>You adjust [src]'s dish to face to the [dir2text(dir)].</span>")
|
to_chat(user, "<span class='notice'>You adjust [src]'s dish to face to the [dir2text(dir)].</span>")
|
||||||
playsound(src, 'sound/items/screwdriver2.ogg', 50, 1)
|
playsound(src, 'sound/items/screwdriver2.ogg', 50, 1)
|
||||||
|
|
||||||
/obj/machinery/doppler_array/proc/sense_explosion(turf/epicenter,devastation_range,heavy_impact_range,light_impact_range,
|
/obj/machinery/doppler_array/proc/sense_explosion(datum/source, turf/epicenter, devastation_range, heavy_impact_range, light_impact_range,
|
||||||
took,orig_dev_range,orig_heavy_range,orig_light_range)
|
took, orig_dev_range, orig_heavy_range, orig_light_range)
|
||||||
if(stat & NOPOWER)
|
if(stat & NOPOWER)
|
||||||
return FALSE
|
return FALSE
|
||||||
var/turf/zone = get_turf(src)
|
var/turf/zone = get_turf(src)
|
||||||
@@ -57,7 +53,7 @@ GLOBAL_LIST_EMPTY(doppler_arrays)
|
|||||||
return FALSE
|
return FALSE
|
||||||
|
|
||||||
if(next_announce > world.time)
|
if(next_announce > world.time)
|
||||||
return
|
return FALSE
|
||||||
next_announce = world.time + cooldown
|
next_announce = world.time + cooldown
|
||||||
|
|
||||||
var/distance = get_dist(epicenter, zone)
|
var/distance = get_dist(epicenter, zone)
|
||||||
@@ -65,11 +61,11 @@ GLOBAL_LIST_EMPTY(doppler_arrays)
|
|||||||
|
|
||||||
if(distance > max_dist)
|
if(distance > max_dist)
|
||||||
return FALSE
|
return FALSE
|
||||||
if(!(direct & dir) && !integrated)
|
if(!(direct & dir))
|
||||||
return FALSE
|
return FALSE
|
||||||
|
|
||||||
|
|
||||||
var/list/messages = list("Explosive disturbance detected.", \
|
var/list/messages = list("Explosive disturbance detected.",
|
||||||
"Epicenter at: grid ([epicenter.x],[epicenter.y]). Temporal displacement of tachyons: [took] seconds.", \
|
"Epicenter at: grid ([epicenter.x],[epicenter.y]). Temporal displacement of tachyons: [took] seconds.", \
|
||||||
"Factual: Epicenter radius: [devastation_range]. Outer radius: [heavy_impact_range]. Shockwave radius: [light_impact_range].")
|
"Factual: Epicenter radius: [devastation_range]. Outer radius: [heavy_impact_range]. Shockwave radius: [light_impact_range].")
|
||||||
|
|
||||||
@@ -77,14 +73,8 @@ GLOBAL_LIST_EMPTY(doppler_arrays)
|
|||||||
if(devastation_range < orig_dev_range || heavy_impact_range < orig_heavy_range || light_impact_range < orig_light_range)
|
if(devastation_range < orig_dev_range || heavy_impact_range < orig_heavy_range || light_impact_range < orig_light_range)
|
||||||
messages += "Theoretical: Epicenter radius: [orig_dev_range]. Outer radius: [orig_heavy_range]. Shockwave radius: [orig_light_range]."
|
messages += "Theoretical: Epicenter radius: [orig_dev_range]. Outer radius: [orig_heavy_range]. Shockwave radius: [orig_light_range]."
|
||||||
|
|
||||||
if(integrated)
|
for(var/message in messages)
|
||||||
var/obj/item/clothing/head/helmet/space/hardsuit/helm = loc
|
say(message)
|
||||||
if(!helm || !istype(helm, /obj/item/clothing/head/helmet/space/hardsuit))
|
|
||||||
return FALSE
|
|
||||||
helm.display_visor_message("Explosion detected! Epicenter: [devastation_range], Outer: [heavy_impact_range], Shock: [light_impact_range]")
|
|
||||||
else
|
|
||||||
for(var/message in messages)
|
|
||||||
say(message)
|
|
||||||
return TRUE
|
return TRUE
|
||||||
|
|
||||||
/obj/machinery/doppler_array/powered()
|
/obj/machinery/doppler_array/powered()
|
||||||
@@ -100,22 +90,16 @@ GLOBAL_LIST_EMPTY(doppler_arrays)
|
|||||||
else
|
else
|
||||||
icon_state = "[initial(icon_state)]-off"
|
icon_state = "[initial(icon_state)]-off"
|
||||||
|
|
||||||
//Portable version, built into EOD equipment. It simply provides an explosion's three damage levels.
|
|
||||||
/obj/machinery/doppler_array/integrated
|
|
||||||
name = "integrated tachyon-doppler module"
|
|
||||||
integrated = TRUE
|
|
||||||
max_dist = 21 //Should detect most explosions in hearing range.
|
|
||||||
use_power = NO_POWER_USE
|
|
||||||
|
|
||||||
/obj/machinery/doppler_array/research
|
/obj/machinery/doppler_array/research
|
||||||
name = "tachyon-doppler research array"
|
name = "tachyon-doppler research array"
|
||||||
desc = "A specialized tachyon-doppler bomb detection array that uses the results of the highest yield of explosions for research."
|
desc = "A specialized tachyon-doppler bomb detection array that uses the results of the highest yield of explosions for research."
|
||||||
var/datum/techweb/linked_techweb
|
var/datum/techweb/linked_techweb
|
||||||
|
|
||||||
/obj/machinery/doppler_array/research/sense_explosion(turf/epicenter, dev, heavy, light, time, orig_dev, orig_heavy, orig_light) //probably needs a way to ignore admin explosives later on
|
/obj/machinery/doppler_array/research/sense_explosion(datum/source, turf/epicenter, devastation_range, heavy_impact_range, light_impact_range,
|
||||||
|
took, orig_dev_range, orig_heavy_range, orig_light_range) //probably needs a way to ignore admin explosives later on
|
||||||
. = ..()
|
. = ..()
|
||||||
if(!.)
|
if(!.)
|
||||||
return FALSE
|
return
|
||||||
if(!istype(linked_techweb))
|
if(!istype(linked_techweb))
|
||||||
say("Warning: No linked research system!")
|
say("Warning: No linked research system!")
|
||||||
return
|
return
|
||||||
@@ -124,14 +108,14 @@ GLOBAL_LIST_EMPTY(doppler_arrays)
|
|||||||
|
|
||||||
/*****The Point Calculator*****/
|
/*****The Point Calculator*****/
|
||||||
|
|
||||||
if(orig_light < 10)
|
if(orig_light_range < 10)
|
||||||
say("Explosion not large enough for research calculations.")
|
say("Explosion not large enough for research calculations.")
|
||||||
return
|
return
|
||||||
else if(orig_light >= INFINITY) // Colton-proofs the doppler array
|
else if(orig_light_range >= INFINITY) // Colton-proofs the doppler array
|
||||||
say("WARNING: INFINITE DENSITY OF TACHYONS DETECTED.")
|
say("WARNING: INFINITE DENSITY OF TACHYONS DETECTED.")
|
||||||
point_gain = TOXINS_RESEARCH_MAX
|
point_gain = TOXINS_RESEARCH_MAX
|
||||||
else
|
else
|
||||||
point_gain = (TOXINS_RESEARCH_MAX * orig_light) / (orig_light + TOXINS_RESEARCH_LAMBDA)//New yogs function has the limit built into it because l'Hopital's rule
|
point_gain = (TOXINS_RESEARCH_MAX * orig_light_range) / (orig_light_range + TOXINS_RESEARCH_LAMBDA)//New yogs function has the limit built into it because l'Hopital's rule
|
||||||
|
|
||||||
|
|
||||||
/*****The Point Capper*****/
|
/*****The Point Capper*****/
|
||||||
|
|||||||
@@ -133,10 +133,22 @@
|
|||||||
severity++
|
severity++
|
||||||
for(var/X in equipment)
|
for(var/X in equipment)
|
||||||
var/obj/item/mecha_parts/mecha_equipment/ME = X
|
var/obj/item/mecha_parts/mecha_equipment/ME = X
|
||||||
ME.ex_act(severity,target)
|
switch(severity)
|
||||||
|
if(EXPLODE_DEVASTATE)
|
||||||
|
SSexplosions.high_mov_atom += ME
|
||||||
|
if(EXPLODE_HEAVY)
|
||||||
|
SSexplosions.med_mov_atom += ME
|
||||||
|
if(EXPLODE_LIGHT)
|
||||||
|
SSexplosions.low_mov_atom += ME
|
||||||
for(var/Y in trackers)
|
for(var/Y in trackers)
|
||||||
var/obj/item/mecha_parts/mecha_tracking/MT = Y
|
var/obj/item/mecha_parts/mecha_tracking/MT = Y
|
||||||
MT.ex_act(severity, target)
|
switch(severity)
|
||||||
|
if(EXPLODE_DEVASTATE)
|
||||||
|
SSexplosions.high_mov_atom += MT
|
||||||
|
if(EXPLODE_HEAVY)
|
||||||
|
SSexplosions.med_mov_atom += MT
|
||||||
|
if(EXPLODE_LIGHT)
|
||||||
|
SSexplosions.low_mov_atom += MT
|
||||||
if(occupant)
|
if(occupant)
|
||||||
occupant.ex_act(severity,target)
|
occupant.ex_act(severity,target)
|
||||||
|
|
||||||
|
|||||||
@@ -316,7 +316,7 @@
|
|||||||
if(target && !target.stat)
|
if(target && !target.stat)
|
||||||
O.throw_at(target, 7, 5)
|
O.throw_at(target, 7, 5)
|
||||||
else
|
else
|
||||||
O.ex_act(EXPLODE_HEAVY)
|
SSexplosions.med_mov_atom += O
|
||||||
|
|
||||||
/obj/effect/anomaly/bhole/proc/grav(r, ex_act_force, pull_chance, turf_removal_chance)
|
/obj/effect/anomaly/bhole/proc/grav(r, ex_act_force, pull_chance, turf_removal_chance)
|
||||||
for(var/t = -r, t < r, t++)
|
for(var/t = -r, t < r, t++)
|
||||||
@@ -335,7 +335,13 @@
|
|||||||
if(prob(pull_chance))
|
if(prob(pull_chance))
|
||||||
for(var/obj/O in T.contents)
|
for(var/obj/O in T.contents)
|
||||||
if(O.anchored)
|
if(O.anchored)
|
||||||
O.ex_act(ex_act_force)
|
switch(ex_act_force)
|
||||||
|
if(EXPLODE_DEVASTATE)
|
||||||
|
SSexplosions.high_mov_atom += O
|
||||||
|
if(EXPLODE_HEAVY)
|
||||||
|
SSexplosions.med_mov_atom += O
|
||||||
|
if(EXPLODE_LIGHT)
|
||||||
|
SSexplosions.low_mov_atom += O
|
||||||
else
|
else
|
||||||
step_towards(O,src)
|
step_towards(O,src)
|
||||||
for(var/mob/living/M in T.contents)
|
for(var/mob/living/M in T.contents)
|
||||||
@@ -343,4 +349,10 @@
|
|||||||
|
|
||||||
//Damaging the turf
|
//Damaging the turf
|
||||||
if( T && prob(turf_removal_chance) )
|
if( T && prob(turf_removal_chance) )
|
||||||
T.ex_act(ex_act_force)
|
switch(ex_act_force)
|
||||||
|
if(EXPLODE_DEVASTATE)
|
||||||
|
SSexplosions.highturf += T
|
||||||
|
if(EXPLODE_HEAVY)
|
||||||
|
SSexplosions.medturf += T
|
||||||
|
if(EXPLODE_LIGHT)
|
||||||
|
SSexplosions.lowturf += T
|
||||||
|
|||||||
@@ -542,10 +542,12 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
|
|||||||
itempush = 0 //too light to push anything
|
itempush = 0 //too light to push anything
|
||||||
return hit_atom.hitby(src, 0, itempush, throwingdatum=throwingdatum)
|
return hit_atom.hitby(src, 0, itempush, throwingdatum=throwingdatum)
|
||||||
|
|
||||||
/obj/item/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback, force)
|
/obj/item/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback, force, quickstart = TRUE)
|
||||||
|
if(HAS_TRAIT(src, TRAIT_NODROP))
|
||||||
|
return
|
||||||
thrownby = thrower
|
thrownby = thrower
|
||||||
callback = CALLBACK(src, .proc/after_throw, callback) //replace their callback with our own
|
callback = CALLBACK(src, .proc/after_throw, callback) //replace their callback with our own
|
||||||
. = ..(target, range, speed, thrower, spin, diagonals_first, callback, force)
|
. = ..(target, range, speed, thrower, spin, diagonals_first, callback, force, quickstart = quickstart)
|
||||||
|
|
||||||
|
|
||||||
/obj/item/proc/after_throw(datum/callback/callback)
|
/obj/item/proc/after_throw(datum/callback/callback)
|
||||||
@@ -800,11 +802,6 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE)
|
|||||||
dropped(M)
|
dropped(M)
|
||||||
return ..()
|
return ..()
|
||||||
|
|
||||||
/obj/item/throw_at(atom/target, range, speed, mob/thrower, spin=TRUE, diagonals_first = FALSE, var/datum/callback/callback)
|
|
||||||
if(HAS_TRAIT(src, TRAIT_NODROP))
|
|
||||||
return
|
|
||||||
return ..()
|
|
||||||
|
|
||||||
/obj/item/proc/canStrip(mob/stripper, mob/owner)
|
/obj/item/proc/canStrip(mob/stripper, mob/owner)
|
||||||
SHOULD_BE_PURE(TRUE)
|
SHOULD_BE_PURE(TRUE)
|
||||||
return !HAS_TRAIT(src, TRAIT_NODROP)
|
return !HAS_TRAIT(src, TRAIT_NODROP)
|
||||||
|
|||||||
@@ -339,7 +339,7 @@
|
|||||||
gender = NEUTER
|
gender = NEUTER
|
||||||
var/immobilize = 0
|
var/immobilize = 0
|
||||||
|
|
||||||
/obj/item/restraints/legcuffs/bola/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback)
|
/obj/item/restraints/legcuffs/bola/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback, quickstart = TRUE)
|
||||||
if(!..())
|
if(!..())
|
||||||
return
|
return
|
||||||
playsound(src.loc,'sound/weapons/bolathrow.ogg', 75, 1)
|
playsound(src.loc,'sound/weapons/bolathrow.ogg', 75, 1)
|
||||||
|
|||||||
@@ -19,9 +19,14 @@
|
|||||||
return FALSE
|
return FALSE
|
||||||
|
|
||||||
/obj/item/storage/contents_explosion(severity, target)
|
/obj/item/storage/contents_explosion(severity, target)
|
||||||
for(var/atom/A in contents)
|
for(var/thing in contents)
|
||||||
A.ex_act(severity, target)
|
switch(severity)
|
||||||
CHECK_TICK
|
if(EXPLODE_DEVASTATE)
|
||||||
|
SSexplosions.high_mov_atom += thing
|
||||||
|
if(EXPLODE_HEAVY)
|
||||||
|
SSexplosions.med_mov_atom += thing
|
||||||
|
if(EXPLODE_LIGHT)
|
||||||
|
SSexplosions.low_mov_atom += thing
|
||||||
|
|
||||||
/obj/item/storage/canStrip(mob/who)
|
/obj/item/storage/canStrip(mob/who)
|
||||||
. = ..()
|
. = ..()
|
||||||
|
|||||||
@@ -617,7 +617,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301
|
|||||||
if(homerun_ready)
|
if(homerun_ready)
|
||||||
user.visible_message("<span class='userdanger'>It's a home run!</span>")
|
user.visible_message("<span class='userdanger'>It's a home run!</span>")
|
||||||
target.throw_at(throw_target, rand(8,10), 14, user)
|
target.throw_at(throw_target, rand(8,10), 14, user)
|
||||||
target.ex_act(EXPLODE_HEAVY)
|
SSexplosions.medturf += throw_target
|
||||||
playsound(get_turf(src), 'sound/weapons/homerun.ogg', 100, 1)
|
playsound(get_turf(src), 'sound/weapons/homerun.ogg', 100, 1)
|
||||||
homerun_ready = 0
|
homerun_ready = 0
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -168,7 +168,7 @@
|
|||||||
return take_damage(M.force*3, mech_damtype, "melee", play_soundeffect, get_dir(src, M)) // multiplied by 3 so we can hit objs hard but not be overpowered against mobs.
|
return take_damage(M.force*3, mech_damtype, "melee", play_soundeffect, get_dir(src, M)) // multiplied by 3 so we can hit objs hard but not be overpowered against mobs.
|
||||||
|
|
||||||
/obj/singularity_act()
|
/obj/singularity_act()
|
||||||
ex_act(EXPLODE_DEVASTATE)
|
SSexplosions.high_mov_atom += src
|
||||||
if(src && !QDELETED(src))
|
if(src && !QDELETED(src))
|
||||||
qdel(src)
|
qdel(src)
|
||||||
return 2
|
return 2
|
||||||
|
|||||||
@@ -80,7 +80,7 @@
|
|||||||
SEND_SIGNAL(src, COMSIG_OBJ_SETANCHORED, anchorvalue)
|
SEND_SIGNAL(src, COMSIG_OBJ_SETANCHORED, anchorvalue)
|
||||||
anchored = anchorvalue
|
anchored = anchorvalue
|
||||||
|
|
||||||
/obj/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback, force)
|
/obj/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback, force, quickstart = TRUE)
|
||||||
..()
|
..()
|
||||||
if(obj_flags & FROZEN)
|
if(obj_flags & FROZEN)
|
||||||
visible_message("<span class='danger'>[src] shatters into a million pieces!</span>")
|
visible_message("<span class='danger'>[src] shatters into a million pieces!</span>")
|
||||||
|
|||||||
@@ -534,8 +534,14 @@ GLOBAL_LIST_EMPTY(lockers)
|
|||||||
req_access += pick(get_all_accesses())
|
req_access += pick(get_all_accesses())
|
||||||
|
|
||||||
/obj/structure/closet/contents_explosion(severity, target)
|
/obj/structure/closet/contents_explosion(severity, target)
|
||||||
for(var/atom/A in contents)
|
for(var/thing in contents)
|
||||||
A.ex_act(severity, target)
|
switch(severity)
|
||||||
|
if(EXPLODE_DEVASTATE)
|
||||||
|
SSexplosions.high_mov_atom += thing
|
||||||
|
if(EXPLODE_HEAVY)
|
||||||
|
SSexplosions.med_mov_atom += thing
|
||||||
|
if(EXPLODE_LIGHT)
|
||||||
|
SSexplosions.low_mov_atom += thing
|
||||||
CHECK_TICK
|
CHECK_TICK
|
||||||
|
|
||||||
/obj/structure/closet/singularity_act()
|
/obj/structure/closet/singularity_act()
|
||||||
|
|||||||
@@ -33,7 +33,13 @@
|
|||||||
|
|
||||||
/obj/structure/extinguisher_cabinet/contents_explosion(severity, target)
|
/obj/structure/extinguisher_cabinet/contents_explosion(severity, target)
|
||||||
if(stored_extinguisher)
|
if(stored_extinguisher)
|
||||||
stored_extinguisher.ex_act(severity, target)
|
switch(severity)
|
||||||
|
if(EXPLODE_DEVASTATE)
|
||||||
|
SSexplosions.high_mov_atom += stored_extinguisher
|
||||||
|
if(EXPLODE_HEAVY)
|
||||||
|
SSexplosions.med_mov_atom += stored_extinguisher
|
||||||
|
if(EXPLODE_LIGHT)
|
||||||
|
SSexplosions.low_mov_atom += stored_extinguisher
|
||||||
|
|
||||||
/obj/structure/extinguisher_cabinet/handle_atom_del(atom/A)
|
/obj/structure/extinguisher_cabinet/handle_atom_del(atom/A)
|
||||||
if(A == stored_extinguisher)
|
if(A == stored_extinguisher)
|
||||||
|
|||||||
@@ -95,9 +95,14 @@
|
|||||||
update_icon()
|
update_icon()
|
||||||
|
|
||||||
/obj/structure/guncase/contents_explosion(severity, target)
|
/obj/structure/guncase/contents_explosion(severity, target)
|
||||||
for(var/atom/A in contents)
|
for(var/thing in contents)
|
||||||
A.ex_act(severity++, target)
|
switch(severity)
|
||||||
CHECK_TICK
|
if(EXPLODE_DEVASTATE)
|
||||||
|
SSexplosions.high_mov_atom += thing
|
||||||
|
if(EXPLODE_HEAVY)
|
||||||
|
SSexplosions.med_mov_atom += thing
|
||||||
|
if(EXPLODE_LIGHT)
|
||||||
|
SSexplosions.low_mov_atom += thing
|
||||||
|
|
||||||
/obj/structure/guncase/shotgun
|
/obj/structure/guncase/shotgun
|
||||||
name = "shotgun locker"
|
name = "shotgun locker"
|
||||||
|
|||||||
@@ -56,8 +56,14 @@
|
|||||||
empty_pod()
|
empty_pod()
|
||||||
|
|
||||||
/obj/structure/transit_tube_pod/contents_explosion(severity, target)
|
/obj/structure/transit_tube_pod/contents_explosion(severity, target)
|
||||||
for(var/atom/movable/AM in contents)
|
for(var/thing in contents)
|
||||||
AM.ex_act(severity, target)
|
switch(severity)
|
||||||
|
if(EXPLODE_DEVASTATE)
|
||||||
|
SSexplosions.high_mov_atom += thing
|
||||||
|
if(EXPLODE_HEAVY)
|
||||||
|
SSexplosions.med_mov_atom += thing
|
||||||
|
if(EXPLODE_LIGHT)
|
||||||
|
SSexplosions.low_mov_atom += thing
|
||||||
|
|
||||||
/obj/structure/transit_tube_pod/singularity_pull(S, current_size)
|
/obj/structure/transit_tube_pod/singularity_pull(S, current_size)
|
||||||
..()
|
..()
|
||||||
|
|||||||
@@ -124,6 +124,10 @@
|
|||||||
soundin = pick('sound/effects/glassbr1.ogg','sound/effects/glassbr2.ogg','sound/effects/glassbr3.ogg')
|
soundin = pick('sound/effects/glassbr1.ogg','sound/effects/glassbr2.ogg','sound/effects/glassbr3.ogg')
|
||||||
if ("explosion")
|
if ("explosion")
|
||||||
soundin = pick('sound/effects/explosion1.ogg','sound/effects/explosion2.ogg')
|
soundin = pick('sound/effects/explosion1.ogg','sound/effects/explosion2.ogg')
|
||||||
|
if ("explosion_creaking")
|
||||||
|
soundin = pick('sound/effects/explosioncreak1.ogg', 'sound/effects/explosioncreak2.ogg')
|
||||||
|
if ("hull_creaking")
|
||||||
|
soundin = pick('sound/effects/creak1.ogg', 'sound/effects/creak2.ogg', 'sound/effects/creak3.ogg')
|
||||||
if ("sparks")
|
if ("sparks")
|
||||||
soundin = pick('sound/effects/sparks1.ogg','sound/effects/sparks2.ogg','sound/effects/sparks3.ogg','sound/effects/sparks4.ogg')
|
soundin = pick('sound/effects/sparks1.ogg','sound/effects/sparks2.ogg','sound/effects/sparks3.ogg','sound/effects/sparks4.ogg')
|
||||||
if ("rustle")
|
if ("rustle")
|
||||||
|
|||||||
@@ -56,6 +56,14 @@
|
|||||||
icon_regular_floor = icon_state
|
icon_regular_floor = icon_state
|
||||||
if(mapload && prob(33))
|
if(mapload && prob(33))
|
||||||
MakeDirty()
|
MakeDirty()
|
||||||
|
if(is_station_level(z))
|
||||||
|
GLOB.station_turfs += src
|
||||||
|
|
||||||
|
|
||||||
|
/turf/open/floor/Destroy()
|
||||||
|
if(is_station_level(z))
|
||||||
|
GLOB.station_turfs -= src
|
||||||
|
..()
|
||||||
|
|
||||||
/turf/open/floor/ex_act(severity, target)
|
/turf/open/floor/ex_act(severity, target)
|
||||||
var/shielded = is_shielded()
|
var/shielded = is_shielded()
|
||||||
|
|||||||
@@ -273,14 +273,8 @@
|
|||||||
fixed_underlay = list("space"=1)
|
fixed_underlay = list("space"=1)
|
||||||
|
|
||||||
/turf/closed/wall/mineral/plastitanium/explosive/ex_act(severity)
|
/turf/closed/wall/mineral/plastitanium/explosive/ex_act(severity)
|
||||||
var/datum/explosion/acted_explosion = null
|
var/obj/item/bombcore/large/bombcore = new(get_turf(src))
|
||||||
for(var/datum/explosion/E in GLOB.explosions)
|
bombcore.detonate()
|
||||||
if(E.explosion_id == explosion_id)
|
|
||||||
acted_explosion = E
|
|
||||||
break
|
|
||||||
if(acted_explosion && istype(acted_explosion.explosion_source, /obj/item/bombcore))
|
|
||||||
var/obj/item/bombcore/large/bombcore = new(get_turf(src))
|
|
||||||
bombcore.detonate()
|
|
||||||
..()
|
..()
|
||||||
|
|
||||||
//have to copypaste this code
|
//have to copypaste this code
|
||||||
|
|||||||
@@ -35,6 +35,16 @@
|
|||||||
|
|
||||||
var/list/dent_decals
|
var/list/dent_decals
|
||||||
|
|
||||||
|
/turf/closed/wall/Initialize(mapload)
|
||||||
|
. = ..()
|
||||||
|
if(is_station_level(z))
|
||||||
|
GLOB.station_turfs += src
|
||||||
|
|
||||||
|
/turf/closed/wall/Destroy()
|
||||||
|
if(is_station_level(z))
|
||||||
|
GLOB.station_turfs -= src
|
||||||
|
..()
|
||||||
|
|
||||||
/turf/closed/wall/examine(mob/user)
|
/turf/closed/wall/examine(mob/user)
|
||||||
. += ..()
|
. += ..()
|
||||||
. += deconstruction_hints(user)
|
. += deconstruction_hints(user)
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
GLOBAL_LIST_EMPTY(station_turfs)
|
||||||
|
|
||||||
/turf
|
/turf
|
||||||
icon = 'icons/turf/floors.dmi'
|
icon = 'icons/turf/floors.dmi'
|
||||||
level = 1
|
level = 1
|
||||||
@@ -23,6 +25,7 @@
|
|||||||
|
|
||||||
var/explosion_level = 0 //for preventing explosion dodging
|
var/explosion_level = 0 //for preventing explosion dodging
|
||||||
var/explosion_id = 0
|
var/explosion_id = 0
|
||||||
|
var/list/explosion_throw_details
|
||||||
|
|
||||||
var/requires_activation //add to air processing after initialize?
|
var/requires_activation //add to air processing after initialize?
|
||||||
var/changing_turf = FALSE
|
var/changing_turf = FALSE
|
||||||
@@ -249,8 +252,6 @@
|
|||||||
|
|
||||||
/turf/Entered(atom/movable/AM)
|
/turf/Entered(atom/movable/AM)
|
||||||
..()
|
..()
|
||||||
if(explosion_level && AM.ex_check(explosion_id))
|
|
||||||
AM.ex_act(explosion_level)
|
|
||||||
|
|
||||||
// If an opaque movable atom moves around we need to potentially update visibility.
|
// If an opaque movable atom moves around we need to potentially update visibility.
|
||||||
if (AM.opacity)
|
if (AM.opacity)
|
||||||
@@ -415,25 +416,19 @@
|
|||||||
/turf/proc/is_shielded()
|
/turf/proc/is_shielded()
|
||||||
|
|
||||||
/turf/contents_explosion(severity, target)
|
/turf/contents_explosion(severity, target)
|
||||||
var/affecting_level
|
for(var/thing in contents)
|
||||||
if(severity == 1)
|
var/atom/movable/movable_thing = thing
|
||||||
affecting_level = 1
|
if(QDELETED(movable_thing))
|
||||||
else if(is_shielded())
|
continue
|
||||||
affecting_level = 3
|
if(!movable_thing.ex_check(explosion_id))
|
||||||
else if(intact)
|
continue
|
||||||
affecting_level = 2
|
switch(severity)
|
||||||
else
|
if(EXPLODE_DEVASTATE)
|
||||||
affecting_level = 1
|
SSexplosions.high_mov_atom += movable_thing
|
||||||
|
if(EXPLODE_HEAVY)
|
||||||
for(var/V in contents)
|
SSexplosions.med_mov_atom += movable_thing
|
||||||
var/atom/A = V
|
if(EXPLODE_LIGHT)
|
||||||
if(!QDELETED(A) && A.level >= affecting_level)
|
SSexplosions.low_mov_atom += movable_thing
|
||||||
if(ismovable(A))
|
|
||||||
var/atom/movable/AM = A
|
|
||||||
if(!AM.ex_check(explosion_id))
|
|
||||||
continue
|
|
||||||
A.ex_act(severity, target)
|
|
||||||
CHECK_TICK
|
|
||||||
|
|
||||||
/turf/narsie_act(force, ignore_mobs, probability = 20)
|
/turf/narsie_act(force, ignore_mobs, probability = 20)
|
||||||
. = (prob(probability) || force)
|
. = (prob(probability) || force)
|
||||||
|
|||||||
@@ -42,5 +42,5 @@
|
|||||||
/obj/effect/clockwork/servant_blocker/ex_act(severity, target)
|
/obj/effect/clockwork/servant_blocker/ex_act(severity, target)
|
||||||
return
|
return
|
||||||
|
|
||||||
/obj/effect/clockwork/servant_blocker/safe_throw_at(atom/target, range, speed, mob/thrower, spin = TRUE, diagonals_first = FALSE, datum/callback/callback, force = MOVE_FORCE_STRONG)
|
/obj/effect/clockwork/servant_blocker/safe_throw_at(atom/target, range, speed, mob/thrower, spin = TRUE, diagonals_first = FALSE, datum/callback/callback, force = MOVE_FORCE_STRONG, quickstart = TRUE)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -136,7 +136,7 @@
|
|||||||
. = ..()
|
. = ..()
|
||||||
setDir(t)
|
setDir(t)
|
||||||
|
|
||||||
/obj/item/assembly/infra/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback, force, gentle = FALSE)
|
/obj/item/assembly/infra/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback, force, gentle = FALSE, quickstart = TRUE)
|
||||||
. = ..()
|
. = ..()
|
||||||
olddir = dir
|
olddir = dir
|
||||||
|
|
||||||
|
|||||||
@@ -63,6 +63,9 @@ GLOBAL_LIST_EMPTY(pipeimages)
|
|||||||
nullifyNode(i)
|
nullifyNode(i)
|
||||||
|
|
||||||
SSair.atmos_machinery -= src
|
SSair.atmos_machinery -= src
|
||||||
|
if(SSair.currentpart == SSAIR_ATMOSMACHINERY)
|
||||||
|
SSair.currentrun -= src
|
||||||
|
SSair.pipenets_needing_rebuilt -= src
|
||||||
|
|
||||||
dropContents()
|
dropContents()
|
||||||
if(pipe_vision_img)
|
if(pipe_vision_img)
|
||||||
|
|||||||
@@ -84,7 +84,7 @@
|
|||||||
|
|
||||||
/obj/machinery/atmospherics/components/binary/circulator/update_icon()
|
/obj/machinery/atmospherics/components/binary/circulator/update_icon()
|
||||||
cut_overlays()
|
cut_overlays()
|
||||||
|
|
||||||
if(anchored)
|
if(anchored)
|
||||||
for(var/direction in GLOB.cardinals)
|
for(var/direction in GLOB.cardinals)
|
||||||
if(!(direction & initialize_directions))
|
if(!(direction & initialize_directions))
|
||||||
@@ -120,7 +120,7 @@
|
|||||||
add_overlay("circ-panel")
|
add_overlay("circ-panel")
|
||||||
set_light(0)
|
set_light(0)
|
||||||
return
|
return
|
||||||
|
|
||||||
icon_state = "circ-assembled-[flipped]"
|
icon_state = "circ-assembled-[flipped]"
|
||||||
|
|
||||||
if(!is_operational())
|
if(!is_operational())
|
||||||
@@ -150,7 +150,7 @@
|
|||||||
/obj/machinery/atmospherics/components/binary/circulator/wrench_act(mob/living/user, obj/item/I)
|
/obj/machinery/atmospherics/components/binary/circulator/wrench_act(mob/living/user, obj/item/I)
|
||||||
if(user.a_intent == INTENT_HARM)
|
if(user.a_intent == INTENT_HARM)
|
||||||
return
|
return
|
||||||
|
|
||||||
if(!panel_open)
|
if(!panel_open)
|
||||||
to_chat(user, "<span class='warning'>Open the panel first!</span>")
|
to_chat(user, "<span class='warning'>Open the panel first!</span>")
|
||||||
return TRUE
|
return TRUE
|
||||||
@@ -186,7 +186,7 @@
|
|||||||
if(node2)
|
if(node2)
|
||||||
node2.atmosinit()
|
node2.atmosinit()
|
||||||
node2.addMember(src)
|
node2.addMember(src)
|
||||||
build_network()
|
SSair.add_to_rebuild_queue(src)
|
||||||
|
|
||||||
update_icon()
|
update_icon()
|
||||||
|
|
||||||
@@ -211,7 +211,7 @@
|
|||||||
|
|
||||||
/obj/machinery/atmospherics/components/binary/circulator/multitool_act(mob/living/user, obj/item/I)
|
/obj/machinery/atmospherics/components/binary/circulator/multitool_act(mob/living/user, obj/item/I)
|
||||||
if(user.a_intent == INTENT_HARM)
|
if(user.a_intent == INTENT_HARM)
|
||||||
return
|
return
|
||||||
if(generator)
|
if(generator)
|
||||||
to_chat(user, "<span class='warning'>Disconnect [generator] first!</span>")
|
to_chat(user, "<span class='warning'>Disconnect [generator] first!</span>")
|
||||||
return TRUE
|
return TRUE
|
||||||
@@ -283,4 +283,3 @@
|
|||||||
generator.kill_circs()
|
generator.kill_circs()
|
||||||
generator.update_icon()
|
generator.update_icon()
|
||||||
..()
|
..()
|
||||||
|
|
||||||
@@ -144,7 +144,8 @@
|
|||||||
var/datum/pipeline/parent = parents[i]
|
var/datum/pipeline/parent = parents[i]
|
||||||
if(!parent)
|
if(!parent)
|
||||||
WARNING("Component is missing a pipenet! Rebuilding...")
|
WARNING("Component is missing a pipenet! Rebuilding...")
|
||||||
build_network()
|
SSair.add_to_rebuild_queue(src)
|
||||||
|
parent = parents[i]
|
||||||
parent.update = 1
|
parent.update = 1
|
||||||
|
|
||||||
/obj/machinery/atmospherics/components/returnPipenets()
|
/obj/machinery/atmospherics/components/returnPipenets()
|
||||||
|
|||||||
@@ -81,7 +81,13 @@
|
|||||||
/obj/machinery/atmospherics/components/unary/cryo_cell/contents_explosion(severity, target)
|
/obj/machinery/atmospherics/components/unary/cryo_cell/contents_explosion(severity, target)
|
||||||
..()
|
..()
|
||||||
if(beaker)
|
if(beaker)
|
||||||
beaker.ex_act(severity, target)
|
switch(severity)
|
||||||
|
if(EXPLODE_DEVASTATE)
|
||||||
|
SSexplosions.high_mov_atom += beaker
|
||||||
|
if(EXPLODE_HEAVY)
|
||||||
|
SSexplosions.med_mov_atom += beaker
|
||||||
|
if(EXPLODE_LIGHT)
|
||||||
|
SSexplosions.low_mov_atom += beaker
|
||||||
|
|
||||||
/obj/machinery/atmospherics/components/unary/cryo_cell/handle_atom_del(atom/A)
|
/obj/machinery/atmospherics/components/unary/cryo_cell/handle_atom_del(atom/A)
|
||||||
..()
|
..()
|
||||||
@@ -453,7 +459,7 @@
|
|||||||
if(node)
|
if(node)
|
||||||
node.atmosinit()
|
node.atmosinit()
|
||||||
node.addMember(src)
|
node.addMember(src)
|
||||||
build_network()
|
SSair.add_to_rebuild_queue(src)
|
||||||
|
|
||||||
/obj/machinery/atmospherics/components/unary/cryo_cell/CtrlClick(mob/user)
|
/obj/machinery/atmospherics/components/unary/cryo_cell/CtrlClick(mob/user)
|
||||||
if(!user.canUseTopic(src, !issilicon(user)))
|
if(!user.canUseTopic(src, !issilicon(user)))
|
||||||
|
|||||||
@@ -103,7 +103,7 @@
|
|||||||
if(node)
|
if(node)
|
||||||
node.atmosinit()
|
node.atmosinit()
|
||||||
node.addMember(src)
|
node.addMember(src)
|
||||||
build_network()
|
SSair.add_to_rebuild_queue(src)
|
||||||
return TRUE
|
return TRUE
|
||||||
|
|
||||||
/obj/machinery/atmospherics/components/unary/thermomachine/ui_status(mob/user)
|
/obj/machinery/atmospherics/components/unary/thermomachine/ui_status(mob/user)
|
||||||
|
|||||||
@@ -37,7 +37,7 @@
|
|||||||
nodes = list()
|
nodes = list()
|
||||||
for(var/obj/machinery/atmospherics/A in needs_nullifying)
|
for(var/obj/machinery/atmospherics/A in needs_nullifying)
|
||||||
A.disconnect(src)
|
A.disconnect(src)
|
||||||
A.build_network()
|
SSair.add_to_rebuild_queue(A)
|
||||||
|
|
||||||
/obj/machinery/atmospherics/pipe/layer_manifold/proc/get_all_connected_nodes()
|
/obj/machinery/atmospherics/pipe/layer_manifold/proc/get_all_connected_nodes()
|
||||||
return front_nodes + back_nodes + nodes
|
return front_nodes + back_nodes + nodes
|
||||||
@@ -141,4 +141,3 @@
|
|||||||
/obj/machinery/atmospherics/pipe/layer_manifold/visible
|
/obj/machinery/atmospherics/pipe/layer_manifold/visible
|
||||||
level = PIPE_VISIBLE_LEVEL
|
level = PIPE_VISIBLE_LEVEL
|
||||||
layer = GAS_PIPE_VISIBLE_LAYER
|
layer = GAS_PIPE_VISIBLE_LAYER
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
var/obj/machinery/atmospherics/oldN = nodes[i]
|
var/obj/machinery/atmospherics/oldN = nodes[i]
|
||||||
..()
|
..()
|
||||||
if(oldN)
|
if(oldN)
|
||||||
oldN.build_network()
|
SSair.add_to_rebuild_queue(oldN)
|
||||||
|
|
||||||
/obj/machinery/atmospherics/pipe/destroy_network()
|
/obj/machinery/atmospherics/pipe/destroy_network()
|
||||||
QDEL_NULL(parent)
|
QDEL_NULL(parent)
|
||||||
|
|||||||
@@ -210,7 +210,7 @@
|
|||||||
pump = new(src, FALSE)
|
pump = new(src, FALSE)
|
||||||
pump.on = TRUE
|
pump.on = TRUE
|
||||||
pump.stat = 0
|
pump.stat = 0
|
||||||
pump.build_network()
|
SSair.add_to_rebuild_queue(pump)
|
||||||
|
|
||||||
/obj/machinery/portable_atmospherics/canister/Initialize()
|
/obj/machinery/portable_atmospherics/canister/Initialize()
|
||||||
. = ..()
|
. = ..()
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
pump = new(src, FALSE)
|
pump = new(src, FALSE)
|
||||||
pump.on = TRUE
|
pump.on = TRUE
|
||||||
pump.stat = 0
|
pump.stat = 0
|
||||||
pump.build_network()
|
SSair.add_to_rebuild_queue(pump)
|
||||||
|
|
||||||
/obj/machinery/portable_atmospherics/pump/Destroy()
|
/obj/machinery/portable_atmospherics/pump/Destroy()
|
||||||
var/turf/T = get_turf(src)
|
var/turf/T = get_turf(src)
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ GLOBAL_DATUM(the_gateway, /obj/machinery/gateway/centerstation)
|
|||||||
/obj/machinery/gateway/proc/toggleon(mob/user)
|
/obj/machinery/gateway/proc/toggleon(mob/user)
|
||||||
return FALSE
|
return FALSE
|
||||||
|
|
||||||
/obj/machinery/gateway/safe_throw_at(atom/target, range, speed, mob/thrower, spin = TRUE, diagonals_first = FALSE, datum/callback/callback, force = MOVE_FORCE_STRONG)
|
/obj/machinery/gateway/safe_throw_at(atom/target, range, speed, mob/thrower, spin = TRUE, diagonals_first = FALSE, datum/callback/callback, force = MOVE_FORCE_STRONG, quickstart = TRUE)
|
||||||
return
|
return
|
||||||
|
|
||||||
/obj/machinery/gateway/centerstation/Initialize()
|
/obj/machinery/gateway/centerstation/Initialize()
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
armor = list("melee" = 30, "bullet" = 50, "laser" = 50, "energy" = 100, "bomb" = 100, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 80)
|
armor = list("melee" = 30, "bullet" = 50, "laser" = 50, "energy" = 100, "bomb" = 100, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 80)
|
||||||
anchored = TRUE //So it cant slide around after landing
|
anchored = TRUE //So it cant slide around after landing
|
||||||
anchorable = FALSE
|
anchorable = FALSE
|
||||||
|
flags_1 = PREVENT_CONTENTS_EXPLOSION_1
|
||||||
//*****NOTE*****: Many of these comments are similarly described in centcom_podlauncher.dm. If you change them here, please consider doing so in the centcom podlauncher code as well!
|
//*****NOTE*****: Many of these comments are similarly described in centcom_podlauncher.dm. If you change them here, please consider doing so in the centcom podlauncher code as well!
|
||||||
var/adminNamed = FALSE //Determines whether or not the pod has been named by an admin. If true, the pod's name will not get overridden when the style of the pod changes (changing the style of the pod normally also changes the name+desc)
|
var/adminNamed = FALSE //Determines whether or not the pod has been named by an admin. If true, the pod's name will not get overridden when the style of the pod changes (changing the style of the pod normally also changes the name+desc)
|
||||||
var/bluespace = FALSE //If true, the pod deletes (in a shower of sparks) after landing
|
var/bluespace = FALSE //If true, the pod deletes (in a shower of sparks) after landing
|
||||||
@@ -111,9 +112,6 @@
|
|||||||
/obj/structure/closet/supplypod/contents_explosion() //Supplypods also protect their contents from the harmful effects of fucking exploding.
|
/obj/structure/closet/supplypod/contents_explosion() //Supplypods also protect their contents from the harmful effects of fucking exploding.
|
||||||
return
|
return
|
||||||
|
|
||||||
/obj/structure/closet/supplypod/prevent_content_explosion() //Useful for preventing epicenter explosions from damaging contents
|
|
||||||
return TRUE
|
|
||||||
|
|
||||||
/obj/structure/closet/supplypod/toggle(mob/living/user) //Supplypods shouldn't be able to be manually opened under any circumstances, as the open() proc generates supply order datums
|
/obj/structure/closet/supplypod/toggle(mob/living/user) //Supplypods shouldn't be able to be manually opened under any circumstances, as the open() proc generates supply order datums
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|||||||
@@ -94,7 +94,7 @@
|
|||||||
candy_cooldown = world.time+1200
|
candy_cooldown = world.time+1200
|
||||||
else
|
else
|
||||||
to_chat(user, "You just took a candy corn! You should wait a couple minutes, lest you burn through your stash.")
|
to_chat(user, "You just took a candy corn! You should wait a couple minutes, lest you burn through your stash.")
|
||||||
|
|
||||||
/obj/item/clothing/head/det_hat/evil
|
/obj/item/clothing/head/det_hat/evil
|
||||||
name = "suspicious fedora"
|
name = "suspicious fedora"
|
||||||
icon_state = "syndicate_fedora"
|
icon_state = "syndicate_fedora"
|
||||||
@@ -123,14 +123,14 @@
|
|||||||
icon_state = "syndicate_fedora"
|
icon_state = "syndicate_fedora"
|
||||||
attack_verb = list("poked", "tipped")
|
attack_verb = list("poked", "tipped")
|
||||||
hitsound = 'sound/weapons/genhit.ogg'
|
hitsound = 'sound/weapons/genhit.ogg'
|
||||||
|
|
||||||
/obj/item/clothing/head/det_hat/evil/throw_impact(atom/hit_atom,)
|
/obj/item/clothing/head/det_hat/evil/throw_impact(atom/hit_atom,)
|
||||||
if(iscarbon(src.loc))
|
if(iscarbon(src.loc))
|
||||||
return ..()
|
return ..()
|
||||||
throw_at(thrownby, throw_range+3, throw_speed, null)
|
throw_at(thrownby, throw_range+3, throw_speed, null)
|
||||||
..()
|
..()
|
||||||
|
|
||||||
/obj/item/clothing/head/det_hat/evil/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback, force)
|
/obj/item/clothing/head/det_hat/evil/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback, force, quickstart = TRUE)
|
||||||
if(iscarbon(thrower))
|
if(iscarbon(thrower))
|
||||||
var/mob/living/carbon/C = thrower
|
var/mob/living/carbon/C = thrower
|
||||||
C.throw_mode_on()
|
C.throw_mode_on()
|
||||||
|
|||||||
@@ -489,12 +489,13 @@
|
|||||||
resistance_flags = ACID_PROOF | FIRE_PROOF
|
resistance_flags = ACID_PROOF | FIRE_PROOF
|
||||||
max_heat_protection_temperature = FIRE_SUIT_MAX_TEMP_PROTECT
|
max_heat_protection_temperature = FIRE_SUIT_MAX_TEMP_PROTECT
|
||||||
armor = list("melee" = 30, "bullet" = 5, "laser" = 10, "energy" = 5, "bomb" = 100, "bio" = 100, "rad" = 60, "fire" = 60, "acid" = 80)
|
armor = list("melee" = 30, "bullet" = 5, "laser" = 10, "energy" = 5, "bomb" = 100, "bio" = 100, "rad" = 60, "fire" = 60, "acid" = 80)
|
||||||
var/obj/machinery/doppler_array/integrated/bomb_radar
|
var/explosion_detection_dist = 21
|
||||||
clothing_flags = STOPSPRESSUREDAMAGE | THICKMATERIAL | SCAN_REAGENTS
|
clothing_flags = STOPSPRESSUREDAMAGE | THICKMATERIAL | SCAN_REAGENTS
|
||||||
actions_types = list(/datum/action/item_action/toggle_helmet_light, /datum/action/item_action/toggle_research_scanner)
|
actions_types = list(/datum/action/item_action/toggle_helmet_light, /datum/action/item_action/toggle_research_scanner)
|
||||||
|
|
||||||
/obj/item/clothing/head/helmet/space/hardsuit/rd/Initialize()
|
/obj/item/clothing/head/helmet/space/hardsuit/rd/Initialize()
|
||||||
. = ..()
|
. = ..()
|
||||||
|
RegisterSignal(SSdcs, COMSIG_GLOB_EXPLOSION, .proc/sense_explosion)
|
||||||
|
|
||||||
/obj/item/clothing/head/helmet/space/hardsuit/rd/equipped(mob/living/carbon/human/user, slot)
|
/obj/item/clothing/head/helmet/space/hardsuit/rd/equipped(mob/living/carbon/human/user, slot)
|
||||||
..()
|
..()
|
||||||
@@ -508,6 +509,15 @@
|
|||||||
var/datum/atom_hud/DHUD = GLOB.huds[DATA_HUD_DIAGNOSTIC_BASIC]
|
var/datum/atom_hud/DHUD = GLOB.huds[DATA_HUD_DIAGNOSTIC_BASIC]
|
||||||
DHUD.remove_hud_from(user)
|
DHUD.remove_hud_from(user)
|
||||||
|
|
||||||
|
/obj/item/clothing/head/helmet/space/hardsuit/rd/proc/sense_explosion(datum/source, turf/epicenter, devastation_range, heavy_impact_range,
|
||||||
|
light_impact_range, took, orig_dev_range, orig_heavy_range, orig_light_range)
|
||||||
|
var/turf/T = get_turf(src)
|
||||||
|
if(T.z != epicenter.z)
|
||||||
|
return
|
||||||
|
if(get_dist(epicenter, T) > explosion_detection_dist)
|
||||||
|
return
|
||||||
|
display_visor_message("Explosion detected! Epicenter: [devastation_range], Outer: [heavy_impact_range], Shock: [light_impact_range]")
|
||||||
|
|
||||||
/obj/item/clothing/suit/space/hardsuit/rd
|
/obj/item/clothing/suit/space/hardsuit/rd
|
||||||
icon_state = "hardsuit-rd"
|
icon_state = "hardsuit-rd"
|
||||||
name = "prototype hardsuit"
|
name = "prototype hardsuit"
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ In my current plan for it, 'solid' will be defined as anything with density == 1
|
|||||||
pull_force = INFINITY
|
pull_force = INFINITY
|
||||||
density = TRUE
|
density = TRUE
|
||||||
anchored = TRUE
|
anchored = TRUE
|
||||||
|
flags_1 = PREVENT_CONTENTS_EXPLOSION_1
|
||||||
var/mob/living/wizard
|
var/mob/living/wizard
|
||||||
var/z_original = 0
|
var/z_original = 0
|
||||||
var/destination
|
var/destination
|
||||||
@@ -100,9 +101,6 @@ In my current plan for it, 'solid' will be defined as anything with density == 1
|
|||||||
walk(src,0)
|
walk(src,0)
|
||||||
walk_towards(src, destination, 1)
|
walk_towards(src, destination, 1)
|
||||||
|
|
||||||
/obj/structure/closet/supplypod/prevent_content_explosion()
|
|
||||||
return TRUE
|
|
||||||
|
|
||||||
/obj/effect/immovablerod/ex_act(severity, target)
|
/obj/effect/immovablerod/ex_act(severity, target)
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
@@ -126,7 +124,10 @@ In my current plan for it, 'solid' will be defined as anything with density == 1
|
|||||||
|
|
||||||
if(isturf(clong) || isobj(clong))
|
if(isturf(clong) || isobj(clong))
|
||||||
if(clong.density)
|
if(clong.density)
|
||||||
clong.ex_act(EXPLODE_HEAVY)
|
if(isturf(clong))
|
||||||
|
SSexplosions.medturf += clong
|
||||||
|
if(isobj(clong))
|
||||||
|
SSexplosions.med_mov_atom += clong
|
||||||
|
|
||||||
else if(isliving(clong))
|
else if(isliving(clong))
|
||||||
penetrate(clong)
|
penetrate(clong)
|
||||||
|
|||||||
@@ -34,6 +34,6 @@
|
|||||||
explosion(get_turf(P), 0, 0, 2)
|
explosion(get_turf(P), 0, 0, 2)
|
||||||
// Only a level 1 explosion actually damages the machine
|
// Only a level 1 explosion actually damages the machine
|
||||||
// at all
|
// at all
|
||||||
P.ex_act(EXPLODE_DEVASTATE)
|
SSexplosions.high_mov_atom += P
|
||||||
else
|
else
|
||||||
P.emp_act(EMP_HEAVY)
|
P.emp_act(EMP_HEAVY)
|
||||||
|
|||||||
@@ -146,7 +146,13 @@
|
|||||||
quality = NEGATIVE
|
quality = NEGATIVE
|
||||||
|
|
||||||
/datum/spacevine_mutation/aggressive_spread/on_spread(obj/structure/spacevine/holder, turf/target)
|
/datum/spacevine_mutation/aggressive_spread/on_spread(obj/structure/spacevine/holder, turf/target)
|
||||||
target.ex_act(severity, null, src) // vine immunity handled at /mob/ex_act
|
switch(severity)
|
||||||
|
if(EXPLODE_DEVASTATE)
|
||||||
|
SSexplosions.highturf += target
|
||||||
|
if(EXPLODE_HEAVY)
|
||||||
|
SSexplosions.medturf += target
|
||||||
|
if(EXPLODE_LIGHT)
|
||||||
|
SSexplosions.lowturf += target
|
||||||
|
|
||||||
/datum/spacevine_mutation/aggressive_spread/on_buckle(obj/structure/spacevine/holder, mob/living/buckled)
|
/datum/spacevine_mutation/aggressive_spread/on_buckle(obj/structure/spacevine/holder, mob/living/buckled)
|
||||||
buckled.ex_act(severity, null, src)
|
buckled.ex_act(severity, null, src)
|
||||||
|
|||||||
@@ -179,7 +179,7 @@
|
|||||||
/obj/machinery/bsa/full/proc/fire(mob/user, turf/bullseye)
|
/obj/machinery/bsa/full/proc/fire(mob/user, turf/bullseye)
|
||||||
var/turf/point = get_front_turf()
|
var/turf/point = get_front_turf()
|
||||||
for(var/turf/T in getline(get_step(point,dir),get_target_turf()))
|
for(var/turf/T in getline(get_step(point,dir),get_target_turf()))
|
||||||
T.ex_act(EXPLODE_DEVASTATE)
|
SSexplosions.highturf += T //also fucks everything else on the turf
|
||||||
point.Beam(get_target_turf(),icon_state="bsa_beam",time=50,maxdistance = world.maxx) //ZZZAP
|
point.Beam(get_target_turf(),icon_state="bsa_beam",time=50,maxdistance = world.maxx) //ZZZAP
|
||||||
new /obj/effect/temp_visual/bsa_splash(point, dir)
|
new /obj/effect/temp_visual/bsa_splash(point, dir)
|
||||||
if(user.client)
|
if(user.client)
|
||||||
|
|||||||
@@ -150,7 +150,7 @@
|
|||||||
for(var/turf/T in linked)
|
for(var/turf/T in linked)
|
||||||
if(prob(30))
|
if(prob(30))
|
||||||
do_sparks(2, 1, T)
|
do_sparks(2, 1, T)
|
||||||
T.ex_act(EXPLODE_LIGHT)
|
SSexplosions.lowturf += T
|
||||||
T.hotspot_expose(1000,500,1)
|
T.hotspot_expose(1000,500,1)
|
||||||
|
|
||||||
if(!(obj_flags & EMAGGED))
|
if(!(obj_flags & EMAGGED))
|
||||||
|
|||||||
@@ -33,6 +33,17 @@
|
|||||||
beaker = null
|
beaker = null
|
||||||
update_icon()
|
update_icon()
|
||||||
|
|
||||||
|
/obj/machinery/biogenerator/contents_explosion(severity, target)
|
||||||
|
..()
|
||||||
|
if(beaker)
|
||||||
|
switch(severity)
|
||||||
|
if(EXPLODE_DEVASTATE)
|
||||||
|
SSexplosions.high_mov_atom += beaker
|
||||||
|
if(EXPLODE_HEAVY)
|
||||||
|
SSexplosions.med_mov_atom += beaker
|
||||||
|
if(EXPLODE_LIGHT)
|
||||||
|
SSexplosions.low_mov_atom += beaker
|
||||||
|
|
||||||
/obj/machinery/biogenerator/RefreshParts()
|
/obj/machinery/biogenerator/RefreshParts()
|
||||||
var/E = 0
|
var/E = 0
|
||||||
var/P = 0
|
var/P = 0
|
||||||
|
|||||||
@@ -102,7 +102,7 @@
|
|||||||
return Leap(AM)
|
return Leap(AM)
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
/obj/item/clothing/mask/facehugger/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback)
|
/obj/item/clothing/mask/facehugger/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback, quickstart = TRUE)
|
||||||
if(!..())
|
if(!..())
|
||||||
return
|
return
|
||||||
if(stat == CONSCIOUS)
|
if(stat == CONSCIOUS)
|
||||||
|
|||||||
@@ -415,9 +415,14 @@
|
|||||||
switch (severity)
|
switch (severity)
|
||||||
if (EXPLODE_DEVASTATE)
|
if (EXPLODE_DEVASTATE)
|
||||||
if(bomb_armor < EXPLODE_GIB_THRESHOLD) //gibs the mob if their bomb armor is lower than EXPLODE_GIB_THRESHOLD
|
if(bomb_armor < EXPLODE_GIB_THRESHOLD) //gibs the mob if their bomb armor is lower than EXPLODE_GIB_THRESHOLD
|
||||||
for(var/I in contents)
|
for(var/thing in contents)
|
||||||
var/atom/A = I
|
switch(severity)
|
||||||
A.ex_act(severity)
|
if(EXPLODE_DEVASTATE)
|
||||||
|
SSexplosions.high_mov_atom += thing
|
||||||
|
if(EXPLODE_HEAVY)
|
||||||
|
SSexplosions.med_mov_atom += thing
|
||||||
|
if(EXPLODE_LIGHT)
|
||||||
|
SSexplosions.low_mov_atom += thing
|
||||||
gib()
|
gib()
|
||||||
return
|
return
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -177,7 +177,7 @@
|
|||||||
for(var/obj/item/I in M.held_items)
|
for(var/obj/item/I in M.held_items)
|
||||||
if(!istype(M, /obj/item/clothing))
|
if(!istype(M, /obj/item/clothing))
|
||||||
if(prob(I.block_chance*2))
|
if(prob(I.block_chance*2))
|
||||||
return
|
return
|
||||||
|
|
||||||
/mob/living/get_photo_description(obj/item/camera/camera)
|
/mob/living/get_photo_description(obj/item/camera/camera)
|
||||||
var/list/mob_details = list()
|
var/list/mob_details = list()
|
||||||
@@ -591,7 +591,7 @@
|
|||||||
|
|
||||||
if(pulling)
|
if(pulling)
|
||||||
update_pull_movespeed()
|
update_pull_movespeed()
|
||||||
|
|
||||||
. = ..()
|
. = ..()
|
||||||
|
|
||||||
if(pulledby && moving_diagonally != FIRST_DIAG_STEP && get_dist(src, pulledby) > 1 && (pulledby != moving_from_pull))//separated from our puller and not in the middle of a diagonal move.
|
if(pulledby && moving_diagonally != FIRST_DIAG_STEP && get_dist(src, pulledby) > 1 && (pulledby != moving_from_pull))//separated from our puller and not in the middle of a diagonal move.
|
||||||
@@ -960,7 +960,7 @@
|
|||||||
return TRUE
|
return TRUE
|
||||||
return FALSE
|
return FALSE
|
||||||
|
|
||||||
/mob/living/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback)
|
/mob/living/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback, quickstart = TRUE)
|
||||||
stop_pulling()
|
stop_pulling()
|
||||||
. = ..()
|
. = ..()
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE
|
rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE
|
||||||
deathsound = 'sound/voice/borg_deathsound.ogg'
|
deathsound = 'sound/voice/borg_deathsound.ogg'
|
||||||
speech_span = SPAN_ROBOT
|
speech_span = SPAN_ROBOT
|
||||||
|
flags_1 = PREVENT_CONTENTS_EXPLOSION_1 | HEAR_1
|
||||||
|
|
||||||
var/datum/ai_laws/laws = null//Now... THEY ALL CAN ALL HAVE LAWS
|
var/datum/ai_laws/laws = null//Now... THEY ALL CAN ALL HAVE LAWS
|
||||||
var/last_lawchange_announce = 0
|
var/last_lawchange_announce = 0
|
||||||
@@ -72,9 +73,6 @@
|
|||||||
/mob/living/silicon/contents_explosion(severity, target)
|
/mob/living/silicon/contents_explosion(severity, target)
|
||||||
return
|
return
|
||||||
|
|
||||||
/mob/living/silicon/prevent_content_explosion()
|
|
||||||
return TRUE
|
|
||||||
|
|
||||||
/mob/living/silicon/proc/cancelAlarm()
|
/mob/living/silicon/proc/cancelAlarm()
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -331,7 +329,7 @@
|
|||||||
return
|
return
|
||||||
if(world.time < client.crew_manifest_delay)
|
if(world.time < client.crew_manifest_delay)
|
||||||
return
|
return
|
||||||
|
|
||||||
client.crew_manifest_delay = world.time + (1 SECONDS)
|
client.crew_manifest_delay = world.time + (1 SECONDS)
|
||||||
var/datum/browser/popup = new(src, "airoster", "Crew Manifest", 387, 420)
|
var/datum/browser/popup = new(src, "airoster", "Crew Manifest", 387, 420)
|
||||||
popup.set_content(GLOB.data_core.get_manifest_html())
|
popup.set_content(GLOB.data_core.get_manifest_html())
|
||||||
|
|||||||
@@ -474,7 +474,10 @@ Difficulty: Hard
|
|||||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/Bump(atom/A)
|
/mob/living/simple_animal/hostile/megafauna/bubblegum/Bump(atom/A)
|
||||||
if(charging)
|
if(charging)
|
||||||
if(isturf(A) || isobj(A) && A.density)
|
if(isturf(A) || isobj(A) && A.density)
|
||||||
A.ex_act(EXPLODE_HEAVY)
|
if(isobj(A))
|
||||||
|
SSexplosions.med_mov_atom += A
|
||||||
|
else
|
||||||
|
SSexplosions.medturf += A
|
||||||
DestroySurroundings()
|
DestroySurroundings()
|
||||||
if(isliving(A))
|
if(isliving(A))
|
||||||
var/mob/living/L = A
|
var/mob/living/L = A
|
||||||
|
|||||||
@@ -259,7 +259,10 @@ Difficulty: Very Hard
|
|||||||
/obj/item/projectile/colossus/on_hit(atom/target, blocked = FALSE)
|
/obj/item/projectile/colossus/on_hit(atom/target, blocked = FALSE)
|
||||||
. = ..()
|
. = ..()
|
||||||
if(isturf(target) || isobj(target))
|
if(isturf(target) || isobj(target))
|
||||||
target.ex_act(EXPLODE_HEAVY)
|
if(isobj(target))
|
||||||
|
SSexplosions.med_mov_atom += target
|
||||||
|
else
|
||||||
|
SSexplosions.medturf += target
|
||||||
|
|
||||||
/obj/item/gps/internal/colossus
|
/obj/item/gps/internal/colossus
|
||||||
icon_state = null
|
icon_state = null
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
mob_size = MOB_SIZE_HUGE
|
mob_size = MOB_SIZE_HUGE
|
||||||
layer = LARGE_MOB_LAYER //Looks weird with them slipping under mineral walls and cameras and shit otherwise
|
layer = LARGE_MOB_LAYER //Looks weird with them slipping under mineral walls and cameras and shit otherwise
|
||||||
mouse_opacity = MOUSE_OPACITY_OPAQUE // Easier to click on in melee, they're giant targets anyway
|
mouse_opacity = MOUSE_OPACITY_OPAQUE // Easier to click on in melee, they're giant targets anyway
|
||||||
|
flags_1 = PREVENT_CONTENTS_EXPLOSION_1
|
||||||
var/list/crusher_loot
|
var/list/crusher_loot
|
||||||
var/elimination = FALSE
|
var/elimination = FALSE
|
||||||
var/anger_modifier = 0
|
var/anger_modifier = 0
|
||||||
@@ -67,9 +68,6 @@
|
|||||||
return
|
return
|
||||||
return ..()
|
return ..()
|
||||||
|
|
||||||
/mob/living/simple_animal/hostile/megafauna/prevent_content_explosion()
|
|
||||||
return TRUE
|
|
||||||
|
|
||||||
/mob/living/simple_animal/hostile/megafauna/death(gibbed, var/list/force_grant)
|
/mob/living/simple_animal/hostile/megafauna/death(gibbed, var/list/force_grant)
|
||||||
if(health > 0)
|
if(health > 0)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -142,7 +142,13 @@
|
|||||||
// Minor explosions are mostly mitigitated by casing.
|
// Minor explosions are mostly mitigitated by casing.
|
||||||
/obj/machinery/modular_computer/ex_act(severity)
|
/obj/machinery/modular_computer/ex_act(severity)
|
||||||
if(cpu)
|
if(cpu)
|
||||||
cpu.ex_act(severity)
|
switch(severity)
|
||||||
|
if(EXPLODE_DEVASTATE)
|
||||||
|
SSexplosions.high_mov_atom += cpu
|
||||||
|
if(EXPLODE_HEAVY)
|
||||||
|
SSexplosions.med_mov_atom += cpu
|
||||||
|
if(EXPLODE_LIGHT)
|
||||||
|
SSexplosions.low_mov_atom += cpu
|
||||||
..()
|
..()
|
||||||
|
|
||||||
// EMPs are similar to explosions, but don't cause physical damage to the casing. Instead they screw up the components
|
// EMPs are similar to explosions, but don't cause physical damage to the casing. Instead they screw up the components
|
||||||
|
|||||||
@@ -95,8 +95,8 @@
|
|||||||
add_fingerprint(user)
|
add_fingerprint(user)
|
||||||
|
|
||||||
|
|
||||||
/obj/item/paperplane/throw_at(atom/target, range, speed, mob/thrower, spin=FALSE, diagonals_first = FALSE, datum/callback/callback)
|
/obj/item/paperplane/throw_at(atom/target, range, speed, mob/thrower, spin=FALSE, diagonals_first = FALSE, datum/callback/callback, quickstart = TRUE)
|
||||||
. = ..(target, range, speed, thrower, FALSE, diagonals_first, callback)
|
. = ..(target, range, speed, thrower, FALSE, diagonals_first, callback, quickstart = TRUE)
|
||||||
|
|
||||||
/obj/item/paperplane/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
|
/obj/item/paperplane/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
|
||||||
if(iscarbon(hit_atom))
|
if(iscarbon(hit_atom))
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
righthand_file = 'icons/mob/inhands/equipment/briefcase_righthand.dmi'
|
righthand_file = 'icons/mob/inhands/equipment/briefcase_righthand.dmi'
|
||||||
resistance_flags = FLAMMABLE
|
resistance_flags = FLAMMABLE
|
||||||
var/persistence_id
|
var/persistence_id
|
||||||
|
flags_1 = PREVENT_CONTENTS_EXPLOSION_1
|
||||||
|
|
||||||
/obj/item/storage/photo_album/Initialize()
|
/obj/item/storage/photo_album/Initialize()
|
||||||
. = ..()
|
. = ..()
|
||||||
|
|||||||
@@ -150,7 +150,7 @@
|
|||||||
|
|
||||||
|
|
||||||
/obj/item/stock_parts/cell/blob_act(obj/structure/blob/B)
|
/obj/item/stock_parts/cell/blob_act(obj/structure/blob/B)
|
||||||
ex_act(EXPLODE_DEVASTATE)
|
SSexplosions.high_mov_atom += src
|
||||||
|
|
||||||
/obj/item/stock_parts/cell/proc/get_electrocute_damage()
|
/obj/item/stock_parts/cell/proc/get_electrocute_damage()
|
||||||
if(charge >= 1000)
|
if(charge >= 1000)
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ GLOBAL_LIST_EMPTY(gravity_generators) // We will keep track of this by adding ne
|
|||||||
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
|
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
|
||||||
var/sprite_number = 0
|
var/sprite_number = 0
|
||||||
|
|
||||||
/obj/machinery/gravity_generator/safe_throw_at(atom/target, range, speed, mob/thrower, spin = TRUE, diagonals_first = FALSE, datum/callback/callback, force = MOVE_FORCE_STRONG)
|
/obj/machinery/gravity_generator/safe_throw_at(atom/target, range, speed, mob/thrower, spin = TRUE, diagonals_first = FALSE, datum/callback/callback, force = MOVE_FORCE_STRONG, quickstart = TRUE)
|
||||||
return FALSE
|
return FALSE
|
||||||
|
|
||||||
/obj/machinery/gravity_generator/ex_act(severity, target)
|
/obj/machinery/gravity_generator/ex_act(severity, target)
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
|
|||||||
icon_state = "darkmatter"
|
icon_state = "darkmatter"
|
||||||
density = TRUE
|
density = TRUE
|
||||||
anchored = TRUE
|
anchored = TRUE
|
||||||
|
flags_1 = PREVENT_CONTENTS_EXPLOSION_1
|
||||||
var/uid = 1
|
var/uid = 1
|
||||||
var/static/gl_uid = 1
|
var/static/gl_uid = 1
|
||||||
light_range = 4
|
light_range = 4
|
||||||
@@ -879,9 +880,6 @@ GLOBAL_DATUM(main_supermatter_engine, /obj/machinery/power/supermatter_crystal)
|
|||||||
/obj/machinery/power/supermatter_crystal/contents_explosion(severity, target)
|
/obj/machinery/power/supermatter_crystal/contents_explosion(severity, target)
|
||||||
return
|
return
|
||||||
|
|
||||||
/obj/machinery/power/supermatter_crystal/prevent_content_explosion()
|
|
||||||
return TRUE
|
|
||||||
|
|
||||||
/obj/machinery/power/supermatter_crystal/engine
|
/obj/machinery/power/supermatter_crystal/engine
|
||||||
is_main_engine = TRUE
|
is_main_engine = TRUE
|
||||||
|
|
||||||
|
|||||||
@@ -473,7 +473,7 @@
|
|||||||
var/turf/closed/wall/W = target
|
var/turf/closed/wall/W = target
|
||||||
W.dismantle_wall(TRUE, TRUE)
|
W.dismantle_wall(TRUE, TRUE)
|
||||||
else
|
else
|
||||||
target.ex_act(EXPLODE_HEAVY)
|
SSexplosions.medturf += target
|
||||||
return TRUE
|
return TRUE
|
||||||
if(ismovable(target))
|
if(ismovable(target))
|
||||||
var/atom/movable/AM = target
|
var/atom/movable/AM = target
|
||||||
|
|||||||
@@ -148,7 +148,13 @@
|
|||||||
if(prob(wallbreak_chance))
|
if(prob(wallbreak_chance))
|
||||||
W.dismantle_wall(TRUE, TRUE)
|
W.dismantle_wall(TRUE, TRUE)
|
||||||
else
|
else
|
||||||
loc.ex_act(amount_destruction)
|
switch(amount_destruction)
|
||||||
|
if(EXPLODE_DEVASTATE)
|
||||||
|
SSexplosions.highturf += loc
|
||||||
|
if(EXPLODE_HEAVY)
|
||||||
|
SSexplosions.medturf += loc
|
||||||
|
if(EXPLODE_LIGHT)
|
||||||
|
SSexplosions.lowturf += loc
|
||||||
else
|
else
|
||||||
qdel(src)
|
qdel(src)
|
||||||
|
|
||||||
|
|||||||
@@ -91,7 +91,10 @@
|
|||||||
/obj/item/projectile/beam/pulse/on_hit(atom/target, blocked = FALSE)
|
/obj/item/projectile/beam/pulse/on_hit(atom/target, blocked = FALSE)
|
||||||
. = ..()
|
. = ..()
|
||||||
if (!QDELETED(target) && (isturf(target) || istype(target, /obj/structure/)))
|
if (!QDELETED(target) && (isturf(target) || istype(target, /obj/structure/)))
|
||||||
target.ex_act(EXPLODE_HEAVY)
|
if(isobj(target))
|
||||||
|
SSexplosions.med_mov_atom += target
|
||||||
|
else
|
||||||
|
SSexplosions.medturf += target
|
||||||
|
|
||||||
/obj/item/projectile/beam/pulse/shotgun
|
/obj/item/projectile/beam/pulse/shotgun
|
||||||
damage = 40
|
damage = 40
|
||||||
|
|||||||
@@ -11,7 +11,10 @@
|
|||||||
if(A == firer)
|
if(A == firer)
|
||||||
forceMove(A.loc)
|
forceMove(A.loc)
|
||||||
return
|
return
|
||||||
A.ex_act(EXPLODE_HEAVY)
|
if(isobj(A))
|
||||||
|
SSexplosions.med_mov_atom += A
|
||||||
|
else if(isturf(A))
|
||||||
|
SSexplosions.medturf += A
|
||||||
playsound(src.loc, 'sound/effects/meteorimpact.ogg', 40, 1)
|
playsound(src.loc, 'sound/effects/meteorimpact.ogg', 40, 1)
|
||||||
for(var/mob/M in urange(10, src))
|
for(var/mob/M in urange(10, src))
|
||||||
if(!M.stat)
|
if(!M.stat)
|
||||||
|
|||||||
@@ -152,7 +152,13 @@
|
|||||||
/obj/machinery/chem_dispenser/contents_explosion(severity, target)
|
/obj/machinery/chem_dispenser/contents_explosion(severity, target)
|
||||||
..()
|
..()
|
||||||
if(beaker)
|
if(beaker)
|
||||||
beaker.ex_act(severity, target)
|
switch(severity)
|
||||||
|
if(EXPLODE_DEVASTATE)
|
||||||
|
SSexplosions.high_mov_atom += beaker
|
||||||
|
if(EXPLODE_HEAVY)
|
||||||
|
SSexplosions.med_mov_atom += beaker
|
||||||
|
if(EXPLODE_LIGHT)
|
||||||
|
SSexplosions.low_mov_atom += beaker
|
||||||
|
|
||||||
/obj/machinery/chem_dispenser/handle_atom_del(atom/A)
|
/obj/machinery/chem_dispenser/handle_atom_del(atom/A)
|
||||||
..()
|
..()
|
||||||
|
|||||||
@@ -53,9 +53,21 @@
|
|||||||
/obj/machinery/chem_master/contents_explosion(severity, target)
|
/obj/machinery/chem_master/contents_explosion(severity, target)
|
||||||
..()
|
..()
|
||||||
if(beaker)
|
if(beaker)
|
||||||
beaker.ex_act(severity, target)
|
switch(severity)
|
||||||
|
if(EXPLODE_DEVASTATE)
|
||||||
|
SSexplosions.high_mov_atom += beaker
|
||||||
|
if(EXPLODE_HEAVY)
|
||||||
|
SSexplosions.med_mov_atom += beaker
|
||||||
|
if(EXPLODE_LIGHT)
|
||||||
|
SSexplosions.low_mov_atom += beaker
|
||||||
if(bottle)
|
if(bottle)
|
||||||
bottle.ex_act(severity, target)
|
switch(severity)
|
||||||
|
if(EXPLODE_DEVASTATE)
|
||||||
|
SSexplosions.high_mov_atom += bottle
|
||||||
|
if(EXPLODE_HEAVY)
|
||||||
|
SSexplosions.med_mov_atom += bottle
|
||||||
|
if(EXPLODE_LIGHT)
|
||||||
|
SSexplosions.low_mov_atom += bottle
|
||||||
|
|
||||||
/obj/machinery/chem_master/handle_atom_del(atom/A)
|
/obj/machinery/chem_master/handle_atom_del(atom/A)
|
||||||
..()
|
..()
|
||||||
|
|||||||
@@ -46,7 +46,13 @@
|
|||||||
|
|
||||||
/obj/machinery/reagentgrinder/contents_explosion(severity, target)
|
/obj/machinery/reagentgrinder/contents_explosion(severity, target)
|
||||||
if(container)
|
if(container)
|
||||||
container.ex_act(severity, target)
|
switch(severity)
|
||||||
|
if(EXPLODE_DEVASTATE)
|
||||||
|
SSexplosions.high_mov_atom += container
|
||||||
|
if(EXPLODE_HEAVY)
|
||||||
|
SSexplosions.med_mov_atom += container
|
||||||
|
if(EXPLODE_LIGHT)
|
||||||
|
SSexplosions.low_mov_atom += container
|
||||||
|
|
||||||
/obj/machinery/reagentgrinder/RefreshParts()
|
/obj/machinery/reagentgrinder/RefreshParts()
|
||||||
speed = 1
|
speed = 1
|
||||||
|
|||||||
@@ -19,8 +19,14 @@
|
|||||||
return ..()
|
return ..()
|
||||||
|
|
||||||
/obj/structure/bigDelivery/contents_explosion(severity, target)
|
/obj/structure/bigDelivery/contents_explosion(severity, target)
|
||||||
for(var/atom/movable/AM in contents)
|
for(var/thing in contents)
|
||||||
AM.ex_act()
|
switch(severity)
|
||||||
|
if(EXPLODE_DEVASTATE)
|
||||||
|
SSexplosions.high_mov_atom += thing
|
||||||
|
if(EXPLODE_HEAVY)
|
||||||
|
SSexplosions.med_mov_atom += thing
|
||||||
|
if(EXPLODE_LIGHT)
|
||||||
|
SSexplosions.low_mov_atom += thing
|
||||||
|
|
||||||
/obj/structure/bigDelivery/attackby(obj/item/W, mob/user, params)
|
/obj/structure/bigDelivery/attackby(obj/item/W, mob/user, params)
|
||||||
if(istype(W, /obj/item/destTagger))
|
if(istype(W, /obj/item/destTagger))
|
||||||
@@ -84,8 +90,14 @@
|
|||||||
var/sortTag = 0
|
var/sortTag = 0
|
||||||
|
|
||||||
/obj/item/smallDelivery/contents_explosion(severity, target)
|
/obj/item/smallDelivery/contents_explosion(severity, target)
|
||||||
for(var/atom/movable/AM in contents)
|
for(var/thing in contents)
|
||||||
AM.ex_act()
|
switch(severity)
|
||||||
|
if(EXPLODE_DEVASTATE)
|
||||||
|
SSexplosions.high_mov_atom += thing
|
||||||
|
if(EXPLODE_HEAVY)
|
||||||
|
SSexplosions.med_mov_atom += thing
|
||||||
|
if(EXPLODE_LIGHT)
|
||||||
|
SSexplosions.low_mov_atom += thing
|
||||||
|
|
||||||
/obj/item/smallDelivery/attack_self(mob/user)
|
/obj/item/smallDelivery/attack_self(mob/user)
|
||||||
user.temporarilyRemoveItemFromInventory(src, TRUE)
|
user.temporarilyRemoveItemFromInventory(src, TRUE)
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ All ShuttleMove procs go here
|
|||||||
/turf/proc/afterShuttleMove(turf/oldT, rotation)
|
/turf/proc/afterShuttleMove(turf/oldT, rotation)
|
||||||
//Dealing with the turf we left behind
|
//Dealing with the turf we left behind
|
||||||
oldT.TransferComponents(src)
|
oldT.TransferComponents(src)
|
||||||
|
SSexplosions.wipe_turf(src)
|
||||||
var/shuttle_boundary = baseturfs.Find(/turf/baseturf_skipover/shuttle)
|
var/shuttle_boundary = baseturfs.Find(/turf/baseturf_skipover/shuttle)
|
||||||
if(shuttle_boundary)
|
if(shuttle_boundary)
|
||||||
oldT.ScrapeAway(baseturfs.len - shuttle_boundary + 1)
|
oldT.ScrapeAway(baseturfs.len - shuttle_boundary + 1)
|
||||||
@@ -251,7 +252,7 @@ All ShuttleMove procs go here
|
|||||||
A.atmosinit()
|
A.atmosinit()
|
||||||
if(A.returnPipenet())
|
if(A.returnPipenet())
|
||||||
A.addMember(src)
|
A.addMember(src)
|
||||||
build_network()
|
SSair.add_to_rebuild_queue(src)
|
||||||
else
|
else
|
||||||
// atmosinit() calls update_icon(), so we don't need to call it
|
// atmosinit() calls update_icon(), so we don't need to call it
|
||||||
update_icon()
|
update_icon()
|
||||||
|
|||||||
@@ -287,7 +287,7 @@
|
|||||||
var/mob/living/M = AM
|
var/mob/living/M = AM
|
||||||
M.Paralyze(stun_amt)
|
M.Paralyze(stun_amt)
|
||||||
to_chat(M, "<span class='userdanger'>You're thrown back by [user]!</span>")
|
to_chat(M, "<span class='userdanger'>You're thrown back by [user]!</span>")
|
||||||
AM.safe_throw_at(throwtarget, ((clamp((maxthrow - (clamp(distfromcaster - 2, 0, distfromcaster))), 3, maxthrow))), 1,user, force = repulse_force)//So stuff gets tossed around at the same time.
|
AM.safe_throw_at(throwtarget, ((clamp((maxthrow - (clamp(distfromcaster - 2, 0, distfromcaster))), 3, maxthrow))), 1,user, force = repulse_force, quickstart = TRUE)//So stuff gets tossed around at the same time.
|
||||||
|
|
||||||
/obj/effect/proc_holder/spell/aoe_turf/repulse/xeno //i fixed conflicts only to find out that this is in the WIZARD file instead of the xeno file?!
|
/obj/effect/proc_holder/spell/aoe_turf/repulse/xeno //i fixed conflicts only to find out that this is in the WIZARD file instead of the xeno file?!
|
||||||
name = "Tail Sweep"
|
name = "Tail Sweep"
|
||||||
@@ -364,7 +364,7 @@
|
|||||||
M.electrocute_act(80, src, illusion = 1)
|
M.electrocute_act(80, src, illusion = 1)
|
||||||
qdel(src)
|
qdel(src)
|
||||||
|
|
||||||
/obj/item/spellpacket/lightningbolt/throw_at(atom/target, range, speed, mob/thrower, spin=TRUE, diagonals_first = FALSE, datum/callback/callback, force = INFINITY)
|
/obj/item/spellpacket/lightningbolt/throw_at(atom/target, range, speed, mob/thrower, spin=TRUE, diagonals_first = FALSE, datum/callback/callback, force = INFINITY, quickstart = TRUE)
|
||||||
. = ..()
|
. = ..()
|
||||||
if(ishuman(thrower))
|
if(ishuman(thrower))
|
||||||
var/mob/living/carbon/human/H = thrower
|
var/mob/living/carbon/human/H = thrower
|
||||||
|
|||||||
@@ -115,7 +115,7 @@
|
|||||||
var/mob/living/silicon/borg = target
|
var/mob/living/silicon/borg = target
|
||||||
borg.adjustBruteLoss(melee_damage_lower)
|
borg.adjustBruteLoss(melee_damage_lower)
|
||||||
return ..()
|
return ..()
|
||||||
|
|
||||||
/mob/living/simple_animal/hostile/swarmer/MiddleClickOn(atom/A)
|
/mob/living/simple_animal/hostile/swarmer/MiddleClickOn(atom/A)
|
||||||
. = ..()
|
. = ..()
|
||||||
if(!LAZYLEN(dronelist))
|
if(!LAZYLEN(dronelist))
|
||||||
@@ -199,7 +199,7 @@
|
|||||||
new /obj/effect/temp_visual/swarmer/disintegration(get_turf(target))
|
new /obj/effect/temp_visual/swarmer/disintegration(get_turf(target))
|
||||||
do_attack_animation(target)
|
do_attack_animation(target)
|
||||||
changeNext_move(CLICK_CD_MELEE)
|
changeNext_move(CLICK_CD_MELEE)
|
||||||
target.ex_act(EXPLODE_LIGHT)
|
SSexplosions.low_mov_atom += target
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when a swarmer attempts to teleport a living entity away
|
* Called when a swarmer attempts to teleport a living entity away
|
||||||
@@ -220,9 +220,9 @@
|
|||||||
|
|
||||||
if(!do_mob(src, target, 30))
|
if(!do_mob(src, target, 30))
|
||||||
return
|
return
|
||||||
|
|
||||||
teleport_target(target)
|
teleport_target(target)
|
||||||
|
|
||||||
/mob/living/simple_animal/hostile/swarmer/proc/teleport_target(mob/living/target)
|
/mob/living/simple_animal/hostile/swarmer/proc/teleport_target(mob/living/target)
|
||||||
var/turf/open/floor/safe_turf = find_safe_turf(zlevels = z, extended_safety_checks = TRUE)
|
var/turf/open/floor/safe_turf = find_safe_turf(zlevels = z, extended_safety_checks = TRUE)
|
||||||
|
|
||||||
@@ -416,7 +416,7 @@
|
|||||||
// TODO get swarmers their own colour rather than just boldtext
|
// TODO get swarmers their own colour rather than just boldtext
|
||||||
if(message)
|
if(message)
|
||||||
swarmer_chat(message)
|
swarmer_chat(message)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes a drone from the swarmer's list.
|
* Removes a drone from the swarmer's list.
|
||||||
*
|
*
|
||||||
@@ -440,7 +440,7 @@ mob/living/simple_animal/hostile/swarmer/proc/remove_drone(mob/drone, force)
|
|||||||
AIStatus = AI_ON
|
AIStatus = AI_ON
|
||||||
melee_damage_lower = 30
|
melee_damage_lower = 30
|
||||||
melee_damage_upper = 30
|
melee_damage_upper = 30
|
||||||
|
|
||||||
/obj/item/projectile/beam/disabler/swarmer/on_hit(atom/target, blocked = FALSE)
|
/obj/item/projectile/beam/disabler/swarmer/on_hit(atom/target, blocked = FALSE)
|
||||||
. = ..()
|
. = ..()
|
||||||
if(!.)
|
if(!.)
|
||||||
|
|||||||
BIN
sound/effects/creak1.ogg
Normal file
BIN
sound/effects/creak1.ogg
Normal file
Binary file not shown.
BIN
sound/effects/creak2.ogg
Normal file
BIN
sound/effects/creak2.ogg
Normal file
Binary file not shown.
BIN
sound/effects/creak3.ogg
Normal file
BIN
sound/effects/creak3.ogg
Normal file
Binary file not shown.
BIN
sound/effects/explosioncreak1.ogg
Normal file
BIN
sound/effects/explosioncreak1.ogg
Normal file
Binary file not shown.
BIN
sound/effects/explosioncreak2.ogg
Normal file
BIN
sound/effects/explosioncreak2.ogg
Normal file
Binary file not shown.
@@ -266,6 +266,7 @@
|
|||||||
#include "code\controllers\subsystem\disease.dm"
|
#include "code\controllers\subsystem\disease.dm"
|
||||||
#include "code\controllers\subsystem\economy.dm"
|
#include "code\controllers\subsystem\economy.dm"
|
||||||
#include "code\controllers\subsystem\events.dm"
|
#include "code\controllers\subsystem\events.dm"
|
||||||
|
#include "code\controllers\subsystem\explosions.dm"
|
||||||
#include "code\controllers\subsystem\fire_burning.dm"
|
#include "code\controllers\subsystem\fire_burning.dm"
|
||||||
#include "code\controllers\subsystem\garbage.dm"
|
#include "code\controllers\subsystem\garbage.dm"
|
||||||
#include "code\controllers\subsystem\icon_smooth.dm"
|
#include "code\controllers\subsystem\icon_smooth.dm"
|
||||||
@@ -337,7 +338,6 @@
|
|||||||
#include "code\datums\embedding_behavior.dm"
|
#include "code\datums\embedding_behavior.dm"
|
||||||
#include "code\datums\emotes.dm"
|
#include "code\datums\emotes.dm"
|
||||||
#include "code\datums\ert.dm"
|
#include "code\datums\ert.dm"
|
||||||
#include "code\datums\explosion.dm"
|
|
||||||
#include "code\datums\forced_movement.dm"
|
#include "code\datums\forced_movement.dm"
|
||||||
#include "code\datums\holocall.dm"
|
#include "code\datums\holocall.dm"
|
||||||
#include "code\datums\http.dm"
|
#include "code\datums\http.dm"
|
||||||
|
|||||||
@@ -57,7 +57,7 @@
|
|||||||
throw_at(thrownby, throw_range+3, throw_speed, null)
|
throw_at(thrownby, throw_range+3, throw_speed, null)
|
||||||
..()
|
..()
|
||||||
|
|
||||||
/obj/item/toy/boomerang/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback, force)
|
/obj/item/toy/boomerang/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback, force, quickstart = TRUE)
|
||||||
if(iscarbon(thrower))
|
if(iscarbon(thrower))
|
||||||
var/mob/living/carbon/C = thrower
|
var/mob/living/carbon/C = thrower
|
||||||
C.throw_mode_on()
|
C.throw_mode_on()
|
||||||
|
|||||||
Reference in New Issue
Block a user