diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index f562f6b913c4..364e06aecb1c 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -1588,6 +1588,7 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new) //gives us the stack trace from CRASH() without ending the current proc. /proc/stack_trace(msg) + message_admins(msg) CRASH(msg) // \ref behaviour got changed in 512 so this is necesary to replicate old behaviour. diff --git a/code/datums/autocells/auto_cell.dm b/code/datums/autocells/auto_cell.dm index fb679c56676e..a08ceba2f6fb 100644 --- a/code/datums/autocells/auto_cell.dm +++ b/code/datums/autocells/auto_cell.dm @@ -21,20 +21,19 @@ // This affects what neighbors you'll get passed in update_state() var/neighbor_type = NEIGHBORS_CARDINAL -/datum/automata_cell/New(turf/T) +/datum/automata_cell/New(turf/location) ..() - if(!istype(T)) + if(!isturf(location)) qdel(src) return - // Attempt to merge the two cells if they end up in the same turf - var/datum/automata_cell/C = T.get_cell(type) - if(C && merge(C)) - qdel(src) - return + // Attempt to merge two cells if they end up in the same turf + var/datum/automata_cell/existing_cell = location.get_cell(type) + if(!merge(existing_cell)) + return // We didn't survive - in_turf = T + in_turf = location LAZYADD(in_turf.autocells, src) GLOB.cellauto_cells += src @@ -44,9 +43,8 @@ /datum/automata_cell/Destroy() . = ..() - if(!QDELETED(in_turf)) - LAZYREMOVE(in_turf.autocells, src) - in_turf = null + LAZYREMOVE(in_turf?.autocells, src) + in_turf = null GLOB.cellauto_cells -= src @@ -65,17 +63,15 @@ if(QDELETED(new_turf)) return - if(!QDELETED(in_turf)) - LAZYREMOVE(in_turf.autocells, src) - in_turf = null + LAZYREMOVE(in_turf?.autocells, src) in_turf = new_turf LAZYADD(in_turf.autocells, src) -// Use this proc to merge this cell with another one if the other cell enters the same turf -// Return TRUE if this cell should survive the merge (the other one will die/be qdeleted) -// Return FALSE if this cell should die and be replaced by the other cell -/datum/automata_cell/proc/merge(datum/automata_cell/other_cell) +/// Use this proc to merge this cell with another one if the other cell enters the same turf +/// Returns TRUE if this cell should survive the merge (the other one will die/be qdeleted) +/// Returns FALSE if this cell died and is replaced by the other cell +/datum/automata_cell/proc/merge(datum/automata_cell/other) return TRUE // Returns a list of neighboring cells diff --git a/code/datums/autocells/explosion.dm b/code/datums/autocells/explosion.dm index 706e75623b71..37fc8deaffa9 100644 --- a/code/datums/autocells/explosion.dm +++ b/code/datums/autocells/explosion.dm @@ -79,20 +79,31 @@ /datum/automata_cell/explosion/death() if(shockwave) qdel(shockwave) + exploded_atoms.Cut() + +/datum/automata_cell/explosion/propagate(dir) + var/datum/automata_cell/explosion/new_cell = ..() + new_cell?.exploded_atoms += exploded_atoms + return new_cell + +// Attempts to merge explosions. Will compare directions to determine effects on power. +// If the other explosion is traveling in the same direction, the explosion is amplified. +// If not, it's weakened +// Returns TRUE if this explosion survived. +/datum/automata_cell/explosion/merge(datum/automata_cell/explosion/other) + if(QDELETED(other)) + return TRUE -// Compare directions. If the other explosion is traveling in the same direction, -// the explosion is amplified. If not, it's weakened -/datum/automata_cell/explosion/merge(datum/automata_cell/explosion/E) // Non-merging explosions take priority - if(!should_merge) + if(!should_merge || !other.should_merge) return TRUE // The strongest of the two explosions should survive the merge // This prevents a weaker explosion merging with a strong one, // the strong one removing all the weaker one's power and just killing the explosion - var/is_stronger = (power >= E.power) - var/datum/automata_cell/explosion/survivor = is_stronger ? src : E - var/datum/automata_cell/explosion/dying = is_stronger ? E : src + var/is_stronger = (power >= other.power) + var/datum/automata_cell/explosion/survivor = is_stronger ? src : other + var/datum/automata_cell/explosion/dying = is_stronger ? other : src // Two epicenters merging, or a new epicenter merging with a traveling wave if((!survivor.direction && !dying.direction) || (survivor.direction && !dying.direction)) @@ -109,11 +120,14 @@ // Two waves traveling the same direction amplifies the explosion if(survivor.direction == dying.direction) survivor.power += dying.power + survivor.exploded_atoms |= dying.exploded_atoms // Two waves travling towards each other weakens the explosion if(survivor.direction == GLOB.reverse_dir[dying.direction]) survivor.power -= dying.power + qdel(dying) + return is_stronger // Get a list of all directions the explosion should propagate to before dying @@ -145,19 +159,19 @@ return // The resistance here will affect the damage taken and the falloff in the propagated explosion var/resistance = max(0, in_turf.get_explosion_resistance(direction)) - for(var/atom/A in in_turf) - resistance += max(0, A.get_explosion_resistance()) + for(var/atom/thing in in_turf) + resistance += max(0, thing.get_explosion_resistance()) // Blow stuff up INVOKE_ASYNC(in_turf, TYPE_PROC_REF(/atom, ex_act), power, direction, explosion_cause_data, 0, enviro) - for(var/atom/A in in_turf) - if(A in exploded_atoms) + for(var/atom/thing in in_turf) + if(thing.gc_destroyed) continue - if(A.gc_destroyed) + if(thing in exploded_atoms) continue - INVOKE_ASYNC(A, TYPE_PROC_REF(/atom, ex_act), power, direction, explosion_cause_data, 0, enviro) - exploded_atoms += A - log_explosion(A, src) + exploded_atoms += thing + INVOKE_ASYNC(thing, TYPE_PROC_REF(/atom, ex_act), power, direction, explosion_cause_data, 0, enviro) + log_explosion(thing, src) var/reflected = FALSE @@ -231,20 +245,20 @@ When the cell processes, we simply don't blow up atoms that were tracked as having entered the turf. */ -/datum/automata_cell/explosion/proc/on_turf_entered(atom/movable/A) +/datum/automata_cell/explosion/proc/on_turf_entered(atom/movable/thing) // Once is enough - if(A in exploded_atoms) + if(thing.gc_destroyed) + return + if(thing in exploded_atoms) return - exploded_atoms += A + exploded_atoms += thing // Note that we don't want to make it a directed ex_act because // it could toss them back and make them get hit by the explosion again - if(A.gc_destroyed) - return - - INVOKE_ASYNC(A, TYPE_PROC_REF(/atom, ex_act), power, null, explosion_cause_data, 0, enviro) - log_explosion(A, src) + // so we indicate this with a direction < 0 + INVOKE_ASYNC(thing, TYPE_PROC_REF(/atom, ex_act), power, -1, explosion_cause_data, 0, enviro) + log_explosion(thing, src) // I'll admit most of the code from here on out is basically just copypasta from DOREC diff --git a/code/datums/components/_component.dm b/code/datums/components/_component.dm index 185a540e7ad3..2be44825bc09 100644 --- a/code/datums/components/_component.dm +++ b/code/datums/components/_component.dm @@ -197,10 +197,10 @@ else if(lookup[sig_type] == src) // We already registered here continue else if(!length(lookup[sig_type])) // One other thing registered here - lookup[sig_type] = list(lookup[sig_type]=TRUE) - lookup[sig_type][src] = TRUE + lookup[sig_type] = list(lookup[sig_type]) + lookup[sig_type] += src else // Many other things have registered here - lookup[sig_type][src] = TRUE + lookup[sig_type] += src signal_enabled = TRUE diff --git a/code/datums/components/weed_food.dm b/code/datums/components/weed_food.dm index e2f0d0b46a63..cb5aa6527640 100644 --- a/code/datums/components/weed_food.dm +++ b/code/datums/components/weed_food.dm @@ -93,6 +93,7 @@ RegisterSignal(parent_mob, COMSIG_LIVING_PREIGNITION, PROC_REF(on_preignition)) RegisterSignal(SSdcs, COMSIG_GLOB_GROUNDSIDE_FORSAKEN_HANDLING, PROC_REF(on_forsaken)) if(parent_turf) + message_admins("[\ref(src)] at [COORD(parent_mob)] RegisterWithParent: Registered [parent_turf] [\ref(parent_turf)] at [COORD(parent_turf)]") RegisterSignal(parent_turf, COMSIG_WEEDNODE_GROWTH, PROC_REF(on_update)) /datum/component/weed_food/UnregisterFromParent() @@ -108,6 +109,7 @@ if(absorbing_weeds) UnregisterSignal(absorbing_weeds, COMSIG_PARENT_QDELETING) if(parent_turf) + message_admins("[\ref(src)] at [COORD(parent_mob)] UnregisterFromParent: Unregistered [parent_turf] [\ref(parent_turf)] at [COORD(parent_turf)]") UnregisterSignal(parent_turf, COMSIG_WEEDNODE_GROWTH) if(parent_buckle) UnregisterSignal(parent_buckle, COMSIG_OBJ_AFTER_BUCKLE) @@ -124,11 +126,13 @@ absorbing_weeds = null if(parent_turf) + message_admins("[\ref(src)] at [COORD(parent_mob)] on_move: Unregistered [parent_turf] [\ref(parent_turf)] at [COORD(parent_turf)]") UnregisterSignal(parent_turf, COMSIG_WEEDNODE_GROWTH) parent_turf = get_turf(parent_mob) if(parent_turf != parent_mob.loc) parent_turf = null // if our location is actually a container, we want to be safe from weeds else + message_admins("[\ref(src)] at [COORD(parent_mob)] on_move: Registered [parent_turf] [\ref(parent_turf)] at [COORD(parent_turf)]") RegisterSignal(parent_turf, COMSIG_WEEDNODE_GROWTH, PROC_REF(on_update)) // We moved, restart or start the proccess diff --git a/code/game/machinery/medical_pod/bodyscanner.dm b/code/game/machinery/medical_pod/bodyscanner.dm index cede827c9dfa..d0ac201afb86 100644 --- a/code/game/machinery/medical_pod/bodyscanner.dm +++ b/code/game/machinery/medical_pod/bodyscanner.dm @@ -46,10 +46,10 @@ return go_out() -/obj/structure/machinery/medical_pod/bodyscanner/ex_act(severity, datum/cause_data/cause_data) +/obj/structure/machinery/medical_pod/bodyscanner/ex_act(severity, direction, datum/cause_data/cause_data) for(var/atom/movable/A as mob|obj in src) A.forceMove(loc) - A.ex_act(severity, , cause_data) + A.ex_act(severity, cause_data=cause_data) switch(severity) if(0 to EXPLOSION_THRESHOLD_LOW) if (prob(25)) diff --git a/code/game/machinery/vending/vendor_types/medical.dm b/code/game/machinery/vending/vendor_types/medical.dm index c502bbf875c5..9ac095133559 100644 --- a/code/game/machinery/vending/vendor_types/medical.dm +++ b/code/game/machinery/vending/vendor_types/medical.dm @@ -15,7 +15,7 @@ unacidable = TRUE /obj/structure/medical_supply_link/ex_act(severity, direction) - return FALSE + return /obj/structure/medical_supply_link/Initialize() . = ..() diff --git a/code/game/objects/explosion_recursive.dm b/code/game/objects/explosion_recursive.dm index f8836f5dad81..a3265b17d9dd 100644 --- a/code/game/objects/explosion_recursive.dm +++ b/code/game/objects/explosion_recursive.dm @@ -26,6 +26,54 @@ For explosion resistance, an explosion should never go through a wall or window explosion resistance exactly as much as their health */ +GLOBAL_VAR_INIT(create_and_destroy_ignore_paths2, generate_ignore_paths2()) +/proc/generate_ignore_paths2() + . = list( + //Never meant to be created, errors out the ass for mobcode reasons + /mob/living/carbon, + /obj/effect/node, + /obj/item/seeds/cutting, + //lighting singleton + /mob/dview, + // These use walk_away() after initialization, which causes false positives + /obj/item/explosive/grenade/flashbang/cluster/segment, + /obj/item/explosive/grenade/flashbang/cluster_piece, + /mob/living/simple_animal/hostile/retaliate/giant_lizard, + /obj/effect/landmark/lizard_spawn, + /obj/effect/fake_attacker, + /atom/movable/lighting_mask, //leave it alone + //This is meant to fail extremely loud every single time it occurs in any environment in any context, and it falsely alarms when this unit test iterates it. Let's not spawn it in. + /obj/merge_conflict_marker, + /obj/effect/projector_anchor, // Needs a link ID set to work as intended + /obj/effect/projector/linked, // Needs a link ID set to work as intended + ) + //This turf existing is an error in and of itself + . += typesof(/turf/baseturf_skipover) + . += typesof(/turf/baseturf_bottom) + //Our system doesn't support it without warning spam from unregister calls on things that never registered + . += typesof(/obj/docking_port) + . += typesof(/obj/item/storage/internal) + // fuck interiors + . += typesof(/obj/vehicle) + . += typesof(/obj/effect/vehicle_spawner) + // Always ought to have an associated escape menu. Any references it could possibly hold would need one regardless. + . += subtypesof(/atom/movable/screen/escape_menu) + . += typesof(/obj/effect/timed_event) + // Need a defined ID, mapping-only, will and should fail loudly if spawned without one + . += typesof(/obj/effect/landmark/dispersal_initiator) + +/mob/verb/explosion_test() + set name = "Explosion Test" + set category = "Debug" + + var/turf/location = get_turf(usr) + var/mob/living/carbon/human/body = new(location) + body.death() + cell_explosion(location, 60, 20, EXPLOSION_FALLOFF_SHAPE_LINEAR, SOUTH, create_cause_data("testing")) + cell_explosion(location, 60, 20, EXPLOSION_FALLOFF_SHAPE_LINEAR, SOUTH, create_cause_data("testing")) + for(var/turf/turf_path as anything in subtypesof(/turf) - GLOB.create_and_destroy_ignore_paths2) + location = location.ChangeTurf(turf_path) + /proc/explosion_rec(turf/epicenter, power, falloff = 20, datum/cause_data/explosion_cause_data) var/obj/effect/explosion/Controller = new /obj/effect/explosion(epicenter) Controller.initiate_explosion(epicenter, power, falloff, explosion_cause_data) @@ -325,19 +373,21 @@ explosion resistance exactly as much as their health if(anchored) return - if(!istype(src.loc, /turf)) + if(!isturf(loc)) return + if(direction < 0) + return // Don't do anything if explicitly directionless + + var/range = min(round(severity/w_class * 0.2, 1), 14) + if(!direction) direction = pick(GLOB.alldirs) - var/range = min(round(severity/src.w_class * 0.2, 1), 14) - if(!direction) - range = round( range/2 ,1) + range = round(range/2, 1) if(range < 1) return - var/speed = max(range*2.5, SPEED_SLOW) var/atom/target = get_ranged_target_turf(src, direction, range) @@ -345,20 +395,21 @@ explosion resistance exactly as much as their health var/scatter = range/4 * scatter_multiplier var/scatter_x = rand(-scatter,scatter) var/scatter_y = rand(-scatter,scatter) - target = locate(target.x + round( scatter_x , 1),target.y + round( scatter_y , 1),target.z) //Locate an adjacent turf. + target = locate(target.x + round(scatter_x , 1), target.y + round(scatter_y , 1), target.z) //Locate an adjacent turf. //time for the explosion to destroy windows, walls, etc which might be in the way INVOKE_ASYNC(src, TYPE_PROC_REF(/atom/movable, throw_atom), target, range, speed, null, TRUE) - return - /mob/proc/explosion_throw(severity, direction) if(anchored) return - if(!istype(src.loc, /turf)) + if(!isturf(loc)) return + if(direction < 0) + return // Don't do anything if explicitly directionless + var/weight = 1 switch(mob_size) if(MOB_SIZE_SMALL) diff --git a/code/game/objects/shrapnel.dm b/code/game/objects/shrapnel.dm index 6b39bcb05fb7..65c210c3a97c 100644 --- a/code/game/objects/shrapnel.dm +++ b/code/game/objects/shrapnel.dm @@ -1,5 +1,7 @@ /proc/create_shrapnel(turf/epicenter, shrapnel_number = 10, shrapnel_direction, shrapnel_spread = 45, datum/ammo/shrapnel_type = /datum/ammo/bullet/shrapnel, datum/cause_data/cause_data, ignore_source_mob = FALSE, on_hit_coefficient = 0.15, use_shrapnel_angle = FALSE) + if(shrapnel_direction < 0) + return // Don't do anything if explicitly directionless epicenter = get_turf(epicenter) diff --git a/code/game/turfs/closed.dm b/code/game/turfs/closed.dm index 5aca4ac781ab..99a8ea9dd997 100644 --- a/code/game/turfs/closed.dm +++ b/code/game/turfs/closed.dm @@ -88,7 +88,7 @@ thing.forceMove(above_current) return -/turf/closed/Enter(atom/movable/mover, atom/forget) +/turf/closed/Enter(atom/movable/mover, atom/old_loc) . = ..() if(!mover.move_intentionally || !istype(mover,/mob/living)) return diff --git a/code/game/turfs/open.dm b/code/game/turfs/open.dm index 9cbfae93835e..f66560e3fd82 100644 --- a/code/game/turfs/open.dm +++ b/code/game/turfs/open.dm @@ -165,12 +165,12 @@ icon_state = "grass1" is_weedable = NOT_WEEDABLE -/turf/open/slippery/Enter(atom/movable/mover, atom/forget) +/turf/open/slippery/Enter(atom/movable/mover, atom/old_loc) . = ..() if(isliving(mover)) return FALSE -/turf/open/slippery/Entered(atom/movable/crosser) +/turf/open/slippery/Entered(atom/movable/crosser, atom/old_loc) . = ..() if(isobserver(crosser) || crosser.anchored) return @@ -178,7 +178,10 @@ if(!(isitem(crosser) || isliving(crosser))) return - INVOKE_ASYNC(crosser, TYPE_PROC_REF(/atom/movable, throw_atom), (get_step(src, dir)), 50, SPEED_FAST, null, TRUE) + if(old_loc != src) + INVOKE_ASYNC(crosser, TYPE_PROC_REF(/atom/movable, throw_atom), (get_step(src, dir)), 50, SPEED_FAST, null, TRUE) + else + INVOKE_NEXT_TICK(crosser, TYPE_PROC_REF(/atom/movable, throw_atom), (get_step(src, dir)), 50, SPEED_FAST, null, TRUE) /turf/open/slippery/hull name = "sloped roof" @@ -853,28 +856,28 @@ default_name = "deep ocean" allow_construction = FALSE -/turf/open/gm/river/ocean/Entered(atom/movable/AM) +/turf/open/gm/river/ocean/Entered(atom/movable/entered_movable, atom/old_loc) . = ..() - if(prob(20)) // fuck you - if(!ismob(AM)) + if(old_loc != src && prob(20)) // fuck you + if(!ismob(entered_movable)) return - var/mob/unlucky_mob = AM - var/turf/target_turf = get_random_turf_in_range(AM, 3, 0) - var/datum/launch_metadata/LM = new() - LM.target = target_turf - LM.range = get_dist(AM.loc, target_turf) - LM.speed = SPEED_FAST - LM.thrower = unlucky_mob - LM.spin = TRUE - LM.pass_flags = NO_FLAGS + var/mob/unlucky_mob = entered_movable + var/turf/target_turf = get_random_turf_in_range(entered_movable, 3, 0) + var/datum/launch_metadata/launch = new() + launch.target = target_turf + launch.range = get_dist(entered_movable.loc, target_turf) + launch.speed = SPEED_FAST + launch.thrower = unlucky_mob + launch.spin = TRUE + launch.pass_flags = NO_FLAGS to_chat(unlucky_mob, SPAN_WARNING("The ocean currents sweep you off your feet and throw you away!")) // Entered can occur during Initialize so we need to not sleep - INVOKE_ASYNC(unlucky_mob, TYPE_PROC_REF(/atom/movable, launch_towards), LM) + INVOKE_ASYNC(unlucky_mob, TYPE_PROC_REF(/atom/movable, launch_towards), launch) return if(world.time % 5) - if(ismob(AM)) - var/mob/rivermob = AM + if(ismob(entered_movable)) + var/mob/rivermob = entered_movable if(!HAS_TRAIT(rivermob, TRAIT_HAULED)) to_chat(rivermob, SPAN_WARNING("Moving through the incredibly deep ocean slows you down a lot!")) diff --git a/code/game/turfs/open_space.dm b/code/game/turfs/open_space.dm index dfbffbc77c2d..3b7c3991514f 100644 --- a/code/game/turfs/open_space.dm +++ b/code/game/turfs/open_space.dm @@ -29,7 +29,7 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr ADD_TRAIT(src, TURF_Z_TRANSPARENT_TRAIT, TRAIT_SOURCE_INHERENT) return INITIALIZE_HINT_LATELOAD -/turf/open_space/Enter(atom/movable/mover, atom/forget) +/turf/open_space/Enter(atom/movable/mover, atom/old_loc) . = ..() if(. && !mover.throwing && isliving(mover) && check_blocked()) to_chat(mover, SPAN_WARNING("It would be too dangerous to go that way.")) @@ -37,7 +37,10 @@ GLOBAL_DATUM_INIT(openspace_backdrop_one_for_all, /atom/movable/openspace_backdr /turf/open_space/Entered(atom/movable/entered_movable, atom/old_loc) . = ..() - check_fall(entered_movable) + if(old_loc != src) + check_fall(entered_movable) + else + INVOKE_NEXT_TICK(src, PROC_REF(check_fall), entered_movable) /turf/open_space/on_throw_end(atom/movable/thrown_atom) check_fall(thrown_atom) diff --git a/code/game/turfs/transit.dm b/code/game/turfs/transit.dm index 95a2e390b201..270d67ebc525 100644 --- a/code/game/turfs/transit.dm +++ b/code/game/turfs/transit.dm @@ -17,8 +17,10 @@ if(!istype(old_loc, /turf/open/space)) var/turf/projected = get_ranged_target_turf(crosser, dir, 10) - INVOKE_ASYNC(crosser, TYPE_PROC_REF(/atom/movable, throw_atom), projected, 50, SPEED_FAST, null, TRUE) - + if(old_loc != src) + INVOKE_ASYNC(crosser, TYPE_PROC_REF(/atom/movable, throw_atom), projected, 50, SPEED_FAST, null, TRUE) + else + INVOKE_NEXT_TICK(crosser, TYPE_PROC_REF(/atom/movable, throw_atom), projected, 50, SPEED_FAST, null, TRUE) addtimer(CALLBACK(src, PROC_REF(handle_crosser), crosser), 0.5 SECONDS) /turf/open/space/transit/proc/handle_crosser(atom/movable/crosser) diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index f9ab30019ca1..5191b4f2c4ee 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -246,8 +246,8 @@ return // Handles whether an atom is able to enter the src turf -/turf/Enter(atom/movable/mover, atom/forget) - if (!mover || !isturf(mover.loc)) +/turf/Enter(atom/movable/mover, atom/old_loc) + if(QDELETED(mover) || !isturf(mover.loc)) return FALSE var/override = SEND_SIGNAL(mover, COMSIG_MOVABLE_TURF_ENTER, src) @@ -277,7 +277,7 @@ mover.Collide(T) return FALSE for (obstacle in T) //First, check objects to block exit - if (mover == obstacle || forget == obstacle) + if (mover == obstacle || old_loc == obstacle) continue A = obstacle if (!istype(A) || !A.can_block_movement) @@ -298,7 +298,7 @@ mover.Collide(T) return FALSE for(obstacle in T) - if(forget == obstacle) + if(old_loc == obstacle) continue A = obstacle if (!istype(A) || !A.can_block_movement) @@ -318,7 +318,7 @@ mover.Collide(T) return FALSE for(obstacle in T) - if(forget == obstacle) + if(old_loc == obstacle) continue A = obstacle if (!istype(A) || !A.can_block_movement) @@ -336,7 +336,7 @@ mover.Collide(src) return FALSE for(obstacle in src) //Then, check atoms in the target turf - if(forget == obstacle) + if(old_loc == obstacle) continue A = obstacle if (!istype(A) || !A.can_block_movement) @@ -357,16 +357,17 @@ return TRUE //Nothing found to block so return success! -/turf/Entered(atom/movable/A) - if(!istype(A)) +/turf/Entered(atom/movable/entered_movable, atom/old_loc) + if(QDELETED(entered_movable)) return - SEND_SIGNAL(src, COMSIG_TURF_ENTERED, A) - SEND_SIGNAL(A, COMSIG_MOVABLE_TURF_ENTERED, src) + SEND_SIGNAL(src, COMSIG_TURF_ENTERED, entered_movable) + SEND_SIGNAL(entered_movable, COMSIG_MOVABLE_TURF_ENTERED, src) // Let explosions know that the atom entered - for(var/datum/automata_cell/explosion/E in autocells) - E.on_turf_entered(A) + if(old_loc != src) + for(var/datum/automata_cell/explosion/cell in autocells) + cell.on_turf_entered(entered_movable) /turf/proc/is_plating() return 0 @@ -499,17 +500,30 @@ changing_turf = TRUE qdel(src) //Just get the side effects and call Destroy // Get signal registrations post-Destroy so stuff that's unregistered on Destroy won't be readded - var/list/old_comp_lookup = comp_lookup?.Copy() - var/list/old_signal_procs = signal_procs?.Copy() + var/list/old_comp_lookup = comp_lookup + var/list/old_signal_procs = signal_procs var/turf/W = new path(src) // WARNING WARNING // Turfs DO NOT lose their signals when they get replaced, REMEMBER THIS // It's possible because turfs are fucked, and if you have one in a list and it's replaced with another one, the list ref points to the new turf + // Enjoy some dumb code to copy signals that you hope didn't change from then to the new turf being New'd if(old_comp_lookup) - LAZYOR(W.comp_lookup, old_comp_lookup) + for(var/key in old_comp_lookup) + var/old_lookup = old_comp_lookup[key] + var/list/old_items = islist(old_lookup) ? old_lookup : list(old_lookup) + var/new_lookup = LAZYACCESS(W.comp_lookup, key) + var/list/new_items = islist(new_lookup) ? new_lookup : !isnull(new_lookup) ? list(new_lookup) : list() + var/list/combined_list = old_items + new_items + LAZYSET(W.comp_lookup, key, length(combined_list) == 1 ? combined_list[1] : combined_list) if(old_signal_procs) - LAZYOR(W.signal_procs, old_signal_procs) + for(var/key in old_signal_procs) + var/old_lookup = old_signal_procs[key] + var/list/old_items = islist(old_lookup) ? old_lookup : list() + var/new_lookup = LAZYACCESS(W.signal_procs, key) + var/list/new_items = islist(new_lookup) ? new_lookup : list() + var/list/combined_list = old_items + new_items + LAZYSET(W.signal_procs, key, combined_list) W.weak_reference = old_ref diff --git a/code/modules/lighting/lighting_mask/lighting_mask.dm b/code/modules/lighting/lighting_mask/lighting_mask.dm index e76590d254bb..dd6f2e2a871d 100644 --- a/code/modules/lighting/lighting_mask/lighting_mask.dm +++ b/code/modules/lighting/lighting_mask/lighting_mask.dm @@ -165,7 +165,7 @@ /atom/movable/lighting_mask/rotating_conical icon_state = "light_conical_rotating" -/atom/movable/lighting_mask/ex_act(severity, target) +/atom/movable/lighting_mask/ex_act(severity) return /atom/movable/lighting_mask/fire_act(exposed_temperature, exposed_volume) diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 7ff77d825c5c..e297b41a9117 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -50,7 +50,7 @@ if(severity >= health && severity >= EXPLOSION_THRESHOLD_GIB) gibbing = TRUE - if(body_position == LYING_DOWN && direction) + if(body_position == LYING_DOWN && direction > 0) severity *= EXPLOSION_PRONE_MULTIPLIER if(HAS_TRAIT(src, TRAIT_HAULED) && !gibbing) // We still probably wanna gib them as well if they were supposed to be gibbed by the explosion in the first place @@ -69,7 +69,7 @@ apply_damage(severity, BRUTE, enviro=enviro) updatehealth() - var/knock_value = min( round( severity*0.1 ,1) ,10) + var/knock_value = min(round(severity*0.1, 1), 10) if(knock_value > 0) apply_effect(knock_value, PARALYZE) explosion_throw(severity, direction) diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 78c4e9b08082..36469a51068b 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -145,7 +145,7 @@ . += "Self Destruct Status: [SShijack.get_sd_eta()]" /mob/living/carbon/human/ex_act(severity, direction, datum/cause_data/cause_data, pierce=0, enviro=FALSE) - if(body_position == LYING_DOWN && direction) + if(body_position == LYING_DOWN && direction > 0) severity *= EXPLOSION_PRONE_MULTIPLIER var/b_loss = 0 diff --git a/code/modules/mob/living/carbon/xenomorph/damage_procs.dm b/code/modules/mob/living/carbon/xenomorph/damage_procs.dm index d59ad11f8eb0..97c25f0430a4 100644 --- a/code/modules/mob/living/carbon/xenomorph/damage_procs.dm +++ b/code/modules/mob/living/carbon/xenomorph/damage_procs.dm @@ -46,7 +46,7 @@ /mob/living/carbon/xenomorph/ex_act(severity, direction, datum/cause_data/cause_data, pierce=0, enviro=FALSE) - if(body_position == LYING_DOWN && direction) + if(body_position == LYING_DOWN && direction > 0) severity *= EXPLOSION_PRONE_MULTIPLIER if(severity >= 30) diff --git a/code/modules/movement/launching/launching.dm b/code/modules/movement/launching/launching.dm index b5c177371b9e..2e0e68684ae2 100644 --- a/code/modules/movement/launching/launching.dm +++ b/code/modules/movement/launching/launching.dm @@ -131,6 +131,9 @@ // Proc for throwing items (should only really be used for throw) /atom/movable/proc/throw_atom(atom/target, range, speed = 0, atom/thrower, spin, launch_type = NORMAL_LAUNCH, pass_flags = NO_FLAGS, list/end_throw_callbacks, list/collision_callbacks, tracking = FALSE) + if(QDELETED(src)) + return // Why throw something deleting? + var/temp_pass_flags = pass_flags switch (launch_type) if (NORMAL_LAUNCH)