From cc13b9954c6135eb1506c6df88a6dfe30b5fdbd8 Mon Sep 17 00:00:00 2001 From: MistakeNot4892 Date: Fri, 6 May 2022 14:53:41 +1000 Subject: [PATCH 01/86] Fixes infinite latencies. --- .../psionics/system/psionics/complexus/complexus_latency.dm | 1 + 1 file changed, 1 insertion(+) diff --git a/mods/content/psionics/system/psionics/complexus/complexus_latency.dm b/mods/content/psionics/system/psionics/complexus/complexus_latency.dm index 482c3c2d05d..373c2283129 100644 --- a/mods/content/psionics/system/psionics/complexus/complexus_latency.dm +++ b/mods/content/psionics/system/psionics/complexus/complexus_latency.dm @@ -8,6 +8,7 @@ return FALSE var/faculty = pick(latencies) + LAZYREMOVE(latencies, faculty) var/new_rank = rand(2,5) owner.set_psi_rank(faculty, new_rank) var/decl/psionic_faculty/faculty_decl = SSpsi.get_faculty(faculty) From 41d4967c1f3b60b0c98cf94f7bdc16e6b58d680f Mon Sep 17 00:00:00 2001 From: PsyCommando Date: Fri, 6 May 2022 20:53:38 -0400 Subject: [PATCH 02/86] Tweaked cable laying a bit * All turfs now use try_build_cable for attempting to build a cable. * try_build_cable warns the user if something is off instead of can_build_cable * can_build_cable now actually only checks if we can build a cable or not, and doesn't actually prints text to the user anymore. So it won't spam the users when just doing a check. * can_build_cable is now defined in /turf since cable can be installed on several branching types of turfs. Same with try_build_cable. --- code/game/turfs/simulated.dm | 7 +---- code/game/turfs/simulated/floor_attackby.dm | 18 ++++++++----- code/game/turfs/turf.dm | 10 +++++++ code/modules/multiz/turf.dm | 29 +++++++++++++-------- code/modules/power/cable.dm | 14 +++++----- code/modules/power/power.dm | 2 +- 6 files changed, 49 insertions(+), 31 deletions(-) diff --git a/code/game/turfs/simulated.dm b/code/game/turfs/simulated.dm index 44cf8fe566c..a200cd8609f 100644 --- a/code/game/turfs/simulated.dm +++ b/code/game/turfs/simulated.dm @@ -167,13 +167,8 @@ else if( istype(M, /mob/living/silicon/robot )) new /obj/effect/decal/cleanable/blood/oil(src) -/turf/simulated/proc/can_build_cable(var/mob/user) - return 0 - /turf/simulated/attackby(var/obj/item/thing, var/mob/user) - if(isCoil(thing) && can_build_cable(user)) - var/obj/item/stack/cable_coil/coil = thing - coil.turf_place(src, user) + if(isCoil(thing) && try_build_cable(thing, user)) return TRUE return ..() diff --git a/code/game/turfs/simulated/floor_attackby.dm b/code/game/turfs/simulated/floor_attackby.dm index 63ce88569a9..46fb71eaa13 100644 --- a/code/game/turfs/simulated/floor_attackby.dm +++ b/code/game/turfs/simulated/floor_attackby.dm @@ -173,11 +173,15 @@ update_icon() return 1 +/turf/simulated/floor/try_build_cable(obj/item/stack/cable_coil/C, mob/user) + if(!can_build_cable(user)) + if(!is_plating() || flooring) + to_chat(user, SPAN_WARNING("Removing the tiling first.")) + if(broken || burnt) + to_chat(user, SPAN_WARNING("This section is too damaged to support anything. Use a welder to fix the damage.")) + return FALSE + return ..() + /turf/simulated/floor/can_build_cable(var/mob/user) - if(!is_plating() || flooring) - to_chat(user, "Removing the tiling first.") - return 0 - if(broken || burnt) - to_chat(user, "This section is too damaged to support anything. Use a welder to fix the damage.") - return 0 - return 1 + //Need to check 'flooring' again since some floor types override is_plating to check for something else than flooring.. + return is_plating() && !flooring && !broken && !burnt diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index e5b8825fc0d..7344e0de2ac 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -437,3 +437,13 @@ var/global/const/enterloopsanity = 100 LAZYADD(., weather) if(flooded) LAZYADD(., global.flood_object) + +/**Whether we can place a cable here */ +/turf/proc/can_build_cable(var/mob/user) + return FALSE + +/**Place a cable if possible, if not warn the user appropriately */ +/turf/proc/try_build_cable(var/obj/item/stack/cable_coil/C, var/mob/user) + if(!can_build_cable(user)) + return FALSE + return C.turf_place(src, user) diff --git a/code/modules/multiz/turf.dm b/code/modules/multiz/turf.dm index 725f3a5037e..7cc125a15ee 100644 --- a/code/modules/multiz/turf.dm +++ b/code/modules/multiz/turf.dm @@ -16,6 +16,9 @@ return 0 return 1 +//////////////////////////////// +// Open SIMULATED +//////////////////////////////// /turf/simulated/open name = "open space" icon = 'icons/turf/space.dmi' @@ -24,6 +27,10 @@ pathweight = 100000 //Seriously, don't try and path over this one numbnuts z_flags = ZM_MIMIC_DEFAULTS | ZM_MIMIC_OVERWRITE | ZM_MIMIC_NO_AO | ZM_ALLOW_ATMOS +/turf/simulated/open/flooded + name = "open water" + flooded = TRUE + /turf/simulated/open/CanZPass(atom/A, direction) if(locate(/obj/structure/catwalk, src)) if(z == A.z) @@ -105,9 +112,7 @@ return TRUE //To lay cable. - if(isCoil(C)) - var/obj/item/stack/cable_coil/coil = C - coil.turf_place(src, user) + if(isCoil(C) && try_build_cable(C, user)) return TRUE for(var/atom/movable/M in below) @@ -121,13 +126,14 @@ //Most things use is_plating to test if there is a cover tile on top (like regular floors) /turf/simulated/open/is_plating() - return 1 + return TRUE -/turf/simulated/open/flooded - name = "open water" - flooded = TRUE +/turf/simulated/open/can_build_cable() + return TRUE -// Whole lot of copypaste below sorry. +//////////////////////////////// +// Open EXTERIOR +//////////////////////////////// /turf/exterior/open name = "open space" icon = 'icons/turf/space.dmi' @@ -205,9 +211,7 @@ return TRUE //To lay cable. - if(isCoil(C)) - var/obj/item/stack/cable_coil/coil = C - coil.turf_place(src, user) + if(isCoil(C) && try_build_cable(C, user)) return TRUE for(var/atom/movable/M in below) @@ -218,3 +222,6 @@ for(var/atom/movable/M in below) if(M.movable_flags & MOVABLE_FLAG_Z_INTERACT) return M.attack_hand(user) + +/turf/exterior/open/can_build_cable() + return TRUE diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm index d25b64c507c..b7ef999212f 100644 --- a/code/modules/power/cable.dm +++ b/code/modules/power/cable.dm @@ -676,6 +676,7 @@ By design, d1 is the smallest direction and d2 is the highest put_cable(F, user, end_dir, dirn) if(end_dir == DOWN) put_cable(GetBelow(F), user, UP, 0) + return TRUE // called when cable_coil is click on an installed obj/cable // or click on a turf that already contains a "node" cable @@ -694,8 +695,7 @@ By design, d1 is the smallest direction and d2 is the highest return if(U == T) //if clicked on the turf we're standing on, try to put a cable in the direction we're facing - turf_place(T,user) - return + return turf_place(T,user) var/dirn = get_dir(C, user) @@ -715,7 +715,7 @@ By design, d1 is the smallest direction and d2 is the highest to_chat(user, "There's already a cable at that position.") return put_cable(U,user,0,fdirn) - return + return TRUE // exisiting cable doesn't point at our position, so see if it's a stub else if(C.d1 == 0) @@ -765,11 +765,12 @@ By design, d1 is the smallest direction and d2 is the highest return C.denode()// this call may have disconnected some cables that terminated on the centre of the turf, if so split the powernets. - return + return TRUE + /obj/item/stack/cable_coil/proc/put_cable(turf/F, mob/user, d1, d2) if(!istype(F)) - return + return FALSE var/obj/structure/cable/C = new(F) C.cableColor(color) @@ -792,11 +793,12 @@ By design, d1 is the smallest direction and d2 is the highest if(C.d2 & (C.d2 - 1))// if the cable is layed diagonally, check the others 2 possible directions C.mergeDiagonalsNetworks(C.d2) - use(1) + . = use(1) if (C.shock(user, 50)) if (prob(50)) //fail new/obj/item/stack/cable_coil(C.loc, 1, C.color) qdel(C) + return FALSE ////////////////////////////// // Misc. diff --git a/code/modules/power/power.dm b/code/modules/power/power.dm index 64e1ccd59d7..a1e0795162a 100644 --- a/code/modules/power/power.dm +++ b/code/modules/power/power.dm @@ -88,7 +88,7 @@ if(isCoil(W)) var/obj/item/stack/cable_coil/coil = W var/turf/T = user.loc - if(!istype(T) || T.density || !T.is_plating()) + if(!istype(T) || T.density || !T.can_build_cable(user)) return if(get_dist(src, user) > 1) return From c3271cb25f272d194e22455b85c167bf5e66ff57 Mon Sep 17 00:00:00 2001 From: PsyCommando Date: Fri, 6 May 2022 20:55:31 -0400 Subject: [PATCH 03/86] Added feedback when trying to use a cable coil on a zcable Now instead of doing nothing, the cable gets connected the way zcable expect, and a message is sent to the user to let them know that yes, even if it doesn't look like it, the cable are indeed connected. --- code/modules/power/cable.dm | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm index b7ef999212f..57cca17cda7 100644 --- a/code/modules/power/cable.dm +++ b/code/modules/power/cable.dm @@ -767,6 +767,11 @@ By design, d1 is the smallest direction and d2 is the highest C.denode()// this call may have disconnected some cables that terminated on the centre of the turf, if so split the powernets. return TRUE + else if(C.d1 == UP) //Special cases for zcables, since they behave weirdly + . = turf_place(T, user) + if(.) + to_chat(user, SPAN_NOTICE("You connect the cable hanging from the ceiling.")) + return . /obj/item/stack/cable_coil/proc/put_cable(turf/F, mob/user, d1, d2) if(!istype(F)) From 25e8c9de8aeccc00bcf6a83a8206ed485e454216 Mon Sep 17 00:00:00 2001 From: PsyCommando Date: Fri, 6 May 2022 20:57:04 -0400 Subject: [PATCH 04/86] Corrected old path typo Seems pretty clear that this proc wasn't meant to be overridden twice on /turf/simulated. --- code/modules/multiz/turf.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/multiz/turf.dm b/code/modules/multiz/turf.dm index 7cc125a15ee..fcd981280d3 100644 --- a/code/modules/multiz/turf.dm +++ b/code/modules/multiz/turf.dm @@ -218,7 +218,7 @@ if(M.movable_flags & MOVABLE_FLAG_Z_INTERACT) return M.attackby(C, user) -/turf/simulated/open/attack_hand(mob/user) +/turf/exterior/open/attack_hand(mob/user) for(var/atom/movable/M in below) if(M.movable_flags & MOVABLE_FLAG_Z_INTERACT) return M.attack_hand(user) From 2b034f2cc2b51aaf97852e1209cbe25443b8ac08 Mon Sep 17 00:00:00 2001 From: PsyCommando Date: Fri, 6 May 2022 20:59:30 -0400 Subject: [PATCH 05/86] General messages cleanup * Used macros for spans. * Used defined stack vars to refer to the stack's contents instead of just using different words each times. * Replaced large unreadable power numbers with power constants instead. --- code/modules/power/cable.dm | 62 ++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm index 57cca17cda7..c66c1f39152 100644 --- a/code/modules/power/cable.dm +++ b/code/modules/power/cable.dm @@ -87,9 +87,9 @@ By design, d1 is the smallest direction and d2 is the highest user.examinate(src) // following code taken from attackby (multitool) if(powernet && (powernet.avail > 0)) - to_chat(user, "[get_wattage()] in power network.") + to_chat(user, SPAN_WARNING("[get_wattage()] in power network.")) else - to_chat(user, "The cable is not powered.") + to_chat(user, SPAN_WARNING("\The [src] is not powered.")) return /////////////////////////////////// @@ -97,10 +97,10 @@ By design, d1 is the smallest direction and d2 is the highest /////////////////////////////////// /obj/structure/cable/proc/get_wattage() - if(powernet.avail >= 1000000000) - return "[round(powernet.avail/1000000, 0.01)] MW" - if(powernet.avail >= 1000000) - return "[round(powernet.avail/1000, 0.01)] kW" + if(powernet.avail >= 1 GIGAWATTS) + return "[round(powernet.avail/(1 MEGAWATTS), 0.01)] MW" + if(powernet.avail >= 1 MEGAWATTS) + return "[round(powernet.avail/(1 KILOWATTS), 0.01)] kW" return "[round(powernet.avail)] W" //If underfloor, hide the cable @@ -153,10 +153,10 @@ By design, d1 is the smallest direction and d2 is the highest else if(isMultitool(W)) if(powernet && (powernet.avail > 0)) // is it powered? - to_chat(user, "[get_wattage()] in power network.") + to_chat(user, SPAN_WARNING("[get_wattage()] in power network.")) else - to_chat(user, "The cable is not powered.") + to_chat(user, SPAN_WARNING("\The [src] is not powered.")) shock(user, 5, 0.2) @@ -166,10 +166,10 @@ By design, d1 is the smallest direction and d2 is the highest var/delay_holder if(W.force < 5) - visible_message("[user] starts sawing away roughly at the cable with \the [W].") + visible_message(SPAN_WARNING("[user] starts sawing away roughly at \the [src] with \the [W].")) delay_holder = 8 SECONDS else - visible_message("[user] begins to cut through the cable with \the [W].") + visible_message(SPAN_WARNING("[user] begins to cut through \the [src] with \the [W].")) delay_holder = 3 SECONDS if(user.do_skilled(delay_holder, SKILL_ELECTRICAL, src)) @@ -177,7 +177,7 @@ By design, d1 is the smallest direction and d2 is the highest if(W.obj_flags & OBJ_FLAG_CONDUCTIBLE) shock(user, 66, 0.7) else - visible_message("[user] stops cutting before any damage is done.") + visible_message(SPAN_WARNING("[user] stops cutting before any damage is done.")) src.add_fingerprint(user) @@ -187,11 +187,11 @@ By design, d1 is the smallest direction and d2 is the highest return if(d1 == UP || d2 == UP) - to_chat(user, "You must cut this cable from above.") + to_chat(user, SPAN_WARNING("You must cut this [src] from above.")) return if(breaker_box) - to_chat(user, "This cable is connected to a nearby breaker box. Use the breaker box to interact with it.") + to_chat(user, SPAN_WARNING("This [src] is connected to a nearby breaker box. Use the breaker box to interact with it.")) return if (shock(user, 50)) @@ -199,7 +199,7 @@ By design, d1 is the smallest direction and d2 is the highest new/obj/item/stack/cable_coil(T, (src.d1 ? 2 : 1), color) - visible_message("[user] cuts the cable.") + visible_message(SPAN_WARNING("[user] cuts \the [src].")) if(HasBelow(z)) for(var/turf/turf in GetBelow(src)) @@ -535,7 +535,7 @@ By design, d1 is the smallest direction and d2 is the highest return ..() if(BP_IS_BRITTLE(S)) - to_chat(user, "\The [H]'s [S.name] is hard and brittle - \the [src] cannot repair it.") + to_chat(user, SPAN_WARNING("\The [H]'s [S.name] is hard and brittle - \the [src] cannot repair it.")) return 1 var/use_amt = min(src.amount, CEILING(S.burn_dam/3), 5) @@ -573,7 +573,7 @@ By design, d1 is the smallest direction and d2 is the highest selected_color = "Red" final_color = possible_cable_colours[selected_color] color = final_color - to_chat(user, "You change \the [src]'s color to [lowertext(selected_color)].") + to_chat(user, SPAN_NOTICE("You change \the [src]'s color to [lowertext(selected_color)].")) /obj/item/stack/cable_coil/proc/update_wclass() if(amount == 1) @@ -587,11 +587,11 @@ By design, d1 is the smallest direction and d2 is the highest return if(get_amount() == 1) - to_chat(user, "A short piece of power cable.") + to_chat(user, "A [singular_name] of cable.") else if(get_amount() == 2) - to_chat(user, "A piece of power cable.") + to_chat(user, "Two [plural_name] of cable.") else - to_chat(user, "A coil of power cable. There are [get_amount()] lengths of cable in the coil.") + to_chat(user, "A coil of power cable. There are [get_amount()] [plural_name] of cable in the coil.") /obj/item/stack/cable_coil/verb/make_restraint() @@ -602,13 +602,13 @@ By design, d1 is the smallest direction and d2 is the highest if(ishuman(M) && !M.incapacitated()) if(!isturf(usr.loc)) return if(!src.use(15)) - to_chat(usr, "You need at least 15 lengths to make restraints!") + to_chat(usr, SPAN_WARNING("You need at least 15 [singular_name] of cable to make restraints!")) return var/obj/item/handcuffs/cable/B = new /obj/item/handcuffs/cable(usr.loc) B.color = color - to_chat(usr, "You wind some cable together to make some restraints.") + to_chat(usr, SPAN_NOTICE("You wind some [plural_name] of cable together to make some restraints.")) else - to_chat(usr, "You cannot do that.") + to_chat(usr, SPAN_NOTICE("You cannot do that.")) /obj/item/stack/cable_coil/cyborg/verb/set_colour() set name = "Change Colour" @@ -644,15 +644,15 @@ By design, d1 is the smallest direction and d2 is the highest return if(get_amount() < 1) // Out of cable - to_chat(user, "There is no cable left.") + to_chat(user, SPAN_WARNING("There is no [plural_name] of cable left.")) return if(get_dist(F,user) > 1) // Too far - to_chat(user, "You can't lay cable at a place that far away.") + to_chat(user, SPAN_WARNING("You can't lay cable at a place that far away.")) return if(!F.is_plating()) // Ff floor is intact, complain - to_chat(user, "You can't lay cable there unless the floor tiles are removed.") + to_chat(user, SPAN_WARNING("You can't lay cable there unless the floor tiles are removed.")) return var/dirn @@ -664,13 +664,13 @@ By design, d1 is the smallest direction and d2 is the highest var/end_dir = 0 if(istype(F) && F.is_open()) if(!can_use(2)) - to_chat(user, "You don't have enough cable to do this!") + to_chat(user, SPAN_WARNING("You don't have enough [plural_name] of cable to do this!")) return end_dir = DOWN for(var/obj/structure/cable/LC in F) if((LC.d1 == dirn && LC.d2 == end_dir ) || ( LC.d2 == dirn && LC.d1 == end_dir)) - to_chat(user, "There's already a cable at that position.") + to_chat(user, SPAN_WARNING("There's already a cable at that position.")) return put_cable(F, user, end_dir, dirn) @@ -691,7 +691,7 @@ By design, d1 is the smallest direction and d2 is the highest return if(get_dist(C, user) > 1) // make sure it's close enough - to_chat(user, "You can't lay cable at a place that far away.") + to_chat(user, SPAN_WARNING("You can't lay cable at a place that far away.")) return if(U == T) //if clicked on the turf we're standing on, try to put a cable in the direction we're facing @@ -702,7 +702,7 @@ By design, d1 is the smallest direction and d2 is the highest // one end of the clicked cable is pointing towards us if(C.d1 == dirn || C.d2 == dirn) if(!U.is_plating()) // can't place a cable if the floor is complete - to_chat(user, "You can't lay cable there unless the floor tiles are removed.") + to_chat(user, SPAN_WARNING("You can't lay cable there unless the floor tiles are removed.")) return else // cable is pointing at us, we're standing on an open tile @@ -712,7 +712,7 @@ By design, d1 is the smallest direction and d2 is the highest for(var/obj/structure/cable/LC in U) // check to make sure there's not a cable there already if(LC.d1 == fdirn || LC.d2 == fdirn) - to_chat(user, "There's already a cable at that position.") + to_chat(user, SPAN_WARNING("There's already a cable at that position.")) return put_cable(U,user,0,fdirn) return TRUE @@ -733,7 +733,7 @@ By design, d1 is the smallest direction and d2 is the highest if(LC == C) // skip the cable we're interacting with continue if((LC.d1 == nd1 && LC.d2 == nd2) || (LC.d1 == nd2 && LC.d2 == nd1) ) // make sure no cable matches either direction - to_chat(user, "There's already a cable at that position.") + to_chat(user, SPAN_WARNING("There's already a cable at that position.")) return From d2ddb7b89971a0d490f314cf38e190bf7d26f94f Mon Sep 17 00:00:00 2001 From: MarinaGryphon Date: Fri, 12 Nov 2021 16:50:32 -0600 Subject: [PATCH 06/86] Fix mind and mob GC --- code/datums/mind/mind.dm | 13 +++++++-- code/modules/mob/living/carbon/human/human.dm | 1 + .../mob/living/simple_animal/friendly/cat.dm | 10 +++---- .../simple_animal/friendly/farm_animals.dm | 4 +++ .../mob/living/simple_animal/hostile/bat.dm | 4 +++ .../living/simple_animal/hostile/hostile.dm | 28 ++++++++++--------- .../simple_animal/hostile/retaliate/drone.dm | 1 + .../simple_animal/hostile/retaliate/parrot.dm | 9 ++++++ .../hostile/retaliate/retaliate.dm | 4 +++ code/modules/mob/mob.dm | 17 +++++------ code/modules/mob/new_player/new_player.dm | 4 +++ mods/content/matchmaking/matchmaker.dm | 8 ++++++ 12 files changed, 74 insertions(+), 29 deletions(-) diff --git a/code/datums/mind/mind.dm b/code/datums/mind/mind.dm index f5560c67258..4f386030978 100644 --- a/code/datums/mind/mind.dm +++ b/code/datums/mind/mind.dm @@ -36,7 +36,6 @@ var/mob/living/original //TODO: remove.not used in any meaningful way ~Carn. First I'll need to tweak the way silicon-mobs handle minds. var/active = 0 - var/list/known_connections //list of known (RNG) relations between people var/gen_relations_info var/assigned_role @@ -47,7 +46,6 @@ var/datum/job/assigned_job var/list/datum/objective/objectives = list() - var/list/datum/objective/special_verbs = list() var/has_been_rev = 0//Tracks if this mind has been a rev or not @@ -71,9 +69,19 @@ /datum/mind/Destroy() QDEL_NULL_LIST(memories) + QDEL_NULL_LIST(objectives) + QDEL_NULL(changeling) SSticker.minds -= src . = ..() +/datum/mind/proc/handle_mob_deletion(mob/living/deleted_mob) + if (current == deleted_mob) + current.spellremove() + current = null + + if (original == deleted_mob) + original = null + /datum/mind/proc/transfer_to(mob/living/new_character) if(!istype(new_character)) to_world_log("## DEBUG: transfer_to(): Some idiot has tried to transfer_to() a non mob/living mob. Please inform Carn") @@ -494,7 +502,6 @@ changeling = null initial_account = null objectives = list() - special_verbs = list() has_been_rev = 0 rev_cooldown = 0 brigged_since = -1 diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 035282c4e12..48a5d4e6392 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -37,6 +37,7 @@ global.human_mob_list -= src worn_underwear = null QDEL_NULL(attack_selector) + QDEL_NULL(vessel) LAZYCLEARLIST(smell_cooldown) . = ..() diff --git a/code/modules/mob/living/simple_animal/friendly/cat.dm b/code/modules/mob/living/simple_animal/friendly/cat.dm index 7022ad9edb8..33c43b92118 100644 --- a/code/modules/mob/living/simple_animal/friendly/cat.dm +++ b/code/modules/mob/living/simple_animal/friendly/cat.dm @@ -127,7 +127,7 @@ /mob/living/simple_animal/cat/hitby(atom/movable/AM, var/datum/thrownthing/TT) . = ..() set_flee_target(TT.thrower? TT.thrower : src.loc) - + /mob/living/simple_animal/cat/harvest_skin() . = ..() . += new/obj/item/cat_hide(get_turf(src)) @@ -136,7 +136,7 @@ name = "cat hide" desc = "The by-product of cat farming." icon = 'icons/obj/items/sheet_hide.dmi' - icon_state = "sheet-cat" + icon_state = "sheet-cat" //Basic friend AI /mob/living/simple_animal/cat/fluff @@ -144,7 +144,7 @@ var/befriend_job = null /mob/living/simple_animal/cat/fluff/handle_movement_target() - if (friend) + if (!QDELETED(friend)) var/follow_dist = 4 if (friend.stat >= DEAD || friend.is_asystole()) //danger follow_dist = 1 @@ -172,12 +172,12 @@ if (prob(10)) say("Meow!") - if (!friend || movement_target != friend) + if (QDELETED(friend) || movement_target != friend) ..() /mob/living/simple_animal/cat/fluff/do_delayed_life_action() ..() - if (stat || !friend) + if (stat || QDELETED(friend)) return if (get_dist(src, friend) <= 1) if (friend.stat >= DEAD || friend.is_asystole()) diff --git a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm index 2d71665bb3d..92dc41cdb89 100644 --- a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm +++ b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm @@ -114,6 +114,10 @@ . = ..() udder = new(50, src) +/mob/living/simple_animal/cow/Destroy() + QDEL_NULL(udder) + . = ..() + /mob/living/simple_animal/cow/attackby(var/obj/item/O, var/mob/user) var/obj/item/chems/glass/G = O if(stat == CONSCIOUS && istype(G) && ATOM_IS_OPEN_CONTAINER(G)) diff --git a/code/modules/mob/living/simple_animal/hostile/bat.dm b/code/modules/mob/living/simple_animal/hostile/bat.dm index ddc66701420..f1bcae968bf 100644 --- a/code/modules/mob/living/simple_animal/hostile/bat.dm +++ b/code/modules/mob/living/simple_animal/hostile/bat.dm @@ -25,6 +25,10 @@ if(istype(L)) owner = L +/mob/living/simple_animal/hostile/scarybat/Destroy() + owner = null + return ..() + /mob/living/simple_animal/hostile/scarybat/FindTarget() . = ..() if(.) diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm index 5c8e8326809..b72eb4b9b9c 100644 --- a/code/modules/mob/living/simple_animal/hostile/hostile.dm +++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm @@ -43,6 +43,11 @@ /obj/structure/wall_frame, /obj/structure/railing) +/mob/living/simple_animal/hostile/Destroy() + LAZYCLEARLIST(friends) + target_mob = null + return ..() + /mob/living/simple_animal/hostile/proc/can_act() if(QDELETED(src) || stat || stop_automation || incapacitated()) return FALSE @@ -101,7 +106,7 @@ walk_to(src, pick(orange(2, src)), 1, move_to_delay) return stop_automated_movement = 1 - if(!target_mob || SA_attackable(target_mob)) + if(QDELETED(target_mob) || SA_attackable(target_mob)) stance = HOSTILE_STANCE_IDLE if(target_mob in ListTargets(10)) if(ranged) @@ -240,18 +245,10 @@ visible_message("\The [src] [fire_desc] at \the [target]!", 1) if(rapid) - spawn(1) - Shoot(target, src.loc, src) - if(casingtype) - new casingtype(get_turf(src)) - spawn(4) - Shoot(target, src.loc, src) - if(casingtype) - new casingtype(get_turf(src)) - spawn(6) - Shoot(target, src.loc, src) - if(casingtype) - new casingtype(get_turf(src)) + var/datum/callback/shoot_cb = CALLBACK(src, .proc/shoot_wrapper, target, loc, src) + addtimer(shoot_cb, 1) + addtimer(shoot_cb, 4) + addtimer(shoot_cb, 6) else Shoot(target, src.loc, src) if(casingtype) @@ -261,6 +258,11 @@ target_mob = null return +/mob/living/simple_animal/hostile/proc/shoot_wrapper(target, location, user) + Shoot(target, location, user) + if (casingtype) + new casingtype(loc) + /mob/living/simple_animal/hostile/proc/Shoot(var/target, var/start, var/user, var/bullet = 0) if(target == start) return diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/drone.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/drone.dm index 23b1066fec8..d4a4a3a4dc1 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/drone.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/drone.dm @@ -171,6 +171,7 @@ qdel(src) /mob/living/simple_animal/hostile/retaliate/malf_drone/Destroy() + QDEL_NULL(ion_trail) //some random debris left behind if(has_loot) spark_at(src, cardinal_only = TRUE) diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/parrot.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/parrot.dm index 55c761792e9..4e1bbe04743 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/parrot.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/parrot.dm @@ -104,6 +104,15 @@ update_icon() +/mob/living/simple_animal/hostile/retaliate/parrot/Destroy() + QDEL_NULL(ears) + parrot_interest = null + parrot_perch = null + if(held_item) + held_item.dropInto(loc) + held_item = null + return ..() + /mob/living/simple_animal/hostile/retaliate/parrot/death(gibbed, deathmessage, show_dead_message) if(held_item) held_item.dropInto(loc) diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/retaliate.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/retaliate.dm index dca1f4ee607..4c0ea689fc7 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/retaliate.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/retaliate.dm @@ -1,6 +1,10 @@ /mob/living/simple_animal/hostile/retaliate var/list/enemies = list() +/mob/living/simple_animal/hostile/retaliate/Destroy() + LAZYCLEARLIST(enemies) + return ..() + /mob/living/simple_animal/hostile/retaliate/Found(var/atom/A) if(isliving(A)) var/mob/living/L = A diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 88b029cf1dc..84fbb139de6 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -26,11 +26,10 @@ if(!istype(screenobj) || !screenobj.globalscreen) qdel(screenobj) client.screen = list() - if(mind && mind.current == src) - spellremove(src) + if(mind) + mind.handle_mob_deletion(src) ghostize() - ..() - return QDEL_HINT_HARDDEL + return ..() /mob/proc/remove_screen_obj_references() hands = null @@ -224,6 +223,8 @@ /mob/proc/Life() SHOULD_NOT_SLEEP(TRUE) + if(QDELETED(src)) + return PROCESS_KILL if(ability_master) ability_master.update_spells(0) @@ -1034,7 +1035,7 @@ return client.mouse_pointer_icon = initial(client.mouse_pointer_icon) - + if(examine_cursor_icon && client.keys_held["Shift"]) client.mouse_pointer_icon = examine_cursor_icon @@ -1083,11 +1084,11 @@ var/turf/T = loc // We're inside something else. - if(!istype(T)) + if(!istype(T)) return WEATHER_PROTECTED - + // Either we're outside being rained on, or we're in turf-local weather being rained on. - if(T.is_outside() || T.weather == weather) + if(T.is_outside() || T.weather == weather) var/list/weather_protection = get_weather_protection() if(LAZYLEN(weather_protection)) return WEATHER_PROTECTED diff --git a/code/modules/mob/new_player/new_player.dm b/code/modules/mob/new_player/new_player.dm index 396d1534eb6..7d7b1df5ab2 100644 --- a/code/modules/mob/new_player/new_player.dm +++ b/code/modules/mob/new_player/new_player.dm @@ -26,6 +26,10 @@ forceMove(null) verbs += /mob/proc/toggle_antag_pool +/mob/new_player/Destroy() + QDEL_NULL(panel) + . = ..() + /mob/new_player/proc/show_lobby_menu(force = FALSE) if(!SScharacter_setup.initialized && !force) return // Not ready yet. diff --git a/mods/content/matchmaking/matchmaker.dm b/mods/content/matchmaking/matchmaker.dm index 01a44dfd0bd..803fea9778f 100644 --- a/mods/content/matchmaking/matchmaker.dm +++ b/mods/content/matchmaking/matchmaker.dm @@ -18,6 +18,14 @@ var/global/datum/matchmaker/matchmaker = new() return TRUE matchmaker.do_matchmaking() return TRUE + +/datum/mind + var/list/known_connections //list of known (RNG) relations between people + +/datum/mind/Destroy() + QDEL_NULL_LIST(known_connections) + . = ..() + /datum/matchmaker var/list/relation_types = list() var/list/relations = list() From c91cd221cd052780880061fa5ad5ec88e5622f11 Mon Sep 17 00:00:00 2001 From: MarinaGryphon Date: Fri, 12 Nov 2021 18:17:42 -0600 Subject: [PATCH 07/86] Fix autosay being garbled --- code/modules/mob/living/carbon/human/say.dm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/code/modules/mob/living/carbon/human/say.dm b/code/modules/mob/living/carbon/human/say.dm index 359e9b504ee..375d3579a07 100644 --- a/code/modules/mob/living/carbon/human/say.dm +++ b/code/modules/mob/living/carbon/human/say.dm @@ -60,6 +60,8 @@ if(!speaking) if(istype(other, /mob/living/silicon)) return TRUE + if(istype(other, /mob/announcer)) + return TRUE if(istype(other, /mob/living/carbon/brain)) return TRUE return ..() From 0c31bda4caa617c538a50516a0483dbfcb4c56cd Mon Sep 17 00:00:00 2001 From: MarinaGryphon Date: Fri, 12 Nov 2021 18:32:02 -0600 Subject: [PATCH 08/86] Fix grammar in unpowered computer message --- .../computers/modular_computer/assembly_computer.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/modular_computers/computers/modular_computer/assembly_computer.dm b/code/modules/modular_computers/computers/modular_computer/assembly_computer.dm index e6d1b671cb5..5d1a810562f 100644 --- a/code/modules/modular_computers/computers/modular_computer/assembly_computer.dm +++ b/code/modules/modular_computers/computers/modular_computer/assembly_computer.dm @@ -84,7 +84,7 @@ if(force_synth || issynth) to_chat(user, SPAN_WARNING("You send an activation signal to \the [assembly_name], but it does not respond.")) else - to_chat(user, SPAN_WARNING("You press the power button but \the [assembly_name], does not respond.")) + to_chat(user, SPAN_WARNING("You press the power button but \the [assembly_name] does not respond.")) shutdown_device() /datum/extension/assembly/modular_computer/shutdown_device() From fa29727614be266bb0df38a46bb669c18db47794 Mon Sep 17 00:00:00 2001 From: MarinaGryphon Date: Wed, 17 Nov 2021 11:21:10 -0600 Subject: [PATCH 09/86] Fix circular reference in thrownthing --- code/controllers/subsystems/throwing.dm | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/code/controllers/subsystems/throwing.dm b/code/controllers/subsystems/throwing.dm index 21adc0015f4..d4519eac6ad 100644 --- a/code/controllers/subsystems/throwing.dm +++ b/code/controllers/subsystems/throwing.dm @@ -26,8 +26,16 @@ SUBSYSTEM_DEF(throwing) var/atom/movable/AM = currentrun[currentrun.len] var/datum/thrownthing/TT = currentrun[AM] currentrun.len-- - if (QDELETED(AM) || QDELETED(TT)) - processing -= AM + if (QDELETED(AM)) + if(!QDELETED(TT)) + qdel(TT) // handles removing from processing list + if (MC_TICK_CHECK) + return + continue + if (QDELETED(TT)) + if(!QDELETED(AM)) + AM.throwing = null + processing -= AM if (MC_TICK_CHECK) return continue @@ -168,10 +176,10 @@ SUBSYSTEM_DEF(throwing) hit = TRUE thrownthing.throw_impact(A, src) break - + if(QDELETED(thrownthing)) return - + if(!hit) thrownthing.throw_impact(get_turf(thrownthing), src) // we haven't hit something yet and we still must, let's hit the ground. thrownthing.space_drift(init_dir) From e2a747ea6171b87f76d64b5ba667fd38113090d4 Mon Sep 17 00:00:00 2001 From: MarinaGryphon Date: Sat, 13 Nov 2021 12:35:00 -0600 Subject: [PATCH 10/86] Fix several more hanging refs --- code/game/movietitles.dm | 2 +- .../mob/living/carbon/human/human_damage.dm | 1 + .../mob/living/carbon/human/human_organs.dm | 16 +++++++++++++--- code/modules/mob/mob.dm | 1 + code/modules/organs/external/_external.dm | 3 +++ 5 files changed, 19 insertions(+), 4 deletions(-) diff --git a/code/game/movietitles.dm b/code/game/movietitles.dm index a603643b1dc..9f37d5e716c 100644 --- a/code/game/movietitles.dm +++ b/code/game/movietitles.dm @@ -88,7 +88,7 @@ var/global/list/end_titles var/client/P = parent if(parent) P.screen -= src - LAZYREMOVE(P.credits, src) + LAZYREMOVE(P?.credits, src) parent = null return ..() diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm index 5157e4da392..a1f2e81d4e6 100644 --- a/code/modules/mob/living/carbon/human/human_damage.dm +++ b/code/modules/mob/living/carbon/human/human_damage.dm @@ -327,6 +327,7 @@ This function restores all organs. var/obj/item/organ/external/current_organ = get_organ(bodypart) if(istype(current_organ)) current_organ.rejuvenate(ignore_prosthetic_prefs) + bad_external_organs.Cut() // otherwise hanging refs will prevent gc after rejuv verbs -= /mob/living/carbon/human/proc/undislocate /mob/living/carbon/human/proc/HealDamage(zone, brute, burn) diff --git a/code/modules/mob/living/carbon/human/human_organs.dm b/code/modules/mob/living/carbon/human/human_organs.dm index 3a31d82b11d..a8051d966b6 100644 --- a/code/modules/mob/living/carbon/human/human_organs.dm +++ b/code/modules/mob/living/carbon/human/human_organs.dm @@ -8,7 +8,7 @@ var/obj/item/organ/external/E = get_organ(zone) if(E) . = E.name -/mob/living/carbon/human/proc/recheck_bad_external_organs() +/mob/living/carbon/human/proc/should_recheck_bad_external_organs() var/damage_this_tick = getToxLoss() for(var/obj/item/organ/external/O in get_external_organs()) damage_this_tick += O.burn_dam + O.brute_dam @@ -17,13 +17,23 @@ . = TRUE last_dam = damage_this_tick +/mob/living/carbon/human/proc/recheck_bad_external_organs() + bad_external_organs.Cut() + for(var/obj/item/organ/external/E in organs) + if(!E || !E.need_process()) + continue + bad_external_organs |= E + // Takes care of organ related updates, such as broken and missing limbs /mob/living/carbon/human/proc/handle_organs() + //processing internal organs is pretty cheap, do that first. + for(var/obj/item/organ/I in internal_organs) + I.Process() - var/force_process = recheck_bad_external_organs() + var/force_process = should_recheck_bad_external_organs() if(force_process) - bad_external_organs.Cut() + recheck_bad_external_organs() for(var/obj/item/organ/external/Ex in get_external_organs()) bad_external_organs |= Ex diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 88b029cf1dc..a8382594e80 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -28,6 +28,7 @@ client.screen = list() if(mind && mind.current == src) spellremove(src) + teleop = null ghostize() ..() return QDEL_HINT_HARDDEL diff --git a/code/modules/organs/external/_external.dm b/code/modules/organs/external/_external.dm index b810ef1b333..fb7569feff1 100644 --- a/code/modules/organs/external/_external.dm +++ b/code/modules/organs/external/_external.dm @@ -120,6 +120,9 @@ LAZYCLEARLIST(internal_organs) LAZYCLEARLIST(implants) + if(owner) + owner.bad_external_organs -= src + /obj/item/organ/external/set_species(specie_name) . = ..() skin_blend = bodytype.limb_blend From b5397fc4831b7fa32e40275431801b461efd57ce Mon Sep 17 00:00:00 2001 From: MistakeNot4892 Date: Mon, 9 May 2022 12:37:48 +1000 Subject: [PATCH 11/86] Reapplying a dangling ref fix to credits from Hearth. --- code/game/movietitles.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/game/movietitles.dm b/code/game/movietitles.dm index a603643b1dc..8b57417b5b6 100644 --- a/code/game/movietitles.dm +++ b/code/game/movietitles.dm @@ -86,9 +86,9 @@ var/global/list/end_titles /obj/screen/credit/Destroy() var/client/P = parent - if(parent) + if(istype(P)) P.screen -= src - LAZYREMOVE(P.credits, src) + LAZYREMOVE(P.credits, src) parent = null return ..() From 30239b8f744f409b330921a280e2c198cc278141 Mon Sep 17 00:00:00 2001 From: MistakeNot4892 Date: Mon, 9 May 2022 12:39:38 +1000 Subject: [PATCH 12/86] Reapplying a GC from hearth again. --- code/modules/admin/verbs/randomverbs.dm | 1 - code/modules/mob/living/carbon/human/say.dm | 2 -- code/modules/mob/mob.dm | 1 + 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm index 0bb545ff9c6..747cea4c332 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -467,7 +467,6 @@ Traitors and the like can also be revived with the previous role mostly intact. if(G_found.mind && !G_found.mind.active) G_found.mind.transfer_to(new_character) //be careful when doing stuff like this! I've already checked the mind isn't in use - new_character.mind.special_verbs = list() else new_character.mind_initialize() if(!new_character.mind.assigned_role) diff --git a/code/modules/mob/living/carbon/human/say.dm b/code/modules/mob/living/carbon/human/say.dm index 375d3579a07..359e9b504ee 100644 --- a/code/modules/mob/living/carbon/human/say.dm +++ b/code/modules/mob/living/carbon/human/say.dm @@ -60,8 +60,6 @@ if(!speaking) if(istype(other, /mob/living/silicon)) return TRUE - if(istype(other, /mob/announcer)) - return TRUE if(istype(other, /mob/living/carbon/brain)) return TRUE return ..() diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 84fbb139de6..acc92c16205 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -28,6 +28,7 @@ client.screen = list() if(mind) mind.handle_mob_deletion(src) + teleop = null ghostize() return ..() From 0e37d2d82064c23a8dedbb54ff7ebd731a9e361b Mon Sep 17 00:00:00 2001 From: MistakeNot4892 Date: Mon, 9 May 2022 12:35:08 +1000 Subject: [PATCH 13/86] Lazylisting bad_external_organs while we're in the neighborhood. --- code/game/movietitles.dm | 2 +- .../mob/living/carbon/human/human_damage.dm | 2 +- .../mob/living/carbon/human/human_defines.dm | 5 ++-- .../mob/living/carbon/human/human_organs.dm | 24 ++++++++----------- code/modules/mob/mob.dm | 1 - code/modules/organs/external/_external.dm | 4 ++-- 6 files changed, 17 insertions(+), 21 deletions(-) diff --git a/code/game/movietitles.dm b/code/game/movietitles.dm index 9f37d5e716c..a603643b1dc 100644 --- a/code/game/movietitles.dm +++ b/code/game/movietitles.dm @@ -88,7 +88,7 @@ var/global/list/end_titles var/client/P = parent if(parent) P.screen -= src - LAZYREMOVE(P?.credits, src) + LAZYREMOVE(P.credits, src) parent = null return ..() diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm index a1f2e81d4e6..31aaaf9dff3 100644 --- a/code/modules/mob/living/carbon/human/human_damage.dm +++ b/code/modules/mob/living/carbon/human/human_damage.dm @@ -327,7 +327,7 @@ This function restores all organs. var/obj/item/organ/external/current_organ = get_organ(bodypart) if(istype(current_organ)) current_organ.rejuvenate(ignore_prosthetic_prefs) - bad_external_organs.Cut() // otherwise hanging refs will prevent gc after rejuv + recheck_bad_external_organs() verbs -= /mob/living/carbon/human/proc/undislocate /mob/living/carbon/human/proc/HealDamage(zone, brute, burn) diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm index f88316c68a5..e83c32463f9 100644 --- a/code/modules/mob/living/carbon/human/human_defines.dm +++ b/code/modules/mob/living/carbon/human/human_defines.dm @@ -45,8 +45,9 @@ var/voice = "" //Instead of new say code calling GetVoice() over and over and over, we're just going to ask this variable, which gets updated in Life() var/last_dam = -1 //Used for determining if we need to process all organs or just some or even none. - var/list/bad_external_organs = list() // organs we check until they are good. - + /// organs we check until they are good. + var/list/bad_external_organs + var/xylophone = 0 //For the spoooooooky xylophone cooldown var/mob/remoteview_target = null diff --git a/code/modules/mob/living/carbon/human/human_organs.dm b/code/modules/mob/living/carbon/human/human_organs.dm index a8051d966b6..38840c65a47 100644 --- a/code/modules/mob/living/carbon/human/human_organs.dm +++ b/code/modules/mob/living/carbon/human/human_organs.dm @@ -18,14 +18,14 @@ last_dam = damage_this_tick /mob/living/carbon/human/proc/recheck_bad_external_organs() - bad_external_organs.Cut() - for(var/obj/item/organ/external/E in organs) - if(!E || !E.need_process()) - continue - bad_external_organs |= E + LAZYCLEARLIST(bad_external_organs) + for(var/obj/item/organ/external/E in get_external_organs()) + if(E.need_process()) + LAZYDISTINCTADD(bad_external_organs, E) // Takes care of organ related updates, such as broken and missing limbs /mob/living/carbon/human/proc/handle_organs() + //processing internal organs is pretty cheap, do that first. for(var/obj/item/organ/I in internal_organs) I.Process() @@ -35,23 +35,19 @@ if(force_process) recheck_bad_external_organs() for(var/obj/item/organ/external/Ex in get_external_organs()) - bad_external_organs |= Ex - - //processing internal organs is pretty cheap, do that first. - for(var/obj/item/organ/I in get_internal_organs()) - I.Process() + LAZYDISTINCTADD(bad_external_organs, Ex) handle_stance() handle_grasp() - if(!force_process && !length(bad_external_organs)) + if(!force_process && !LAZYLEN(bad_external_organs)) return for(var/obj/item/organ/external/E in bad_external_organs) if(!E) continue if(!E.need_process()) - bad_external_organs -= E + LAZYREMOVE(bad_external_organs, E) continue else E.Process() @@ -283,7 +279,7 @@ return if(!O.is_internal()) refresh_modular_limb_verbs() - bad_external_organs -= O + LAZYREMOVE(bad_external_organs, O) //#TODO: wish we could invalidate the human icons to trigger a single update when the organ state changes multiple times in a row if(update_icon) @@ -303,4 +299,4 @@ /mob/living/carbon/human/delete_organs() . = ..() - bad_external_organs?.Cut() \ No newline at end of file + LAZYCLEARLIST(bad_external_organs) diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index a8382594e80..88b029cf1dc 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -28,7 +28,6 @@ client.screen = list() if(mind && mind.current == src) spellremove(src) - teleop = null ghostize() ..() return QDEL_HINT_HARDDEL diff --git a/code/modules/organs/external/_external.dm b/code/modules/organs/external/_external.dm index fb7569feff1..68de99d8ef2 100644 --- a/code/modules/organs/external/_external.dm +++ b/code/modules/organs/external/_external.dm @@ -121,7 +121,7 @@ LAZYCLEARLIST(implants) if(owner) - owner.bad_external_organs -= src + LAZYREMOVE(owner.bad_external_organs, src) /obj/item/organ/external/set_species(specie_name) . = ..() @@ -1560,7 +1560,7 @@ Note that amputating the affected organ does in fact remove the infection from t /obj/item/organ/external/add_ailment(var/datum/ailment/ailment) . = ..() if(. && owner) - owner.bad_external_organs |= src + LAZYDISTINCTADD(owner.bad_external_organs, src) /obj/item/organ/external/die() //External organs dying on a dime causes some real issues in combat if(!BP_IS_PROSTHETIC(src) && !BP_IS_CRYSTAL(src)) From 40a492d61305c71be60c12506c1bc5028246ae67 Mon Sep 17 00:00:00 2001 From: afterthought Date: Mon, 9 May 2022 19:37:09 -0400 Subject: [PATCH 14/86] Simplifies and modernizes report access. --- code/game/jobs/access.dm | 8 ---- .../programs/generic/deck_management.dm | 21 ++++++++--- .../file_system/reports/deck_reports.dm | 32 ++++------------ .../file_system/reports/report.dm | 37 ++++++------------- .../file_system/reports/report_field.dm | 22 ++--------- .../file_system/reports/warrant.dm | 4 +- 6 files changed, 40 insertions(+), 84 deletions(-) diff --git a/code/game/jobs/access.dm b/code/game/jobs/access.dm index 2c15361663c..aa8f06c356b 100644 --- a/code/game/jobs/access.dm +++ b/code/game/jobs/access.dm @@ -47,14 +47,6 @@ return FALSE return TRUE -//Checks if the access (constant or list) is contained in one of the entries of access_patterns, a list of lists. -/proc/has_access_pattern(list/access_patterns, access) - if(!islist(access)) - access = list(access) - for(var/access_pattern in access_patterns) - if(has_access(access_pattern, access)) - return 1 - // Used for retrieving required access information, if available /atom/movable/proc/get_req_access() return null diff --git a/code/modules/modular_computers/file_system/programs/generic/deck_management.dm b/code/modules/modular_computers/file_system/programs/generic/deck_management.dm index 608f973f3cf..a9c4306f9a4 100644 --- a/code/modules/modular_computers/file_system/programs/generic/deck_management.dm +++ b/code/modules/modular_computers/file_system/programs/generic/deck_management.dm @@ -185,12 +185,22 @@ prototype_shuttle = selected_shuttle report_prototypes = list() for(var/report_type in subtypesof(/datum/computer_file/report/recipient/shuttle)) - var/datum/computer_file/report/recipient/shuttle/new_report = new report_type - if(new_report.access_shuttle) - new_report.set_access(null, selected_shuttle.logging_access, override = 0) - report_prototypes += new_report + report_prototypes += create_report(report_type, selected_shuttle) return 1 +/datum/nano_module/deck_management/proc/create_report(report_type, datum/shuttle/given_shuttle) + var/datum/computer_file/report/recipient/shuttle/new_report = new report_type + if(new_report.access_shuttle && given_shuttle.logging_access) + var/old_access = new_report.write_access?.Copy() + var/new_access = list() + for(var/group in old_access) // We add logging_access as an OR option to every AND requirement + var/new_group = list() + new_group += group // this listifies it if it was not already a list + new_group |= given_shuttle.logging_access + new_access += list(new_group) + new_report.set_access(null, new_access, TRUE) + return new_report + /datum/nano_module/deck_management/proc/set_mission(mission_ID) var/datum/shuttle_log/my_log = SSshuttle.shuttle_logs[selected_shuttle] var/datum/shuttle_mission/mission = my_log.mission_from_ID(mission_ID) @@ -256,8 +266,7 @@ if(selected_mission.flight_plan) selected_report = selected_mission.flight_plan.clone()//We always make a new one to buffer changes until submitted. else - selected_report = new /datum/computer_file/report/flight_plan - selected_report.set_access(null, selected_shuttle.logging_access, override = 0) + selected_report = create_report(/datum/computer_file/report/flight_plan, selected_shuttle) else if(selected_mission.stage in list(SHUTTLE_MISSION_PLANNED, SHUTTLE_MISSION_QUEUED)) return 1 //Hold your horses until the mission is started on these reports. diff --git a/code/modules/modular_computers/file_system/reports/deck_reports.dm b/code/modules/modular_computers/file_system/reports/deck_reports.dm index 84e48d9a46e..08f75763ad3 100644 --- a/code/modules/modular_computers/file_system/reports/deck_reports.dm +++ b/code/modules/modular_computers/file_system/reports/deck_reports.dm @@ -6,10 +6,7 @@ var/datum/report_field/people/leader //Give these a special name for easier access. var/datum/report_field/people/manifest var/datum/report_field/planned_depart - -/datum/computer_file/report/flight_plan/New() - ..() - set_access(null, access_bridge) + write_access = list(access_bridge) /datum/computer_file/report/flight_plan/Destroy() leader = null @@ -31,11 +28,8 @@ /datum/computer_file/report/recipient/shuttle var/datum/report_field/shuttle var/datum/report_field/mission - var/access_shuttle = 0 //Set to 1 to give the shuttle's logging access as an access_edit pattern. - -/datum/computer_file/report/recipient/shuttle/New() - ..() - set_access(null, access_bridge) + var/access_shuttle = 0 //Set to 1 to give the shuttle's logging access write permissions when created + write_access = list(access_bridge) /datum/computer_file/report/recipient/shuttle/Destroy() shuttle = null @@ -52,10 +46,7 @@ /datum/computer_file/report/recipient/shuttle/damage form_name = "DC243" title = "Post-flight Damage Assessment" - -/datum/computer_file/report/recipient/shuttle/damage/New() - ..() - set_access(null, access_cargo, override = 0) + write_access = list(list(access_bridge, access_cargo)) /datum/computer_file/report/recipient/shuttle/damage/generate_fields() ..() @@ -68,10 +59,7 @@ /datum/computer_file/report/recipient/shuttle/fuel form_name = "DC12" title = "Post-flight Refueling Report" - -/datum/computer_file/report/recipient/shuttle/fuel/New() - ..() - set_access(null, access_cargo, override = 0) + write_access = list(list(access_bridge, access_cargo)) /datum/computer_file/report/recipient/shuttle/fuel/generate_fields() ..() @@ -83,10 +71,7 @@ /datum/computer_file/report/recipient/shuttle/atmos form_name = "DC245" title = "Post-flight Atmospherics Assessment" - -/datum/computer_file/report/recipient/shuttle/atmos/New() - ..() - set_access(null, access_cargo, override = 0) + write_access = list(list(access_bridge, access_cargo)) /datum/computer_file/report/recipient/shuttle/atmos/generate_fields() ..() @@ -98,10 +83,7 @@ /datum/computer_file/report/recipient/shuttle/gear form_name = "DC248b" title = "Post-flight Emergency Supply Inventory; Summary Version" - -/datum/computer_file/report/recipient/shuttle/gear/New() - ..() - set_access(null, access_cargo, override = 0) + write_access = list(list(access_bridge, access_cargo)) /datum/computer_file/report/recipient/shuttle/gear/generate_fields() ..() diff --git a/code/modules/modular_computers/file_system/reports/report.dm b/code/modules/modular_computers/file_system/reports/report.dm index 1aaa74bc18a..14e4a2277df 100644 --- a/code/modules/modular_computers/file_system/reports/report.dm +++ b/code/modules/modular_computers/file_system/reports/report.dm @@ -5,7 +5,7 @@ var/form_name = "AB1" //Form code, for maximum bureaucracy. var/creator //The name of the mob that made the report. var/file_time //Time submitted. - write_access = list() //The access required to submit the report. See documentation below. + write_access = list() //The access required to submit the report. read_access = list() //The access required to view the report. mod_access = list(list(access_bridge)) //Changing the read/write access of the file should generally require higher access than the write access itself. var/list/datum/report_field/fields = list() //A list of fields the report comes with, in order that they should be displayed. @@ -16,6 +16,7 @@ /datum/computer_file/report/New() ..() generate_fields() + initialize_access() /datum/computer_file/report/Destroy() QDEL_NULL_LIST(fields) @@ -23,40 +24,26 @@ /* This proc resets the access to the report, resulting in just one access requirement for read/write. -Arguments can be access values (numbers) or lists of access values. If null is passed to one of the arguments, that access type is left alone. Pass list() to reset to no access needed instead. The recursive option resets access to all fields in the report as well. -If the override option is set to 0, the access supplied will instead be added as another OR access field in the access list in the index access_group. -If null is passed to access_group then a new access group will be added instead. */ -/datum/computer_file/report/proc/set_access(read_access, write_access, recursive = 1, override = 1, access_group = 1) +/datum/computer_file/report/proc/set_access(read_access, write_access, recursive = TRUE) if(read_access) if(!islist(read_access)) read_access = list(read_access) - if(override) - src.read_access = read_access - else - if(access_group && access_group <= src.read_access.len) // Add the passed access as an OR access field in an existing access group - if(!islist(src.read_access[access_group])) // If the index isn't actually a list, make it one. - src.read_access[access_group] = list(src.read_access[access_group]) - src.read_access[access_group] += read_access - else // Add an entire new access group to the access requirements. - src.read_access += list(read_access) + src.read_access = read_access if(write_access) if(!islist(write_access)) write_access = list(write_access) - if(override) - src.write_access = write_access - else - if(access_group && access_group <= src.write_access.len) - if(!islist(src.write_access[access_group])) - src.write_access[access_group] = list(src.write_access[access_group]) - src.write_access[access_group] += write_access - else - src.write_access += list(write_access) + src.write_access = write_access if(recursive) for(var/datum/report_field/field in fields) - field.set_access(read_access, write_access, override, TRUE, access_group) + field.set_access(read_access, write_access, TRUE) + +// The default behavior propagates (non-empty) preset access to the fields which allow such propogation. +// You can override or modify this behavior on subtypes. +/datum/computer_file/report/proc/initialize_access() + set_access(length(read_access) ? read_access : null, length(write_access) ? write_access : null, TRUE) //Looking up fields. Names might not be unique unless you ensure otherwise. /datum/computer_file/report/proc/field_from_ID(ID) @@ -190,4 +177,4 @@ Overriden so that read access is required to have write access if(!.) return for(var/datum/report_field/field in fields) - field.set_access(read_access, write_access, TRUE, TRUE) \ No newline at end of file + field.set_access(read_access, write_access, TRUE) \ No newline at end of file diff --git a/code/modules/modular_computers/file_system/reports/report_field.dm b/code/modules/modular_computers/file_system/reports/report_field.dm index e8b6d9aad59..38ae04459fe 100644 --- a/code/modules/modular_computers/file_system/reports/report_field.dm +++ b/code/modules/modular_computers/file_system/reports/report_field.dm @@ -21,32 +21,18 @@ . = ..() //Access stuff. Can be given access constants or lists. See report access procs for documentation. -/datum/report_field/proc/set_access(read_access, write_access, override = 1, recursive = FALSE, access_group = 1) +//For fields, the recursive argument indicates whether this access set is being propogated onto the whole report at once or not. +/datum/report_field/proc/set_access(read_access, write_access, recursive = FALSE) if(recursive && !can_mod_access) return if(read_access) if(!islist(read_access)) read_access = list(read_access) - if(override) - src.read_access = read_access - else - if(access_group && access_group <= src.read_access.len) - if(!islist(src.read_access[access_group])) - src.read_access[access_group] = list(src.read_access[access_group]) - src.read_access[access_group] += read_access - else - src.read_access += list(read_access) + src.read_access = read_access if(write_access) if(!islist(write_access)) write_access = list(write_access) - if(override) - src.write_access = write_access - else - if(access_group && access_group <= src.write_access.len) - if(!islist(src.write_access[access_group])) - src.write_access[access_group] = list(src.write_access[access_group]) - else - src.write_access[access_group] += write_access + src.write_access = write_access // Analogous to get_file_perms on reports. Read access is required to have write access. /datum/report_field/proc/get_perms(accesses, mob/user) diff --git a/code/modules/modular_computers/file_system/reports/warrant.dm b/code/modules/modular_computers/file_system/reports/warrant.dm index d262970e126..c32a22435b2 100644 --- a/code/modules/modular_computers/file_system/reports/warrant.dm +++ b/code/modules/modular_computers/file_system/reports/warrant.dm @@ -35,13 +35,13 @@ /datum/computer_file/report/warrant/arrest title = "Arrest Warrant" form_name = "W-104-A" + write_access = list(access_security) /datum/computer_file/report/warrant/arrest/generate_fields() add_field(/datum/report_field/text_label/header, "Arrest Warrant") add_field(/datum/report_field/simple_text, "Name", "Unknown") add_field(/datum/report_field/pencode_text, "Charges", "No charges") add_field(/datum/report_field/signature, "Authorized by", "Unathorized") - set_access(write_access = access_security) /datum/computer_file/report/warrant/arrest/get_category() . = ..() @@ -74,13 +74,13 @@ /datum/computer_file/report/warrant/search title = "Search Warrant" form_name = "W-104-S" + write_access = list(access_security) /datum/computer_file/report/warrant/search/generate_fields() add_field(/datum/report_field/text_label/header, "Search Warrant") add_field(/datum/report_field/simple_text, "Person/Location", "Unknown") add_field(/datum/report_field/pencode_text, "Reason", "No reason") add_field(/datum/report_field/signature, "Authorized by", "Unathorized") - set_access(write_access = access_security) /datum/computer_file/report/warrant/search/get_category() . = ..() From b2541e74da7f82791143ccf8b2f9c3346a20d39e Mon Sep 17 00:00:00 2001 From: NebulaSS13Bot Date: Tue, 10 May 2022 00:43:13 +0000 Subject: [PATCH 15/86] Automatic changelog generation [ci skip] --- html/changelog.html | 9 +++++++++ html/changelogs/.all_changelog.yml | 8 ++++++++ html/changelogs/AutoChangeLog-pr-2262.yml | 7 ------- html/changelogs/AutoChangeLog-pr-2352.yml | 5 ----- 4 files changed, 17 insertions(+), 12 deletions(-) delete mode 100644 html/changelogs/AutoChangeLog-pr-2262.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-2352.yml diff --git a/html/changelog.html b/html/changelog.html index 7175134257b..4388ca8b799 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -52,6 +52,15 @@ -->
+

10 May 2022

+

tag if you want to specify another name or several people. --> updated:

+
    +
  • Adds user accounts and network groups which allows for custom access systems tied to computer networks
  • +
  • Adds access requirements tied to computer files for read/write
  • +
  • Removes previous grant based computer network access system
  • +
  • You can now hack industrial fabs to print shields, or craft a buckler from a stool.
  • +
+

09 May 2022

tag if you want to specify another name or several people. --> updated: