diff --git a/code/__DEFINES/MC.dm b/code/__DEFINES/MC.dm index bad64846d6..cad75fbfe4 100644 --- a/code/__DEFINES/MC.dm +++ b/code/__DEFINES/MC.dm @@ -22,49 +22,45 @@ #define START_PROCESSING(Processor, Datum) if (!(Datum.datum_flags & DF_ISPROCESSING)) {Datum.datum_flags |= DF_ISPROCESSING;Processor.processing += Datum} #define STOP_PROCESSING(Processor, Datum) Datum.datum_flags &= ~DF_ISPROCESSING;Processor.processing -= Datum;Processor.currentrun -= Datum -//SubSystem flags (Please design any new flags so that the default is off, to make adding flags to subsystems easier) +//! SubSystem flags (Please design any new flags so that the default is off, to make adding flags to subsystems easier) -//subsystem does not initialize. -#define SS_NO_INIT (1<<0) +/// subsystem does not initialize. +#define SS_NO_INIT 1 -//subsystem does not fire. -// (like can_fire = 0, but keeps it from getting added to the processing subsystems list) -// (Requires a MC restart to change) -#define SS_NO_FIRE (1<<1) +/** subsystem does not fire. */ +/// (like can_fire = 0, but keeps it from getting added to the processing subsystems list) +/// (Requires a MC restart to change) +#define SS_NO_FIRE 2 -//subsystem only runs on spare cpu (after all non-background subsystems have ran that tick) -// SS_BACKGROUND has its own priority bracket -#define SS_BACKGROUND (1<<2) +/** Subsystem only runs on spare cpu (after all non-background subsystems have ran that tick) */ +/// SS_BACKGROUND has its own priority bracket, this overrides SS_TICKER's priority bump +#define SS_BACKGROUND 4 -//subsystem does not tick check, and should not run unless there is enough time (or its running behind (unless background)) -#define SS_NO_TICK_CHECK (1<<3) +/// subsystem does not tick check, and should not run unless there is enough time (or its running behind (unless background)) +#define SS_NO_TICK_CHECK 8 -//Treat wait as a tick count, not DS, run every wait ticks. -// (also forces it to run first in the tick, above even SS_NO_TICK_CHECK subsystems) -// (implies all runlevels because of how it works) -// (overrides SS_BACKGROUND) -// This is designed for basically anything that works as a mini-mc (like SStimer) -#define SS_TICKER (1<<4) +/** Treat wait as a tick count, not DS, run every wait ticks. */ +/// (also forces it to run first in the tick (unless SS_BACKGROUND)) +/// (implies all runlevels because of how it works) +/// This is designed for basically anything that works as a mini-mc (like SStimer) +#define SS_TICKER 16 -//keep the subsystem's timing on point by firing early if it fired late last fire because of lag -// ie: if a 20ds subsystem fires say 5 ds late due to lag or what not, its next fire would be in 15ds, not 20ds. -#define SS_KEEP_TIMING (1<<5) +/** keep the subsystem's timing on point by firing early if it fired late last fire because of lag */ +/// ie: if a 20ds subsystem fires say 5 ds late due to lag or what not, its next fire would be in 15ds, not 20ds. +#define SS_KEEP_TIMING 32 -//Calculate its next fire after its fired. -// (IE: if a 5ds wait SS takes 2ds to run, its next fire should be 5ds away, not 3ds like it normally would be) -// This flag overrides SS_KEEP_TIMING -#define SS_POST_FIRE_TIMING (1<<6) +/** Calculate its next fire after its fired. */ +/// (IE: if a 5ds wait SS takes 2ds to run, its next fire should be 5ds away, not 3ds like it normally would be) +/// This flag overrides SS_KEEP_TIMING +#define SS_POST_FIRE_TIMING 64 -/// Show in stat() by default even if SS_NO_FIRE -#define SS_ALWAYS_SHOW_STAT (1<<7) - -//SUBSYSTEM STATES -#define SS_IDLE 0 //aint doing shit. -#define SS_QUEUED 1 //queued to run -#define SS_RUNNING 2 //actively running -#define SS_PAUSED 3 //paused by mc_tick_check -#define SS_SLEEPING 4 //fire() slept. -#define SS_PAUSING 5 //in the middle of pausing +//! SUBSYSTEM STATES +#define SS_IDLE 0 /// ain't doing shit. +#define SS_QUEUED 1 /// queued to run +#define SS_RUNNING 2 /// actively running +#define SS_PAUSED 3 /// paused by mc_tick_check +#define SS_SLEEPING 4 /// fire() slept. +#define SS_PAUSING 5 /// in the middle of pausing #define SUBSYSTEM_DEF(X) GLOBAL_REAL(SS##X, /datum/controller/subsystem/##X);\ /datum/controller/subsystem/##X/New(){\ diff --git a/code/__DEFINES/dcs/helpers.dm b/code/__DEFINES/dcs/helpers.dm index 182035db9b..ba2b9a704a 100644 --- a/code/__DEFINES/dcs/helpers.dm +++ b/code/__DEFINES/dcs/helpers.dm @@ -6,9 +6,16 @@ #define SEND_GLOBAL_SIGNAL(sigtype, arguments...) ( SEND_SIGNAL(SSdcs, sigtype, ##arguments) ) +/// Signifies that this proc is used to handle signals. +/// Every proc you pass to RegisterSignal must have this. +#define SIGNAL_HANDLER SHOULD_NOT_SLEEP(TRUE) + +/// Signifies that this proc is used to handle signals, but also sleeps. +/// Do not use this for new work. +#define SIGNAL_HANDLER_DOES_SLEEP + /// A wrapper for _AddElement that allows us to pretend we're using normal named arguments #define AddElement(arguments...) _AddElement(list(##arguments)) - /// A wrapper for _RemoveElement that allows us to pretend we're using normal named arguments #define RemoveElement(arguments...) _RemoveElement(list(##arguments)) diff --git a/code/__DEFINES/movement.dm b/code/__DEFINES/movement.dm new file mode 100644 index 0000000000..93d5eb9816 --- /dev/null +++ b/code/__DEFINES/movement.dm @@ -0,0 +1,16 @@ +/// The minimum for glide_size to be clamped to. +#define MIN_GLIDE_SIZE 1 +/// The maximum for glide_size to be clamped to. +/// This shouldn't be higher than the icon size, and generally you shouldn't be changing this, but it's here just in case. +#define MAX_GLIDE_SIZE 32 + +/// Compensating for time dialation +GLOBAL_VAR_INIT(glide_size_multiplier, 1.0) + +///Broken down, here's what this does: +/// divides the world icon_size (32) by delay divided by ticklag to get the number of pixels something should be moving each tick. +/// The division result is given a min value of 1 to prevent obscenely slow glide sizes from being set +/// Then that's multiplied by the global glide size multiplier. 1.25 by default feels pretty close to spot on. This is just to try to get byond to behave. +/// The whole result is then clamped to within the range above. +/// Not very readable but it works +#define DELAY_TO_GLIDE_SIZE(delay) (clamp(((32 / max((delay) / world.tick_lag, 1)) * GLOB.glide_size_multiplier), MIN_GLIDE_SIZE, MAX_GLIDE_SIZE)) diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm index 346df744d0..c560e51739 100644 --- a/code/__DEFINES/subsystems.dm +++ b/code/__DEFINES/subsystems.dm @@ -174,7 +174,6 @@ #define FIRE_PRIORITY_AIR_TURFS 40 #define FIRE_PRIORITY_DEFAULT 50 #define FIRE_PRIORITY_PARALLAX 65 -#define FIRE_PRIORITY_INSTRUMENTS 80 #define FIRE_PRIORITY_MOBS 100 #define FIRE_PRIORITY_TGUI 110 #define FIRE_PRIORITY_PROJECTILES 200 diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index 794a495ae3..be5071419f 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -1202,7 +1202,7 @@ GLOBAL_REAL_VAR(list/stack_trace_storage) GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new) //Version of view() which ignores darkness, because BYOND doesn't have it (I actually suggested it but it was tagged redundant, BUT HEARERS IS A T- /rant). -/proc/dview(var/range = world.view, var/center, var/invis_flags = 0) +/proc/dview(range = world.view, center, invis_flags = 0) if(!center) return @@ -1222,6 +1222,10 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new) var/ready_to_die = FALSE /mob/dview/Initialize() //Properly prevents this mob from gaining huds or joining any global lists + SHOULD_CALL_PARENT(FALSE) + if(flags_1 & INITIALIZED_1) + stack_trace("Warning: [src]([type]) initialized multiple times!") + flags_1 |= INITIALIZED_1 return INITIALIZE_HINT_NORMAL /mob/dview/Destroy(force = FALSE) diff --git a/code/controllers/subsystem/lighting.dm b/code/controllers/subsystem/lighting.dm index 992b1d12c9..19345f3c8d 100644 --- a/code/controllers/subsystem/lighting.dm +++ b/code/controllers/subsystem/lighting.dm @@ -1,14 +1,15 @@ +GLOBAL_LIST_EMPTY(lighting_update_lights) // List of lighting sources queued for update. +GLOBAL_LIST_EMPTY(lighting_update_corners) // List of lighting corners queued for update. +GLOBAL_LIST_EMPTY(lighting_update_objects) // List of lighting objects queued for update. + SUBSYSTEM_DEF(lighting) name = "Lighting" wait = 2 init_order = INIT_ORDER_LIGHTING flags = SS_TICKER - var/static/list/sources_queue = list() // List of lighting sources queued for update. - var/static/list/corners_queue = list() // List of lighting corners queued for update. - var/static/list/objects_queue = list() // List of lighting objects queued for update. /datum/controller/subsystem/lighting/stat_entry(msg) - msg = "L:[length(sources_queue)]|C:[length(corners_queue)]|O:[length(objects_queue)]" + msg = "L:[length(GLOB.lighting_update_lights)]|C:[length(GLOB.lighting_update_corners)]|O:[length(GLOB.lighting_update_objects)]" return ..() @@ -31,10 +32,9 @@ SUBSYSTEM_DEF(lighting) MC_SPLIT_TICK_INIT(3) if(!init_tick_checks) MC_SPLIT_TICK - var/list/queue = sources_queue var/i = 0 - for (i in 1 to length(queue)) - var/datum/light_source/L = queue[i] + for (i in 1 to GLOB.lighting_update_lights.len) + var/datum/light_source/L = GLOB.lighting_update_lights[i] L.update_corners() @@ -45,15 +45,14 @@ SUBSYSTEM_DEF(lighting) else if (MC_TICK_CHECK) break if (i) - queue.Cut(1, i+1) + GLOB.lighting_update_lights.Cut(1, i+1) i = 0 if(!init_tick_checks) MC_SPLIT_TICK - queue = corners_queue - for (i in 1 to length(queue)) - var/datum/lighting_corner/C = queue[i] + for (i in 1 to GLOB.lighting_update_corners.len) + var/datum/lighting_corner/C = GLOB.lighting_update_corners[i] C.update_objects() C.needs_update = FALSE @@ -62,16 +61,15 @@ SUBSYSTEM_DEF(lighting) else if (MC_TICK_CHECK) break if (i) - queue.Cut(1, i+1) + GLOB.lighting_update_corners.Cut(1, i+1) i = 0 if(!init_tick_checks) MC_SPLIT_TICK - queue = objects_queue - for (i in 1 to length(queue)) - var/atom/movable/lighting_object/O = queue[i] + for (i in 1 to GLOB.lighting_update_objects.len) + var/atom/movable/lighting_object/O = GLOB.lighting_update_objects[i] if (QDELETED(O)) continue @@ -83,7 +81,7 @@ SUBSYSTEM_DEF(lighting) else if (MC_TICK_CHECK) break if (i) - queue.Cut(1, i+1) + GLOB.lighting_update_objects.Cut(1, i+1) /datum/controller/subsystem/lighting/Recover() diff --git a/code/controllers/subsystem/minimum_spawns.dm b/code/controllers/subsystem/minimum_spawns.dm index caab2b1949..b9d19b6cd2 100644 --- a/code/controllers/subsystem/minimum_spawns.dm +++ b/code/controllers/subsystem/minimum_spawns.dm @@ -1,7 +1,7 @@ SUBSYSTEM_DEF(min_spawns) name = "Minimum Spawns" /// this hot steaming pile of garbage makes sure theres a minimum of tendrils scattered around init_order = INIT_ORDER_DEFAULT - flags = SS_BACKGROUND | SS_NO_FIRE | SS_ALWAYS_SHOW_STAT + flags = SS_BACKGROUND | SS_NO_FIRE wait = 2 var/where_we_droppin_boys_iterations = 0 var/snaxi_snowflake_check = FALSE @@ -71,7 +71,7 @@ GLOBAL_LIST_INIT(minimum_snow_under_spawns, list( continue if(typesof(/turf/open/lava) in orange(9, TT)) continue - valid_mining_turfs_2.Add(TT) + valid_mining_turfs_2.Add(TT) else for(var/z_level in SSmapping.levels_by_trait(ZTRAIT_LAVA_RUINS)) for(var/turf/TT in Z_TURFS(z_level)) @@ -103,14 +103,14 @@ GLOBAL_LIST_INIT(minimum_snow_under_spawns, list( for(var/mob/living/simple_animal/hostile/megafauna/H in urange(70,RT)) //prevents mob clumps if((istype(MS_tospawn, /mob/living/simple_animal/hostile/megafauna)) && get_dist(RT, H) <= 70) active_spawns.Add(MS_tospawn) - continue //let's try not to dump megas too close to each other? + continue //let's try not to dump megas too close to each other? if((istype(MS_tospawn, /obj/structure/spawner)) && get_dist(RT, H) <= 40) active_spawns.Add(MS_tospawn) continue //let's at least /try/ to space these out? for(var/obj/structure/spawner/LT in urange(70,RT)) //prevents tendril/mega clumps if((istype(MS_tospawn, /mob/living/simple_animal/hostile/megafauna)) && get_dist(RT, LT) <= 70) active_spawns.Add(MS_tospawn) - continue //let's try not to dump megas too close to each other? + continue //let's try not to dump megas too close to each other? if((istype(MS_tospawn, /obj/structure/spawner)) && get_dist(RT, LT) <= 40) active_spawns.Add(MS_tospawn) continue //let's at least /try/ to space these out? @@ -127,7 +127,7 @@ GLOBAL_LIST_INIT(minimum_snow_under_spawns, list( for(var/mob/living/simple_animal/hostile/H in urange(70,RT2)) //prevents mob clumps if((istype(MS2_tospawn, /mob/living/simple_animal/hostile/megafauna) || ismegafauna(H)) && get_dist(RT2, H) <= 70) active_spawns_2.Add(MS2_tospawn) - continue //let's try not to dump megas too close to each other? + continue //let's try not to dump megas too close to each other? if((istype(MS2_tospawn, /obj/structure/spawner)) && get_dist(RT2, H) <= 40) active_spawns_2.Add(MS2_tospawn) continue //let's at least /try/ to space these out? diff --git a/code/controllers/subsystem/throwing.dm b/code/controllers/subsystem/throwing.dm index 8c5abc5469..e5d6b0bbd0 100644 --- a/code/controllers/subsystem/throwing.dm +++ b/code/controllers/subsystem/throwing.dm @@ -57,6 +57,7 @@ SUBSYSTEM_DEF(throwing) var/dx var/dy var/force = MOVE_FORCE_DEFAULT + var/gentle = FALSE var/pure_diagonal var/diagonal_error var/datum/callback/callback @@ -64,15 +65,42 @@ SUBSYSTEM_DEF(throwing) var/delayed_time = 0 var/last_move = 0 + +/datum/thrownthing/New(thrownthing, target, target_turf, init_dir, maxrange, speed, thrower, diagonals_first, force, gentle, callback, target_zone) + . = ..() + src.thrownthing = thrownthing + RegisterSignal(thrownthing, COMSIG_PARENT_QDELETING, .proc/on_thrownthing_qdel) + src.target = target + src.target_turf = target_turf + src.init_dir = init_dir + src.maxrange = maxrange + src.speed = speed + src.thrower = thrower + src.diagonals_first = diagonals_first + src.force = force + src.gentle = gentle + src.callback = callback + src.target_zone = target_zone + + /datum/thrownthing/Destroy() SSthrowing.processing -= thrownthing thrownthing.throwing = null thrownthing = null target = null thrower = null - callback = null + if(callback) + QDEL_NULL(callback) //It stores a reference to the thrownthing, its source. Let's clean that. return ..() + +///Defines the datum behavior on the thrownthing's qdeletion event. +/datum/thrownthing/proc/on_thrownthing_qdel(atom/movable/source, force) + SIGNAL_HANDLER + + qdel(src) + + /datum/thrownthing/proc/tick() var/atom/movable/AM = thrownthing if (!isturf(AM.loc) || !AM.throwing) @@ -112,7 +140,7 @@ SUBSYSTEM_DEF(throwing) finalize() return - AM.Move(step, get_dir(AM, step)) + AM.Move(step, get_dir(AM, step), DELAY_TO_GLIDE_SIZE(1 / speed)) if (!AM.throwing) // we hit something during our move finalize(hit = TRUE) @@ -136,15 +164,21 @@ SUBSYSTEM_DEF(throwing) if (A == target) hit = TRUE thrownthing.throw_impact(A, src) + if(QDELETED(thrownthing)) //throw_impact can delete things, such as glasses smashing + return //deletion should already be handled by on_thrownthing_qdel() break if (!hit) thrownthing.throw_impact(get_turf(thrownthing), src) // we haven't hit something yet and we still must, let's hit the ground. + if(QDELETED(thrownthing)) //throw_impact can delete things, such as glasses smashing + return //deletion should already be handled by on_thrownthing_qdel() thrownthing.newtonian_move(init_dir) else thrownthing.newtonian_move(init_dir) if(target) thrownthing.throw_impact(target, src) + if(QDELETED(thrownthing)) //throw_impact can delete things, such as glasses smashing + return //deletion should already be handled by on_thrownthing_qdel() if (callback) callback.Invoke() diff --git a/code/controllers/subsystem/vis_overlays.dm b/code/controllers/subsystem/vis_overlays.dm index 0635709074..b0e5d6c689 100644 --- a/code/controllers/subsystem/vis_overlays.dm +++ b/code/controllers/subsystem/vis_overlays.dm @@ -5,10 +5,12 @@ SUBSYSTEM_DEF(vis_overlays) init_order = INIT_ORDER_VIS var/list/vis_overlay_cache + var/list/unique_vis_overlays var/list/currentrun /datum/controller/subsystem/vis_overlays/Initialize() vis_overlay_cache = list() + unique_vis_overlays = list() return ..() /datum/controller/subsystem/vis_overlays/fire(resumed = FALSE) @@ -29,31 +31,45 @@ SUBSYSTEM_DEF(vis_overlays) return //the "thing" var can be anything with vis_contents which includes images -/datum/controller/subsystem/vis_overlays/proc/add_vis_overlay(atom/movable/thing, icon, iconstate, layer, plane, dir, alpha = 255, add_appearance_flags = NONE) - . = "[icon]|[iconstate]|[layer]|[plane]|[dir]|[alpha]|[add_appearance_flags]" - var/obj/effect/overlay/vis/overlay = vis_overlay_cache[.] - if(!overlay) - overlay = new - overlay.icon = icon - overlay.icon_state = iconstate - overlay.layer = layer - overlay.plane = plane - overlay.dir = dir - overlay.alpha = alpha - overlay.appearance_flags |= add_appearance_flags - vis_overlay_cache[.] = overlay +/datum/controller/subsystem/vis_overlays/proc/add_vis_overlay(atom/movable/thing, icon, iconstate, layer, plane, dir, alpha = 255, add_appearance_flags = NONE, unique = FALSE) + var/obj/effect/overlay/vis/overlay + if(!unique) + . = "[icon]|[iconstate]|[layer]|[plane]|[dir]|[alpha]|[add_appearance_flags]" + overlay = vis_overlay_cache[.] + if(!overlay) + overlay = _create_new_vis_overlay(icon, iconstate, layer, plane, dir, alpha, add_appearance_flags) + vis_overlay_cache[.] = overlay + else + overlay.unused = 0 else - overlay.unused = 0 + overlay = _create_new_vis_overlay(icon, iconstate, layer, plane, dir, alpha, add_appearance_flags) + overlay.cache_expiration = -1 + var/cache_id = "\ref[overlay]@{[world.time]}" + unique_vis_overlays += overlay + vis_overlay_cache[cache_id] = overlay + . = overlay thing.vis_contents += overlay if(!isatom(thing)) // Automatic rotation is not supported on non atoms - return + return overlay if(!thing.managed_vis_overlays) thing.managed_vis_overlays = list(overlay) - RegisterSignal(thing, COMSIG_ATOM_DIR_CHANGE, .proc/rotate_vis_overlay) else thing.managed_vis_overlays += overlay + return overlay + +/datum/controller/subsystem/vis_overlays/proc/_create_new_vis_overlay(icon, iconstate, layer, plane, dir, alpha, add_appearance_flags) + var/obj/effect/overlay/vis/overlay = new + overlay.icon = icon + overlay.icon_state = iconstate + overlay.layer = layer + overlay.plane = plane + overlay.dir = dir + overlay.alpha = alpha + overlay.appearance_flags |= add_appearance_flags + return overlay + /datum/controller/subsystem/vis_overlays/proc/remove_vis_overlay(atom/movable/thing, list/overlays) thing.vis_contents -= overlays @@ -62,15 +78,3 @@ SUBSYSTEM_DEF(vis_overlays) thing.managed_vis_overlays -= overlays if(!length(thing.managed_vis_overlays)) thing.managed_vis_overlays = null - UnregisterSignal(thing, COMSIG_ATOM_DIR_CHANGE) - -/datum/controller/subsystem/vis_overlays/proc/rotate_vis_overlay(atom/thing, old_dir, new_dir) - if(old_dir == new_dir) - return - var/rotation = dir2angle(old_dir) - dir2angle(new_dir) - var/list/overlays_to_remove = list() - for(var/i in thing.managed_vis_overlays) - var/obj/effect/overlay/vis/overlay = i - add_vis_overlay(thing, overlay.icon, overlay.icon_state, overlay.layer, overlay.plane, turn(overlay.dir, rotation), overlay.alpha, overlay.appearance_flags) - overlays_to_remove += overlay - remove_vis_overlay(thing, overlays_to_remove) diff --git a/code/datums/brain_damage/imaginary_friend.dm b/code/datums/brain_damage/imaginary_friend.dm index e5e1434ab8..f35389f171 100644 --- a/code/datums/brain_damage/imaginary_friend.dm +++ b/code/datums/brain_damage/imaginary_friend.dm @@ -92,7 +92,7 @@ trauma = _trauma owner = trauma.owner - setup_friend() + INVOKE_ASYNC(src, .proc/setup_friend) join = new join.Grant(src) diff --git a/code/datums/holocall.dm b/code/datums/holocall.dm index 4bf02e8587..c54f6c971a 100644 --- a/code/datums/holocall.dm +++ b/code/datums/holocall.dm @@ -237,7 +237,7 @@ /obj/item/disk/holodisk/Initialize(mapload) . = ..() if(preset_record_text) - build_record() + INVOKE_ASYNC(src, .proc/build_record) /obj/item/disk/holodisk/Destroy() QDEL_NULL(record) @@ -425,42 +425,42 @@ "} /obj/item/disk/holodisk/ruin/snowengieruin - name = "Blackbox Print-out #EB412" - desc = "A holodisk containing the last moments of EB412. There's a bloody fingerprint on it." - preset_image_type = /datum/preset_holoimage/engineer - preset_record_text = {" - NAME Dave Tundrale - SAY Maria, how's Build? - DELAY 10 - NAME Maria Dell - PRESET /datum/preset_holoimage/engineer/atmos - SAY It's fine, don't worry. I've got Plastic on it. And frankly, i'm kinda busy with, the, uhhm, incinerator. - DELAY 30 - NAME Dave Tundrale - PRESET /datum/preset_holoimage/engineer - SAY Aight, wonderful. The science mans been kinda shit though. No RCDs- - DELAY 20 - NAME Maria Dell - PRESET /datum/preset_holoimage/engineer/atmos - SAY Enough about your RCDs. They're not even that important, just bui- - DELAY 15 - SOUND explosion - DELAY 10 - SAY Oh, shit! - DELAY 10 - PRESET /datum/preset_holoimage/engineer/atmos/rig - LANGUAGE /datum/language/narsie - NAME Unknown - SAY RISE, MY LORD!! - DELAY 10 - LANGUAGE /datum/language/common - NAME Plastic - PRESET /datum/preset_holoimage/engineer/rig - SAY Fuck, fuck, fuck! - DELAY 20 - SAY It's loose! CALL THE FUCKING SHUTT- - DELAY 10 - PRESET /datum/preset_holoimage/corgi - NAME Blackbox Automated Message - SAY Connection lost. Dumping audio logs to disk. - DELAY 50"} + name = "Blackbox Print-out #EB412" + desc = "A holodisk containing the last moments of EB412. There's a bloody fingerprint on it." + preset_image_type = /datum/preset_holoimage/engineer + preset_record_text = {" + NAME Dave Tundrale + SAY Maria, how's Build? + DELAY 10 + NAME Maria Dell + PRESET /datum/preset_holoimage/engineer/atmos + SAY It's fine, don't worry. I've got Plastic on it. And frankly, i'm kinda busy with, the, uhhm, incinerator. + DELAY 30 + NAME Dave Tundrale + PRESET /datum/preset_holoimage/engineer + SAY Aight, wonderful. The science mans been kinda shit though. No RCDs- + DELAY 20 + NAME Maria Dell + PRESET /datum/preset_holoimage/engineer/atmos + SAY Enough about your RCDs. They're not even that important, just bui- + DELAY 15 + SOUND explosion + DELAY 10 + SAY Oh, shit! + DELAY 10 + PRESET /datum/preset_holoimage/engineer/atmos/rig + LANGUAGE /datum/language/narsie + NAME Unknown + SAY RISE, MY LORD!! + DELAY 10 + LANGUAGE /datum/language/common + NAME Plastic + PRESET /datum/preset_holoimage/engineer/rig + SAY Fuck, fuck, fuck! + DELAY 20 + SAY It's loose! CALL THE FUCKING SHUTT- + DELAY 10 + PRESET /datum/preset_holoimage/corgi + NAME Blackbox Automated Message + SAY Connection lost. Dumping audio logs to disk. + DELAY 50"} diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 9607dc4dce..bfdcf82024 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -1,12 +1,22 @@ +/** + * The base type for nearly all physical objects in SS13 + + * Lots and lots of functionality lives here, although in general we are striving to move + * as much as possible to the components/elements system + */ /atom layer = TURF_LAYER plane = GAME_PLANE - var/level = 2 - var/article // If non-null, overrides a/an/some in all cases + appearance_flags = TILE_BOUND + var/level = 2 + ///If non-null, overrides a/an/some in all cases + var/article + + ///First atom flags var var/flags_1 = NONE + ///Intearaction flags var/interaction_flags_atom = NONE - var/datum/reagents/reagents = null var/flags_ricochet = NONE @@ -15,35 +25,52 @@ ///When a projectile ricochets off this atom, it deals the normal damage * this modifier to this atom var/ricochet_damage_mod = 0.33 - //This atom's HUD (med/sec, etc) images. Associative list. + ///Reagents holder + var/datum/reagents/reagents = null + + ///This atom's HUD (med/sec, etc) images. Associative list. var/list/image/hud_list = null - //HUD images that this atom can provide. + ///HUD images that this atom can provide. var/list/hud_possible - //Value used to increment ex_act() if reactionary_explosions is on + ///Value used to increment ex_act() if reactionary_explosions is on var/explosion_block = 0 - var/list/atom_colours //used to store the different colors on an atom - //its inherent color, the colored paint applied on it, special color effect etc... + /** + * used to store the different colors on an atom + * + * its inherent color, the colored paint applied on it, special color effect etc... + */ + var/list/atom_colours - var/list/remove_overlays // a very temporary list of overlays to remove - var/list/add_overlays // a very temporary list of overlays to add - var/list/managed_vis_overlays //vis overlays managed by SSvis_overlays to automaticaly turn them like other overlays - ///overlays managed by update_overlays() to prevent removing overlays that weren't added by the same proc + /// a very temporary list of overlays to remove + var/list/remove_overlays + /// a very temporary list of overlays to add + var/list/add_overlays + + ///vis overlays managed by SSvis_overlays to automaticaly turn them like other overlays + var/list/managed_vis_overlays + ///overlays managed by [update_overlays][/atom/proc/update_overlays] to prevent removing overlays that weren't added by the same proc var/list/managed_overlays + ///Proximity monitor associated with this atom var/datum/proximity_monitor/proximity_monitor + ///Last fingerprints to touch this atom var/fingerprintslast var/list/filter_data //For handling persistent filters + ///Price of an item in a vending machine, overriding the base vending machine price. Define in terms of paycheck defines as opposed to raw numbers. var/custom_price + ///Price of an item in a vending machine, overriding the premium vending machine price. Define in terms of paycheck defines as opposed to raw numbers. var/custom_premium_price + //List of datums orbiting this atom var/datum/component/orbiter/orbiters var/rad_flags = NONE // Will move to flags_1 when i can be arsed to + /// Radiation insulation types var/rad_insulation = RAD_NO_INSULATION ///The custom materials this atom is made of, used by a lot of things like furniture, walls, and floors (if I finish the functionality, that is.) @@ -72,6 +99,16 @@ ///Mobs that are currently do_after'ing this atom, to be cleared from on Destroy() var/list/targeted_by +/** + * Called when an atom is created in byond (built in engine proc) + * + * Not a lot happens here in SS13 code, as we offload most of the work to the + * [Intialization][/atom/proc/Initialize] proc, mostly we run the preloader + * if the preloader is being used and then call [InitAtom][/datum/controller/subsystem/atoms/proc/InitAtom] of which the ultimate + * result is that the Intialize proc is called. + * + * We also generate a tag here if the DF_USE_TAG flag is set on the atom + */ /atom/New(loc, ...) //atom creation method that preloads variables at creation if(GLOB.use_preloader && (src.type == GLOB._preloader.target_path))//in case the instanciated atom is creating other atoms in New() @@ -87,24 +124,50 @@ //we were deleted return -//Called after New if the map is being loaded. mapload = TRUE -//Called from base of New if the map is not being loaded. mapload = FALSE -//This base must be called or derivatives must set initialized to TRUE -//must not sleep -//Other parameters are passed from New (excluding loc), this does not happen if mapload is TRUE -//Must return an Initialize hint. Defined in __DEFINES/subsystems.dm - -//Note: the following functions don't call the base for optimization and must copypasta: -// /turf/Initialize -// /turf/open/space/Initialize - +/** + * The primary method that objects are setup in SS13 with + * + * we don't use New as we have better control over when this is called and we can choose + * to delay calls or hook other logic in and so forth + * + * During roundstart map parsing, atoms are queued for intialization in the base atom/New(), + * After the map has loaded, then Initalize is called on all atoms one by one. NB: this + * is also true for loading map templates as well, so they don't Initalize until all objects + * in the map file are parsed and present in the world + * + * If you're creating an object at any point after SSInit has run then this proc will be + * immediately be called from New. + * + * mapload: This parameter is true if the atom being loaded is either being intialized during + * the Atom subsystem intialization, or if the atom is being loaded from the map template. + * If the item is being created at runtime any time after the Atom subsystem is intialized then + * it's false. + * + * You must always call the parent of this proc, otherwise failures will occur as the item + * will not be seen as initalized (this can lead to all sorts of strange behaviour, like + * the item being completely unclickable) + * + * You must not sleep in this proc, or any subprocs + * + * Any parameters from new are passed through (excluding loc), naturally if you're loading from a map + * there are no other arguments + * + * Must return an [initialization hint][INITIALIZE_HINT_NORMAL] or a runtime will occur. + * + * Note: the following functions don't call the base for optimization and must copypasta handling: + * * [/turf/proc/Initialize] + * * [/turf/open/space/proc/Initialize] + */ /atom/proc/Initialize(mapload, ...) + // SHOULD_NOT_SLEEP(TRUE) + SHOULD_CALL_PARENT(TRUE) if(flags_1 & INITIALIZED_1) stack_trace("Warning: [src]([type]) initialized multiple times!") flags_1 |= INITIALIZED_1 if(loc) SEND_SIGNAL(loc, COMSIG_ATOM_CREATED, src) /// Sends a signal that the new atom `src`, has been created at `loc` + //atom color stuff if(color) add_atom_colour(color, FIXED_COLOUR_PRIORITY) @@ -126,14 +189,34 @@ return INITIALIZE_HINT_NORMAL -//called if Initialize returns INITIALIZE_HINT_LATELOAD +/** + * Late Intialization, for code that should run after all atoms have run Intialization + * + * To have your LateIntialize proc be called, your atoms [Initalization][/atom/proc/Initialize] + * proc must return the hint + * [INITIALIZE_HINT_LATELOAD] otherwise you will never be called. + * + * useful for doing things like finding other machines on GLOB.machines because you can guarantee + * that all atoms will actually exist in the "WORLD" at this time and that all their Intialization + * code has been run + */ /atom/proc/LateInitialize() - return + set waitfor = FALSE -// Put your AddComponent() calls here +/// Put your [AddComponent] calls here /atom/proc/ComponentInitialize() return +/** + * Top level of the destroy chain for most atoms + * + * Cleans up the following: + * * Removes alternate apperances from huds that see them + * * qdels the reagent holder from atoms if it exists + * * clears the orbiters list + * * clears overlays and priority overlays + * * clears the light object + */ /atom/Destroy() if(alternate_appearances) for(var/K in alternate_appearances) @@ -143,6 +226,8 @@ if(reagents) qdel(reagents) + orbiters = null // The component is attached to us normaly and will be deleted elsewhere + LAZYCLEARLIST(overlays) for(var/i in targeted_by) @@ -179,6 +264,16 @@ /atom/proc/CanPass(atom/movable/mover, turf/target) return !density +/** + * Is this atom currently located on centcom + * + * Specifically, is it on the z level and within the centcom areas + * + * You can also be in a shuttleshuttle during endgame transit + * + * Used in gamemode to identify mobs who have escaped and for some other areas of the code + * who don't want atoms where they shouldn't be + */ /atom/proc/onCentCom() var/turf/T = get_turf(src) if(!T) @@ -209,6 +304,13 @@ if(T in shuttle_area) return TRUE +/** + * Is the atom in any of the centcom syndicate areas + * + * Either in the syndie base on centcom, or any of their shuttles + * + * Also used in gamemode code for win conditions + */ /atom/proc/onSyndieBase() var/turf/T = get_turf(src) if(!T) @@ -222,6 +324,23 @@ return FALSE +/** + * Is the atom in an away mission + * + * Must be in the away mission z-level to return TRUE + * + * Also used in gamemode code for win conditions + */ +/atom/proc/onAwayMission() + var/turf/T = get_turf(src) + if(!T) + return FALSE + + if(is_away_level(T.z)) + return TRUE + + return FALSE + /atom/proc/attack_hulk(mob/living/carbon/human/user, does_attack_animation = FALSE) SEND_SIGNAL(src, COMSIG_ATOM_HULK_ATTACK, user) if(does_attack_animation) @@ -415,7 +534,7 @@ /// Updates the overlays of the atom /atom/proc/update_overlays() - SHOULD_CALL_PARENT(1) + SHOULD_CALL_PARENT(TRUE) . = list() SEND_SIGNAL(src, COMSIG_ATOM_UPDATE_OVERLAYS, .) @@ -1161,3 +1280,4 @@ // first of all make sure we valid var/mouseparams = list2params(paramslist) usr_client.Click(src, loc, null, mouseparams) + return TRUE diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 4715c3bed3..d7106f6231 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -1,5 +1,7 @@ /atom/movable layer = OBJ_LAYER + glide_size = 8 + appearance_flags = TILE_BOUND|PIXEL_SCALE var/last_move = null var/last_move_time = 0 var/anchored = FALSE @@ -28,8 +30,6 @@ var/atom/movable/moving_from_pull //attempt to resume grab after moving instead of before. var/list/client_mobs_in_contents // This contains all the client mobs within this container var/list/acted_explosions //for explosion dodging - glide_size = 8 - appearance_flags = TILE_BOUND|PIXEL_SCALE var/datum/forced_movement/force_moving = null //handled soley by forced_movement.dm var/movement_type = GROUND //Incase you have multiple types, you automatically use the most useful one. IE: Skating on ice, flippers on water, flying over chasm/space, etc. var/atom/movable/pulling @@ -59,6 +59,42 @@ em_block = new(src, render_target) vis_contents += em_block + +/atom/movable/Destroy(force) + QDEL_NULL(proximity_monitor) + QDEL_NULL(language_holder) + QDEL_NULL(em_block) + + unbuckle_all_mobs(force = TRUE) + + if(loc) + //Restore air flow if we were blocking it (movables with ATMOS_PASS_PROC will need to do this manually if necessary) + if(((CanAtmosPass == ATMOS_PASS_DENSITY && density) || CanAtmosPass == ATMOS_PASS_NO) && isturf(loc)) + CanAtmosPass = ATMOS_PASS_YES + air_update_turf(TRUE) + loc.handle_atom_del(src) + + // if(opacity) + // RemoveElement(/datum/element/light_blocking) + + invisibility = INVISIBILITY_ABSTRACT + + if(pulledby) + pulledby.stop_pulling() + + if(orbiting) + orbiting.end_orbit(src) + orbiting = null + + . = ..() + + for(var/movable_content in contents) + qdel(movable_content) + + LAZYCLEARLIST(client_mobs_in_contents) + + moveToNullspace() + /atom/movable/proc/update_emissive_block() if(blocks_emissive != EMISSIVE_BLOCK_GENERIC) return @@ -114,12 +150,13 @@ return T.zPassOut(src, direction, destination) && destination.zPassIn(src, direction, T) /atom/movable/vv_edit_var(var_name, var_value) - var/static/list/banned_edits = list("step_x", "step_y", "step_size") - var/static/list/careful_edits = list("bound_x", "bound_y", "bound_width", "bound_height") - if(var_name in banned_edits) + var/static/list/banned_edits = list("step_x" = TRUE, "step_y" = TRUE, "step_size" = TRUE, "bounds" = TRUE) + var/static/list/careful_edits = list("bound_x" = TRUE, "bound_y" = TRUE, "bound_width" = TRUE, "bound_height" = TRUE) + if(banned_edits[var_name]) return FALSE //PLEASE no. - if((var_name in careful_edits) && (var_value % world.icon_size) != 0) + if((careful_edits[var_name]) && (var_value % world.icon_size) != 0) return FALSE + switch(var_name) if(NAMEOF(src, x)) var/turf/T = locate(var_value, y, z) @@ -140,13 +177,24 @@ return TRUE return FALSE if(NAMEOF(src, loc)) - if(istype(var_value, /atom)) + if(isatom(var_value) || isnull(var_value)) forceMove(var_value) return TRUE - else if(isnull(var_value)) - moveToNullspace() - return TRUE return FALSE + if(NAMEOF(src, anchored)) + set_anchored(var_value) + . = TRUE + if(NAMEOF(src, pulledby)) + set_pulledby(var_value) + . = TRUE + if(NAMEOF(src, glide_size)) + set_glide_size(var_value) + . = TRUE + + if(!isnull(.)) + datum_flags |= DF_VAR_EDITED + return + return ..() /atom/movable/proc/start_pulling(atom/movable/AM, state, force = move_force, supress_message = FALSE) @@ -168,48 +216,68 @@ AMob.grabbedby(src) return TRUE stop_pulling() + + // SEND_SIGNAL(src, COMSIG_ATOM_START_PULL, AM, state, force) + if(AM.pulledby) log_combat(AM, AM.pulledby, "pulled from", src) AM.pulledby.stop_pulling() //an object can't be pulled by two mobs at once. pulling = AM - AM.pulledby = src + AM.set_pulledby(src) setGrabState(state) if(ismob(AM)) var/mob/M = AM log_combat(src, M, "grabbed", addition="passive grab") if(!supress_message) - visible_message("[src] has grabbed [M] passively!") + M.visible_message("[src] grabs [M] passively.", \ + "[src] grabs you passively.") return TRUE /atom/movable/proc/stop_pulling() if(!pulling) return - pulling.pulledby = null + pulling.set_pulledby(null) var/mob/living/ex_pulled = pulling + setGrabState(GRAB_PASSIVE) pulling = null - setGrabState(0) if(isliving(ex_pulled)) var/mob/living/L = ex_pulled L.update_mobility()// mob gets up if it was lyng down in a chokehold +///Reports the event of the change in value of the pulledby variable. +/atom/movable/proc/set_pulledby(new_pulledby) + if(new_pulledby == pulledby) + return FALSE //null signals there was a change, be sure to return FALSE if none happened here. + . = pulledby + pulledby = new_pulledby + + /atom/movable/proc/Move_Pulled(atom/A) if(!pulling) - return + return FALSE if(pulling.anchored || pulling.move_resist > move_force || !pulling.Adjacent(src)) stop_pulling() - return + return FALSE if(isliving(pulling)) var/mob/living/L = pulling if(L.buckled && L.buckled.buckle_prevents_pull) //if they're buckled to something that disallows pulling, prevent it stop_pulling() - return + return FALSE if(A == loc && pulling.density) - return - if(!Process_Spacemove(get_dir(pulling.loc, A))) - return - step(pulling, get_dir(pulling.loc, A)) + return FALSE + var/move_dir = get_dir(pulling.loc, A) + if(!Process_Spacemove(move_dir)) + return FALSE + pulling.Move(get_step(pulling.loc, move_dir), move_dir, glide_size) return TRUE +/mob/living/Move_Pulled(atom/A) + . = ..() + if(!. || !isliving(A)) + return + var/mob/living/L = A + set_pull_offsets(L, grab_state) + /atom/movable/proc/check_pulling() if(pulling) var/atom/movable/pullee = pulling @@ -229,54 +297,51 @@ if(pulledby && moving_diagonally != FIRST_DIAG_STEP && get_dist(src, pulledby) > 1) //separated from our puller and not in the middle of a diagonal move. pulledby.stop_pulling() -/atom/movable/Destroy(force) - QDEL_NULL(proximity_monitor) - QDEL_NULL(language_holder) - QDEL_NULL(em_block) - unbuckle_all_mobs(force=1) +/atom/movable/proc/set_glide_size(target = 8) + // SEND_SIGNAL(src, COMSIG_MOVABLE_UPDATE_GLIDE_SIZE, target) + glide_size = target - . = ..() + for(var/m in buckled_mobs) + var/mob/buckled_mob = m + buckled_mob.set_glide_size(target) - if(loc) - //Restore air flow if we were blocking it (movables with ATMOS_PASS_PROC will need to do this manually if necessary) - if(((CanAtmosPass == ATMOS_PASS_DENSITY && density) || CanAtmosPass == ATMOS_PASS_NO) && isturf(loc)) - CanAtmosPass = ATMOS_PASS_YES - air_update_turf(TRUE) - loc.handle_atom_del(src) - for(var/atom/movable/AM in contents) - qdel(AM) - moveToNullspace() - invisibility = INVISIBILITY_ABSTRACT - if(pulledby) - pulledby.stop_pulling() - - if(orbiting) - orbiting.end_orbit(src) - orbiting = null +///Sets the anchored var and returns if it was sucessfully changed or not. +/atom/movable/proc/set_anchored(anchorvalue) + SHOULD_CALL_PARENT(TRUE) + if(anchored == anchorvalue) + return + . = anchored + anchored = anchorvalue + // SEND_SIGNAL(src, COMSIG_MOVABLE_SET_ANCHORED, anchorvalue) /atom/movable/proc/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) - set waitfor = 0 + set waitfor = FALSE var/hitpush = TRUE var/impact_signal = SEND_SIGNAL(src, COMSIG_MOVABLE_IMPACT, hit_atom, throwingdatum) if(impact_signal & COMPONENT_MOVABLE_IMPACT_FLIP_HITPUSH) hitpush = FALSE // hacky, tie this to something else or a proper workaround later - if(impact_signal & ~COMPONENT_MOVABLE_IMPACT_NEVERMIND) // in case a signal interceptor broke or deleted the thing before we could process our hit - return hit_atom.hitby(src, throwingdatum = throwingdatum, hitpush = hitpush) + if(!(impact_signal && (impact_signal & COMPONENT_MOVABLE_IMPACT_NEVERMIND))) // in case a signal interceptor broke or deleted the thing before we could process our hit + return hit_atom.hitby(src, throwingdatum=throwingdatum, hitpush=hitpush) /atom/movable/hitby(atom/movable/AM, skipcatch, hitpush = TRUE, blocked, datum/thrownthing/throwingdatum) if(!anchored && hitpush && (!throwingdatum || (throwingdatum.force >= (move_resist * MOVE_FORCE_PUSH_RATIO)))) 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 = INFINITY, messy_throw = TRUE) +/atom/movable/proc/safe_throw_at(atom/target, range, speed, mob/thrower, spin = TRUE, diagonals_first = FALSE, datum/callback/callback, force = MOVE_FORCE_STRONG, gentle = FALSE) if((force < (move_resist * MOVE_FORCE_THROW_RATIO)) || (move_resist == INFINITY)) return - return throw_at(target, range, speed, thrower, spin, diagonals_first, callback, force, messy_throw) + return throw_at(target, range, speed, thrower, spin, diagonals_first, callback, force, gentle) -/atom/movable/proc/throw_at(atom/target, range, speed, mob/thrower, spin = TRUE, diagonals_first = FALSE, datum/callback/callback, force = INFINITY, messy_throw = TRUE) //If this returns FALSE then callback will not be called. +///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, gentle = FALSE, quickstart = TRUE) . = FALSE + + if(QDELETED(src)) + CRASH("Qdeleted thing being thrown around.") + if (!target || speed <= 0) return @@ -288,7 +353,7 @@ //They are moving! Wouldn't it be cool if we calculated their momentum and added it to the throw? if (thrower && thrower.last_move && thrower.client && thrower.client.move_delay >= world.time + world.tick_lag*2) - var/user_momentum = thrower.movement_delay() + var/user_momentum = thrower.movement_delay() //cached_multiplicative_slowdown if (!user_momentum) //no movement_delay, this means they move once per byond tick, lets calculate from that instead. user_momentum = world.tick_lag @@ -312,19 +377,13 @@ . = TRUE // No failure conditions past this point. - var/datum/thrownthing/TT = new() - TT.thrownthing = src - TT.target = target - TT.target_turf = get_turf(target) - TT.init_dir = get_dir(src, target) - TT.maxrange = range - TT.speed = speed - TT.thrower = thrower - TT.diagonals_first = diagonals_first - TT.force = force - TT.callback = callback - if(!QDELETED(thrower)) - TT.target_zone = thrower.zone_selected + var/target_zone + if(QDELETED(thrower)) + thrower = null //Let's not pass a qdeleting reference if any. + else + target_zone = thrower.zone_selected + + var/datum/thrownthing/TT = new(src, target, get_turf(target), get_dir(src, target), range, speed, thrower, diagonals_first, force, gentle, callback, target_zone) var/dist_x = abs(target.x - src.x) var/dist_y = abs(target.y - src.y) @@ -359,7 +418,8 @@ SSthrowing.processing[src] = TT if (SSthrowing.state == SS_PAUSED && length(SSthrowing.currentrun)) SSthrowing.currentrun[src] = TT - TT.tick() + if (quickstart) + TT.tick() /atom/movable/proc/force_pushed(atom/movable/pusher, force = MOVE_FORCE_DEFAULT, direction) return FALSE @@ -382,13 +442,13 @@ return TRUE return ..() -// called when this atom is removed from a storage item, which is passed on as S. The loc variable is already set to the new destination before this is called. -/atom/movable/proc/on_exit_storage(datum/component/storage/concrete/S) - return +/// called when this atom is removed from a storage item, which is passed on as S. The loc variable is already set to the new destination before this is called. +/atom/movable/proc/on_exit_storage(datum/component/storage/concrete/S) // rename S to master_storage + // SEND_SIGNAL(src, COMSIG_STORAGE_EXITED, master_storage) -// called when this atom is added into a storage item, which is passed on as S. The loc variable is already set to the storage item. +/// called when this atom is added into a storage item, which is passed on as S. The loc variable is already set to the storage item. /atom/movable/proc/on_enter_storage(datum/component/storage/concrete/S) - return + // SEND_SIGNAL(src, COMSIG_STORAGE_ENTERED, master_storage) /atom/movable/proc/get_spacemove_backup() var/atom/movable/dense_object_backup @@ -422,24 +482,26 @@ return //don't do an animation if attacking self var/pixel_x_diff = 0 var/pixel_y_diff = 0 + var/turn_dir = 1 var/direction = get_dir(src, A) if(direction & NORTH) pixel_y_diff = 8 + turn_dir = prob(50) ? -1 : 1 else if(direction & SOUTH) pixel_y_diff = -8 + turn_dir = prob(50) ? -1 : 1 if(direction & EAST) pixel_x_diff = 8 else if(direction & WEST) pixel_x_diff = -8 + turn_dir = -1 - var/matrix/OM = matrix(transform) - var/matrix/M = matrix(transform) - M.Turn(pixel_x_diff ? pixel_x_diff*2 : pick(-16, 16)) - - animate(src, pixel_x = pixel_x + pixel_x_diff, pixel_y = pixel_y + pixel_y_diff, transform = M, time = 2) - animate(src, pixel_x = pixel_x - pixel_x_diff, pixel_y = pixel_y - pixel_y_diff, transform = OM, time = 2) + var/matrix/initial_transform = matrix(transform) + var/matrix/rotated_transform = transform.Turn(15 * turn_dir) + animate(src, pixel_x = pixel_x + pixel_x_diff, pixel_y = pixel_y + pixel_y_diff, transform=rotated_transform, time = 1, easing=BACK_EASING|EASE_IN) + animate(pixel_x = pixel_x - pixel_x_diff, pixel_y = pixel_y - pixel_y_diff, transform=initial_transform, time = 2, easing=SINE_EASING) /atom/movable/proc/do_item_attack_animation(atom/A, visual_effect_icon, obj/item/used_item) var/image/I @@ -450,21 +512,21 @@ I.plane = GAME_PLANE // Scale the icon. - I.transform *= 0.75 + I.transform *= 0.4 // The icon should not rotate. I.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA // Set the direction of the icon animation. var/direction = get_dir(src, A) if(direction & NORTH) - I.pixel_y = -16 + I.pixel_y = -12 else if(direction & SOUTH) - I.pixel_y = 16 + I.pixel_y = 12 if(direction & EAST) - I.pixel_x = -16 + I.pixel_x = -14 else if(direction & WEST) - I.pixel_x = 16 + I.pixel_x = 14 if(!direction) // Attacked self?! I.pixel_z = 16 @@ -472,10 +534,12 @@ if(!I) return - flick_overlay(I, GLOB.clients, 5) // 5 ticks/half a second + flick_overlay(I, GLOB.clients, 10) // And animate the attack! - animate(I, alpha = 175, pixel_x = 0, pixel_y = 0, pixel_z = 0, time = 3) + animate(I, alpha = 175, transform = matrix() * 0.75, pixel_x = 0, pixel_y = 0, pixel_z = 0, time = 3) + animate(time = 1) + animate(alpha = 0, time = 3, easing = CIRCULAR_EASING|EASE_OUT) /atom/movable/vv_get_dropdown() . = ..() @@ -495,16 +559,14 @@ /atom/movable/proc/float(on) if(throwing) return - if(on && (!(movement_type & FLOATING) || floating_need_update)) - animate(src, pixel_y = pixel_y + 2, time = 10, loop = -1) - sleep(10) - animate(src, pixel_y = pixel_y - 2, time = 10, loop = -1) - if(!(movement_type & FLOATING)) - setMovetype(movement_type | FLOATING) - else if (!on && movement_type & FLOATING) + if(on && !(movement_type & FLOATING)) + animate(src, pixel_y = 2, time = 10, loop = -1, flags = ANIMATION_RELATIVE) + animate(pixel_y = -2, time = 10, loop = -1, flags = ANIMATION_RELATIVE) + setMovetype(movement_type | FLOATING) + else if (!on && (movement_type & FLOATING)) animate(src, pixel_y = initial(pixel_y), time = 10) setMovetype(movement_type & ~FLOATING) - floating_need_update = FALSE + floating_need_update = FALSE // assume it's done /* Language procs * Unless you are doing something very specific, these are the ones you want to use. @@ -611,10 +673,32 @@ return FALSE return TRUE -/// Updates the grab state of the movable -/// This exists to act as a hook for behaviour +/** + * Updates the grab state of the movable + * + * This exists to act as a hook for behaviour + */ /atom/movable/proc/setGrabState(newstate) + if(newstate == grab_state) + return + // SEND_SIGNAL(src, COMSIG_MOVABLE_SET_GRAB_STATE, newstate) + . = grab_state grab_state = newstate + // switch(grab_state) // Current state. + // if(GRAB_PASSIVE) + // REMOVE_TRAIT(pulling, TRAIT_IMMOBILIZED, CHOKEHOLD_TRAIT) + // REMOVE_TRAIT(pulling, TRAIT_HANDS_BLOCKED, CHOKEHOLD_TRAIT) + // if(. >= GRAB_NECK) // Previous state was a a neck-grab or higher. + // REMOVE_TRAIT(pulling, TRAIT_FLOORED, CHOKEHOLD_TRAIT) + // if(GRAB_AGGRESSIVE) + // if(. >= GRAB_NECK) // Grab got downgraded. + // REMOVE_TRAIT(pulling, TRAIT_FLOORED, CHOKEHOLD_TRAIT) + // else // Grab got upgraded from a passive one. + // ADD_TRAIT(pulling, TRAIT_IMMOBILIZED, CHOKEHOLD_TRAIT) + // ADD_TRAIT(pulling, TRAIT_HANDS_BLOCKED, CHOKEHOLD_TRAIT) + // if(GRAB_NECK, GRAB_KILL) + // if(. <= GRAB_AGGRESSIVE) + // ADD_TRAIT(pulling, TRAIT_FLOORED, CHOKEHOLD_TRAIT) /obj/item/proc/do_pickup_animation(atom/target) set waitfor = FALSE @@ -626,31 +710,24 @@ I.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA var/turf/T = get_turf(src) var/direction - var/to_x = 0 - var/to_y = 0 + var/to_x = initial(target.pixel_x) + var/to_y = initial(target.pixel_y) if(!QDELETED(T) && !QDELETED(target)) direction = get_dir(T, target) if(direction & NORTH) - to_y = 32 + to_y += 32 else if(direction & SOUTH) - to_y = -32 + to_y -= 32 if(direction & EAST) - to_x = 32 + to_x += 32 else if(direction & WEST) - to_x = -32 + to_x -= 32 if(!direction) - to_y = 16 + to_y += 16 flick_overlay(I, GLOB.clients, 6) var/matrix/M = new M.Turn(pick(-30, 30)) animate(I, alpha = 175, pixel_x = to_x, pixel_y = to_y, time = 3, transform = M, easing = CUBIC_EASING) sleep(1) animate(I, alpha = 0, transform = matrix(), time = 1) - -/atom/movable/proc/set_anchored(anchorvalue) //literally only for plumbing ran - SHOULD_CALL_PARENT(TRUE) - if(anchored == anchorvalue) - return - . = anchored - anchored = anchorvalue diff --git a/code/game/atoms_movement.dm b/code/game/atoms_movement.dm index db9424d983..406c08dd77 100644 --- a/code/game/atoms_movement.dm +++ b/code/game/atoms_movement.dm @@ -5,8 +5,7 @@ // Here's where we rewrite how byond handles movement except slightly different // To be removed on step_ conversion // All this work to prevent a second bump -/atom/movable/Move(atom/newloc, direct=0) - set waitfor = FALSE //n o +/atom/movable/Move(atom/newloc, direct=0, glide_size_override = 0) . = FALSE if(!newloc || newloc == loc) return @@ -52,8 +51,7 @@ // //////////////////////////////////////// -/atom/movable/Move(atom/newloc, direct) - set waitfor = FALSE //n o +/atom/movable/Move(atom/newloc, direct, glide_size_override = 0) var/atom/movable/pullee = pulling var/turf/T = loc if(!moving_from_pull) @@ -61,6 +59,9 @@ if(!loc || !newloc) return FALSE var/atom/oldloc = loc + //Early override for some cases like diagonal movement + if(glide_size_override) + set_glide_size(glide_size_override) if(loc != newloc) if (!(direct & (direct - 1))) //Cardinal move @@ -120,32 +121,38 @@ return if(!loc || (loc == oldloc && oldloc != newloc)) - last_move = NONE + last_move = 0 return if(.) - last_move = direct - setDir(direct) - - if(has_buckled_mobs() && !handle_buckled_mob_movement(loc,direct)) //movement failed due to buckled mob(s) - return FALSE - - if(pulling && pulling == pullee && pulling != moving_from_pull) //we were pulling a thing and didn't lose it during our move. - if(pulling.anchored) - stop_pulling() - else - var/pull_dir = get_dir(src, pulling) - //puller and pullee more than one tile away or in diagonal position - if(get_dist(src, pulling) > 1 || (moving_diagonally != SECOND_DIAG_STEP && ((pull_dir - 1) & pull_dir))) - pulling.moving_from_pull = src - pulling.Move(T, get_dir(pulling, T)) //the pullee tries to reach our previous position - pulling.moving_from_pull = null Moved(oldloc, direct) + if(. && pulling && pulling == pullee && pulling != moving_from_pull) //we were pulling a thing and didn't lose it during our move. + if(pulling.anchored) + stop_pulling() + else + var/pull_dir = get_dir(src, pulling) + //puller and pullee more than one tile away or in diagonal position + if(get_dist(src, pulling) > 1 || (moving_diagonally != SECOND_DIAG_STEP && ((pull_dir - 1) & pull_dir))) + pulling.moving_from_pull = src + pulling.Move(T, get_dir(pulling, T), glide_size) //the pullee tries to reach our previous position + pulling.moving_from_pull = null + check_pulling() -/atom/movable/proc/handle_buckled_mob_movement(newloc,direct) + + //glide_size strangely enough can change mid movement animation and update correctly while the animation is playing + //This means that if you don't override it late like this, it will just be set back by the movement update that's called when you move turfs. + if(glide_size_override) + set_glide_size(glide_size_override) + + last_move = direct + setDir(direct) + if(. && has_buckled_mobs() && !handle_buckled_mob_movement(loc, direct, glide_size_override)) //movement failed due to buckled mob(s) + return FALSE + +/atom/movable/proc/handle_buckled_mob_movement(newloc, direct, glide_size_override) for(var/m in buckled_mobs) var/mob/living/buckled_mob = m - if(!buckled_mob.Move(newloc, direct)) + if(!buckled_mob.Move(newloc, direct, glide_size_override)) forceMove(buckled_mob.loc) last_move = buckled_mob.last_move inertia_dir = last_move @@ -155,6 +162,7 @@ //Called after a successful Move(). By this point, we've already moved /atom/movable/proc/Moved(atom/OldLoc, Dir, Forced = FALSE) + SHOULD_CALL_PARENT(TRUE) SEND_SIGNAL(src, COMSIG_MOVABLE_MOVED, OldLoc, Dir, Forced) if (!inertia_moving) inertia_next_move = world.time + inertia_move_delay @@ -174,6 +182,8 @@ //oldloc = old location on atom, inserted when forceMove is called and ONLY when forceMove is called! /atom/movable/Crossed(atom/movable/AM, oldloc) + // SHOULD_CALL_PARENT(TRUE) + . = ..() SEND_SIGNAL(src, COMSIG_MOVABLE_CROSSED, AM) /atom/movable/Uncross(atom/movable/AM, atom/newloc) @@ -204,7 +214,11 @@ var/atom/movable/AM = item AM.onTransitZ(old_z,new_z) +///Proc to modify the movement_type and hook behavior associated with it changing. /atom/movable/proc/setMovetype(newval) + if(movement_type == newval) + return + . = movement_type movement_type = newval ///////////// FORCED MOVEMENT ///////////// @@ -268,37 +282,44 @@ old_area.Exited(src, null) loc = null -//Called whenever an object moves and by mobs when they attempt to move themselves through space -//And when an object or action applies a force on src, see newtonian_move() below -//Return 0 to have src start/keep drifting in a no-grav area and 1 to stop/not start drifting -//Mobs should return 1 if they should be able to move of their own volition, see client/Move() in mob_movement.dm -//movement_dir == 0 when stopping or any dir when trying to move +/** + * Called whenever an object moves and by mobs when they attempt to move themselves through space + * And when an object or action applies a force on src, see [newtonian_move][/atom/movable/proc/newtonian_move] + * + * Return 0 to have src start/keep drifting in a no-grav area and 1 to stop/not start drifting + * + * Mobs should return 1 if they should be able to move of their own volition, see [/client/proc/Move] + * + * Arguments: + * * movement_dir - 0 when stopping or any dir when trying to move + */ /atom/movable/proc/Process_Spacemove(movement_dir = 0) if(has_gravity(src)) - return 1 + return TRUE - if(pulledby) - return 1 + if(pulledby && (pulledby.pulledby != src || moving_from_pull)) + return TRUE if(throwing) - return 1 + return TRUE if(!isturf(loc)) - return 1 + return TRUE if(locate(/obj/structure/lattice) in range(1, get_turf(src))) //Not realistic but makes pushing things in space easier - return 1 + return TRUE - return 0 + return FALSE -/atom/movable/proc/newtonian_move(direction) //Only moves the object if it's under no gravity - if(!loc || Process_Spacemove(0)) +/// Only moves the object if it's under no gravity +/atom/movable/proc/newtonian_move(direction) + if(!isturf(loc) || Process_Spacemove(0)) inertia_dir = 0 - return 0 + return FALSE inertia_dir = direction if(!direction) - return 1 + return TRUE inertia_last_loc = loc SSspacedrift.processing[src] = src - return 1 + return TRUE diff --git a/code/game/machinery/doors/alarmlock.dm b/code/game/machinery/doors/alarmlock.dm index a563200575..fa516f4b6b 100644 --- a/code/game/machinery/doors/alarmlock.dm +++ b/code/game/machinery/doors/alarmlock.dm @@ -23,7 +23,7 @@ . = ..() SSradio.remove_object(src, air_frequency) air_connection = SSradio.add_object(src, air_frequency, RADIO_TO_AIRALARM) - open() + INVOKE_ASYNC(src, .proc/open) /obj/machinery/door/airlock/alarmlock/receive_signal(datum/signal/signal) ..() diff --git a/code/game/machinery/slotmachine.dm b/code/game/machinery/slotmachine.dm index 6282d74346..1fadad168e 100644 --- a/code/game/machinery/slotmachine.dm +++ b/code/game/machinery/slotmachine.dm @@ -11,6 +11,8 @@ #define SPIN_TIME 65 //As always, deciseconds. #define REEL_DEACTIVATE_DELAY 7 #define SEVEN "7" +#define HOLOCHIP 1 +#define COIN 2 /obj/machinery/computer/slot_machine name = "slot machine" @@ -21,40 +23,48 @@ use_power = IDLE_POWER_USE idle_power_usage = 50 circuit = /obj/item/circuitboard/computer/slot_machine + light_color = LIGHT_COLOR_BROWN var/money = 3000 //How much money it has CONSUMED var/plays = 0 - var/working = 0 + var/working = FALSE var/balance = 0 //How much money is in the machine, ready to be CONSUMED. var/jackpots = 0 + var/paymode = HOLOCHIP //toggles between HOLOCHIP/COIN, defined above + var/cointype = /obj/item/coin/iron //default cointype + var/list/coinvalues = list() var/list/reels = list(list("", "", "") = 0, list("", "", "") = 0, list("", "", "") = 0, list("", "", "") = 0, list("", "", "") = 0) var/list/symbols = list(SEVEN = 1, "&" = 2, "@" = 2, "$" = 2, "?" = 2, "#" = 2, "!" = 2, "%" = 2) //if people are winning too much, multiply every number in this list by 2 and see if they are still winning too much. - light_color = LIGHT_COLOR_BROWN /obj/machinery/computer/slot_machine/Initialize() . = ..() jackpots = rand(1, 4) //false hope plays = rand(75, 200) - toggle_reel_spin(1) //The reels won't spin unless we activate them + INVOKE_ASYNC(src, .proc/toggle_reel_spin, TRUE)//The reels won't spin unless we activate them var/list/reel = reels[1] for(var/i = 0, i < reel.len, i++) //Populate the reels. randomize_reels() - toggle_reel_spin(0) + INVOKE_ASYNC(src, .proc/toggle_reel_spin, FALSE) + + for(cointype in typesof(/obj/item/coin)) + var/obj/item/coin/C = new cointype + coinvalues["[cointype]"] = C.get_item_credit_value() + qdel(C) //Sigh /obj/machinery/computer/slot_machine/Destroy() if(balance) - give_coins(balance) + give_payout(balance) return ..() -/obj/machinery/computer/slot_machine/process() +/obj/machinery/computer/slot_machine/process(delta_time) . = ..() //Sanity checks. if(!.) return . - money++ //SPESSH MAJICKS + money += round(delta_time / 2) //SPESSH MAJICKS /obj/machinery/computer/slot_machine/update_icon_state() if(stat & NOPOWER) @@ -69,27 +79,46 @@ else icon_state = "slots1" -/obj/machinery/computer/slot_machine/power_change() - ..() - update_icon() - /obj/machinery/computer/slot_machine/attackby(obj/item/I, mob/living/user, params) if(istype(I, /obj/item/coin)) var/obj/item/coin/C = I - if(prob(2)) - if(!user.transferItemToLoc(C, drop_location())) - return - C.throw_at(user, 3, 10) - if(prob(10)) - balance = max(balance - SPIN_PRICE, 0) - to_chat(user, "[src] spits your coin back out!") + if(paymode == COIN) + if(prob(2)) + if(!user.transferItemToLoc(C, drop_location())) + return + C.throw_at(user, 3, 10) + if(prob(10)) + balance = max(balance - SPIN_PRICE, 0) + to_chat(user, "[src] spits your coin back out!") + else + if(!user.temporarilyRemoveItemFromInventory(C)) + return + to_chat(user, "You insert [C] into [src]'s slot!") + balance += C.value + qdel(C) else - if(!user.temporarilyRemoveItemFromInventory(C)) + to_chat(user, "This machine is only accepting holochips!") + else if(istype(I, /obj/item/holochip)) + if(paymode == HOLOCHIP) + var/obj/item/holochip/H = I + if(!user.temporarilyRemoveItemFromInventory(H)) return - to_chat(user, "You insert [C] into [src]'s slot!") - balance += C.value - qdel(C) + to_chat(user, "You insert [H.credits] holocredits into [src]'s slot!") + balance += H.credits + qdel(H) + else + to_chat(user, "This machine is only accepting coins!") + else if(I.tool_behaviour == TOOL_MULTITOOL) + if(balance > 0) + visible_message("[src] says, 'ERROR! Please empty the machine balance before altering paymode'") //Prevents converting coins into holocredits and vice versa + else + if(paymode == HOLOCHIP) + paymode = COIN + visible_message("[src] says, 'This machine now works with COINS!'") + else + paymode = HOLOCHIP + visible_message("[src] says, 'This machine now works with HOLOCHIPS!'") else return ..() @@ -101,8 +130,7 @@ var/datum/effect_system/spark_spread/spark_system = new /datum/effect_system/spark_spread() spark_system.set_up(4, 0, src.loc) spark_system.start() - playsound(src, "sparks", 50, 1) - return TRUE + playsound(src, "sparks", 50, TRUE) /obj/machinery/computer/slot_machine/ui_interact(mob/living/user) . = ..() @@ -127,8 +155,9 @@ Play!

[reeltext] -
- Refund balance
"} +
"} + if(balance > 0) + dat+="Refund balance
" var/datum/browser/popup = new(user, "slotmachine", "Slot Machine") popup.set_content(dat) @@ -143,21 +172,22 @@ spin(usr) else if(href_list["refund"]) - give_coins(balance) - balance = 0 + if(balance > 0) + give_payout(balance) + balance = 0 /obj/machinery/computer/slot_machine/emp_act(severity) . = ..() if(stat & (NOPOWER|BROKEN) || . & EMP_PROTECT_SELF) return - if(prob(1500 / severity)) + if(prob(15 * severity)) return - if(prob(1 * severity/100)) // :^) + if(prob(1)) // :^) obj_flags |= EMAGGED var/severity_ascending = 4 - severity money = max(rand(money - (200 * severity_ascending), money + (200 * severity_ascending)), 0) balance = max(rand(balance - (50 * severity_ascending), balance + (50 * severity_ascending)), 0) - money -= max(0, give_coins(min(rand(-50, 100 * severity_ascending)), money)) //This starts at -50 because it shouldn't always dispense coins yo + money -= max(0, give_payout(min(rand(-50, 100 * severity_ascending)), money)) //This starts at -50 because it shouldn't always dispense coins yo spin() /obj/machinery/computer/slot_machine/proc/spin(mob/user) @@ -174,37 +204,43 @@ balance -= SPIN_PRICE money += SPIN_PRICE plays += 1 - working = 1 + working = TRUE toggle_reel_spin(1) update_icon() updateDialog() - spawn(0) - while(working) - randomize_reels() - updateDialog() - sleep(2) + var/spin_loop = addtimer(CALLBACK(src, .proc/do_spin), 2, TIMER_LOOP|TIMER_STOPPABLE) - spawn(SPIN_TIME - (REEL_DEACTIVATE_DELAY * reels.len)) //WARNING: no sanity checking for user since it's not needed and would complicate things (machine should still spin even if user is gone), be wary of this if you're changing this code. - toggle_reel_spin(0, REEL_DEACTIVATE_DELAY) - working = 0 - give_prizes(the_name, user) - update_icon() - updateDialog() + addtimer(CALLBACK(src, .proc/finish_spinning, spin_loop, user, the_name), SPIN_TIME - (REEL_DEACTIVATE_DELAY * reels.len)) + //WARNING: no sanity checking for user since it's not needed and would complicate things (machine should still spin even if user is gone), be wary of this if you're changing this code. + +/obj/machinery/computer/slot_machine/proc/do_spin() + randomize_reels() + updateDialog() + +/obj/machinery/computer/slot_machine/proc/finish_spinning(spin_loop, mob/user, the_name) + toggle_reel_spin(0, REEL_DEACTIVATE_DELAY) + working = FALSE + deltimer(spin_loop) + give_prizes(the_name, user) + update_icon() + updateDialog() /obj/machinery/computer/slot_machine/proc/can_spin(mob/user) if(stat & NOPOWER) to_chat(user, "The slot machine has no power!") + return FALSE if(stat & BROKEN) to_chat(user, "The slot machine is broken!") + return FALSE if(working) to_chat(user, "You need to wait until the machine stops spinning before you can play again!") - return 0 + return FALSE if(balance < SPIN_PRICE) to_chat(user, "Insufficient money to play!") - return 0 - return 1 + return FALSE + return TRUE /obj/machinery/computer/slot_machine/proc/toggle_reel_spin(value, delay = 0) //value is 1 or 0 aka on or off for(var/list/reel in reels) @@ -223,23 +259,25 @@ var/linelength = get_lines() if(reels[1][2] + reels[2][2] + reels[3][2] + reels[4][2] + reels[5][2] == "[SEVEN][SEVEN][SEVEN][SEVEN][SEVEN]") - visible_message("[src] says, 'JACKPOT! You win [money] credits worth of coins!'") + visible_message("[src] says, 'JACKPOT! You win [money] credits!'") priority_announce("Congratulations to [user ? user.real_name : usrname] for winning the jackpot at the slot machine in [get_area(src)]!") jackpots += 1 - balance += money - give_coins(JACKPOT) + balance += money - give_payout(JACKPOT) money = 0 - - for(var/i = 0, i < 5, i++) - var/cointype = pick(subtypesof(/obj/item/coin)) - var/obj/item/coin/C = new cointype(loc) - random_step(C, 2, 50) + if(paymode == HOLOCHIP) + new /obj/item/holochip(loc,JACKPOT) + else + for(var/i = 0, i < 5, i++) + cointype = pick(subtypesof(/obj/item/coin)) + var/obj/item/coin/C = new cointype(loc) + random_step(C, 2, 50) else if(linelength == 5) - visible_message("[src] says, 'Big Winner! You win a thousand credits worth of coins!'") + visible_message("[src] says, 'Big Winner! You win a thousand credits!'") give_money(BIG_PRIZE) else if(linelength == 4) - visible_message("[src] says, 'Winner! You win four hundred credits worth of coins!'") + visible_message("[src] says, 'Winner! You win four hundred credits!'") give_money(SMALL_PRIZE) else if(linelength == 3) @@ -271,12 +309,15 @@ /obj/machinery/computer/slot_machine/proc/give_money(amount) var/amount_to_give = money >= amount ? amount : money - var/surplus = amount_to_give - give_coins(amount_to_give) + var/surplus = amount_to_give - give_payout(amount_to_give) money = max(0, money - amount) balance += surplus -/obj/machinery/computer/slot_machine/proc/give_coins(amount) - var/cointype = obj_flags & EMAGGED ? /obj/item/coin/iron : /obj/item/coin/silver +/obj/machinery/computer/slot_machine/proc/give_payout(amount) + if(paymode == HOLOCHIP) + cointype = /obj/item/holochip + else + cointype = obj_flags & EMAGGED ? /obj/item/coin/iron : /obj/item/coin/silver if(!(obj_flags & EMAGGED)) amount = dispense(amount, cointype, null, 0) @@ -288,22 +329,25 @@ return amount -/obj/machinery/computer/slot_machine/proc/dispense(amount = 0, cointype = /obj/item/coin/silver, mob/living/target, throwit = FALSE) - var/value = GLOB.coin_values[cointype] || GLOB.coin_values[/obj/item/coin/iron] - INVOKE_ASYNC(src, .proc/become_rich, amount, value, cointype, target, throwit) - return amount % value +/obj/machinery/computer/slot_machine/proc/dispense(amount = 0, cointype = /obj/item/coin/silver, mob/living/target, throwit = 0) + if(paymode == HOLOCHIP) + var/obj/item/holochip/H = new /obj/item/holochip(loc,amount) -/obj/machinery/computer/slot_machine/proc/become_rich(amount, value, cointype = /obj/item/coin/silver, mob/living/target, throwit = FALSE) - if(value <= 0) - return - while(amount >= value && !QDELETED(src)) - var/obj/item/coin/C = new cointype(loc) //DOUBLE THE PAIN - amount -= value if(throwit && target) - C.throw_at(target, 3, 10) - else - random_step(C, 2, 40) - CHECK_TICK + H.throw_at(target, 3, 10) + else + var/value = coinvalues["[cointype]"] + if(value <= 0) + CRASH("Coin value of zero, refusing to payout in dispenser") + while(amount >= value) + var/obj/item/coin/C = new cointype(loc) //DOUBLE THE PAIN + amount -= value + if(throwit && target) + C.throw_at(target, 3, 10) + else + random_step(C, 2, 40) + + return amount #undef SEVEN #undef SPIN_TIME @@ -311,3 +355,5 @@ #undef BIG_PRIZE #undef SMALL_PRIZE #undef SPIN_PRICE +#undef HOLOCHIP +#undef COIN diff --git a/code/game/objects/effects/alien_acid.dm b/code/game/objects/effects/alien_acid.dm index 5276062121..6496b392c3 100644 --- a/code/game/objects/effects/alien_acid.dm +++ b/code/game/objects/effects/alien_acid.dm @@ -53,6 +53,7 @@ return 0 /obj/effect/acid/Crossed(AM as mob|obj) + . = ..() if(isliving(AM)) var/mob/living/L = AM if(L.movement_type & FLYING) diff --git a/code/game/objects/effects/anomalies.dm b/code/game/objects/effects/anomalies.dm index 9d6d034364..8f8b83bfde 100644 --- a/code/game/objects/effects/anomalies.dm +++ b/code/game/objects/effects/anomalies.dm @@ -138,7 +138,7 @@ /obj/effect/anomaly/grav/high/Initialize(mapload, new_lifespan) . = ..() - setup_grav_field() + INVOKE_ASYNC(src, .proc/setup_grav_field) /obj/effect/anomaly/grav/high/proc/setup_grav_field() grav_field = make_field(/datum/proximity_monitor/advanced/gravity, list("current_range" = 7, "host" = src, "gravity_value" = rand(0,3))) diff --git a/code/game/objects/effects/decals/cleanable/robots.dm b/code/game/objects/effects/decals/cleanable/robots.dm index 2765330977..62086fc540 100644 --- a/code/game/objects/effects/decals/cleanable/robots.dm +++ b/code/game/objects/effects/decals/cleanable/robots.dm @@ -65,4 +65,5 @@ /obj/effect/decal/cleanable/oil/slippery /obj/effect/decal/cleanable/oil/slippery/Initialize() + . = ..() AddComponent(/datum/component/slippery, 80, (NO_SLIP_WHEN_WALKING | SLIDE)) diff --git a/code/game/objects/effects/proximity.dm b/code/game/objects/effects/proximity.dm index ab35d213ea..5c477501f4 100644 --- a/code/game/objects/effects/proximity.dm +++ b/code/game/objects/effects/proximity.dm @@ -5,6 +5,7 @@ var/list/checkers //list of /obj/effect/abstract/proximity_checkers var/current_range var/ignore_if_not_on_turf //don't check turfs in range if the host's loc isn't a turf + var/wire = FALSE /datum/proximity_monitor/New(atom/_host, range, _ignore_if_not_on_turf = TRUE) checkers = list() @@ -35,6 +36,8 @@ return ..() /datum/proximity_monitor/proc/HandleMove() + SIGNAL_HANDLER + var/atom/_host = host var/atom/new_host_loc = _host.loc if(last_host_loc != new_host_loc) @@ -58,6 +61,8 @@ var/atom/_host = host var/atom/loc_to_use = ignore_if_not_on_turf ? _host.loc : get_turf(_host) + if(wire && !isturf(loc_to_use)) //it makes assemblies attached on wires work + loc_to_use = get_turf(loc_to_use) if(!isturf(loc_to_use)) //only check the host's loc if(range) var/obj/effect/abstract/proximity_checker/pc @@ -109,4 +114,5 @@ /obj/effect/abstract/proximity_checker/Crossed(atom/movable/AM) set waitfor = FALSE - monitor?.hasprox_receiver.HasProximity(AM) + . = ..() + monitor?.hasprox_receiver?.HasProximity(AM) diff --git a/code/game/objects/effects/spawners/bundle.dm b/code/game/objects/effects/spawners/bundle.dm index 4304fc3c9c..58cd0f4fa9 100644 --- a/code/game/objects/effects/spawners/bundle.dm +++ b/code/game/objects/effects/spawners/bundle.dm @@ -170,6 +170,7 @@ /obj/item/clothing/under/rank/civilian/mime/sexy) /obj/effect/spawner/bundle/crate/Initialize(mapload) + SHOULD_CALL_PARENT(FALSE) if(items && items.len) var/turf/T = get_turf(src) var/obj/structure/closet/LC = locate(/obj/structure/closet) in T diff --git a/code/game/objects/items/grenades/plastic.dm b/code/game/objects/items/grenades/plastic.dm index 014487332c..5f93f28786 100644 --- a/code/game/objects/items/grenades/plastic.dm +++ b/code/game/objects/items/grenades/plastic.dm @@ -84,6 +84,7 @@ /obj/item/grenade/plastic/Crossed(atom/movable/AM) if(nadeassembly) nadeassembly.Crossed(AM) + . = ..() /obj/item/grenade/plastic/on_found(mob/finder) if(nadeassembly) diff --git a/code/game/objects/items/plushes.dm b/code/game/objects/items/plushes.dm index 9bc20565a6..557ae1c731 100644 --- a/code/game/objects/items/plushes.dm +++ b/code/game/objects/items/plushes.dm @@ -447,6 +447,7 @@ GLOBAL_LIST_INIT(valid_plushie_paths, valid_plushie_paths()) can_random_spawn = FALSE /obj/item/toy/plush/random/Initialize() + SHOULD_CALL_PARENT(FALSE) var/newtype var/list/snowflake_list = CONFIG_GET(keyed_list/snowflake_plushies) diff --git a/code/game/objects/items/puzzle_pieces.dm b/code/game/objects/items/puzzle_pieces.dm index 648ba27897..432247eb9a 100644 --- a/code/game/objects/items/puzzle_pieces.dm +++ b/code/game/objects/items/puzzle_pieces.dm @@ -134,11 +134,10 @@ /obj/item/pressure_plate/hologrid/Crossed(atom/movable/AM) . = ..() if(trigger_item && istype(AM, specific_item) && !claimed) - AM.anchored = TRUE + AM.set_anchored(TRUE) flick("laserbox_burn", AM) trigger() - sleep(15) - qdel(AM) + QDEL_IN(AM, 15) // snowflake code until undertile elements /obj/item/pressure_plate/hologrid/hide() diff --git a/code/game/objects/items/stacks/stack.dm b/code/game/objects/items/stacks/stack.dm index 3e2bb675fa..520a400630 100644 --- a/code/game/objects/items/stacks/stack.dm +++ b/code/game/objects/items/stacks/stack.dm @@ -65,7 +65,7 @@ if(merge) for(var/obj/item/stack/S in loc) if(S.merge_type == merge_type) - merge(S) + INVOKE_ASYNC(src, .proc/merge, S) var/list/temp_recipes = get_main_recipes() recipes = temp_recipes.Copy() if(material_type) diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm index 4e82df2452..97fced4eb7 100644 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -531,6 +531,7 @@ pop_burst() /obj/item/toy/snappop/Crossed(H as mob|obj) + . = ..() if(ishuman(H) || issilicon(H)) //i guess carp and shit shouldn't set them off var/mob/living/carbon/M = H if(issilicon(H) || M.m_intent == MOVE_INTENT_RUN) diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm index 31f11a199c..1ef0726e63 100644 --- a/code/game/objects/structures/tables_racks.dm +++ b/code/game/objects/structures/tables_racks.dm @@ -269,13 +269,13 @@ UnregisterSignal(source, COMSIG_MOVABLE_MOVED) /obj/structure/table/rolling/Moved(atom/OldLoc, Dir) + . = ..() for(var/mob/M in OldLoc.contents)//Kidnap everyone on top M.forceMove(loc) for(var/x in attached_items) var/atom/movable/AM = x if(!AM.Move(loc)) RemoveItemFromTable(AM, AM.loc) - return TRUE /* * Glass tables diff --git a/code/game/objects/structures/traps.dm b/code/game/objects/structures/traps.dm index 4c8379d14f..e6a76f36ca 100644 --- a/code/game/objects/structures/traps.dm +++ b/code/game/objects/structures/traps.dm @@ -56,6 +56,7 @@ animate(src, alpha = initial(alpha), time = time_between_triggers) /obj/structure/trap/Crossed(atom/movable/AM) + . = ..() if(last_trigger + time_between_triggers > world.time) return // Don't want the traps triggered by sparks, ghosts or projectiles. @@ -67,6 +68,7 @@ return if(M.anti_magic_check()) flare() + return if(charges <= 0) return flare() diff --git a/code/game/turfs/space/space.dm b/code/game/turfs/space/space.dm index b150d4930e..586b425be7 100644 --- a/code/game/turfs/space/space.dm +++ b/code/game/turfs/space/space.dm @@ -24,7 +24,13 @@ //This is used to optimize the map loader return +/** + * Space Initialize + * + * Doesn't call parent, see [/atom/proc/Initialize] + */ /turf/open/space/Initialize() + SHOULD_CALL_PARENT(FALSE) icon_state = SPACE_ICON_STATE air = space_gas update_air_ref() @@ -35,6 +41,15 @@ stack_trace("Warning: [src]([type]) initialized multiple times!") flags_1 |= INITIALIZED_1 + // if (length(smoothing_groups)) + // sortTim(smoothing_groups) //In case it's not properly ordered, let's avoid duplicate entries with the same values. + // SET_BITFLAG_LIST(smoothing_groups) + // if (length(canSmoothWith)) + // sortTim(canSmoothWith) + // if(canSmoothWith[length(canSmoothWith)] > MAX_S_TURF) //If the last element is higher than the maximum turf-only value, then it must scan turf contents for smoothing targets. + // smoothing_flags |= SMOOTH_OBJ + // SET_BITFLAG_LIST(canSmoothWith) + var/area/A = loc if(!IS_DYNAMIC_LIGHTING(src) && IS_DYNAMIC_LIGHTING(A)) add_overlay(/obj/effect/fullbright) @@ -48,6 +63,13 @@ if (opacity) has_opaque_atom = TRUE + var/turf/T = SSmapping.get_turf_above(src) + if(T) + T.multiz_turf_new(src, DOWN) + T = SSmapping.get_turf_below(src) + if(T) + T.multiz_turf_new(src, UP) + ComponentInitialize() return INITIALIZE_HINT_NORMAL @@ -73,6 +95,10 @@ /turf/open/space/Assimilate_Air() return +//IT SHOULD RETURN NULL YOU MONKEY, WHY IN TARNATION WHAT THE FUCKING FUCK +/turf/open/space/remove_air(amount) + return null + /turf/open/space/proc/update_starlight() if(CONFIG_GET(flag/starlight)) for(var/t in RANGE_TURFS(1,src)) //RANGE_TURFS is in code\__HELPERS\game.dm @@ -89,9 +115,8 @@ /turf/open/space/proc/CanBuildHere() return TRUE -/turf/open/space/handle_slip(mob/living/carbon/C, knockdown_amount, obj/O, lube) - if(lube & FLYING_DOESNT_HELP) - return ..() +/turf/open/space/handle_slip() + return // no lube bullshit, this is space /turf/open/space/attackby(obj/item/C, mob/user, params) ..() @@ -106,15 +131,16 @@ return if(L) if(R.use(1)) + qdel(L) to_chat(user, "You construct a catwalk.") - playsound(src, 'sound/weapons/genhit.ogg', 50, 1) + playsound(src, 'sound/weapons/genhit.ogg', 50, TRUE) new/obj/structure/lattice/catwalk(src) else to_chat(user, "You need two rods to build a catwalk!") return if(R.use(1)) to_chat(user, "You construct a lattice.") - playsound(src, 'sound/weapons/genhit.ogg', 50, 1) + playsound(src, 'sound/weapons/genhit.ogg', 50, TRUE) ReplaceWithLattice() else to_chat(user, "You need one rod to build a lattice.") @@ -125,7 +151,7 @@ var/obj/item/stack/tile/plasteel/S = C if(S.use(1)) qdel(L) - playsound(src, 'sound/weapons/genhit.ogg', 50, 1) + playsound(src, 'sound/weapons/genhit.ogg', 50, TRUE) to_chat(user, "You build a floor.") PlaceOnTop(/turf/open/floor/plating, flags = CHANGETURF_INHERIT_AIR) else diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index 55d945535d..c2fee908fb 100755 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -1,8 +1,11 @@ +GLOBAL_LIST_EMPTY(station_turfs) + +/// Any floor or wall. What makes up the station and the rest of the map. /turf icon = 'icons/turf/floors.dmi' - level = 1 - vis_flags = VIS_INHERIT_PLANE|VIS_INHERIT_ID //when this be added to vis_contents of something it inherit something.plane and be associatet with something on clicking, - //important for visualisation of turf in openspace and interraction with openspace that show you turf. + flags_1 = CAN_BE_DIRTY_1 + vis_flags = VIS_INHERIT_ID|VIS_INHERIT_PLANE // Important for interaction with and visualization of openspace. + luminosity = 1 var/intact = 1 @@ -19,8 +22,6 @@ var/blocks_air = FALSE - flags_1 = CAN_BE_DIRTY_1 - var/list/image/blueprint_data //for the station blueprints, images of objects eg: pipes var/explosion_level = 0 //for preventing explosion dodging @@ -41,7 +42,13 @@ return FALSE . = ..() +/** + * Turf Initialize + * + * Doesn't call parent, see [/atom/proc/Initialize] + */ /turf/Initialize(mapload) + SHOULD_CALL_PARENT(FALSE) if(flags_1 & INITIALIZED_1) stack_trace("Warning: [src]([type]) initialized multiple times!") flags_1 |= INITIALIZED_1 @@ -49,7 +56,7 @@ // by default, vis_contents is inherited from the turf that was here before vis_contents.Cut() - if(color) + if(color) // is this being used? This is here because parent isn't being called add_atom_colour(color, FIXED_COLOUR_PRIORITY) assemble_baseturfs() @@ -57,6 +64,7 @@ levelupdate() if(smooth) queue_smooth(src) + visibilityChanged() for(var/atom/movable/AM in src) @@ -76,11 +84,10 @@ var/turf/T = SSmapping.get_turf_above(src) if(T) T.multiz_turf_new(src, DOWN) - SEND_SIGNAL(T, COMSIG_TURF_MULTIZ_NEW, src, DOWN) T = SSmapping.get_turf_below(src) if(T) T.multiz_turf_new(src, UP) - SEND_SIGNAL(T, COMSIG_TURF_MULTIZ_NEW, src, UP) + if (opacity) has_opaque_atom = TRUE @@ -112,8 +119,6 @@ var/turf/B = new world.turf(src) for(var/A in B.contents) qdel(A) - for(var/I in B.vars) - B.vars[I] = null return SSair.remove_from_active(src) visibilityChanged() @@ -122,12 +127,14 @@ requires_activation = FALSE ..() -/turf/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) +/turf/on_attack_hand(mob/user) user.Move_Pulled(src) /turf/proc/multiz_turf_del(turf/T, dir) + // SEND_SIGNAL(src, COMSIG_TURF_MULTIZ_DEL, T, dir) /turf/proc/multiz_turf_new(turf/T, dir) + SEND_SIGNAL(src, COMSIG_TURF_MULTIZ_NEW, T, dir) //zPassIn doesn't necessarily pass an atom! //direction is direction of travel of air @@ -158,13 +165,14 @@ prev_turf.visible_message("[mov_name] falls through [prev_turf]!") if(flags & FALL_INTERCEPTED) return - if(zFall(A, ++levels)) + if(zFall(A, levels + 1)) return FALSE A.visible_message("[A] crashes into [src]!") A.onZImpact(src, levels) return TRUE /turf/proc/can_zFall(atom/movable/A, levels = 1, turf/target) + SHOULD_BE_PURE(TRUE) return zPassOut(A, DOWN, target) && target.zPassIn(A, DOWN, src) /turf/proc/zFall(atom/movable/A, levels = 1, force = FALSE) @@ -217,49 +225,54 @@ stack_trace("Non movable passed to turf CanPass : [mover]") return FALSE +//There's a lot of QDELETED() calls here if someone can figure out how to optimize this but not runtime when something gets deleted by a Bump/CanPass/Cross call, lemme know or go ahead and fix this mess - kevinz000 /turf/Enter(atom/movable/mover, atom/oldloc) // Do not call ..() // Byond's default turf/Enter() doesn't have the behaviour we want with Bump() // By default byond will call Bump() on the first dense object in contents // Here's hoping it doesn't stay like this for years before we finish conversion to step_ var/atom/firstbump - if(!CanPass(mover, src)) - firstbump = src - else + var/canPassSelf = CanPass(mover, src) + if(canPassSelf || (mover.movement_type & UNSTOPPABLE)) for(var/i in contents) + if(QDELETED(mover)) + return FALSE //We were deleted, do not attempt to proceed with movement. if(i == mover || i == mover.loc) // Multi tile objects and moving out of other objects continue - if(QDELETED(mover)) - break var/atom/movable/thing = i if(!thing.Cross(mover)) - if(CHECK_BITFIELD(mover.movement_type, UNSTOPPABLE)) + if(QDELETED(mover)) //Mover deleted from Cross/CanPass, do not proceed. + return FALSE + if((mover.movement_type & UNSTOPPABLE)) mover.Bump(thing) continue else if(!firstbump || ((thing.layer > firstbump.layer || thing.flags_1 & ON_BORDER_1) && !(firstbump.flags_1 & ON_BORDER_1))) firstbump = thing + if(QDELETED(mover)) //Mover deleted from Cross/CanPass/Bump, do not proceed. + return FALSE + if(!canPassSelf) //Even if mover is unstoppable they need to bump us. + firstbump = src if(firstbump) - if(!QDELETED(mover)) - mover.Bump(firstbump) - return CHECK_BITFIELD(mover.movement_type, UNSTOPPABLE) + mover.Bump(firstbump) + return (mover.movement_type & UNSTOPPABLE) return TRUE /turf/Exit(atom/movable/mover, atom/newloc) . = ..() - if(!.) + if(!. || QDELETED(mover)) return FALSE for(var/i in contents) - if(QDELETED(mover)) - break if(i == mover) continue var/atom/movable/thing = i if(!thing.Uncross(mover, newloc)) if(thing.flags_1 & ON_BORDER_1) mover.Bump(thing) - if(!CHECK_BITFIELD(mover.movement_type, UNSTOPPABLE)) + if(!(mover.movement_type & UNSTOPPABLE)) return FALSE + if(QDELETED(mover)) + return FALSE //We were deleted. /turf/Entered(atom/movable/AM) ..() @@ -271,6 +284,7 @@ has_opaque_atom = TRUE // Make sure to do this before reconsider_lights(), incase we're on instant updates. Guaranteed to be on in this case. reconsider_lights() + /turf/open/Entered(atom/movable/AM) ..() //melting @@ -278,7 +292,6 @@ var/obj/O = AM if(O.obj_flags & FROZEN) O.make_unfrozen() - if(!AM.zfalling) zFall(AM) @@ -336,14 +349,13 @@ /turf/proc/levelupdate() for(var/obj/O in src) - if(O.level == 1 && (O.flags_1 & INITIALIZED_1)) - O.hide(src.intact) + if(O.flags_1 & INITIALIZED_1) + // SEND_SIGNAL(O, COMSIG_OBJ_HIDE, intact) + O.hide(intact) // override for space turfs, since they should never hide anything /turf/open/space/levelupdate() - for(var/obj/O in src) - if(O.level == 1 && (O.flags_1 & INITIALIZED_1)) - O.hide(0) + return // Removes all signs of lattice on the pos of the turf -Donkieyo /turf/proc/RemoveLattice() @@ -368,13 +380,13 @@ if(.) return if(length(src_object.contents())) - to_chat(user, "You start dumping out the contents...") - if(!do_after(user,20,target=src_object.parent)) + to_chat(usr, "You start dumping out the contents...") + if(!do_after(usr,20,target=src_object.parent)) return FALSE var/list/things = src_object.contents() var/datum/progressbar/progress = new(user, things.len, src) - while (do_after(user, 10, TRUE, src, FALSE, CALLBACK(src_object, /datum/component/storage.proc/mass_remove_from_storage, src, things, progress))) + while (do_after(usr, 1 SECONDS, TRUE, src, FALSE, CALLBACK(src_object, /datum/component/storage.proc/mass_remove_from_storage, src, things, progress))) stoplag(1) qdel(progress) @@ -494,10 +506,8 @@ I.loc = src I.setDir(AM.dir) I.alpha = 128 - LAZYADD(blueprint_data, I) - /turf/proc/add_blueprints_preround(atom/movable/AM) if(!SSticker.HasRoundStarted()) add_blueprints(AM) @@ -531,7 +541,7 @@ if(!forced) return if(has_gravity(src)) - playsound(src, "bodyfall", 50, 1) + playsound(src, "bodyfall", 50, TRUE) faller.drop_all_held_items() /turf/proc/photograph(limit=20) diff --git a/code/modules/antagonists/bloodsucker/bloodsucker_sunlight.dm b/code/modules/antagonists/bloodsucker/bloodsucker_sunlight.dm index 43163f6a70..2cb50c6b3b 100644 --- a/code/modules/antagonists/bloodsucker/bloodsucker_sunlight.dm +++ b/code/modules/antagonists/bloodsucker/bloodsucker_sunlight.dm @@ -13,8 +13,9 @@ var/nightime_duration = 900 //15 Minutes /obj/effect/sunlight/Initialize() - countdown() - hud_tick() + . = ..() + INVOKE_ASYNC(src, .proc/countdown) + INVOKE_ASYNC(src, .proc/hud_tick) /obj/effect/sunlight/proc/countdown() set waitfor = FALSE diff --git a/code/modules/antagonists/clockcult/clock_structures/trap_triggers/pressure_sensor.dm b/code/modules/antagonists/clockcult/clock_structures/trap_triggers/pressure_sensor.dm index af29bc9b31..c5d1bc2ded 100644 --- a/code/modules/antagonists/clockcult/clock_structures/trap_triggers/pressure_sensor.dm +++ b/code/modules/antagonists/clockcult/clock_structures/trap_triggers/pressure_sensor.dm @@ -15,3 +15,5 @@ audible_message("*click*") playsound(src, 'sound/items/screwdriver2.ogg', 50, TRUE) activate() + + . = ..() diff --git a/code/modules/antagonists/clockcult/clock_structures/trap_triggers/pressure_sensor_mech.dm b/code/modules/antagonists/clockcult/clock_structures/trap_triggers/pressure_sensor_mech.dm index 10a5b7787f..21735ad6d7 100644 --- a/code/modules/antagonists/clockcult/clock_structures/trap_triggers/pressure_sensor_mech.dm +++ b/code/modules/antagonists/clockcult/clock_structures/trap_triggers/pressure_sensor_mech.dm @@ -8,7 +8,7 @@ alpha = 75 /obj/structure/destructible/clockwork/trap/trigger/pressure_sensor/mech/Crossed(atom/movable/AM) - + . = ..() if(!istype(AM,/obj/mecha/)) return diff --git a/code/modules/antagonists/clockcult/clock_structures/traps/steam_vent.dm b/code/modules/antagonists/clockcult/clock_structures/traps/steam_vent.dm index 6aede1592e..7d6eea1c79 100644 --- a/code/modules/antagonists/clockcult/clock_structures/traps/steam_vent.dm +++ b/code/modules/antagonists/clockcult/clock_structures/traps/steam_vent.dm @@ -21,3 +21,5 @@ if(isliving(AM) && opacity) var/mob/living/L = AM L.adjust_fire_stacks(-1) //It's wet! + return + . = ..() diff --git a/code/modules/assembly/holder.dm b/code/modules/assembly/holder.dm index bf56449a0c..84e70bbbb3 100644 --- a/code/modules/assembly/holder.dm +++ b/code/modules/assembly/holder.dm @@ -62,6 +62,7 @@ master.update_icon() /obj/item/assembly_holder/Crossed(atom/movable/AM as mob|obj) + . = ..() if(a_left) a_left.Crossed(AM) if(a_right) diff --git a/code/modules/atmospherics/environmental/LINDA_turf_tile.dm b/code/modules/atmospherics/environmental/LINDA_turf_tile.dm index eee8859485..244b51bd2b 100644 --- a/code/modules/atmospherics/environmental/LINDA_turf_tile.dm +++ b/code/modules/atmospherics/environmental/LINDA_turf_tile.dm @@ -49,6 +49,7 @@ SSair.add_to_active(T) return ..() +/// Function for Extools Atmos /turf/proc/update_air_ref() /////////////////GAS MIXTURE PROCS/////////////////// diff --git a/code/modules/awaymissions/capture_the_flag.dm b/code/modules/awaymissions/capture_the_flag.dm index 3426208fae..d32905e007 100644 --- a/code/modules/awaymissions/capture_the_flag.dm +++ b/code/modules/awaymissions/capture_the_flag.dm @@ -7,6 +7,8 @@ #define AMMO_DROP_LIFETIME 300 #define CTF_REQUIRED_PLAYERS 4 + + /obj/item/ctf name = "banner" icon = 'icons/obj/items_and_weapons.dmi' @@ -16,13 +18,13 @@ righthand_file = 'icons/mob/inhands/equipment/banners_righthand.dmi' desc = "A banner with Nanotrasen's logo on it." slowdown = 2 - item_flags = SLOWS_WHILE_IN_HAND throw_speed = 0 throw_range = 1 force = 200 armour_penetration = 1000 resistance_flags = INDESTRUCTIBLE anchored = TRUE + item_flags = SLOWS_WHILE_IN_HAND var/team = WHITE_TEAM var/reset_cooldown = 0 var/anyonecanpickup = TRUE @@ -53,12 +55,13 @@ to_chat(M, "\The [src] has been returned to base!") STOP_PROCESSING(SSobj, src) -/obj/item/ctf/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags) +//ATTACK HAND IGNORING PARENT RETURN VALUE +/obj/item/ctf/on_attack_hand(mob/living/user) if(!is_ctf_target(user) && !anyonecanpickup) - to_chat(user, "Non players shouldn't be moving the flag!") + to_chat(user, "Non-players shouldn't be moving the flag!") return if(team in user.faction) - to_chat(user, "You can't move your own flag!") + to_chat(user, "You can't move your own flag!") return if(loc == user) if(!user.dropItemToGround(src)) @@ -68,7 +71,7 @@ if(!user.put_in_active_hand(src)) dropped(user) return - user.anchored = TRUE + user.set_anchored(TRUE) user.status_flags &= ~CANPUSH for(var/mob/M in GLOB.player_list) var/area/mob_area = get_area(M) @@ -79,7 +82,7 @@ /obj/item/ctf/dropped(mob/user) ..() - user.anchored = FALSE + user.set_anchored(FALSE) user.status_flags |= CANPUSH reset_cooldown = world.time + 200 //20 seconds START_PROCESSING(SSobj, src) @@ -172,20 +175,20 @@ GLOB.poi_list.Remove(src) ..() -/obj/machinery/capture_the_flag/process() +/obj/machinery/capture_the_flag/process(delta_time) for(var/i in spawned_mobs) if(!i) spawned_mobs -= i continue // Anyone in crit, automatically reap - var/mob/living/M = i - if(M.InCritical() || M.stat == DEAD) - ctf_dust_old(M) + var/mob/living/living_participant = i + if(living_participant.InCritical() || living_participant.stat == DEAD) + ctf_dust_old(living_participant) else // The changes that you've been hit with no shield but not // instantly critted are low, but have some healing. - M.adjustBruteLoss(-5) - M.adjustFireLoss(-5) + living_participant.adjustBruteLoss(-2.5 * delta_time) + living_participant.adjustFireLoss(-2.5 * delta_time) /obj/machinery/capture_the_flag/red name = "Red CTF Controller" @@ -212,6 +215,10 @@ toggle_all_ctf(user) return + + // if(!(GLOB.ghost_role_flags & GHOSTROLE_MINIGAME)) + // to_chat(user, "CTF has been temporarily disabled by admins.") + // return people_who_want_to_play |= user.ckey var/num = people_who_want_to_play.len var/remaining = CTF_REQUIRED_PLAYERS - num @@ -227,7 +234,7 @@ return if(user.ckey in team_members) if(user.ckey in recently_dead_ckeys) - to_chat(user, "It must be more than [DisplayTimeText(respawn_cooldown)] from your last death to respawn!") + to_chat(user, "It must be more than [DisplayTimeText(respawn_cooldown)] from your last death to respawn!") return var/client/new_team_member = user.client if(user.mind && user.mind.current) @@ -239,10 +246,10 @@ if(CTF == src || CTF.ctf_enabled == FALSE) continue if(user.ckey in CTF.team_members) - to_chat(user, "No switching teams while the round is going!") + to_chat(user, "No switching teams while the round is going!") return if(CTF.team_members.len < src.team_members.len) - to_chat(user, "[src.team] has more team members than [CTF.team]. Try joining [CTF.team] team to even things up.") + to_chat(user, "[src.team] has more team members than [CTF.team]! Try joining [CTF.team] team to even things up.") return team_members |= user.ckey var/client/new_team_member = user.client @@ -258,7 +265,7 @@ addtimer(CALLBACK(src, .proc/clear_cooldown, body.ckey), respawn_cooldown, TIMER_UNIQUE) body.dust() -/obj/machinery/capture_the_flag/proc/clear_cooldown(var/ckey) +/obj/machinery/capture_the_flag/proc/clear_cooldown(ckey) recently_dead_ckeys -= ckey /obj/machinery/capture_the_flag/proc/spawn_team_member(client/new_team_member) @@ -270,7 +277,7 @@ M.equipOutfit(ctf_gear) M.dna.species.punchdamagehigh = 25 M.dna.species.punchdamagelow = 25 - M.AddElement(/datum/element/ghost_role_eligibility) + M.AddElement(/datum/element/ghost_role_eligibility) //?? spawned_mobs += M /obj/machinery/capture_the_flag/Topic(href, href_list) @@ -293,14 +300,15 @@ victory() /obj/machinery/capture_the_flag/proc/victory() - for(var/mob/M in GLOB.mob_list) - var/area/mob_area = get_area(M) + for(var/mob/_competitor in GLOB.mob_living_list) + var/mob/living/competitor = _competitor + var/area/mob_area = get_area(competitor) if(istype(mob_area, /area/ctf)) - to_chat(M, "[team] team wins!") - to_chat(M, "Teams have been cleared. Click on the machines to vote to begin another round.") - for(var/obj/item/ctf/W in M) - M.dropItemToGround(W) - M.dust() + to_chat(competitor, "[team] team wins!") + to_chat(competitor, "Teams have been cleared. Click on the machines to vote to begin another round.") + for(var/obj/item/ctf/W in competitor) + competitor.dropItemToGround(W) + competitor.dust() for(var/obj/machinery/control_point/control in GLOB.machines) control.icon_state = "dominator" control.controlling = null @@ -328,7 +336,7 @@ dead_barricades.Cut() - notify_ghosts("[name] has been activated!", enter_link="(Click to join the [team] team!) or click on the controller directly!", source = src, action=NOTIFY_ATTACK) + notify_ghosts("[name] has been activated!", enter_link="(Click to join the [team] team!) or click on the controller directly!", source = src, action=NOTIFY_ATTACK, header = "CTF has been activated") if(!arena_reset) reset_the_arena() @@ -355,10 +363,10 @@ ctf_enabled = FALSE arena_reset = FALSE var/area/A = get_area(src) - for(var/i in GLOB.mob_list) - var/mob/M = i - if((get_area(A) == A) && (M.ckey in team_members)) - M.dust() + for(var/_competitor in GLOB.mob_living_list) + var/mob/living/competitor = _competitor + if((get_area(A) == A) && (competitor.ckey in team_members)) + competitor.dust() team_members.Cut() spawned_mobs.Cut() recently_dead_ckeys.Cut() @@ -375,18 +383,18 @@ CTF.ctf_gear = initial(ctf_gear) CTF.respawn_cooldown = DEFAULT_RESPAWN -/proc/ctf_floor_vanish(atom/target) - if(isturf(target.loc)) - qdel(target) - /obj/item/gun/ballistic/automatic/pistol/deagle/ctf desc = "This looks like it could really hurt in melee." force = 75 mag_type = /obj/item/ammo_box/magazine/m50/ctf -/obj/item/gun/ballistic/automatic/pistol/deagle/ctf/dropped(mob/user) +/obj/item/gun/ballistic/automatic/pistol/deagle/ctf/dropped() . = ..() - addtimer(CALLBACK(GLOBAL_PROC, /proc/ctf_floor_vanish, src), 1) + addtimer(CALLBACK(src, .proc/floor_vanish), 1) + +/obj/item/gun/ballistic/automatic/pistol/deagle/ctf/proc/floor_vanish() + if(isturf(loc)) + qdel(src) /obj/item/ammo_box/magazine/m50/ctf ammo_type = /obj/item/ammo_casing/a50/ctf @@ -400,6 +408,7 @@ /obj/item/projectile/bullet/ctf/prehit(atom/target) if(is_ctf_target(target)) damage = 60 + return //PROJECTILE_PIERCE_NONE /// hey uhh don't hit anyone behind them . = ..() /obj/item/gun/ballistic/automatic/laser/ctf @@ -407,16 +416,24 @@ desc = "This looks like it could really hurt in melee." force = 50 -/obj/item/gun/ballistic/automatic/laser/ctf/dropped(mob/user) +/obj/item/gun/ballistic/automatic/laser/ctf/dropped() . = ..() - addtimer(CALLBACK(GLOBAL_PROC, /proc/ctf_floor_vanish, src), 1) + addtimer(CALLBACK(src, .proc/floor_vanish), 1) + +/obj/item/gun/ballistic/automatic/laser/ctf/proc/floor_vanish() + if(isturf(loc)) + qdel(src) /obj/item/ammo_box/magazine/recharge/ctf ammo_type = /obj/item/ammo_casing/caseless/laser/ctf -/obj/item/ammo_box/magazine/recharge/ctf/dropped(mob/user) +/obj/item/ammo_box/magazine/recharge/ctf/dropped() . = ..() - addtimer(CALLBACK(GLOBAL_PROC, /proc/ctf_floor_vanish, src), 1) + addtimer(CALLBACK(src, .proc/floor_vanish), 1) + +/obj/item/ammo_box/magazine/recharge/ctf/proc/floor_vanish() + if(isturf(loc)) + qdel(src) /obj/item/ammo_casing/caseless/laser/ctf projectile_type = /obj/item/projectile/beam/ctf @@ -428,15 +445,16 @@ /obj/item/projectile/beam/ctf/prehit(atom/target) if(is_ctf_target(target)) damage = 150 + return //PROJECTILE_PIERCE_NONE /// hey uhhh don't hit anyone behind them . = ..() /proc/is_ctf_target(atom/target) . = FALSE if(istype(target, /obj/structure/barricade/security/ctf)) . = TRUE - if(isliving(target)) - var/mob/living/H = target - if((RED_TEAM in H.faction) || (BLUE_TEAM in H.faction)) + if(ishuman(target)) + var/mob/living/carbon/human/H = target + if(istype(H.wear_suit, /obj/item/clothing/suit/space/hardsuit/shielded/ctf)) . = TRUE // RED TEAM GUNS @@ -482,7 +500,11 @@ /obj/item/claymore/ctf/dropped(mob/user) . = ..() - addtimer(CALLBACK(GLOBAL_PROC, /proc/ctf_floor_vanish, src), 1) + addtimer(CALLBACK(src, .proc/floor_vanish), 1) + +/obj/item/claymore/ctf/proc/floor_vanish() + if(isturf(loc)) + qdel(src) /datum/outfit/ctf name = "CTF" @@ -491,27 +513,28 @@ suit = /obj/item/clothing/suit/space/hardsuit/shielded/ctf toggle_helmet = FALSE // see the whites of their eyes shoes = /obj/item/clothing/shoes/combat - gloves = /obj/item/clothing/gloves/tackler/combat + gloves = /obj/item/clothing/gloves/combat + id = /obj/item/card/id/away belt = /obj/item/gun/ballistic/automatic/pistol/deagle/ctf l_pocket = /obj/item/ammo_box/magazine/recharge/ctf r_pocket = /obj/item/ammo_box/magazine/recharge/ctf r_hand = /obj/item/gun/ballistic/automatic/laser/ctf back = /obj/item/claymore/ctf -/datum/outfit/ctf/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE, client/preference_source) +/datum/outfit/ctf/post_equip(mob/living/carbon/human/H, visualsOnly=FALSE) if(visualsOnly) return var/list/no_drops = list() var/obj/item/card/id/W = H.wear_id no_drops += W W.registered_name = H.real_name - W.update_label(W.registered_name, W.assignment) + W.update_label() - // The shielded hardsuit is already TRAIT_NODROP - no_drops += H.get_item_by_slot(SLOT_GLOVES) - no_drops += H.get_item_by_slot(SLOT_SHOES) - no_drops += H.get_item_by_slot(SLOT_W_UNIFORM) - no_drops += H.get_item_by_slot(SLOT_EARS) + no_drops += H.get_item_by_slot(ITEM_SLOT_OCLOTHING) + no_drops += H.get_item_by_slot(ITEM_SLOT_GLOVES) + no_drops += H.get_item_by_slot(ITEM_SLOT_FEET) + no_drops += H.get_item_by_slot(ITEM_SLOT_ICLOTHING) + no_drops += H.get_item_by_slot(ITEM_SLOT_EARS) for(var/i in no_drops) var/obj/item/I = i ADD_TRAIT(I, TRAIT_NODROP, CAPTURE_THE_FLAG_TRAIT) @@ -525,6 +548,7 @@ r_hand = /obj/item/gun/ballistic/automatic/laser/ctf/red l_pocket = /obj/item/ammo_box/magazine/recharge/ctf/red r_pocket = /obj/item/ammo_box/magazine/recharge/ctf/red + id = /obj/item/card/id/syndicate_command //it's red /datum/outfit/ctf/red/instagib r_hand = /obj/item/gun/energy/laser/instakill/red @@ -535,12 +559,13 @@ r_hand = /obj/item/gun/ballistic/automatic/laser/ctf/blue l_pocket = /obj/item/ammo_box/magazine/recharge/ctf/blue r_pocket = /obj/item/ammo_box/magazine/recharge/ctf/blue + id = /obj/item/card/id/centcom //it's blue /datum/outfit/ctf/blue/instagib r_hand = /obj/item/gun/energy/laser/instakill/blue shoes = /obj/item/clothing/shoes/jackboots/fast -/datum/outfit/ctf/red/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE, client/preference_source) +/datum/outfit/ctf/red/post_equip(mob/living/carbon/human/H) ..() var/obj/item/radio/R = H.ears R.set_frequency(FREQ_CTF_RED) @@ -548,7 +573,7 @@ R.independent = TRUE H.dna.species.stunmod = 0 -/datum/outfit/ctf/blue/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE, client/preference_source) +/datum/outfit/ctf/blue/post_equip(mob/living/carbon/human/H) ..() var/obj/item/radio/R = H.ears R.set_frequency(FREQ_CTF_BLUE) @@ -595,6 +620,10 @@ /obj/structure/barricade/security/ctf/make_debris() new /obj/effect/ctf/dead_barricade(get_turf(src)) +/obj/structure/table/reinforced/ctf + resistance_flags = INDESTRUCTIBLE + flags_1 = NODECONSTRUCT_1 + /obj/effect/ctf density = FALSE anchored = TRUE @@ -617,10 +646,11 @@ QDEL_IN(src, AMMO_DROP_LIFETIME) /obj/effect/ctf/ammo/Crossed(atom/movable/AM) + . = ..() reload(AM) -/obj/effect/ctf/ammo/Bump(atom/movable/AM) - reload(AM) +/obj/effect/ctf/ammo/Bump(atom/A) + reload(A) /obj/effect/ctf/ammo/Bumped(atom/movable/AM) reload(AM) @@ -636,7 +666,7 @@ qdel(G) O.equip(M) to_chat(M, "Ammunition reloaded!") - playsound(get_turf(M), 'sound/weapons/shotgunpump.ogg', 50, 1, -1) + playsound(get_turf(M), 'sound/weapons/shotgunpump.ogg', 50, TRUE, -1) qdel(src) break @@ -667,18 +697,18 @@ resistance_flags = INDESTRUCTIBLE var/obj/machinery/capture_the_flag/controlling var/team = "none" - var/point_rate = 1 + var/point_rate = 0.5 -/obj/machinery/control_point/process() +/obj/machinery/control_point/process(delta_time) if(controlling) - controlling.control_points += point_rate + controlling.control_points += point_rate * delta_time if(controlling.control_points >= controlling.control_points_to_win) controlling.victory() /obj/machinery/control_point/attackby(mob/user, params) capture(user) -/obj/machinery/control_point/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) +/obj/machinery/control_point/on_attack_hand(mob/user) capture(user) /obj/machinery/control_point/proc/capture(mob/user) diff --git a/code/modules/awaymissions/corpse.dm b/code/modules/awaymissions/corpse.dm index e68c45a84c..cd5c2f76f3 100644 --- a/code/modules/awaymissions/corpse.dm +++ b/code/modules/awaymissions/corpse.dm @@ -66,7 +66,7 @@ /obj/effect/mob_spawn/Initialize(mapload) . = ..() if(instant || (roundstart && (mapload || (SSticker && SSticker.current_state > GAME_STATE_SETTING_UP)))) - create() + INVOKE_ASYNC(src, .proc/create) else if(ghost_usable) GLOB.poi_list |= src LAZYADD(GLOB.mob_spawners[job_description ? job_description : name], src) diff --git a/code/modules/awaymissions/mission_code/wildwest.dm b/code/modules/awaymissions/mission_code/wildwest.dm index f13341faf3..bc7e2cbd08 100644 --- a/code/modules/awaymissions/mission_code/wildwest.dm +++ b/code/modules/awaymissions/mission_code/wildwest.dm @@ -132,6 +132,7 @@ var/triggered = 0 /obj/effect/meatgrinder/Crossed(atom/movable/AM) + . = ..() Bumped(AM) /obj/effect/meatgrinder/Bumped(atom/movable/AM) diff --git a/code/modules/events/spacevine.dm b/code/modules/events/spacevine.dm index 7cf11848e8..edc062f78f 100644 --- a/code/modules/events/spacevine.dm +++ b/code/modules/events/spacevine.dm @@ -340,6 +340,7 @@ playsound(src.loc, 'sound/items/welder.ogg', 100, TRUE) /obj/structure/spacevine/Crossed(atom/movable/AM) + . = ..() if(!isliving(AM)) return for(var/datum/spacevine_mutation/SM in mutations) diff --git a/code/modules/events/travelling_trader.dm b/code/modules/events/travelling_trader.dm index eeb1acdba5..1f9c69a9f0 100644 --- a/code/modules/events/travelling_trader.dm +++ b/code/modules/events/travelling_trader.dm @@ -99,7 +99,7 @@ new reward(get_turf(src)) /mob/living/carbon/human/dummy/travelling_trader/Initialize() - ..() + . = ..() // return a hint you fuck add_atom_colour("#570d6b", FIXED_COLOUR_PRIORITY) //make them purple (otherworldly!) set_light(1, -0.7, "#AAD84B") ADD_TRAIT(src,TRAIT_PIERCEIMMUNE, "trader_pierce_immune") //don't let people take their blood diff --git a/code/modules/fields/fields.dm b/code/modules/fields/fields.dm index 8710282021..cb8d3e8dcf 100644 --- a/code/modules/fields/fields.dm +++ b/code/modules/fields/fields.dm @@ -16,7 +16,7 @@ if(!F.check_variables() && !override_checks) QDEL_NULL(F) if(start_field && (F || override_checks)) - F.Initialize() + F.begin_field() return F /datum/proximity_monitor/advanced @@ -78,11 +78,11 @@ /datum/proximity_monitor/advanced/proc/process_edge_turf(turf/T) -/datum/proximity_monitor/advanced/New() +/datum/proximity_monitor/advanced/New(atom/_host, range, _ignore_if_not_on_turf = TRUE) if(requires_processing) START_PROCESSING(SSfields, src) -/datum/proximity_monitor/advanced/proc/Initialize() +/datum/proximity_monitor/advanced/proc/begin_field() setup_field() post_setup_field() @@ -154,7 +154,7 @@ var/atom/_host = host var/atom/new_host_loc = _host.loc if(last_host_loc != new_host_loc) - recalculate_field() + INVOKE_ASYNC(src, .proc/recalculate_field) /datum/proximity_monitor/advanced/proc/post_setup_field() @@ -302,7 +302,7 @@ /obj/item/multitool/field_debug/attack_self(mob/user) operating = !operating - to_chat(user, "You turn [src] [operating? "on":"off"].") + to_chat(user, "You turn [src] [operating? "on":"off"].") UnregisterSignal(listeningTo, COMSIG_MOVABLE_MOVED) listeningTo = null if(!istype(current) && operating) @@ -312,13 +312,15 @@ else if(!operating) QDEL_NULL(current) -/obj/item/multitool/field_debug/dropped(mob/user) +/obj/item/multitool/field_debug/dropped() . = ..() if(listeningTo) UnregisterSignal(listeningTo, COMSIG_MOVABLE_MOVED) listeningTo = null /obj/item/multitool/field_debug/proc/on_mob_move() + SIGNAL_HANDLER + check_turf(get_turf(src)) /obj/item/multitool/field_debug/process() diff --git a/code/modules/fields/timestop.dm b/code/modules/fields/timestop.dm index 56abef8cd6..a96a44a789 100644 --- a/code/modules/fields/timestop.dm +++ b/code/modules/fields/timestop.dm @@ -33,7 +33,7 @@ if(G.summoner && locate(/obj/effect/proc_holder/spell/aoe_turf/timestop) in G.summoner.mind.spell_list) //It would only make sense that a person's stand would also be immune. immune[G] = TRUE if(start) - timestop() + INVOKE_ASYNC(src, .proc/timestop) /obj/effect/timestop/Destroy() qdel(chronofield) @@ -42,7 +42,7 @@ /obj/effect/timestop/proc/timestop() target = get_turf(src) - playsound(src, 'sound/magic/timeparadox2.ogg', 75, 1, -1) + playsound(src, 'sound/magic/timeparadox2.ogg', 75, TRUE, -1) chronofield = make_field(/datum/proximity_monitor/advanced/timestop, list("current_range" = freezerange, "host" = src, "immune" = immune, "check_anti_magic" = check_anti_magic, "check_holy" = check_holy)) QDEL_IN(src, duration) @@ -112,6 +112,8 @@ unfreeze_turf(T) /datum/proximity_monitor/advanced/timestop/proc/unfreeze_atom(atom/movable/A) + SIGNAL_HANDLER + if(A.throwing) unfreeze_throwing(A) if(isliving(A)) @@ -128,12 +130,14 @@ frozen_things -= A global_frozen_atoms -= A + /datum/proximity_monitor/advanced/timestop/proc/freeze_mecha(obj/mecha/M) M.completely_disabled = TRUE /datum/proximity_monitor/advanced/timestop/proc/unfreeze_mecha(obj/mecha/M) M.completely_disabled = FALSE + /datum/proximity_monitor/advanced/timestop/proc/freeze_throwing(atom/movable/AM) var/datum/thrownthing/T = AM.throwing T.paused = TRUE @@ -160,7 +164,7 @@ /datum/proximity_monitor/advanced/timestop/process() for(var/i in frozen_mobs) var/mob/living/m = i - m.Stun(20, 1, 1) + m.Stun(20, ignore_canstun = TRUE) /datum/proximity_monitor/advanced/timestop/setup_field_turf(turf/T) for(var/i in T.contents) @@ -168,6 +172,7 @@ freeze_turf(T) return ..() + /datum/proximity_monitor/advanced/timestop/proc/freeze_projectile(obj/item/projectile/P) P.paused = TRUE @@ -176,18 +181,18 @@ /datum/proximity_monitor/advanced/timestop/proc/freeze_mob(mob/living/L) frozen_mobs += L - L.Stun(20, 1, 1) + L.Stun(20, ignore_canstun = TRUE) ADD_TRAIT(L, TRAIT_MUTE, TIMESTOP_TRAIT) walk(L, 0) //stops them mid pathing even if they're stunimmune if(isanimal(L)) var/mob/living/simple_animal/S = L S.toggle_ai(AI_OFF) - if(ishostile(L)) - var/mob/living/simple_animal/hostile/H = L - H.LoseTarget() + if(ishostile(L)) + var/mob/living/simple_animal/hostile/H = L + H.LoseTarget() /datum/proximity_monitor/advanced/timestop/proc/unfreeze_mob(mob/living/L) - L.AdjustStun(-20, 1, 1) + L.AdjustStun(-20, ignore_canstun = TRUE) REMOVE_TRAIT(L, TRAIT_MUTE, TIMESTOP_TRAIT) frozen_mobs -= L if(isanimal(L)) diff --git a/code/modules/fields/turf_objects.dm b/code/modules/fields/turf_objects.dm index d37036d83c..1af924294a 100644 --- a/code/modules/fields/turf_objects.dm +++ b/code/modules/fields/turf_objects.dm @@ -24,11 +24,12 @@ desc = "Get off my turf!" /obj/effect/abstract/proximity_checker/advanced/field_turf/CanPass(atom/movable/AM, turf/target) + . = ..() if(parent) return parent.field_turf_canpass(AM, src, target) - return TRUE /obj/effect/abstract/proximity_checker/advanced/field_turf/Crossed(atom/movable/AM) + . = ..() if(parent) return parent.field_turf_crossed(AM, src) return TRUE @@ -48,11 +49,12 @@ desc = "Edgy description here." /obj/effect/abstract/proximity_checker/advanced/field_edge/CanPass(atom/movable/AM, turf/target) + . = ..() if(parent) return parent.field_edge_canpass(AM, src, target) - return TRUE /obj/effect/abstract/proximity_checker/advanced/field_edge/Crossed(atom/movable/AM) + . = ..() if(parent) return parent.field_edge_crossed(AM, src) return TRUE diff --git a/code/modules/flufftext/Hallucination.dm b/code/modules/flufftext/Hallucination.dm index 56c96c3559..cc18207a29 100644 --- a/code/modules/flufftext/Hallucination.dm +++ b/code/modules/flufftext/Hallucination.dm @@ -139,10 +139,11 @@ GLOBAL_LIST_INIT(hallucination_list, list( Show() /obj/effect/hallucination/simple/Moved(atom/OldLoc, Dir) + . = ..() Show() /obj/effect/hallucination/simple/Destroy() - if(target && target.client) + if(target?.client) target.client.images.Remove(current_image) active = FALSE return ..() @@ -1093,6 +1094,7 @@ GLOBAL_LIST_INIT(hallucination_list, list( target.client.images += image /obj/effect/hallucination/danger/lava/Crossed(atom/movable/AM) + . = ..() if(AM == target) target.adjustStaminaLoss(20) new /datum/hallucination/fire(target) diff --git a/code/modules/holiday/halloween/jacqueen.dm b/code/modules/holiday/halloween/jacqueen.dm index 90016954fc..4212a2e296 100644 --- a/code/modules/holiday/halloween/jacqueen.dm +++ b/code/modules/holiday/halloween/jacqueen.dm @@ -50,16 +50,18 @@ var/cached_z /// I'm busy, don't move. var/busy = FALSE + var/static/blacklisted_items = typecacheof(list( - /obj/effect, - /obj/belly, - /obj/mafia_game_board, - /obj/docking_port, - /obj/shapeshift_holder, - /obj/screen)) + /obj/effect, + /obj/belly, + /obj/mafia_game_board, + /obj/docking_port, + /obj/shapeshift_holder, + /obj/screen + )) /mob/living/simple_animal/jacq/Initialize() - ..() + . = ..() //fuck you jacq, return a hint you shit cached_z = z poof() @@ -158,23 +160,18 @@ return FALSE /mob/living/simple_animal/jacq/proc/gender_check(mob/living/carbon/C) - var/gender = "lamb" - if(C) - if(C.gender == MALE) - gender = "laddie" - if(C.gender == FEMALE) - gender = "lassie" - return gender + . = "lamb" + switch(C) + if(MALE) + . = "laddie" + if(FEMALE) + . = "lassie" //Ye wee bugger, gerrout of it. Ye've nae tae enjoy reading the code fer mae secrets like. /mob/living/simple_animal/jacq/proc/chit_chat(mob/living/carbon/C) //Very important var/gender = gender_check(C) - if(C) - if(C.gender == MALE) - gender = "laddie" - if(C.gender == FEMALE) - gender = "lassie" + // it physicaly cannot fail*. Why is there a fucking dupe if(!progression["[C.real_name]"] || !(progression["[C.real_name]"] & JACQ_HELLO)) visible_message("[src] smiles ominously at [C], \"Well halo there [gender]! Ah'm Jacqueline, tae great Pumpqueen, great tae meet ye.\"") diff --git a/code/modules/integrated_electronics/core/assemblies.dm b/code/modules/integrated_electronics/core/assemblies.dm index 7c9f811c34..6cb578dfb1 100644 --- a/code/modules/integrated_electronics/core/assemblies.dm +++ b/code/modules/integrated_electronics/core/assemblies.dm @@ -578,6 +578,7 @@ return FALSE /obj/item/electronic_assembly/Moved(oldLoc, dir) + . = ..() for(var/I in assembly_components) var/obj/item/integrated_circuit/IC = I IC.ext_moved(oldLoc, dir) diff --git a/code/modules/mob/dead/dead.dm b/code/modules/mob/dead/dead.dm index 87f9d716bd..223366c7ab 100644 --- a/code/modules/mob/dead/dead.dm +++ b/code/modules/mob/dead/dead.dm @@ -8,6 +8,7 @@ INITIALIZE_IMMEDIATE(/mob/dead) throwforce = 0 /mob/dead/Initialize() + SHOULD_CALL_PARENT(FALSE) if(flags_1 & INITIALIZED_1) stack_trace("Warning: [src]([type]) initialized multiple times!") flags_1 |= INITIALIZED_1 @@ -68,14 +69,15 @@ INITIALIZE_IMMEDIATE(/mob/dead) set desc= "Jump to the other server" if(mob_transforming) return - var/list/csa = CONFIG_GET(keyed_list/cross_server) + var/list/our_id = CONFIG_GET(string/cross_comms_name) + var/list/csa = CONFIG_GET(keyed_list/cross_server) - our_id var/pick switch(csa.len) if(0) remove_verb(src, /mob/dead/proc/server_hop) to_chat(src, "Server Hop has been disabled.") if(1) - pick = csa[0] + pick = csa[1] else pick = input(src, "Pick a server to jump to", "Server Hop") as null|anything in csa @@ -100,7 +102,7 @@ INITIALIZE_IMMEDIATE(/mob/dead) winset(src, null, "command=.options") //other wise the user never knows if byond is downloading resources - C << link("[addr]?server_hop=[key]") + C << link("[addr]") /mob/dead/proc/update_z(new_z) // 1+ to register, null to unregister if (registered_z != new_z) diff --git a/code/modules/mob/living/carbon/alien/special/facehugger.dm b/code/modules/mob/living/carbon/alien/special/facehugger.dm index 5392e7b2d5..ca2946fd8a 100644 --- a/code/modules/mob/living/carbon/alien/special/facehugger.dm +++ b/code/modules/mob/living/carbon/alien/special/facehugger.dm @@ -91,8 +91,8 @@ Attach(M) /obj/item/clothing/mask/facehugger/Crossed(atom/target) + . = ..() HasProximity(target) - return /obj/item/clothing/mask/facehugger/on_found(mob/finder) if(stat == CONSCIOUS) diff --git a/code/modules/mob/living/living_movement.dm b/code/modules/mob/living/living_movement.dm index 75d712afb9..b1402f1f7d 100644 --- a/code/modules/mob/living/living_movement.dm +++ b/code/modules/mob/living/living_movement.dm @@ -99,14 +99,6 @@ if(lying && !buckled && prob(getBruteLoss()*200/maxHealth)) makeTrail(newloc, T, old_direction) - -/mob/living/Move_Pulled(atom/A) - . = ..() - if(!. || !isliving(A)) - return - var/mob/living/L = A - set_pull_offsets(L, grab_state) - /mob/living/forceMove(atom/destination) stop_pulling() if(buckled) diff --git a/code/modules/mob/living/simple_animal/friendly/cockroach.dm b/code/modules/mob/living/simple_animal/friendly/cockroach.dm index 384fa8146f..f33c179911 100644 --- a/code/modules/mob/living/simple_animal/friendly/cockroach.dm +++ b/code/modules/mob/living/simple_animal/friendly/cockroach.dm @@ -37,23 +37,25 @@ return ..() -/mob/living/simple_animal/cockroach/Crossed(var/atom/movable/AM) - if(ismob(AM)) - if(isliving(AM)) - var/mob/living/A = AM - if(A.mob_size > MOB_SIZE_SMALL && !(A.movement_type & FLYING)) - if(prob(squish_chance)) - A.visible_message("[A] squashed [src].", "You squashed [src].") - adjustBruteLoss(1) //kills a normal cockroach - else - visible_message("[src] avoids getting crushed.") - else - if(isstructure(AM)) +/mob/living/simple_animal/cockroach/Crossed(atom/movable/AM) + . = ..() + if(isliving(AM)) + var/mob/living/A = AM + if(A.mob_size > MOB_SIZE_SMALL && !(A.movement_type & FLYING)) + if(HAS_TRAIT(A, TRAIT_PACIFISM)) + A.visible_message("[A] carefully steps over [src].", "You carefully step over [src] to avoid hurting it.") + return if(prob(squish_chance)) - AM.visible_message("[src] was crushed under [AM].") - adjustBruteLoss(1) + A.visible_message("[A] squashed [src].", "You squashed [src].") + adjustBruteLoss(1) //kills a normal cockroach else visible_message("[src] avoids getting crushed.") + else if(isstructure(AM)) + if(prob(squish_chance)) + AM.visible_message("[src] is crushed under [AM].") + adjustBruteLoss(1) + else + visible_message("[src] avoids getting crushed.") /mob/living/simple_animal/cockroach/ex_act() //Explosions are a terrible way to handle a cockroach. return diff --git a/code/modules/mob/living/simple_animal/friendly/dog.dm b/code/modules/mob/living/simple_animal/friendly/dog.dm index 0584995583..49581b91a7 100644 --- a/code/modules/mob/living/simple_animal/friendly/dog.dm +++ b/code/modules/mob/living/simple_animal/friendly/dog.dm @@ -263,7 +263,7 @@ /mob/living/simple_animal/pet/dog/corgi/proc/place_on_head(obj/item/item_to_add, mob/user) if(istype(item_to_add, /obj/item/grenade/plastic)) // last thing he ever wears, I guess - item_to_add.afterattack(src,user,1) + INVOKE_ASYNC(item_to_add, /obj/item.proc/afterattack, src, user, 1) return if(inventory_head) @@ -271,13 +271,15 @@ to_chat(user, "You can't put more than one hat on [src]!") return if(!item_to_add) - user.visible_message("[user] pets [src].","You rest your hand on [src]'s head for a moment.") + user.visible_message("[user] pets [src].", "You rest your hand on [src]'s head for a moment.") + if(flags_1 & HOLOGRAM_1) + return SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, src, /datum/mood_event/pet_animal, src) return if(user && !user.temporarilyRemoveItemFromInventory(item_to_add)) to_chat(user, "\The [item_to_add] is stuck to your hand, you cannot put it on [src]'s head!") - return 0 + return var/valid = FALSE if(ispath(item_to_add.dog_fashion, /datum/dog_fashion/head)) @@ -287,11 +289,11 @@ if(valid) if(health <= 0) - to_chat(user, "There is merely a dull, lifeless look in [real_name]'s eyes as you put the [item_to_add] on [p_them()].") + to_chat(user, "There is merely a dull, lifeless look in [real_name]'s eyes as you put the [item_to_add] on [p_them()].") else if(user) - user.visible_message("[user] puts [item_to_add] on [real_name]'s head. [src] looks at [user] and barks once.", - "You put [item_to_add] on [real_name]'s head. [src] gives you a peculiar look, then wags [p_their()] tail once and barks.", - "You hear a friendly-sounding bark.") + user.visible_message("[user] puts [item_to_add] on [real_name]'s head. [src] looks at [user] and barks once.", + "You put [item_to_add] on [real_name]'s head. [src] gives you a peculiar look, then wags [p_their()] tail once and barks.", + "You hear a friendly-sounding bark.") item_to_add.forceMove(src) src.inventory_head = item_to_add update_corgi_fluff() @@ -361,7 +363,7 @@ icon_state = "old_corgi" icon_living = "old_corgi" icon_dead = "old_corgi_dead" - desc = "At a ripe old age of [record_age] Ian's not as spry as he used to be, but he'll always be the HoP's beloved corgi." //RIP + desc = "At a ripe old age of [record_age], Ian's not as spry as he used to be, but he'll always be the HoP's beloved corgi." //RIP turns_per_move = 20 RemoveElement(/datum/element/mob_holder, held_icon) AddElement(/datum/element/mob_holder, "old_corgi") diff --git a/code/modules/mob/living/simple_animal/guardian/types/ranged.dm b/code/modules/mob/living/simple_animal/guardian/types/ranged.dm index e7c4e2f352..e2bcdd5684 100644 --- a/code/modules/mob/living/simple_animal/guardian/types/ranged.dm +++ b/code/modules/mob/living/simple_animal/guardian/types/ranged.dm @@ -110,6 +110,7 @@ /obj/effect/snare/Crossed(AM as mob|obj) + . = ..() if(isliving(AM) && spawner && spawner.summoner && AM != spawner && !spawner.hasmatchingsummoner(AM)) to_chat(spawner.summoner, "[AM] has crossed surveillance snare, [name].") var/list/guardians = spawner.summoner.hasparasites() diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/goliath_broodmother.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/goliath_broodmother.dm index 4e8f4f6160..ef51dc572f 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/goliath_broodmother.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/goliath_broodmother.dm @@ -219,6 +219,9 @@ /obj/effect/temp_visual/goliath_tentacle/broodmother/patch/Initialize(mapload, new_spawner) . = ..() + INVOKE_ASYNC(src, .proc/createpatch) + +/obj/effect/temp_visual/goliath_tentacle/broodmother/patch/proc/createpatch() var/tentacle_locs = spiral_range_turfs(1, get_turf(src)) for(var/T in tentacle_locs) new /obj/effect/temp_visual/goliath_tentacle/broodmother(T, spawner) diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/frog.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/frog.dm index 8424a0a576..f0fe85008a 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/frog.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/frog.dm @@ -42,7 +42,8 @@ butcher_results = list(/obj/item/reagent_containers/food/snacks/nugget = 5) /mob/living/simple_animal/hostile/retaliate/frog/Crossed(AM as mob|obj) + . = ..() if(!stat && isliving(AM)) var/mob/living/L = AM if(L.mob_size > MOB_SIZE_TINY) - playsound(src, stepped_sound, 50, 1) + playsound(src, stepped_sound, 50, TRUE) diff --git a/code/modules/movespeed/_movespeed_modifier.dm b/code/modules/movespeed/_movespeed_modifier.dm index 9c8036bd55..b1631a9821 100644 --- a/code/modules/movespeed/_movespeed_modifier.dm +++ b/code/modules/movespeed/_movespeed_modifier.dm @@ -96,7 +96,7 @@ GLOBAL_LIST_EMPTY(movespeed_modification_cache) return TRUE remove_movespeed_modifier(existing, FALSE) if(length(movespeed_modification)) - BINARY_INSERT(type_or_datum.id, movespeed_modification, datum/movespeed_modifier, type_or_datum, priority, COMPARE_VALUE) + BINARY_INSERT(type_or_datum.id, movespeed_modification, /datum/movespeed_modifier, type_or_datum, priority, COMPARE_VALUE) LAZYSET(movespeed_modification, type_or_datum.id, type_or_datum) if(update) update_movespeed() diff --git a/code/modules/power/singularity/containment_field.dm b/code/modules/power/singularity/containment_field.dm index dfb51df9cf..2ca9b7513c 100644 --- a/code/modules/power/singularity/containment_field.dm +++ b/code/modules/power/singularity/containment_field.dm @@ -56,12 +56,14 @@ else ..() -/obj/machinery/field/containment/Crossed(mob/mover) - if(isliving(mover)) - shock(mover) +/obj/machinery/field/containment/Crossed(atom/movable/AM) + . = ..() + if(isliving(AM)) + shock(AM) + + if(ismachinery(AM) || isstructure(AM) || ismecha(AM)) + bump_field(AM) - if(ismachinery(mover) || isstructure(mover) || ismecha(mover)) - bump_field(mover) /obj/machinery/field/containment/proc/set_master(master1,master2) if(!master1 || !master2) diff --git a/code/modules/power/singularity/particle_accelerator/particle.dm b/code/modules/power/singularity/particle_accelerator/particle.dm index 9e098446d1..7ecde364ae 100644 --- a/code/modules/power/singularity/particle_accelerator/particle.dm +++ b/code/modules/power/singularity/particle_accelerator/particle.dm @@ -44,6 +44,7 @@ movement_range = 0 /obj/effect/accelerated_particle/Crossed(atom/A) + . = ..() if(isliving(A)) toxmob(A) diff --git a/code/modules/recycling/disposal/construction.dm b/code/modules/recycling/disposal/construction.dm index 348e687e03..c6d015df34 100644 --- a/code/modules/recycling/disposal/construction.dm +++ b/code/modules/recycling/disposal/construction.dm @@ -14,12 +14,12 @@ var/obj/pipe_type = /obj/structure/disposalpipe/segment var/pipename -/obj/structure/disposalconstruct/Initialize(loc, _pipe_type, _dir = SOUTH, flip = FALSE, obj/make_from) +/obj/structure/disposalconstruct/Initialize(mapload, _pipe_type, _dir = SOUTH, flip = FALSE, obj/make_from) . = ..() if(make_from) pipe_type = make_from.type setDir(make_from.dir) - anchored = TRUE + set_anchored(TRUE) else if(_pipe_type) @@ -34,6 +34,8 @@ update_icon() + // AddElement(/datum/element/undertile, TRAIT_T_RAY_VISIBLE) + /obj/structure/disposalconstruct/Move() var/old_dir = dir ..() diff --git a/code/modules/ruins/objects_and_mobs/necropolis_gate.dm b/code/modules/ruins/objects_and_mobs/necropolis_gate.dm index fd2f4377e7..5f9b810070 100644 --- a/code/modules/ruins/objects_and_mobs/necropolis_gate.dm +++ b/code/modules/ruins/objects_and_mobs/necropolis_gate.dm @@ -274,6 +274,7 @@ GLOBAL_DATUM(necropolis_gate, /obj/structure/necropolis_gate/legion_gate) return /obj/structure/stone_tile/Crossed(atom/movable/AM) + . = ..() if(falling || fallen) return var/turf/T = get_turf(src) diff --git a/code/modules/ruins/spaceruin_code/hilbertshotel.dm b/code/modules/ruins/spaceruin_code/hilbertshotel.dm index 4859fcfca0..33c4a70634 100644 --- a/code/modules/ruins/spaceruin_code/hilbertshotel.dm +++ b/code/modules/ruins/spaceruin_code/hilbertshotel.dm @@ -21,6 +21,9 @@ GLOBAL_VAR_INIT(hhmysteryRoomNumber, 1337) /obj/item/hilbertshotel/Initialize() . = ..() //Load templates + INVOKE_ASYNC(src, .proc/prepare_rooms) + +/obj/item/hilbertshotel/proc/prepare_rooms() hotelRoomTemp = new() hotelRoomTempEmpty = new() hotelRoomTempLore = new() diff --git a/code/modules/spells/spell_types/spacetime_distortion.dm b/code/modules/spells/spell_types/spacetime_distortion.dm index 5797cbf8b7..5a8776b16b 100644 --- a/code/modules/spells/spell_types/spacetime_distortion.dm +++ b/code/modules/spells/spell_types/spacetime_distortion.dm @@ -1,6 +1,6 @@ /obj/effect/proc_holder/spell/spacetime_dist name = "Spacetime Distortion" - desc = "Entangle the strings of spacetime to deny easy movement around you. The strings vibrate..." + desc = "Entangle the strings of space-time in an area around you, randomizing the layout and making proper movement impossible. The strings vibrate..." charge_max = 300 var/duration = 150 range = 7 @@ -10,8 +10,9 @@ sound = 'sound/effects/magic.ogg' cooldown_min = 300 level_max = 0 + // action_icon_state = "spacetime" -/obj/effect/proc_holder/spell/spacetime_dist/can_cast(mob/user = usr, skipcharge = FALSE, silent = FALSE) +/obj/effect/proc_holder/spell/spacetime_dist/can_cast(mob/user = usr) if(ready) return ..() return FALSE @@ -97,10 +98,11 @@ busy = TRUE flick("purplesparkles", src) AM.forceMove(get_turf(src)) - playsound(get_turf(src),sound,70,0) + playsound(get_turf(src),sound,70,FALSE) busy = FALSE /obj/effect/cross_action/spacetime_dist/Crossed(atom/movable/AM) + . = ..() if(!busy) walk_link(AM) @@ -110,7 +112,8 @@ else walk_link(user) -/obj/effect/cross_action/spacetime_dist/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) +//ATTACK HAND IGNORING PARENT RETURN VALUE +/obj/effect/cross_action/spacetime_dist/on_attack_hand(mob/user) walk_link(user) /obj/effect/cross_action/spacetime_dist/attack_paw(mob/user) diff --git a/tgstation.dme b/tgstation.dme index e48f612ecc..97b639e95a 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -78,6 +78,7 @@ #include "code\__DEFINES\mobs.dm" #include "code\__DEFINES\monkeys.dm" #include "code\__DEFINES\move_force.dm" +#include "code\__DEFINES\movement.dm" #include "code\__DEFINES\movespeed_modification.dm" #include "code\__DEFINES\nanites.dm" #include "code\__DEFINES\networks.dm"