From 09616e4292f9b29d000b292d0b2be39ca36ef5d4 Mon Sep 17 00:00:00 2001 From: KubeRoot Date: Thu, 8 Jul 2021 03:53:21 +0200 Subject: [PATCH] Port harddel fixes, as well as "Fixes stasis bed runtimes" --- code/__DEFINES/cooldowns.dm | 2 +- code/__DEFINES/mobs.dm | 6 ++ code/__DEFINES/subsystems.dm | 3 + code/__HELPERS/_logging.dm | 5 + code/_compile_options.dm | 3 + code/_onclick/hud/radial.dm | 15 ++- code/_onclick/hud/radial_persistent.dm | 2 +- code/controllers/subsystem/atoms.dm | 3 + code/controllers/subsystem/garbage.dm | 20 +++- code/datums/browser.dm | 18 +++- code/datums/components/squeak.dm | 2 +- code/datums/components/storage/storage.dm | 16 ++- code/datums/dash_weapon.dm | 14 +-- code/datums/hud.dm | 1 + code/datums/mind.dm | 20 +++- .../game/gamemodes/clown_ops/clown_weapons.dm | 5 +- code/game/gamemodes/objective.dm | 5 + code/game/machinery/camera/tracking.dm | 8 +- code/game/machinery/computer/Operating.dm | 23 +++-- code/game/machinery/launch_pad.dm | 51 +++++----- code/game/machinery/stasis.dm | 8 +- code/game/objects/effects/anomalies.dm | 2 +- code/game/objects/items.dm | 6 +- code/game/objects/items/chrono_eraser.dm | 8 +- .../objects/items/devices/transfer_valve.dm | 4 + code/game/objects/items/dice.dm | 6 +- .../objects/items/implants/implant_track.dm | 14 ++- code/game/objects/items/melee/energy.dm | 4 + code/game/objects/items/melee/misc.dm | 2 +- code/game/objects/structures/tables_racks.dm | 31 ++++-- code/game/objects/structures/traps.dm | 10 +- .../antagonists/abductor/equipment/gland.dm | 4 +- .../blob/blobstrains/_blobstrain.dm | 4 + code/modules/antagonists/blob/overmind.dm | 1 + code/modules/antagonists/cult/cult_items.dm | 11 ++- .../antagonists/disease/disease_disease.dm | 1 + .../antagonists/disease/disease_mob.dm | 2 + .../antagonists/slaughter/slaughter.dm | 2 +- code/modules/assembly/assembly.dm | 4 + code/modules/assembly/flash.dm | 15 +-- .../portable/portable_atmospherics.dm | 4 +- code/modules/awaymissions/capture_the_flag.dm | 20 +++- .../awaymissions/mission_code/Cabin.dm | 2 +- .../awaymissions/mission_code/TheFactory.dm | 2 +- code/modules/cargo/supplypod.dm | 6 +- code/modules/client/verbs/suicide.dm | 4 +- code/modules/clothing/head/misc.dm | 2 +- code/modules/clothing/masks/gasmask.dm | 2 +- .../modules/clothing/spacesuits/chronosuit.dm | 5 + code/modules/clothing/spacesuits/hardsuit.dm | 9 +- code/modules/clothing/suits/toggles.dm | 5 +- code/modules/clothing/under/accessories.dm | 17 +++- code/modules/events/wizard/greentext.dm | 3 +- code/modules/fields/timestop.dm | 2 +- code/modules/guardian/guardian.dm | 7 +- code/modules/holodeck/holo_effect.dm | 81 ++++++++++----- code/modules/language/language_holder.dm | 4 +- code/modules/lighting/lighting_source.dm | 3 +- code/modules/mining/laborcamp/laborstacker.dm | 16 ++- .../mining/lavaland/necropolis_chests.dm | 6 ++ code/modules/mining/machine_stacking.dm | 18 +++- code/modules/mob/dead/new_player/login.dm | 4 +- code/modules/mob/living/blood.dm | 1 - code/modules/mob/living/brain/brain.dm | 3 +- code/modules/mob/living/brain/brain_item.dm | 3 + code/modules/mob/living/carbon/human/human.dm | 1 + .../mob/living/carbon/human/human_defense.dm | 2 +- .../carbon/human/species_types/golems.dm | 4 +- .../carbon/human/species_types/jellypeople.dm | 98 +++++++++++-------- code/modules/mob/living/living.dm | 2 +- code/modules/mob/living/living_defense.dm | 5 +- code/modules/mob/living/silicon/ai/ai.dm | 8 +- .../modules/mob/living/silicon/robot/robot.dm | 12 +-- .../mob/living/simple_animal/bot/honkbot.dm | 5 +- .../mob/living/simple_animal/bot/secbot.dm | 5 +- .../mob/living/simple_animal/constructs.dm | 19 ++-- .../simple_animal/friendly/farm_animals.dm | 2 +- .../living/simple_animal/friendly/snake.dm | 3 +- .../mob/living/simple_animal/hostile/bees.dm | 3 +- .../simple_animal/hostile/cat_butcher.dm | 5 +- .../simple_animal/hostile/giant_spider.dm | 2 + .../living/simple_animal/hostile/hostile.dm | 73 ++++++++------ .../simple_animal/hostile/jungle/mook.dm | 3 +- .../simple_animal/hostile/mecha_pilot.dm | 4 +- .../hostile/megafauna/bubblegum.dm | 2 +- .../hostile/megafauna/colossus.dm | 13 ++- .../hostile/megafauna/hierophant.dm | 2 +- .../hostile/mining_mobs/basilisk.dm | 3 +- .../hostile/mining_mobs/elites/elite.dm | 7 +- .../hostile/mining_mobs/elites/herald.dm | 2 +- .../hostile/retaliate/retaliate.dm | 29 +++++- .../mob/living/simple_animal/slime/life.dm | 45 +++++---- .../mob/living/simple_animal/slime/powers.dm | 2 +- .../mob/living/simple_animal/slime/slime.dm | 69 +++++++++++-- code/modules/mob/logout.dm | 5 +- code/modules/mob/mob.dm | 26 +++++ code/modules/mob/mob_defines.dm | 4 +- code/modules/mob/mob_lists.dm | 7 ++ .../NTNet/NTNRC/conversation.dm | 8 ++ .../computers/machinery/console_presets.dm | 2 - .../file_system/programs/ntnrc_client.dm | 8 ++ .../file_system/programs/sm_monitor.dm | 19 +++- .../modular_computers/hardware/hard_drive.dm | 2 +- code/modules/ninja/suit/suit.dm | 5 + .../projectiles/ammunition/energy/portal.dm | 5 +- .../projectiles/guns/energy/laser_gatling.dm | 9 ++ .../projectiles/guns/energy/special.dm | 4 +- code/modules/projectiles/projectile.dm | 7 +- .../projectiles/projectile/special/curse.dm | 2 +- .../projectile/special/wormhole.dm | 8 +- .../chemistry/reagents/other_reagents.dm | 2 +- code/modules/reagents/reagent_containers.dm | 14 +-- .../reagents/reagent_containers/blood_pack.dm | 2 +- .../reagents/reagent_containers/borghydro.dm | 2 +- code/modules/recycling/disposal/bin.dm | 2 +- .../research/nanites/nanite_chamber.dm | 1 - .../nanites/nanite_chamber_computer.dm | 15 ++- .../research/nanites/nanite_programs.dm | 3 + .../nanites/nanite_programs/utility.dm | 2 +- .../crossbreeding/_status_effects.dm | 2 +- .../xenobiology/crossbreeding/burning.dm | 8 +- .../research/xenobiology/xenobio_camera.dm | 4 +- .../ruins/objects_and_mobs/ash_walker_den.dm | 9 ++ code/modules/shuttle/emergency.dm | 5 + code/modules/shuttle/shuttle.dm | 18 +++- code/modules/spells/spell.dm | 6 ++ code/modules/surgery/organs/augments_arms.dm | 4 +- code/modules/vending/_vending.dm | 11 ++- code/modules/zombie/organs.dm | 2 +- 129 files changed, 878 insertions(+), 375 deletions(-) diff --git a/code/__DEFINES/cooldowns.dm b/code/__DEFINES/cooldowns.dm index 2510db0fbfe..979839224b5 100644 --- a/code/__DEFINES/cooldowns.dm +++ b/code/__DEFINES/cooldowns.dm @@ -61,7 +61,7 @@ #define COOLDOWN_DECLARE(cd_index) var/##cd_index = 0 -#define COOLDOWN_START(cd_source, cd_index, cd_time) (cd_source.cd_index = world.time + cd_time) +#define COOLDOWN_START(cd_source, cd_index, cd_time) (cd_source.cd_index = world.time + (cd_time)) //Returns true if the cooldown has run its course, false otherwise #define COOLDOWN_FINISHED(cd_source, cd_index) (cd_source.cd_index < world.time) diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index 916483d1088..76f58732032 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -389,3 +389,9 @@ #define FLAVOR_TEXT_GOOD "good" //ie do not cause evil #define FLAVOR_TEXT_NONE "none" #define FLAVOR_TEXT_GOAL_ANTAG "blob" //is antag, but should work towards its goals +<<<<<<< HEAD +======= + +//Saves a proc call, life is suffering. If who has no targets_from var, we assume it's just who +#define GET_TARGETS_FROM(who) (who.targets_from ? who.get_targets_from() : who) +>>>>>>> e260143132 (Port harddel fixes, as well as "Fixes stasis bed runtimes" (#4598)) diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm index b26e7adce92..11a6d692ce5 100644 --- a/code/__DEFINES/subsystems.dm +++ b/code/__DEFINES/subsystems.dm @@ -85,6 +85,9 @@ ///Call qdel on the atom after intialization #define INITIALIZE_HINT_QDEL 2 +///Call qdel with a force of TRUE after initialization +#define INITIALIZE_HINT_QDEL_FORCE 3 + ///type and all subtypes should always immediately call Initialize in New() #define INITIALIZE_IMMEDIATE(X) ##X/New(loc, ...){\ ..();\ diff --git a/code/__HELPERS/_logging.dm b/code/__HELPERS/_logging.dm index 13acbef8e1c..f8ed5fd70b1 100644 --- a/code/__HELPERS/_logging.dm +++ b/code/__HELPERS/_logging.dm @@ -35,6 +35,11 @@ SEND_TEXT(world.log, text) #endif +#ifdef REFERENCE_TRACKING_LOG +#define log_reftracker(msg) log_world("## REF SEARCH [msg]") +#else +#define log_reftracker(msg) +#endif /* Items with ADMINPRIVATE prefixed are stripped from public logs. */ /proc/log_admin(text) diff --git a/code/_compile_options.dm b/code/_compile_options.dm index 67ddf05702c..f96dcd3ae1d 100644 --- a/code/_compile_options.dm +++ b/code/_compile_options.dm @@ -22,6 +22,9 @@ //#define LEGACY_REFERENCE_TRACKING #ifdef LEGACY_REFERENCE_TRACKING +///Should we be logging our findings or not +#define REFERENCE_TRACKING_LOG + ///Use the legacy reference on things hard deleting by default. //#define GC_FAILURE_HARD_LOOKUP #ifdef GC_FAILURE_HARD_LOOKUP diff --git a/code/_onclick/hud/radial.dm b/code/_onclick/hud/radial.dm index 39926a52eab..53b50f93256 100644 --- a/code/_onclick/hud/radial.dm +++ b/code/_onclick/hud/radial.dm @@ -9,6 +9,17 @@ GLOBAL_LIST_EMPTY(radial_menus) plane = ABOVE_HUD_PLANE var/datum/radial_menu/parent +/atom/movable/screen/radial/proc/set_parent(new_value) + if(parent) + UnregisterSignal(parent, COMSIG_PARENT_QDELETING) + parent = new_value + if(parent) + RegisterSignal(parent, COMSIG_PARENT_QDELETING, .proc/handle_parent_del) + +/atom/movable/screen/radial/proc/handle_parent_del() + SIGNAL_HANDLER + set_parent(null) + /atom/movable/screen/radial/slice icon_state = "radial_slice" var/choice @@ -132,7 +143,7 @@ GLOBAL_LIST_EMPTY(radial_menus) for(var/i in 1 to elements_to_add) //Create all elements var/atom/movable/screen/radial/slice/new_element = new /atom/movable/screen/radial/slice new_element.tooltips = use_tooltips - new_element.parent = src + new_element.set_parent(src) elements += new_element var/page = 1 @@ -222,7 +233,7 @@ GLOBAL_LIST_EMPTY(radial_menus) /datum/radial_menu/New() close_button = new - close_button.parent = src + close_button.set_parent(src) /datum/radial_menu/proc/Reset() choices.Cut() diff --git a/code/_onclick/hud/radial_persistent.dm b/code/_onclick/hud/radial_persistent.dm index e7f7c664ad7..1c46ecee56d 100644 --- a/code/_onclick/hud/radial_persistent.dm +++ b/code/_onclick/hud/radial_persistent.dm @@ -26,7 +26,7 @@ /datum/radial_menu/persistent/New() close_button = new /atom/movable/screen/radial/persistent/center - close_button.parent = src + close_button.set_parent(src) /datum/radial_menu/persistent/element_chosen(choice_id,mob/user) diff --git a/code/controllers/subsystem/atoms.dm b/code/controllers/subsystem/atoms.dm index 6aa97c2a643..f139d4692b1 100644 --- a/code/controllers/subsystem/atoms.dm +++ b/code/controllers/subsystem/atoms.dm @@ -97,6 +97,9 @@ SUBSYSTEM_DEF(atoms) if(INITIALIZE_HINT_QDEL) qdel(A) qdeleted = TRUE + if(INITIALIZE_HINT_QDEL_FORCE) + qdel(A, force = TRUE) + qdeleted = TRUE else BadInitializeCalls[the_type] |= BAD_INIT_NO_HINT diff --git a/code/controllers/subsystem/garbage.dm b/code/controllers/subsystem/garbage.dm index 5a14185f84c..b0d189b638b 100644 --- a/code/controllers/subsystem/garbage.dm +++ b/code/controllers/subsystem/garbage.dm @@ -148,29 +148,36 @@ SUBSYSTEM_DEF(garbage) // Something's still referring to the qdel'd object. fail_counts[level]++ + + #ifdef REFERENCE_TRACKING + var/ref_searching = FALSE + #endif + switch (level) if (GC_QUEUE_CHECK) #ifdef REFERENCE_TRACKING D.find_references() #elif defined(LEGACY_REFERENCE_TRACKING) if(reference_find_on_fail[refID]) - D.find_references_legacy() + INVOKE_ASYNC(D, /datum/proc/find_references_legacy) + ref_searching = TRUE #ifdef GC_FAILURE_HARD_LOOKUP else - D.find_references_legacy() + INVOKE_ASYNC(D, /datum/proc/find_references_legacy) + ref_searching = TRUE #endif reference_find_on_fail -= refID #endif var/type = D.type var/datum/qdel_item/I = items[type] - #ifdef TESTING + log_world("## TESTING: GC: -- \ref[D] | [type] was unable to be GC'd --") + #ifdef TESTING for(var/c in GLOB.admins) //Using testing() here would fill the logs with ADMIN_VV garbage var/client/admin = c if(!check_rights_for(admin, R_ADMIN)) continue to_chat(admin, "## TESTING: GC: -- [ADMIN_VV(D)] | [type] was unable to be GC'd --") - testing("GC: -- \ref[src] | [type] was unable to be GC'd --") #endif #ifdef REFERENCE_TRACKING GLOB.deletion_failures += D //It should no longer be bothered by the GC, manual deletion only. @@ -185,6 +192,11 @@ SUBSYSTEM_DEF(garbage) Queue(D, level+1) + #ifdef REFERENCE_TRACKING + if(ref_searching) + return + #endif + if (MC_TICK_CHECK) return if (count) diff --git a/code/datums/browser.dm b/code/datums/browser.dm index ee9ef86bea3..fb458d353b1 100644 --- a/code/datums/browser.dm +++ b/code/datums/browser.dm @@ -4,7 +4,7 @@ var/window_id // window_id is used as the window name for browse and onclose var/width = 0 var/height = 0 - var/atom/ref = null + var/datum/weakref/ref = null var/window_options = "can_close=1;can_minimize=1;can_maximize=0;can_resize=1;titlebar=1;" // window option is set using window_id var/stylesheets[0] var/scripts[0] @@ -17,6 +17,7 @@ /datum/browser/New(nuser, nwindow_id, ntitle = 0, nwidth = 0, nheight = 0, var/atom/nref = null) user = nuser + RegisterSignal(user, COMSIG_PARENT_QDELETING, .proc/user_deleted) window_id = nwindow_id if (ntitle) title = format_text(ntitle) @@ -25,7 +26,11 @@ if (nheight) height = nheight if (nref) - ref = nref + ref = WEAKREF(nref) + +/datum/browser/proc/user_deleted(datum/source) + SIGNAL_HANDLER + user = null /datum/browser/proc/add_head_content(nhead_content) head_content = nhead_content @@ -111,8 +116,13 @@ /datum/browser/proc/setup_onclose() set waitfor = 0 //winexists sleeps, so we don't need to. for (var/i in 1 to 10) - if (user && winexists(user, window_id)) - onclose(user, window_id, ref) + if (user?.client && winexists(user, window_id)) + var/atom/send_ref + if(ref) + send_ref = ref.resolve() + if(!send_ref) + ref = null + onclose(user, window_id, send_ref) break /datum/browser/proc/close() diff --git a/code/datums/components/squeak.dm b/code/datums/components/squeak.dm index fed8ab28408..af8af255364 100644 --- a/code/datums/components/squeak.dm +++ b/code/datums/components/squeak.dm @@ -66,7 +66,7 @@ if(istype(AM, /obj/effect/dummy/phased_mob)) //don't squeek if they're in a phased/jaunting container. return var/atom/current_parent = parent - if(isturf(current_parent.loc)) + if(isturf(current_parent?.loc)) play_squeak() /datum/component/squeak/proc/use_squeak() diff --git a/code/datums/components/storage/storage.dm b/code/datums/components/storage/storage.dm index f56547b779a..5e1cf86b30e 100644 --- a/code/datums/components/storage/storage.dm +++ b/code/datums/components/storage/storage.dm @@ -366,20 +366,27 @@ M.client.screen |= boxes M.client.screen |= closer M.client.screen |= real_location.contents - M.active_storage = src + M.set_active_storage(src) LAZYOR(is_using, M) + RegisterSignal(M, COMSIG_PARENT_QDELETING, .proc/mob_deleted) return TRUE +/datum/component/storage/proc/mob_deleted(datum/source) + SIGNAL_HANDLER + hide_from(source) + /datum/component/storage/proc/hide_from(mob/M) + if(M.active_storage == src) + M.set_active_storage(null) + LAZYREMOVE(is_using, M) + + UnregisterSignal(M, COMSIG_PARENT_QDELETING) if(!M.client) return TRUE var/atom/real_location = real_location() M.client.screen -= boxes M.client.screen -= closer M.client.screen -= real_location.contents - if(M.active_storage == src) - M.active_storage = null - LAZYREMOVE(is_using, M) return TRUE /datum/component/storage/proc/close(mob/M) @@ -451,6 +458,7 @@ cansee |= M else LAZYREMOVE(is_using, M) + UnregisterSignal(M, COMSIG_PARENT_QDELETING) return cansee //Tries to dump content diff --git a/code/datums/dash_weapon.dm b/code/datums/dash_weapon.dm index 7f5cf721930..8c8639d1383 100644 --- a/code/datums/dash_weapon.dm +++ b/code/datums/dash_weapon.dm @@ -6,7 +6,6 @@ var/current_charges = 1 var/max_charges = 1 var/charge_rate = 250 - var/mob/living/carbon/human/holder var/obj/item/dashing_item var/dash_sound = 'sound/magic/blink.ogg' var/recharge_sound = 'sound/magic/charge.ogg' @@ -17,7 +16,10 @@ /datum/action/innate/dash/Grant(mob/user, obj/dasher) . = ..() dashing_item = dasher - holder = user + +/datum/action/innate/dash/Destroy() + dashing_item = null + return ..() /datum/action/innate/dash/IsAvailable() if(current_charges > 0) @@ -26,7 +28,7 @@ return FALSE /datum/action/innate/dash/Activate() - dashing_item.attack_self(holder) //Used to toggle dash behavior in the dashing item + dashing_item.attack_self(owner) //Used to toggle dash behavior in the dashing item /datum/action/innate/dash/proc/Teleport(mob/user, atom/target) if(!IsAvailable()) @@ -39,14 +41,14 @@ var/obj/spot2 = new phasein(get_turf(user), user.dir) spot1.Beam(spot2,beam_effect,time=20) current_charges-- - holder.update_action_buttons_icon() + owner.update_action_buttons_icon() addtimer(CALLBACK(src, .proc/charge), charge_rate) else to_chat(user, "You cannot dash here!") /datum/action/innate/dash/proc/charge() current_charges = CLAMP(current_charges + 1, 0, max_charges) - holder.update_action_buttons_icon() + owner.update_action_buttons_icon() if(recharge_sound) playsound(dashing_item, recharge_sound, 50, 1) - to_chat(holder, "[src] now has [current_charges]/[max_charges] charges.") + to_chat(owner, "[src] now has [current_charges]/[max_charges] charges.") diff --git a/code/datums/hud.dm b/code/datums/hud.dm index f38d9f65bda..0cda7290d47 100644 --- a/code/datums/hud.dm +++ b/code/datums/hud.dm @@ -104,6 +104,7 @@ GLOBAL_LIST_INIT(huds, list( /datum/atom_hud/proc/unregister_mob(datum/source, force) SIGNAL_HANDLER remove_hud_from(source, TRUE) + remove_from_hud(source) /datum/atom_hud/proc/show_hud_images_after_cooldown(M) if(queued_to_see[M]) diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 6afd8794aca..5da0fa7ca6c 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -88,8 +88,22 @@ qdel(i) antag_datums = null QDEL_NULL(language_holder) + set_current(null) return ..() +/datum/mind/proc/set_current(mob/new_current) + if(new_current && QDELING(new_current)) + CRASH("Tried to set a mind's current var to a qdeleted mob, what the fuck") + if(current) + UnregisterSignal(src, COMSIG_PARENT_QDELETING) + current = new_current + if(current) + RegisterSignal(src, COMSIG_PARENT_QDELETING, .proc/clear_current) + +/datum/mind/proc/clear_current(datum/source) + SIGNAL_HANDLER + set_current(null) + /datum/mind/proc/get_language_holder() if(!language_holder) language_holder = new (src) @@ -108,13 +122,13 @@ key = new_character.key if(new_character.mind) //disassociate any mind currently in our new body's mind variable - new_character.mind.current = null + new_character.mind.set_current(null) var/datum/atom_hud/antag/hud_to_transfer = antag_hud//we need this because leave_hud() will clear this list var/mob/living/old_current = current if(current) current.transfer_observers_to(new_character) //transfer anyone observing the old character to the new one - current = new_character //associate ourself with our new body + set_current(new_character) //associate ourself with our new body new_character.mind = src //and associate our new body with ourself for(var/a in antag_datums) //Makes sure all antag datums effects are applied in the new body var/datum/antagonist/A = a @@ -726,7 +740,7 @@ SSticker.minds += mind if(!mind.name) mind.name = real_name - mind.current = src + mind.set_current(src) /mob/living/carbon/mind_initialize() ..() diff --git a/code/game/gamemodes/clown_ops/clown_weapons.dm b/code/game/gamemodes/clown_ops/clown_weapons.dm index 01f1b88f919..f96e4d18217 100644 --- a/code/game/gamemodes/clown_ops/clown_weapons.dm +++ b/code/game/gamemodes/clown_ops/clown_weapons.dm @@ -160,8 +160,9 @@ if(iscarbon(hit_atom) && !caught)//if they are a carbon and they didn't catch it var/datum/component/slippery/slipper = GetComponent(/datum/component/slippery) slipper.Slip(src, hit_atom) - if(thrownby && !caught) - addtimer(CALLBACK(src, /atom/movable.proc/throw_at, thrownby, throw_range+2, throw_speed, null, TRUE), 1) + var/mob/thrown_by = thrownby?.resolve() + if(thrown_by && !caught) + addtimer(CALLBACK(src, /atom/movable.proc/throw_at, thrown_by, throw_range+2, throw_speed, null, TRUE), 1) else return ..() diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index cb2cb4fd628..3aa370c078c 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -17,6 +17,11 @@ GLOBAL_LIST_EMPTY(objectives) if(text) explanation_text = text +//Apparently objectives can be qdel'd. Learn a new thing every day +/datum/objective/Destroy() + GLOB.objectives -= src + return ..() + /datum/objective/proc/get_owners() // Combine owner and team into a single list. . = (team && team.members) ? team.members.Copy() : list() if(owner) diff --git a/code/game/machinery/camera/tracking.dm b/code/game/machinery/camera/tracking.dm index bf1b84fe5d4..767cb90abad 100644 --- a/code/game/machinery/camera/tracking.dm +++ b/code/game/machinery/camera/tracking.dm @@ -49,9 +49,9 @@ track.namecounts[name] = 1 if(ishuman(L)) - track.humans[name] = L + track.humans[name] = WEAKREF(L) else - track.others[name] = L + track.others[name] = WEAKREF(L) var/list/targets = sortList(track.humans) + sortList(track.others) @@ -67,9 +67,9 @@ if(!track.initialized) trackable_mobs() - var/mob/target = (isnull(track.humans[target_name]) ? track.others[target_name] : track.humans[target_name]) + var/datum/weakref/target = (isnull(track.humans[target_name]) ? track.others[target_name] : track.humans[target_name]) - ai_actual_track(target) + ai_actual_track(target.resolve()) /mob/living/silicon/ai/proc/ai_actual_track(mob/living/target) if(!istype(target)) diff --git a/code/game/machinery/computer/Operating.dm b/code/game/machinery/computer/Operating.dm index 13c5d45a80a..32c55ae451b 100644 --- a/code/game/machinery/computer/Operating.dm +++ b/code/game/machinery/computer/Operating.dm @@ -7,7 +7,7 @@ icon_screen = "crew" icon_keyboard = "med_key" circuit = /obj/item/circuitboard/computer/operating - var/mob/living/carbon/human/patient + var/obj/structure/table/optable/table var/obj/machinery/stasis/sbed var/list/advanced_surgeries = list() @@ -21,11 +21,11 @@ /obj/machinery/computer/operating/Destroy() for(var/direction in GLOB.cardinals) - table = locate(/obj/structure/table/optable, get_step(src, direction)) + table = locate(/obj/structure/table/optable) in get_step(src, direction) if(table && table.computer == src) table.computer = null else - sbed = locate(/obj/machinery/stasis, get_step(src, direction)) + sbed = locate(/obj/machinery/stasis) in get_step(src, direction) if(sbed && sbed.op_computer == src) sbed.op_computer = null . = ..() @@ -50,12 +50,12 @@ /obj/machinery/computer/operating/proc/find_table() for(var/direction in GLOB.cardinals) - table = locate(/obj/structure/table/optable, get_step(src, direction)) + table = locate(/obj/structure/table/optable) in get_step(src, direction) if(table) table.computer = src break else - sbed = locate(/obj/machinery/stasis, get_step(src, direction)) + sbed = locate(/obj/machinery/stasis) in get_step(src, direction) if(sbed) sbed.op_computer = src break @@ -80,17 +80,24 @@ surgery["desc"] = initial(S.desc) surgeries += list(surgery) data["surgeries"] = surgeries - data["patient"] = null + + //If there's no patient just hop to it yeah? + if(!table && !sbed) + data["patient"] = null + return data + + var/mob/living/carbon/human/patient + if(table) data["table"] = table - if(!table.check_patient()) + if(!table.check_eligible_patient()) return data data["patient"] = list() patient = table.patient else if(sbed) data["table"] = sbed - if(!sbed.check_patient()) + if(!ishuman(sbed.occupant) && !ismonkey(sbed.occupant)) return data data["patient"] = list() patient = sbed.occupant diff --git a/code/game/machinery/launch_pad.dm b/code/game/machinery/launch_pad.dm index afe87add691..cc4686b78ec 100644 --- a/code/game/machinery/launch_pad.dm +++ b/code/game/machinery/launch_pad.dm @@ -43,7 +43,8 @@ update_indicator() /obj/machinery/launchpad/Destroy() - qdel(hud_list[DIAG_LAUNCHPAD_HUD]) + for(var/datum/atom_hud/data/diagnostic/diag_hud in GLOB.huds) + diag_hud.remove_from_hud(src) return ..() /obj/machinery/launchpad/examine(mob/user) @@ -257,9 +258,9 @@ /obj/machinery/launchpad/briefcase/attackby(obj/item/I, mob/user, params) if(istype(I, /obj/item/launchpad_remote)) var/obj/item/launchpad_remote/L = I - if(L.pad == src) //do not attempt to link when already linked + if(L.pad == WEAKREF(src)) //do not attempt to link when already linked return ..() - L.pad = src + L.pad = WEAKREF(src) to_chat(user, "You link [src] to [L].") else return ..() @@ -296,9 +297,9 @@ /obj/item/storage/briefcase/launchpad/attackby(obj/item/I, mob/user, params) if(istype(I, /obj/item/launchpad_remote)) var/obj/item/launchpad_remote/L = I - if(L.pad == src.pad) //do not attempt to link when already linked + if(L.pad == WEAKREF(src.pad)) //do not attempt to link when already linked return ..() - L.pad = src.pad + L.pad = WEAKREF(src.pad) to_chat(user, "You link [pad] to [L].") else return ..() @@ -310,11 +311,12 @@ icon_state = "folder" w_class = WEIGHT_CLASS_SMALL var/sending = TRUE - var/obj/machinery/launchpad/briefcase/pad + //A weakref to our linked pad + var/datum/weakref/pad /obj/item/launchpad_remote/Initialize(mapload, pad) //remote spawns linked to the briefcase pad . = ..() - src.pad = pad + src.pad = WEAKREF(pad) /obj/item/launchpad_remote/attack_self(mob/user) . = ..() @@ -335,16 +337,17 @@ /obj/item/launchpad_remote/ui_data(mob/user) var/list/data = list() - data["has_pad"] = pad ? TRUE : FALSE - if(pad) - data["pad_closed"] = pad.closed - if(!pad || pad.closed) + var/obj/machinery/launchpad/briefcase/our_pad = pad.resolve() + data["has_pad"] = our_pad ? TRUE : FALSE + if(our_pad) + data["pad_closed"] = our_pad.closed + if(!our_pad || our_pad.closed) return data - data["pad_name"] = pad.display_name - data["range"] = pad.range - data["x"] = pad.x_offset - data["y"] = pad.y_offset + data["pad_name"] = our_pad.display_name + data["range"] = our_pad.range + data["x"] = our_pad.x_offset + data["y"] = our_pad.y_offset return data /obj/item/launchpad_remote/proc/teleport(mob/user, obj/machinery/launchpad/pad) @@ -359,18 +362,22 @@ /obj/item/launchpad_remote/ui_act(action, params) if(..()) return + var/obj/machinery/launchpad/briefcase/our_pad = pad.resolve() + if(!our_pad) + pad = null + return TRUE switch(action) if("set_pos") var/new_x = text2num(params["x"]) var/new_y = text2num(params["y"]) - pad.set_offset(new_x, new_y) + our_pad.set_offset(new_x, new_y) . = TRUE if("move_pos") var/plus_x = text2num(params["x"]) var/plus_y = text2num(params["y"]) - pad.set_offset( - x = pad.x_offset + plus_x, - y = pad.y_offset + plus_y + our_pad.set_offset( + x = our_pad.x_offset + plus_x, + y = our_pad.y_offset + plus_y ) . = TRUE if("rename") @@ -378,16 +385,16 @@ var/new_name = params["name"] if(!new_name) return - pad.display_name = new_name + our_pad.display_name = new_name if("remove") . = TRUE if(usr && alert(usr, "Are you sure?", "Unlink Launchpad", "I'm Sure", "Abort") != "Abort") pad = null if("launch") sending = TRUE - teleport(usr, pad) + teleport(usr, our_pad) . = TRUE if("pull") sending = FALSE - teleport(usr, pad) + teleport(usr, our_pad) . = TRUE diff --git a/code/game/machinery/stasis.dm b/code/game/machinery/stasis.dm index 5b586c4d182..0ffe8aa21f1 100644 --- a/code/game/machinery/stasis.dm +++ b/code/game/machinery/stasis.dm @@ -22,7 +22,7 @@ /obj/machinery/stasis/Initialize() . = ..() for(var/direction in GLOB.cardinals) - op_computer = locate(/obj/machinery/computer/operating, get_step(src, direction)) + op_computer = locate(/obj/machinery/computer/operating) in get_step(src, direction) if(op_computer) op_computer.sbed = src break @@ -123,12 +123,6 @@ chill_out(L) update_icon() -/obj/machinery/stasis/proc/check_patient() - if(occupant) - return TRUE - else - return FALSE - /obj/machinery/stasis/post_unbuckle_mob(mob/living/L) thaw_them(L) if(L == occupant) diff --git a/code/game/objects/effects/anomalies.dm b/code/game/objects/effects/anomalies.dm index 589de20766c..7f2144adfcd 100644 --- a/code/game/objects/effects/anomalies.dm +++ b/code/game/objects/effects/anomalies.dm @@ -54,7 +54,7 @@ /obj/effect/anomaly/Destroy() GLOB.poi_list.Remove(src) STOP_PROCESSING(SSobj, src) - qdel(countdown) + QDEL_NULL(countdown) return ..() /obj/effect/anomaly/proc/anomalyEffect(delta_time) diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 320681b517a..628dc7c5b4e 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -120,7 +120,8 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) /// list() of species types, if a species cannot put items in a certain slot, but species type is in list, it will be able to wear that item var/list/species_exception = null - var/mob/thrownby = null + ///A weakref to the mob who threw the item + var/datum/weakref/thrownby = null mouse_drag_pointer = MOUSE_ACTIVE_POINTER //the icon to indicate this object is being dragged @@ -739,11 +740,10 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) /obj/item/throw_at(atom/target, range, speed, mob/thrower, spin=1, diagonals_first = 0, datum/callback/callback, force, quickstart = TRUE) if(HAS_TRAIT(src, TRAIT_NODROP)) return - thrownby = thrower + thrownby = WEAKREF(thrower) callback = CALLBACK(src, .proc/after_throw, callback) //replace their callback with our own . = ..(target, range, speed, thrower, spin, diagonals_first, callback, force, quickstart = quickstart) - /obj/item/proc/after_throw(datum/callback/callback) if (callback) //call the original callback . = callback.Invoke() diff --git a/code/game/objects/items/chrono_eraser.dm b/code/game/objects/items/chrono_eraser.dm index 53f3490e660..b7d40fb0011 100644 --- a/code/game/objects/items/chrono_eraser.dm +++ b/code/game/objects/items/chrono_eraser.dm @@ -133,6 +133,10 @@ if(istype(C)) gun = C.gun +/obj/item/projectile/energy/chrono_beam/Destroy() + gun = null + return ..() + /obj/item/projectile/energy/chrono_beam/on_hit(atom/target) if(target && gun && isliving(target)) var/obj/structure/chrono_field/F = new(target.loc, target, gun) @@ -151,7 +155,9 @@ gun = loc . = ..() - +/obj/item/ammo_casing/energy/chrono_beam/Destroy() + gun = null + return ..() diff --git a/code/game/objects/items/devices/transfer_valve.dm b/code/game/objects/items/devices/transfer_valve.dm index afd321b8a6f..7694e7c015d 100644 --- a/code/game/objects/items/devices/transfer_valve.dm +++ b/code/game/objects/items/devices/transfer_valve.dm @@ -16,6 +16,10 @@ var/valve_open = FALSE var/toggle = TRUE +/obj/item/transfer_valve/Destroy() + attached_device = null + return ..() + /obj/item/transfer_valve/IsAssemblyHolder() return TRUE diff --git a/code/game/objects/items/dice.dm b/code/game/objects/items/dice.dm index 157aeb25567..7043741244d 100644 --- a/code/game/objects/items/dice.dm +++ b/code/game/objects/items/dice.dm @@ -182,8 +182,10 @@ diceroll(user) /obj/item/dice/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) - diceroll(thrownby) - . = ..() + var/mob/thrown_by = thrownby?.resolve() + if(thrown_by) + diceroll(thrown_by) + return ..() /obj/item/dice/proc/diceroll(mob/user) result = roll(sides) diff --git a/code/game/objects/items/implants/implant_track.dm b/code/game/objects/items/implants/implant_track.dm index d0455905eb9..4370bf908b2 100644 --- a/code/game/objects/items/implants/implant_track.dm +++ b/code/game/objects/items/implants/implant_track.dm @@ -2,8 +2,12 @@ name = "tracking implant" desc = "Track with this." activated = FALSE - var/lifespan_postmortem = 6000 //for how many deciseconds after user death will the implant work? - var/allow_teleport = TRUE //will people implanted with this act as teleporter beacons? + ///for how many deciseconds after user death will the implant work? + var/lifespan_postmortem = 6000 + ///will people implanted with this act as teleporter beacons? + var/allow_teleport = TRUE + ///The id of the timer that's qdeleting us + var/timerid /obj/item/implant/tracking/c38 name = "TRAC implant" @@ -13,7 +17,11 @@ /obj/item/implant/tracking/c38/Initialize() . = ..() - QDEL_IN(src, lifespan) + timerid = QDEL_IN(src, lifespan) + +/obj/item/implant/tracking/c38/Destroy() + deltimer(timerid) + return ..() /obj/item/implant/tracking/New() ..() diff --git a/code/game/objects/items/melee/energy.dm b/code/game/objects/items/melee/energy.dm index c3a4800ad23..59e5a51472b 100644 --- a/code/game/objects/items/melee/energy.dm +++ b/code/game/objects/items/melee/energy.dm @@ -267,6 +267,10 @@ spark_system.set_up(5, 0, src) spark_system.attach(src) +/obj/item/melee/transforming/energy/blade/Destroy() + QDEL_NULL(spark_system) + return ..() + /obj/item/melee/transforming/energy/blade/transform_weapon(mob/living/user, supress_message_text) return diff --git a/code/game/objects/items/melee/misc.dm b/code/game/objects/items/melee/misc.dm index 616a05bdd29..1805f2d146e 100644 --- a/code/game/objects/items/melee/misc.dm +++ b/code/game/objects/items/melee/misc.dm @@ -316,7 +316,7 @@ if(!iscarbon(user)) target.LAssailant = null else - target.LAssailant = user + target.LAssailant = WEAKREF(user) cooldown_check = world.time + cooldown else var/wait_desc = get_wait_description() diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm index bf2498090d6..cf50599462a 100644 --- a/code/game/objects/structures/tables_racks.dm +++ b/code/game/objects/structures/tables_racks.dm @@ -494,7 +494,7 @@ /obj/structure/table/optable/Initialize() . = ..() for(var/direction in GLOB.cardinals) - computer = locate(/obj/machinery/computer/operating, get_step(src, direction)) + computer = locate(/obj/machinery/computer/operating) in get_step(src, direction) if(computer) computer.table = src break @@ -508,17 +508,34 @@ pushed_mob.forceMove(loc) pushed_mob.set_resting(TRUE, TRUE) visible_message("[user] has laid [pushed_mob] on [src].") - check_patient() + get_patient() -/obj/structure/table/optable/proc/check_patient() - var/mob/living/carbon/human/M = locate(/mob/living/carbon/human, loc) +/obj/structure/table/optable/proc/get_patient() + var/mob/living/carbon/M = locate(/mob/living/carbon) in loc if(M) if(M.resting) - patient = M - return TRUE + set_patient(M) else - patient = null + set_patient(null) + +/obj/structure/table/optable/proc/set_patient(new_patient) + if(patient) + UnregisterSignal(patient, COMSIG_PARENT_QDELETING) + patient = new_patient + if(patient) + RegisterSignal(patient, COMSIG_PARENT_QDELETING, .proc/patient_deleted) + +/obj/structure/table/optable/proc/patient_deleted(datum/source) + SIGNAL_HANDLER + set_patient(null) + +/obj/structure/table/optable/proc/check_eligible_patient() + get_patient() + if(!patient) return FALSE + if(ishuman(patient) || ismonkey(patient)) + return TRUE + return FALSE /* * Racks diff --git a/code/game/objects/structures/traps.dm b/code/game/objects/structures/traps.dm index 2c209ead993..18b795196bf 100644 --- a/code/game/objects/structures/traps.dm +++ b/code/game/objects/structures/traps.dm @@ -108,6 +108,12 @@ time_between_triggers = 10 flare_message = "[src] snaps shut!" +/obj/structure/trap/stun/hunter/Destroy() + if(!QDELETED(stored_item)) + qdel(stored_item) + stored_item = null + return ..() + /obj/structure/trap/stun/hunter/Crossed(atom/movable/AM) if(isliving(AM)) var/mob/living/L = AM @@ -161,7 +167,9 @@ forceMove(stored_trap)//moves item into trap /obj/item/bountytrap/Destroy() - qdel(stored_trap) + if(!QDELETED(stored_trap)) + qdel(stored_trap) + stored_trap = null QDEL_NULL(radio) QDEL_NULL(spark_system) . = ..() diff --git a/code/modules/antagonists/abductor/equipment/gland.dm b/code/modules/antagonists/abductor/equipment/gland.dm index 9f7fc96c4d8..cbda7198281 100644 --- a/code/modules/antagonists/abductor/equipment/gland.dm +++ b/code/modules/antagonists/abductor/equipment/gland.dm @@ -145,8 +145,8 @@ owner.vomit(20) var/mob/living/simple_animal/slime/Slime = new(get_turf(owner), "grey") - Slime.Friends = list(owner) - Slime.Leader = owner + Slime.set_friends(list(owner)) + Slime.set_leader(owner) /obj/item/organ/heart/gland/mindshock true_name = "neural crosstalk uninhibitor" diff --git a/code/modules/antagonists/blob/blobstrains/_blobstrain.dm b/code/modules/antagonists/blob/blobstrains/_blobstrain.dm index faf4a22f08e..34b82011cd1 100644 --- a/code/modules/antagonists/blob/blobstrains/_blobstrain.dm +++ b/code/modules/antagonists/blob/blobstrains/_blobstrain.dm @@ -22,6 +22,10 @@ GLOBAL_LIST_INIT(valid_blobstrains, subtypesof(/datum/blobstrain) - list(/datum/ stack_trace("blobstrain created without overmind") overmind = new_overmind +/datum/blobstrain/Destroy() + overmind = null + return ..() + /datum/blobstrain/proc/on_gain() overmind.color = complementary_color for(var/BL in GLOB.blobs) diff --git a/code/modules/antagonists/blob/overmind.dm b/code/modules/antagonists/blob/overmind.dm index b77644cd062..b728b2877e8 100644 --- a/code/modules/antagonists/blob/overmind.dm +++ b/code/modules/antagonists/blob/overmind.dm @@ -174,6 +174,7 @@ GLOBAL_LIST_EMPTY(blob_nodes) SSticker.force_ending = 1 /mob/camera/blob/Destroy() + QDEL_NULL(blobstrain) for(var/BL in GLOB.blobs) var/obj/structure/blob/B = BL if(B && B.overmind == src) diff --git a/code/modules/antagonists/cult/cult_items.dm b/code/modules/antagonists/cult/cult_items.dm index b9ed924c557..417bacb66ee 100644 --- a/code/modules/antagonists/cult/cult_items.dm +++ b/code/modules/antagonists/cult/cult_items.dm @@ -117,7 +117,16 @@ linked_action = new(src) AddComponent(/datum/component/butchering, 50, 80) +<<<<<<< HEAD /obj/item/twohanded/required/cult_bastard/examine(mob/user) +======= +/obj/item/cult_bastard/Destroy() + QDEL_NULL(jaunt) + QDEL_NULL(linked_action) + return ..() + +/obj/item/cult_bastard/examine(mob/user) +>>>>>>> e260143132 (Port harddel fixes, as well as "Fixes stasis bed runtimes" (#4598)) . = ..() if(contents.len) . += "There are [contents.len] souls trapped within the sword's core." @@ -194,7 +203,7 @@ phaseout = /obj/effect/temp_visual/dir_setting/cult/phase/out /datum/action/innate/dash/cult/IsAvailable() - if(iscultist(holder) && current_charges) + if(iscultist(owner) && current_charges) return TRUE else return FALSE diff --git a/code/modules/antagonists/disease/disease_disease.dm b/code/modules/antagonists/disease/disease_disease.dm index 2909aac4d37..c9d976d6766 100644 --- a/code/modules/antagonists/disease/disease_disease.dm +++ b/code/modules/antagonists/disease/disease_disease.dm @@ -13,6 +13,7 @@ /datum/disease/advance/sentient_disease/Destroy() . = ..() + overmind = null GLOB.sentient_disease_instances -= src /datum/disease/advance/sentient_disease/remove_disease() diff --git a/code/modules/antagonists/disease/disease_mob.dm b/code/modules/antagonists/disease/disease_mob.dm index 8c2e4ef1b0b..757c5b2cb93 100644 --- a/code/modules/antagonists/disease/disease_mob.dm +++ b/code/modules/antagonists/disease/disease_mob.dm @@ -73,10 +73,12 @@ the new instance inside the host to be updated to the template's stats. /mob/camera/disease/Destroy() . = ..() QDEL_NULL(adaptation_menu_action) + disease_template = null for(var/V in GLOB.sentient_disease_instances) var/datum/disease/advance/sentient_disease/S = V if(S.overmind == src) S.overmind = null + browser = null /mob/camera/disease/Login() ..() diff --git a/code/modules/antagonists/slaughter/slaughter.dm b/code/modules/antagonists/slaughter/slaughter.dm index 1fcf3956e1a..cdd47e9a4f7 100644 --- a/code/modules/antagonists/slaughter/slaughter.dm +++ b/code/modules/antagonists/slaughter/slaughter.dm @@ -49,7 +49,7 @@ deathmessage = "screams in anger as it collapses into a puddle of viscera!" /mob/living/simple_animal/slaughter/Initialize() - ..() + . = ..() var/obj/effect/proc_holder/spell/bloodcrawl/bloodspell = new AddSpell(bloodspell) if(istype(loc, /obj/effect/dummy/phased_mob/slaughter)) diff --git a/code/modules/assembly/assembly.dm b/code/modules/assembly/assembly.dm index 730e47b39af..a6ad3c3f10b 100644 --- a/code/modules/assembly/assembly.dm +++ b/code/modules/assembly/assembly.dm @@ -29,6 +29,10 @@ var/next_activate = 0 //When we're next allowed to activate - for spam control var/activate_delay = 30 +/obj/item/assembly/Destroy() + holder = null + return ..() + /obj/item/assembly/get_part_rating() return 1 diff --git a/code/modules/assembly/flash.dm b/code/modules/assembly/flash.dm index 9ce9f93682b..053cb0d9ccd 100644 --- a/code/modules/assembly/flash.dm +++ b/code/modules/assembly/flash.dm @@ -336,19 +336,22 @@ desc = "A high-powered photon projector implant normally used for lighting purposes, but also doubles as a flashbulb weapon. Self-repair protocols fix the flashbulb if it ever burns out." var/flashcd = 20 var/overheat = 0 - var/obj/item/organ/cyberimp/arm/flash/I = null + //Wearef to our arm + var/datum/weakref/arm /obj/item/assembly/flash/armimplant/burn_out() - if(I?.owner) - to_chat(I.owner, "Your photon projector implant overheats and deactivates!") - I.Retract() + var/obj/item/organ/cyberimp/arm/flash/real_arm = arm.resolve() + if(real_arm?.owner) + to_chat(real_arm.owner, "Your photon projector implant overheats and deactivates!") + real_arm.Retract() overheat = TRUE addtimer(CALLBACK(src, .proc/cooldown), flashcd * 2) /obj/item/assembly/flash/armimplant/try_use_flash(mob/user = null) if(overheat) - if(I?.owner) - to_chat(I.owner, "Your photon projector is running too hot to be used again so quickly!") + var/obj/item/organ/cyberimp/arm/flash/real_arm = arm.resolve() + if(real_arm?.owner) + to_chat(real_arm.owner, "Your photon projector is running too hot to be used again so quickly!") return FALSE overheat = TRUE addtimer(CALLBACK(src, .proc/cooldown), flashcd) diff --git a/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm b/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm index 1f6fa821752..5eb7c439d92 100644 --- a/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm +++ b/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm @@ -24,11 +24,11 @@ return 1 /obj/machinery/portable_atmospherics/Destroy() - SSair.atmos_machinery -= src - disconnect() qdel(air_contents) air_contents = null + + SSair.atmos_machinery -= src return ..() diff --git a/code/modules/awaymissions/capture_the_flag.dm b/code/modules/awaymissions/capture_the_flag.dm index 53786b3f663..24d99faa023 100644 --- a/code/modules/awaymissions/capture_the_flag.dm +++ b/code/modules/awaymissions/capture_the_flag.dm @@ -39,12 +39,16 @@ . = ..() if(!reset) reset = new reset_path(get_turf(src)) + reset.flag = src /obj/item/twohanded/ctf/process() if(is_ctf_target(loc)) //don't reset from someone's hands. return PROCESS_KILL if(world.time > reset_cooldown) - forceMove(get_turf(src.reset)) + var/turf/our_turf = get_turf(src.reset) + if(!our_turf) + return TRUE + forceMove(our_turf) for(var/mob/M in GLOB.player_list) var/area/mob_area = get_area(M) if(istype(mob_area, /area/ctf)) @@ -112,6 +116,13 @@ icon_state = "banner" desc = "This is where a banner with Nanotrasen's logo on it would go." layer = LOW_ITEM_LAYER + var/obj/item/ctf/flag + +/obj/effect/ctf/flag_reset/Destroy() + if(flag) + flag.reset = null + flag = null + return ..() /obj/effect/ctf/flag_reset/red name = "red flag landmark" @@ -643,6 +654,13 @@ for(var/obj/machinery/capture_the_flag/CTF in GLOB.machines) CTF.dead_barricades += src +/obj/effect/ctf/dead_barricade/Destroy() + for(var/obj/machinery/capture_the_flag/CTF in GLOB.machines) + //if(CTF.game_id != game_id) + // continue + CTF.dead_barricades -= src + return ..() + /obj/effect/ctf/dead_barricade/proc/respawn() if(!QDELETED(src)) new /obj/structure/barricade/security/ctf(get_turf(src)) diff --git a/code/modules/awaymissions/mission_code/Cabin.dm b/code/modules/awaymissions/mission_code/Cabin.dm index 0c14d884c8c..c9ba3a6897a 100644 --- a/code/modules/awaymissions/mission_code/Cabin.dm +++ b/code/modules/awaymissions/mission_code/Cabin.dm @@ -45,7 +45,7 @@ var/active = 1 /obj/structure/firepit/Initialize() - ..() + . = ..() toggleFirepit() /obj/structure/firepit/interact(mob/living/user) diff --git a/code/modules/awaymissions/mission_code/TheFactory.dm b/code/modules/awaymissions/mission_code/TheFactory.dm index dee081baacb..1e8f9a6a734 100644 --- a/code/modules/awaymissions/mission_code/TheFactory.dm +++ b/code/modules/awaymissions/mission_code/TheFactory.dm @@ -222,7 +222,7 @@ /mob/living/simple_animal/hostile/proc/summon_backup_nosound(distance, exact_faction_match) do_alert_animation(src) - for(var/mob/living/simple_animal/hostile/M in oview(distance, targets_from)) + for(var/mob/living/simple_animal/hostile/M in oview(distance, GET_TARGETS_FROM(src))) if(faction_check_mob(M, TRUE)) if(M.AIStatus == AI_OFF) return diff --git a/code/modules/cargo/supplypod.dm b/code/modules/cargo/supplypod.dm index 4c0e03eb4fc..272edbfdc9b 100644 --- a/code/modules/cargo/supplypod.dm +++ b/code/modules/cargo/supplypod.dm @@ -463,17 +463,19 @@ return glow_effect.layer = LOW_ITEM_LAYER glow_effect.fadeAway(delays[POD_OPENING]) - remove_glow() + //Trust the signals /obj/structure/closet/supplypod/proc/remove_glow() SIGNAL_HANDLER UnregisterSignal(glow_effect, COMSIG_PARENT_QDELETING) + vis_contents -= glow_effect glow_effect = null /obj/structure/closet/supplypod/Destroy() open_pod(src, broken = TRUE) //Lets dump our contents by opening up deleteRubble() - endGlow() + //Trust the signals even harder + qdel(glow_effect) return ..() //------------------------------------TEMPORARY_VISUAL-------------------------------------// diff --git a/code/modules/client/verbs/suicide.dm b/code/modules/client/verbs/suicide.dm index 5af546dfce8..c2943b1c67c 100644 --- a/code/modules/client/verbs/suicide.dm +++ b/code/modules/client/verbs/suicide.dm @@ -3,9 +3,9 @@ /mob/proc/set_suicide(suicide_state) suiciding = suicide_state if(suicide_state) - GLOB.suicided_mob_list += src + add_to_mob_suicide_list() else - GLOB.suicided_mob_list -= src + remove_from_mob_suicide_list() /mob/living/carbon/set_suicide(suicide_state) //you thought that box trick was pretty clever, didn't you? well now hardmode is on, boyo. . = ..() diff --git a/code/modules/clothing/head/misc.dm b/code/modules/clothing/head/misc.dm index 39492b0f40c..1f531b36242 100644 --- a/code/modules/clothing/head/misc.dm +++ b/code/modules/clothing/head/misc.dm @@ -142,7 +142,7 @@ if(!ishuman(user)) return var/mob/living/carbon/human/H = user - if(H.get_item_by_slot(ITEM_SLOT_HEAD) == src) + if(H.get_item_by_slot(ITEM_SLOT_HEAD) == src && !QDELETED(src)) //This can be called as a part of destroy user.remove_language(/datum/language/piratespeak/, TRUE, TRUE, LANGUAGE_HAT) to_chat(user, "You can no longer speak like a pirate.") diff --git a/code/modules/clothing/masks/gasmask.dm b/code/modules/clothing/masks/gasmask.dm index 4a32564d9b6..7ecd65228bd 100644 --- a/code/modules/clothing/masks/gasmask.dm +++ b/code/modules/clothing/masks/gasmask.dm @@ -34,7 +34,7 @@ /obj/item/clothing/mask/gas/welding/up /obj/item/clothing/mask/gas/welding/up/Initialize() - ..() + . = ..() visor_toggling() // ******************************************************************** diff --git a/code/modules/clothing/spacesuits/chronosuit.dm b/code/modules/clothing/spacesuits/chronosuit.dm index 0d62c611818..d295e6dca48 100644 --- a/code/modules/clothing/spacesuits/chronosuit.dm +++ b/code/modules/clothing/spacesuits/chronosuit.dm @@ -65,6 +65,7 @@ /obj/item/clothing/suit/space/chronos/Destroy() dropped() + QDEL_NULL(teleport_now) return ..() /obj/item/clothing/suit/space/chronos/emp_act(severity) @@ -328,6 +329,10 @@ check_flags = AB_CHECK_CONSCIOUS //|AB_CHECK_INSIDE var/obj/item/clothing/suit/space/chronos/chronosuit = null +/datum/action/innate/chrono_teleport/Destroy() + chronosuit = null + return ..() + /datum/action/innate/chrono_teleport/IsAvailable() return (chronosuit && chronosuit.activated && chronosuit.camera && !chronosuit.teleporting) diff --git a/code/modules/clothing/spacesuits/hardsuit.dm b/code/modules/clothing/spacesuits/hardsuit.dm index 306866ad04c..d6317ca1e32 100644 --- a/code/modules/clothing/spacesuits/hardsuit.dm +++ b/code/modules/clothing/spacesuits/hardsuit.dm @@ -27,6 +27,9 @@ START_PROCESSING(SSobj, src) /obj/item/clothing/head/helmet/space/hardsuit/Destroy() + if(!QDELETED(suit)) + qdel(suit) + suit = null QDEL_NULL(soundloop) STOP_PROCESSING(SSobj, src) return ..() @@ -110,7 +113,6 @@ var/obj/item/tank/jetpack/suit/jetpack = null pocket_storage_component_path = null - /obj/item/clothing/suit/space/hardsuit/Initialize() if(jetpack && ispath(jetpack)) jetpack = new jetpack(src) @@ -878,6 +880,7 @@ /datum/action/item_action/toggle_beacon, /datum/action/item_action/toggle_beacon_frequency ) + jetpack = /obj/item/tank/jetpack/suit /obj/item/clothing/suit/space/hardsuit/shielded/syndi/multitool_act(mob/living/user, obj/item/I) . = ..() @@ -896,10 +899,6 @@ to_chat(user, "You update the hardsuit's hardware, changing back the shield's color to red.") user.update_inv_wear_suit() -/obj/item/clothing/suit/space/hardsuit/shielded/syndi/Initialize() - jetpack = new /obj/item/tank/jetpack/suit(src) - . = ..() - /obj/item/clothing/suit/space/hardsuit/shielded/syndi/ui_action_click(mob/user, datum/actiontype) switch(actiontype.type) if(/datum/action/item_action/toggle_helmet) diff --git a/code/modules/clothing/suits/toggles.dm b/code/modules/clothing/suits/toggles.dm index dd7608adbc8..39f2dcfb647 100644 --- a/code/modules/clothing/suits/toggles.dm +++ b/code/modules/clothing/suits/toggles.dm @@ -130,10 +130,11 @@ . = ..() /obj/item/clothing/suit/space/hardsuit/Destroy() - if(helmet) + if(!QDELETED(helmet)) helmet.suit = null qdel(helmet) - qdel(jetpack) + helmet = null + QDEL_NULL(jetpack) return ..() /obj/item/clothing/head/helmet/space/hardsuit/Destroy() diff --git a/code/modules/clothing/under/accessories.dm b/code/modules/clothing/under/accessories.dm index 8ce36829cbd..137518c9a56 100755 --- a/code/modules/clothing/under/accessories.dm +++ b/code/modules/clothing/under/accessories.dm @@ -12,6 +12,10 @@ var/datum/component/storage/detached_pockets var/attachment_slot = CHEST +/obj/item/clothing/accessory/Destroy() + set_detached_pockets(null) + return ..() + /obj/item/clothing/accessory/proc/can_attach_accessory(obj/item/clothing/U, mob/user) if(!attachment_slot || (U && U.body_parts_covered & attachment_slot)) return TRUE @@ -24,7 +28,7 @@ if(SEND_SIGNAL(U, COMSIG_CONTAINS_STORAGE)) return FALSE U.TakeComponent(storage) - detached_pockets = storage + set_detached_pockets(storage) U.attached_accessory = src forceMove(U) layer = FLOAT_LAYER @@ -67,6 +71,17 @@ U.attached_accessory = null U.accessory_overlay = null +/obj/item/clothing/accessory/proc/set_detached_pockets(new_pocket) + if(detached_pockets) + UnregisterSignal(detached_pockets, COMSIG_PARENT_QDELETING) + detached_pockets = new_pocket + if(detached_pockets) + RegisterSignal(detached_pockets, COMSIG_PARENT_QDELETING, .proc/handle_pockets_del) + +/obj/item/clothing/accessory/proc/handle_pockets_del(datum/source) + SIGNAL_HANDLER + set_detached_pockets(null) + /obj/item/clothing/accessory/proc/on_uniform_equip(obj/item/clothing/under/U, user) return diff --git a/code/modules/events/wizard/greentext.dm b/code/modules/events/wizard/greentext.dm index 82e72df3b9d..569e026e7ac 100644 --- a/code/modules/events/wizard/greentext.dm +++ b/code/modules/events/wizard/greentext.dm @@ -83,7 +83,8 @@ if(!(resistance_flags & ON_FIRE) && !force) return QDEL_HINT_LETMELIVE - SSticker.round_end_events -= roundend_callback + LAZYREMOVE(SSticker.round_end_events, roundend_callback) + roundend_callback = null //This ought to free the callback datum, and prevent us from harddeling GLOB.poi_list.Remove(src) for(var/i in GLOB.player_list) var/mob/M = i diff --git a/code/modules/fields/timestop.dm b/code/modules/fields/timestop.dm index bc5502438f9..9d410a43a0b 100644 --- a/code/modules/fields/timestop.dm +++ b/code/modules/fields/timestop.dm @@ -42,7 +42,7 @@ timestop() /obj/effect/timestop/Destroy() - qdel(chronofield) + QDEL_NULL(chronofield) playsound(src, 'sound/magic/timeparadox2.ogg', 75, TRUE, frequency = -1) //reverse! return ..() diff --git a/code/modules/guardian/guardian.dm b/code/modules/guardian/guardian.dm index 998aad3c529..1ae6ae323f0 100644 --- a/code/modules/guardian/guardian.dm +++ b/code/modules/guardian/guardian.dm @@ -342,9 +342,10 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians return loc != summoner?.current /mob/living/simple_animal/hostile/guardian/Shoot(atom/targeted_atom) - if( QDELETED(targeted_atom) || targeted_atom == targets_from.loc || targeted_atom == targets_from ) + var/atom/target_from = GET_TARGETS_FROM(src) + if( QDELETED(targeted_atom) || targeted_atom == target_from.loc || targeted_atom == target_from ) return - var/turf/startloc = get_turf(targets_from) + var/turf/startloc = get_turf(target_from) var/obj/item/projectile/P = new /obj/item/projectile/guardian(startloc) playsound(src, projectilesound, 100, 1) P.color = guardiancolor @@ -355,7 +356,7 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians P.yo = targeted_atom.y - startloc.y P.xo = targeted_atom.x - startloc.x if(AIStatus != AI_ON)//Don't want mindless mobs to have their movement screwed up firing in space - newtonian_move(get_dir(targeted_atom, targets_from)) + newtonian_move(get_dir(targeted_atom, target_from)) P.original = targeted_atom P.preparePixelProjectile(targeted_atom, src) P.fire() diff --git a/code/modules/holodeck/holo_effect.dm b/code/modules/holodeck/holo_effect.dm index 3161c9c7ec4..5e1f2109de3 100644 --- a/code/modules/holodeck/holo_effect.dm +++ b/code/modules/holodeck/holo_effect.dm @@ -28,31 +28,36 @@ /obj/effect/holodeck_effect/cards icon = 'icons/obj/toy.dmi' icon_state = "deck_nanotrasen_full" - var/obj/item/toy/cards/deck/D + var/obj/item/toy/cards/deck/deck /obj/effect/holodeck_effect/cards/activate(var/obj/machinery/computer/holodeck/HC) - D = new(loc) + deck = new(loc) safety(!(HC.obj_flags & EMAGGED)) - D.holo = HC - return D + deck.holo = HC + RegisterSignal(deck, COMSIG_PARENT_QDELETING, .proc/handle_card_delete) + return deck + +/obj/effect/holodeck_effect/cards/proc/handle_card_delete(datum/source) + SIGNAL_HANDLER + deck = null /obj/effect/holodeck_effect/cards/safety(active) - if(!D) + if(!deck) return if(active) - D.card_hitsound = null - D.card_force = 0 - D.card_throwforce = 0 - D.card_throw_speed = 3 - D.card_throw_range = 7 - D.card_attack_verb = list("attacked") + deck.card_hitsound = null + deck.card_force = 0 + deck.card_throwforce = 0 + deck.card_throw_speed = 3 + deck.card_throw_range = 7 + deck.card_attack_verb = list("attacked") else - D.card_hitsound = 'sound/weapons/bladeslice.ogg' - D.card_force = 5 - D.card_throwforce = 10 - D.card_throw_speed = 3 - D.card_throw_range = 7 - D.card_attack_verb = list("attacked", "sliced", "diced", "slashed", "cut") + deck.card_hitsound = 'sound/weapons/bladeslice.ogg' + deck.card_force = 5 + deck.card_throwforce = 10 + deck.card_throw_speed = 3 + deck.card_throw_range = 7 + deck.card_attack_verb = list("attacked", "sliced", "diced", "slashed", "cut") /obj/effect/holodeck_effect/sparks/activate(var/obj/machinery/computer/holodeck/HC) @@ -76,24 +81,29 @@ /obj/effect/holodeck_effect/mobspawner var/mobtype = /mob/living/simple_animal/hostile/carp/holocarp - var/mob/mob = null + var/mob/our_mob = null /obj/effect/holodeck_effect/mobspawner/activate(var/obj/machinery/computer/holodeck/HC) if(islist(mobtype)) mobtype = pick(mobtype) - mob = new mobtype(loc) - mob.flags_1 |= HOLOGRAM_1 + our_mob = new mobtype(loc) + our_mob.flags_1 |= HOLOGRAM_1 // these vars are not really standardized but all would theoretically create stuff on death - for(var/v in list("butcher_results","corpse","weapon1","weapon2","blood_volume") & mob.vars) - mob.vars[v] = null - return mob + for(var/v in list("butcher_results","corpse","weapon1","weapon2","blood_volume") & our_mob.vars) + our_mob.vars[v] = null + RegisterSignal(our_mob, COMSIG_PARENT_QDELETING, .proc/handle_mob_delete) + return our_mob /obj/effect/holodeck_effect/mobspawner/deactivate(var/obj/machinery/computer/holodeck/HC) - if(mob) - HC.derez(mob) + if(our_mob) + HC.derez(our_mob) qdel(src) +/obj/effect/holodeck_effect/mobspawner/proc/handle_mob_delete(datum/source) + SIGNAL_HANDLER + our_mob = null + /obj/effect/holodeck_effect/mobspawner/pet mobtype = list( /mob/living/simple_animal/butterfly, /mob/living/simple_animal/chick/holo, @@ -117,3 +127,24 @@ /obj/effect/holodeck_effect/mobspawner/penguin_baby mobtype = /mob/living/simple_animal/pet/penguin/baby +<<<<<<< HEAD +======= + +/obj/effect/holodeck_effect/mobspawner/cat + mobtype = /mob/living/simple_animal/pet/cat + +/obj/effect/holodeck_effect/mobspawner/butterfly + mobtype = /mob/living/simple_animal/butterfly + +/obj/effect/holodeck_effect/mobspawner/clown + mobtype = list (/mob/living/simple_animal/hostile/retaliate/clown = 10, + /mob/living/simple_animal/hostile/retaliate/clown/banana = 6, /mob/living/simple_animal/hostile/retaliate/clown/honkling = 6, + /mob/living/simple_animal/hostile/retaliate/clown/fleshclown = 3, /mob/living/simple_animal/hostile/retaliate/clown/longface = 3, + /mob/living/simple_animal/hostile/retaliate/clown/mutant = 1, /mob/living/simple_animal/hostile/retaliate/clown/mutant/blob = 1) + +/obj/effect/holodeck_effect/mobspawner/psycho + mobtype = list (/mob/living/simple_animal/hostile/psycho/regular = 9, + /mob/living/simple_animal/hostile/psycho/muzzle = 3, + /mob/living/simple_animal/hostile/psycho/fast = 3, + /mob/living/simple_animal/hostile/psycho/trap = 1) +>>>>>>> e260143132 (Port harddel fixes, as well as "Fixes stasis bed runtimes" (#4598)) diff --git a/code/modules/language/language_holder.dm b/code/modules/language/language_holder.dm index 6485f34d61d..00b1013f4af 100644 --- a/code/modules/language/language_holder.dm +++ b/code/modules/language/language_holder.dm @@ -53,7 +53,9 @@ Key procs var/atom/owner /// Initializes, and copies in the languages from the current atom if available. -/datum/language_holder/New(_owner) +/datum/language_holder/New(atom/_owner) + if(_owner && QDELING(_owner)) + CRASH("Langauge holder added to a qdeleting thing, what the fuck \ref[_owner]") owner = _owner if(istype(owner, /datum/mind)) var/datum/mind/M = owner diff --git a/code/modules/lighting/lighting_source.dm b/code/modules/lighting/lighting_source.dm index 24d757c6c47..d12a129e89f 100644 --- a/code/modules/lighting/lighting_source.dm +++ b/code/modules/lighting/lighting_source.dm @@ -67,7 +67,8 @@ source_atom = null source_turf = null pixel_turf = null - . = ..() + + return ..() // Yes this doesn't align correctly on anything other than 4 width tabs. // If you want it to go switch everybody to elastic tab stops. diff --git a/code/modules/mining/laborcamp/laborstacker.dm b/code/modules/mining/laborcamp/laborstacker.dm index d179ab9a943..85fdbf54e82 100644 --- a/code/modules/mining/laborcamp/laborstacker.dm +++ b/code/modules/mining/laborcamp/laborstacker.dm @@ -18,9 +18,12 @@ GLOBAL_LIST(labor_sheet_values) /obj/machinery/mineral/labor_claim_console/Initialize() . = ..() - Radio = new/obj/item/radio(src) + Radio = new /obj/item/radio(src) Radio.listening = FALSE locate_stacking_machine() + //If we can't find a stacking machine end it all ok? + if(!stacking_machine) + return INITIALIZE_HINT_QDEL if(!GLOB.labor_sheet_values) var/sheet_list = list() @@ -31,6 +34,13 @@ GLOBAL_LIST(labor_sheet_values) sheet_list += list(list("ore" = initial(sheet.name), "value" = initial(sheet.point_value))) GLOB.labor_sheet_values = sortList(sheet_list, /proc/cmp_sheet_list) +/obj/machinery/mineral/labor_claim_console/Destroy() + QDEL_NULL(Radio) + if(stacking_machine) + stacking_machine.console = null + stacking_machine = null + return ..() + /proc/cmp_sheet_list(list/a, list/b) return a["value"] - b["value"] @@ -114,9 +124,7 @@ GLOBAL_LIST(labor_sheet_values) /obj/machinery/mineral/labor_claim_console/proc/locate_stacking_machine() stacking_machine = locate(/obj/machinery/mineral/stacking_machine, get_step(src, machinedir)) if(stacking_machine) - stacking_machine.CONSOLE = src - else - qdel(src) + stacking_machine.console = src /obj/machinery/mineral/labor_claim_console/emag_act(mob/user) if(!(obj_flags & EMAGGED)) diff --git a/code/modules/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm index 5a38b942a8a..2ac4f789b60 100644 --- a/code/modules/mining/lavaland/necropolis_chests.dm +++ b/code/modules/mining/lavaland/necropolis_chests.dm @@ -359,6 +359,12 @@ var/obj/item/warp_cube/linked var/teleporting = FALSE +/obj/item/warp_cube/Destroy() + if(!QDELETED(linked)) + qdel(linked) + linked = null + return ..() + /obj/item/warp_cube/attack_self(mob/user) if(!linked) to_chat(user, "[src] fizzles uselessly.") diff --git a/code/modules/mining/machine_stacking.dm b/code/modules/mining/machine_stacking.dm index 51d6d9c3b43..47ae34b5fbc 100644 --- a/code/modules/mining/machine_stacking.dm +++ b/code/modules/mining/machine_stacking.dm @@ -14,7 +14,13 @@ . = ..() machine = locate(/obj/machinery/mineral/stacking_machine, get_step(src, machinedir)) if (machine) - machine.CONSOLE = src + machine.console = src + +/obj/machinery/mineral/stacking_unit_console/Destroy() + if(machine) + machine.console = null + machine = null + return ..() /obj/machinery/mineral/stacking_unit_console/ui_interact(mob/user) . = ..() @@ -74,7 +80,7 @@ circuit = /obj/item/circuitboard/machine/stacking_machine input_dir = EAST output_dir = WEST - var/obj/machinery/mineral/stacking_unit_console/CONSOLE + var/obj/machinery/mineral/stacking_unit_console/console var/stk_types = list() var/stk_amt = list() var/stack_list[0] //Key: Type. Value: Instance of type. @@ -88,7 +94,9 @@ materials = AddComponent(/datum/component/remote_materials, "stacking", mapload, FALSE, mapload && force_connect) /obj/machinery/mineral/stacking_machine/Destroy() - CONSOLE = null + if(console) + console.machine = null + console = null materials = null return ..() @@ -108,8 +116,8 @@ /obj/machinery/mineral/stacking_machine/multitool_act(mob/living/user, obj/item/multitool/M) if(istype(M)) if(istype(M.buffer, /obj/machinery/mineral/stacking_unit_console)) - CONSOLE = M.buffer - CONSOLE.machine = src + console = M.buffer + console.machine = src to_chat(user, "You link [src] to the console in [M]'s buffer.") return TRUE diff --git a/code/modules/mob/dead/new_player/login.dm b/code/modules/mob/dead/new_player/login.dm index 734e5a59b03..97e97bb31e0 100644 --- a/code/modules/mob/dead/new_player/login.dm +++ b/code/modules/mob/dead/new_player/login.dm @@ -4,8 +4,8 @@ client.set_db_player_flags() if(!mind) mind = new /datum/mind(key) - mind.active = 1 - mind.current = src + mind.active = TRUE + mind.set_current(src) ..() diff --git a/code/modules/mob/living/blood.dm b/code/modules/mob/living/blood.dm index 921fe3cc853..72e3793fa11 100644 --- a/code/modules/mob/living/blood.dm +++ b/code/modules/mob/living/blood.dm @@ -166,7 +166,6 @@ if(blood_id == /datum/reagent/blood) //actual blood reagent var/blood_data = list() //set the blood data - blood_data["donor"] = src blood_data["viruses"] = list() for(var/thing in diseases) diff --git a/code/modules/mob/living/brain/brain.dm b/code/modules/mob/living/brain/brain.dm index 37ff6bd4ffc..b570e906e81 100644 --- a/code/modules/mob/living/brain/brain.dm +++ b/code/modules/mob/living/brain/brain.dm @@ -29,9 +29,10 @@ if(stat!=DEAD) //If not dead. death(1) //Brains can die again. AND THEY SHOULD AHA HA HA HA HA HA if(mind) //You aren't allowed to return to brains that don't exist - mind.current = null + mind.set_current(null) ghostize() //Ghostize checks for key so nothing else is necessary. container = null + QDEL_NULL(stored_dna) return ..() /mob/living/brain/update_mobility() diff --git a/code/modules/mob/living/brain/brain_item.dm b/code/modules/mob/living/brain/brain_item.dm index b5c9a410906..fc9d3d22b8d 100644 --- a/code/modules/mob/living/brain/brain_item.dm +++ b/code/modules/mob/living/brain/brain_item.dm @@ -197,6 +197,9 @@ if(brainmob) QDEL_NULL(brainmob) QDEL_LIST(traumas) + + if(owner?.mind) //You aren't allowed to return to brains that don't exist + owner.mind.set_current(null) return ..() /obj/item/organ/brain/on_life() diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 430a8ca967b..9ad68bdf4c4 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -41,6 +41,7 @@ /mob/living/carbon/human/Destroy() QDEL_NULL(physiology) + QDEL_LIST(bioware) return ..() diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 8236ae53904..e3b58e798e6 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -142,7 +142,7 @@ if(istype(AM, /obj/item)) I = AM throwpower = I.throwforce - if(I.thrownby == src) //No throwing stuff at yourself to trigger hit reactions + if(I.thrownby == WEAKREF(src)) //No throwing stuff at yourself to trigger hit reactions return ..() if(check_shields(AM, throwpower, "\the [AM.name]", THROWN_PROJECTILE_ATTACK)) hitpush = FALSE diff --git a/code/modules/mob/living/carbon/human/species_types/golems.dm b/code/modules/mob/living/carbon/human/species_types/golems.dm index 4a32c7e3f10..f19ff833fa9 100644 --- a/code/modules/mob/living/carbon/human/species_types/golems.dm +++ b/code/modules/mob/living/carbon/human/species_types/golems.dm @@ -440,7 +440,7 @@ var/obj/item/I if(istype(AM, /obj/item)) I = AM - if(I.thrownby == H) //No throwing stuff at yourself to trigger the teleport + if(I.thrownby == WEAKREF(H)) //No throwing stuff at yourself to trigger the teleport return 0 else reactive_teleport(H) @@ -564,7 +564,7 @@ var/obj/item/I if(istype(AM, /obj/item)) I = AM - if(I.thrownby == H) //No throwing stuff at yourself to make bananas + if(I.thrownby == WEAKREF(H)) //No throwing stuff at yourself to make bananas return 0 else new/obj/item/grown/bananapeel/specialpeel(get_turf(H)) diff --git a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm index 985f9ca02b2..d5d5955daaa 100644 --- a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm @@ -414,18 +414,25 @@ var/datum/action/innate/use_extract/major/extract_major var/extract_cooldown = 0 +//Species datums don't normally implement destroy, but JELLIES SUCK ASS OUT OF A STEEL STRAW +/datum/species/jelly/luminescent/Destroy(force, ...) + current_extract = null + QDEL_NULL(glow) + QDEL_NULL(integrate_extract) + QDEL_NULL(extract_major) + QDEL_NULL(extract_minor) + return ..() + + /datum/species/jelly/luminescent/on_species_loss(mob/living/carbon/C) ..() if(current_extract) current_extract.forceMove(C.drop_location()) current_extract = null - qdel(glow) - if(integrate_extract) - integrate_extract.Remove(C) - if(extract_minor) - extract_minor.Remove(C) - if(extract_major) - extract_major.Remove(C) + QDEL_NULL(glow) + QDEL_NULL(integrate_extract) + QDEL_NULL(extract_major) + QDEL_NULL(extract_minor) /datum/species/jelly/luminescent/on_species_gain(mob/living/carbon/C, datum/species/old_species) ..() @@ -468,13 +475,9 @@ button_icon_state = "slimeconsume" icon_icon = 'icons/mob/actions/actions_slime.dmi' background_icon_state = "bg_alien" - var/datum/species/jelly/luminescent/species - -/datum/action/innate/integrate_extract/New(_species) - ..() - species = _species /datum/action/innate/integrate_extract/proc/update_name() + var/datum/species/jelly/luminescent/species = target if(!species || !species.current_extract) name = "Integrate Extract" desc = "Eat a slime extract to use its properties." @@ -483,6 +486,7 @@ desc = "Eject your current slime extract." /datum/action/innate/integrate_extract/UpdateButtonIcon(status_only, force) + var/datum/species/jelly/luminescent/species = target if(!species || !species.current_extract) button_icon_state = "slimeconsume" else @@ -491,11 +495,13 @@ /datum/action/innate/integrate_extract/ApplyIcon(atom/movable/screen/movable/action_button/current_button, force) ..(current_button, TRUE) + var/datum/species/jelly/luminescent/species = target if(species?.current_extract) current_button.add_overlay(mutable_appearance(species.current_extract.icon, species.current_extract.icon_state)) /datum/action/innate/integrate_extract/Activate() var/mob/living/carbon/human/H = owner + var/datum/species/jelly/luminescent/species = target if(!is_species(H, /datum/species/jelly/luminescent) || !species) return CHECK_DNA_AND_SPECIES(H) @@ -531,25 +537,23 @@ icon_icon = 'icons/mob/actions/actions_slime.dmi' background_icon_state = "bg_alien" var/activation_type = SLIME_ACTIVATE_MINOR - var/datum/species/jelly/luminescent/species - -/datum/action/innate/use_extract/New(_species) - ..() - species = _species /datum/action/innate/use_extract/IsAvailable() if(..()) + var/datum/species/jelly/luminescent/species = target if(species && species.current_extract && (world.time > species.extract_cooldown)) return TRUE return FALSE /datum/action/innate/use_extract/ApplyIcon(atom/movable/screen/movable/action_button/current_button, force) ..(current_button, TRUE) + var/datum/species/jelly/luminescent/species = owner if(species && species.current_extract) current_button.add_overlay(mutable_appearance(species.current_extract.icon, species.current_extract.icon_state)) /datum/action/innate/use_extract/Activate() var/mob/living/carbon/human/H = owner + var/datum/species/jelly/luminescent/species = owner if(!is_species(H, /datum/species/jelly/luminescent) || !species) return CHECK_DNA_AND_SPECIES(H) @@ -576,22 +580,33 @@ var/datum/action/innate/link_minds/link_minds var/list/mob/living/linked_mobs = list() var/list/datum/action/innate/linked_speech/linked_actions = list() - var/mob/living/carbon/human/slimelink_owner + var/datum/weakref/slimelink_owner var/current_link_id = 0 +//Species datums don't normally implement destroy, but JELLIES SUCK ASS OUT OF A STEEL STRAW +/datum/species/jelly/stargazer/Destroy() + for(var/mob/living/link_to_clear as anything in linked_mobs) + unlink_mob(link_to_clear) + linked_mobs.Cut() + QDEL_NULL(project_thought) + QDEL_NULL(link_minds) + slimelink_owner = null + return ..() + /datum/species/jelly/stargazer/on_species_loss(mob/living/carbon/C) ..() - for(var/M in linked_mobs) - unlink_mob(M) + for(var/mob/living/link_to_clear as anything in linked_mobs) + unlink_mob(link_to_clear) if(project_thought) - project_thought.Remove(C) + QDEL_NULL(project_thought) if(link_minds) - link_minds.Remove(C) + QDEL_NULL(link_minds) + slimelink_owner = null /datum/species/jelly/stargazer/spec_death(gibbed, mob/living/carbon/human/H) ..() - for(var/M in linked_mobs) - unlink_mob(M) + for(var/mob/living/link_to_clear as anything in linked_mobs) + unlink_mob(link_to_clear) /datum/species/jelly/stargazer/on_species_gain(mob/living/carbon/C, datum/species/old_species) ..() @@ -599,7 +614,7 @@ project_thought.Grant(C) link_minds = new(src) link_minds.Grant(C) - slimelink_owner = C + slimelink_owner = WEAKREF(C) link_mob(C) /datum/species/jelly/stargazer/proc/link_mob(mob/living/M) @@ -607,14 +622,18 @@ return FALSE if(HAS_TRAIT(M, TRAIT_MINDSHIELD)) //mindshield implant, no dice return FALSE + var/mob/living/carbon/human/owner = slimelink_owner.resolve() if(istype(M.get_item_by_slot(ITEM_SLOT_HEAD), /obj/item/clothing/head/foilhat)) - to_chat(M, "[slimelink_owner.real_name]'s no-good syndicate mind-slime is blocked by your protective headgear!") + if(owner) + to_chat(M, "[owner.real_name]'s no-good syndicate mind-slime is blocked by your protective headgear!") return FALSE if(M in linked_mobs) return FALSE + if(!owner) + return FALSE linked_mobs.Add(M) - to_chat(M, "You are now connected to [slimelink_owner.real_name]'s Slime Link.") + to_chat(M, "You are now connected to [owner.real_name]'s Slime Link.") var/datum/action/innate/linked_speech/action = new(src) linked_actions.Add(action) action.Grant(M) @@ -626,9 +645,12 @@ return var/datum/action/innate/linked_speech/action = linked_actions[link_id] action.Remove(M) - to_chat(M, "You are no longer connected to [slimelink_owner.real_name]'s Slime Link.") + var/mob/living/carbon/human/owner = slimelink_owner.resolve() + if(owner) + to_chat(M, "You are no longer connected to [owner.real_name]'s Slime Link.") linked_mobs -= M linked_actions -= action + qdel(action) /datum/action/innate/linked_speech name = "Slimelink" @@ -636,14 +658,10 @@ button_icon_state = "link_speech" icon_icon = 'icons/mob/actions/actions_slime.dmi' background_icon_state = "bg_alien" - var/datum/species/jelly/stargazer/species - -/datum/action/innate/linked_speech/New(_species) - ..() - species = _species /datum/action/innate/linked_speech/Activate() var/mob/living/carbon/human/H = owner + var/datum/species/jelly/stargazer/species = target if(!species || !(H in species.linked_mobs)) to_chat(H, "The link seems to have been severed...") Remove(H) @@ -660,9 +678,11 @@ species.unlink_mob(H) return - if(message) - var/msg = "\[[species.slimelink_owner.real_name]'s Slime Link\] [H]: [message]" - log_directed_talk(H, species.slimelink_owner, msg, LOG_SAY, "slime link") + var/mob/living/carbon/human/star_owner = species.slimelink_owner.resolve() + + if(message && star_owner) + var/msg = "\[[star_owner.real_name]'s Slime Link\] [H]: [message]" + log_directed_talk(H, star_owner, msg, LOG_SAY, "slime link") for(var/X in species.linked_mobs) var/mob/living/M = X if(QDELETED(M) || M.stat == DEAD) @@ -715,11 +735,6 @@ button_icon_state = "mindlink" icon_icon = 'icons/mob/actions/actions_slime.dmi' background_icon_state = "bg_alien" - var/datum/species/jelly/stargazer/species - -/datum/action/innate/link_minds/New(_species) - ..() - species = _species /datum/action/innate/link_minds/Activate() var/mob/living/carbon/human/H = owner @@ -732,6 +747,7 @@ return var/mob/living/target = H.pulling + var/datum/species/jelly/stargazer/species = target to_chat(H, "You begin linking [target]'s mind to yours...") to_chat(target, "You feel a foreign presence within your mind...") diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 5c4373a4d2a..644abbad204 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -307,7 +307,7 @@ if(!iscarbon(src)) M.LAssailant = null else - M.LAssailant = usr + M.LAssailant = WEAKREF(usr) if(isliving(M)) var/mob/living/L = M //Share diseases that are spread by touch diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index abce98f4b03..ef4c4893c3d 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -94,8 +94,9 @@ "You're hit by [I]!") var/armor = run_armor_check(zone, "melee", "Your armor has protected your [parse_zone(zone)].", "Your armor has softened hit to your [parse_zone(zone)].",I.armour_penetration) apply_damage(I.throwforce, dtype, zone, armor) - if(I.thrownby) - log_combat(I.thrownby, src, "threw and hit", I) + var/mob/thrown_by = I.thrownby?.resolve() + if(thrown_by) + log_combat(thrown_by, src, "threw and hit", I) else return 1 else diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 218ac4e3adc..ef8c5c083b7 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -440,9 +440,11 @@ trackeable += track.humans + track.others var/list/target = list() for(var/I in trackeable) - var/mob/M = trackeable[I] - if(M.name == string) - target += M + var/datum/weakref/to_resolve = trackeable[I] + var/mob/to_track = to_resolve.resolve() + if(!to_track || to_track.name != string) + continue + target += to_track if(name == string) target += src if(target.len) diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 6da4b714648..f1c7fcc87ff 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -190,12 +190,12 @@ if(T && istype(radio) && istype(radio.keyslot)) radio.keyslot.forceMove(T) radio.keyslot = null - qdel(wires) - qdel(module) - qdel(eye_lights) - wires = null - module = null - eye_lights = null + QDEL_NULL(wires) + QDEL_NULL(eye_lights) + QDEL_NULL(inv1) + QDEL_NULL(inv2) + QDEL_NULL(inv3) + QDEL_NULL(spark_system) cell = null return ..() diff --git a/code/modules/mob/living/simple_animal/bot/honkbot.dm b/code/modules/mob/living/simple_animal/bot/honkbot.dm index 1f5305e617b..73bd2b58831 100644 --- a/code/modules/mob/living/simple_animal/bot/honkbot.dm +++ b/code/modules/mob/living/simple_animal/bot/honkbot.dm @@ -159,8 +159,9 @@ Maintenance panel panel is [open ? "opened" : "closed"]"}, if(istype(AM, /obj/item)) playsound(src, honksound, 50, TRUE, -1) var/obj/item/I = AM - if(I.throwforce < health && I.thrownby && (istype(I.thrownby, /mob/living/carbon/human))) - var/mob/living/carbon/human/H = I.thrownby + var/mob/thrown_by = I.thrownby?.resolve() + if(I.throwforce < health && thrown_by && (istype(thrown_by, /mob/living/carbon/human))) + var/mob/living/carbon/human/H = thrown_by retaliate(H) ..() diff --git a/code/modules/mob/living/simple_animal/bot/secbot.dm b/code/modules/mob/living/simple_animal/bot/secbot.dm index 2970f3da114..cbb130e619a 100644 --- a/code/modules/mob/living/simple_animal/bot/secbot.dm +++ b/code/modules/mob/living/simple_animal/bot/secbot.dm @@ -223,8 +223,9 @@ Auto Patrol: []"}, /mob/living/simple_animal/bot/secbot/hitby(atom/movable/AM, skipcatch = FALSE, hitpush = TRUE, blocked = FALSE, datum/thrownthing/throwingdatum) if(istype(AM, /obj/item)) var/obj/item/I = AM - if(I.throwforce < src.health && I.thrownby && ishuman(I.thrownby)) - var/mob/living/carbon/human/H = I.thrownby + var/mob/thrown_by = I.thrownby?.resolve() + if(I.throwforce < src.health && thrown_by && ishuman(thrown_by)) + var/mob/living/carbon/human/H = thrown_by retaliate(H) ..() diff --git a/code/modules/mob/living/simple_animal/constructs.dm b/code/modules/mob/living/simple_animal/constructs.dm index 892a7b5e6c3..b21e2d7fc23 100644 --- a/code/modules/mob/living/simple_animal/constructs.dm +++ b/code/modules/mob/living/simple_animal/constructs.dm @@ -41,6 +41,7 @@ var/can_repair_constructs = FALSE var/can_repair_self = FALSE var/runetype + var/datum/action/innate/cult/create_rune/our_rune var/holy = FALSE chat_color = "#FF6262" mobchatspan = "cultmobsay" @@ -66,12 +67,16 @@ S.action.button.moved = "6:[pos],4:-2" spellnum++ if(runetype) - var/datum/action/innate/cult/create_rune/CR = new runetype(src) - CR.Grant(src) + our_rune = new runetype(src) + our_rune.Grant(src) var/pos = 2+spellnum*31 - CR.button.screen_loc = "6:[pos],4:-2" - CR.button.moved = "6:[pos],4:-2" + our_rune.button.screen_loc = "6:[pos],4:-2" + our_rune.button.moved = "6:[pos],4:-2" +/mob/living/simple_animal/hostile/construct/Destroy() + QDEL_NULL(our_rune) + return ..() + /mob/living/simple_animal/hostile/construct/Login() ..() to_chat(src, playstyle_string) @@ -448,15 +453,11 @@ background_icon_state = "bg_demon" buttontooltipstyle = "cult" button_icon_state = "cult_mark" - var/mob/living/simple_animal/hostile/construct/harvester/the_construct - -/datum/action/innate/seek_prey/Grant(var/mob/living/C) - the_construct = C - ..() /datum/action/innate/seek_prey/Activate() if(GLOB.cult_narsie == null) return + var/mob/living/simple_animal/hostile/construct/harvester/the_construct = owner if(the_construct.seeking) desc = "None can hide from Nar'Sie, activate to track a survivor attempting to flee the red harvest!" button_icon_state = "cult_mark" 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 fb7c800af7e..ae69d07864b 100644 --- a/code/modules/mob/living/simple_animal/friendly/farm_animals.dm +++ b/code/modules/mob/living/simple_animal/friendly/farm_animals.dm @@ -50,7 +50,7 @@ Retaliate() if(enemies.len && prob(10)) - enemies = list() + clear_enemies() LoseTarget() src.visible_message("[src] calms down.") if(stat == CONSCIOUS) diff --git a/code/modules/mob/living/simple_animal/friendly/snake.dm b/code/modules/mob/living/simple_animal/friendly/snake.dm index eee06ede1c0..5b070d075c2 100644 --- a/code/modules/mob/living/simple_animal/friendly/snake.dm +++ b/code/modules/mob/living/simple_animal/friendly/snake.dm @@ -42,9 +42,10 @@ /mob/living/simple_animal/hostile/retaliate/poison/snake/ListTargets(atom/the_target) + var/atom/target_from = GET_TARGETS_FROM(src) var/list/living_mobs = list() var/list/mice = list() - for(var/mob/living/HM in oview(vision_range, targets_from)) + for(var/mob/living/HM in oview(vision_range, target_from)) //Yum a tasty mouse if(istype(HM, /mob/living/simple_animal/mouse)) mice += HM diff --git a/code/modules/mob/living/simple_animal/hostile/bees.dm b/code/modules/mob/living/simple_animal/hostile/bees.dm index 4c70eab0987..6fdfa7438b6 100644 --- a/code/modules/mob/living/simple_animal/hostile/bees.dm +++ b/code/modules/mob/living/simple_animal/hostile/bees.dm @@ -89,7 +89,8 @@ return ..() else . = list() // The following code is only very slightly slower than just returning oview(vision_range, targets_from), but it saves us much more work down the line - var/list/searched_for = oview(vision_range, targets_from) + var/atom/target_from = GET_TARGETS_FROM(src) + var/list/searched_for = oview(vision_range, target_from) for(var/obj/A in searched_for) . += A for(var/mob/A in searched_for) diff --git a/code/modules/mob/living/simple_animal/hostile/cat_butcher.dm b/code/modules/mob/living/simple_animal/hostile/cat_butcher.dm index e93e3093b16..0f20b19a88c 100644 --- a/code/modules/mob/living/simple_animal/hostile/cat_butcher.dm +++ b/code/modules/mob/living/simple_animal/hostile/cat_butcher.dm @@ -152,8 +152,9 @@ for(var/pos_targ in Targets) Targets[pos_targ] = 1 var/atom/A = pos_targ - var/target_dist = get_dist(targets_from, target) - var/possible_target_distance = get_dist(targets_from, A) + var/atom/target_from = GET_TARGETS_FROM(src) + var/target_dist = get_dist(target_from, target) + var/possible_target_distance = get_dist(target_from, A) if(target_dist < max(possible_target_distance, 3)) Targets -= A for(var/pos_targ in Targets) diff --git a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm index 8b5edaf1e6f..ebab54c114f 100644 --- a/code/modules/mob/living/simple_animal/hostile/giant_spider.dm +++ b/code/modules/mob/living/simple_animal/hostile/giant_spider.dm @@ -362,6 +362,8 @@ action_icon = 'icons/mob/actions/actions_animal.dmi' action_icon_state = "wrap_0" action_background_icon_state = "bg_alien" + //Set this to false since we're our own action, for some reason + has_action = FALSE /obj/effect/proc_holder/wrap/Initialize() . = ..() diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm index 5af8c5e4f69..0421393f0bf 100644 --- a/code/modules/mob/living/simple_animal/hostile/hostile.dm +++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm @@ -46,8 +46,9 @@ var/stat_attack = CONSCIOUS //Mobs with stat_attack to UNCONSCIOUS will attempt to attack things that are unconscious, Mobs with stat_attack set to DEAD will attempt to attack the dead. var/stat_exclusive = FALSE //Mobs with this set to TRUE will exclusively attack things defined by stat_attack, stat_attack DEAD means they will only attack corpses var/attack_same = 0 //Set us to 1 to allow us to attack our own faction - //Use set_targets_from to modify this var - var/atom/targets_from = null //all range/attack/etc. calculations should be done from this atom, defaults to the mob itself, useful for Vehicles and such + //Use GET_TARGETS_FROM(mob) to access this + //Attempting to call GET_TARGETS_FROM(mob) when this var is null will just return mob as a base + var/datum/weakref/targets_from //all range/attack/etc. calculations should be done from the atom this weakrefs, useful for Vehicles and such. var/attack_all_objects = FALSE //if true, equivalent to having a wanted_objects list containing ALL objects. var/lose_patience_timer_id //id for a timer to call LoseTarget(), used to stop mobs fixating on a target they can't reach @@ -55,14 +56,9 @@ /mob/living/simple_animal/hostile/Initialize() . = ..() - - if(!targets_from) - set_targets_from(src) wanted_objects = typecacheof(wanted_objects) - /mob/living/simple_animal/hostile/Destroy() - set_targets_from(null) //We can't use losetarget here because fucking cursed blobs override it to do nothing the motherfuckers GiveTarget(null) return ..() @@ -82,7 +78,8 @@ EscapeConfinement() if(AICanContinue(possible_targets)) - if(!QDELETED(target) && !targets_from.Adjacent(target)) + var/atom/target_from = GET_TARGETS_FROM(src) + if(!QDELETED(target) && !target_from.Adjacent(target)) DestroyPathToTarget() if(!MoveToTarget(possible_targets)) //if we lose our target if(AIShouldSleep(possible_targets)) // we try to acquire a new one @@ -132,14 +129,15 @@ //////////////HOSTILE MOB TARGETTING AND AGGRESSION//////////// /mob/living/simple_animal/hostile/proc/ListTargets() //Step 1, find out what we can see + var/atom/target_from = GET_TARGETS_FROM(src) if(!search_objects) var/static/target_list = typecacheof(list(/obj/machinery/porta_turret, /obj/mecha)) //mobs are handled via ismob(A) . = list() - for(var/atom/A as() in dview(vision_range, get_turf(targets_from), SEE_INVISIBLE_MINIMUM)) + for(var/atom/A as() in dview(vision_range, get_turf(target_from), SEE_INVISIBLE_MINIMUM)) if((ismob(A) && A != src) || target_list[A.type]) . += A else - . = oview(vision_range, targets_from) + . = oview(vision_range, target_from) /mob/living/simple_animal/hostile/proc/FindTarget(var/list/possible_targets, var/HasTargetsList = 0)//Step 2, filter down possible targets to things we actually care about . = list() @@ -177,10 +175,11 @@ /mob/living/simple_animal/hostile/proc/PickTarget(list/Targets)//Step 3, pick amongst the possible, attackable targets if(target != null)//If we already have a target, but are told to pick again, calculate the lowest distance between all possible, and pick from the lowest distance targets + var/atom/target_from = GET_TARGETS_FROM(src) for(var/pos_targ in Targets) var/atom/A = pos_targ - var/target_dist = get_dist(targets_from, target) - var/possible_target_distance = get_dist(targets_from, A) + var/target_dist = get_dist(target_from, target) + var/possible_target_distance = get_dist(target_from, A) if(target_dist < possible_target_distance) Targets -= A if(!Targets.len)//We didnt find nothin! @@ -261,7 +260,8 @@ GainPatience() /mob/living/simple_animal/hostile/proc/CheckAndAttack() - if(target && targets_from && isturf(targets_from.loc) && target.Adjacent(targets_from) && !incapacitated()) + var/atom/target_from = GET_TARGETS_FROM(src) + if(target && isturf(target_from.loc) && target.Adjacent(target_from) && !incapacitated()) AttackingTarget() /mob/living/simple_animal/hostile/proc/MoveToTarget(list/possible_targets)//Step 5, handle movement between us and our target @@ -269,14 +269,15 @@ if(!target || !CanAttack(target)) LoseTarget() return 0 + var/atom/target_from = GET_TARGETS_FROM(src) if(target in possible_targets) var/turf/T = get_turf(src) if(target.get_virtual_z_level() != T.get_virtual_z_level()) LoseTarget() return 0 - var/target_distance = get_dist(targets_from,target) + var/target_distance = get_dist(target_from,target) if(ranged) //We ranged? Shoot at em - if(!target.Adjacent(targets_from) && ranged_cooldown <= world.time) //But make sure they're not in range for a melee attack and our range attack is off cooldown + if(!target.Adjacent(target_from) && ranged_cooldown <= world.time) //But make sure they're not in range for a melee attack and our range attack is off cooldown OpenFire(target) if(!Process_Spacemove()) //Drifting walk(src,0) @@ -289,7 +290,7 @@ else Goto(target,move_to_delay,minimum_distance) if(target) - if(targets_from && isturf(targets_from.loc) && target.Adjacent(targets_from)) //If they're next to us, attack + if(isturf(target_from.loc) && target.Adjacent(target_from)) //If they're next to us, attack MeleeAction() else if(rapid_melee > 1 && target_distance <= melee_queue_distance) @@ -298,7 +299,7 @@ return 1 return 0 if(environment_smash) - if(target.loc != null && get_dist(targets_from, target.loc) <= vision_range) //We can't see our target, but he's in our vision range still + if(target.loc != null && get_dist(target_from, target.loc) <= vision_range) //We can't see our target, but he's in our vision range still if(ranged_ignores_vision && ranged_cooldown <= world.time) //we can't see our target... but we can fire at them! OpenFire(target) if((environment_smash & ENVIRONMENT_SMASH_WALLS) || (environment_smash & ENVIRONMENT_SMASH_RWALLS)) //If we're capable of smashing through walls, forget about vision completely after finding our target @@ -364,7 +365,8 @@ /mob/living/simple_animal/hostile/proc/summon_backup(distance, exact_faction_match) do_alert_animation(src) playsound(loc, 'sound/machines/chime.ogg', 50, 1, -1) - for(var/mob/living/simple_animal/hostile/M in oview(distance, targets_from)) + var/atom/target_from = GET_TARGETS_FROM(src) + for(var/mob/living/simple_animal/hostile/M in oview(distance, target_from)) if(faction_check_mob(M, TRUE)) if(M.AIStatus == AI_OFF) return @@ -398,9 +400,10 @@ /mob/living/simple_animal/hostile/proc/Shoot(atom/targeted_atom) - if( QDELETED(targeted_atom) || targeted_atom == targets_from.loc || targeted_atom == targets_from ) + var/atom/target_from = GET_TARGETS_FROM(src) + if(QDELETED(targeted_atom) || targeted_atom == target_from.loc || targeted_atom == target_from ) return - var/turf/startloc = get_turf(targets_from) + var/turf/startloc = get_turf(target_from) if(casingtype) var/obj/item/ammo_casing/casing = new casingtype(startloc) playsound(src, projectilesound, 100, 1) @@ -414,7 +417,7 @@ P.yo = targeted_atom.y - startloc.y P.xo = targeted_atom.x - startloc.x if(AIStatus != AI_ON)//Don't want mindless mobs to have their movement screwed up firing in space - newtonian_move(get_dir(targeted_atom, targets_from)) + newtonian_move(get_dir(targeted_atom, target_from)) P.original = targeted_atom P.preparePixelProjectile(targeted_atom, src) P.fire() @@ -442,15 +445,16 @@ dodging = TRUE /mob/living/simple_animal/hostile/proc/DestroyObjectsInDirection(direction) - var/turf/T = get_step(targets_from, direction) + var/atom/target_from = GET_TARGETS_FROM(src) + var/turf/T = get_step(target_from, direction) if(QDELETED(T)) return - if(T.Adjacent(targets_from)) + if(T.Adjacent(target_from)) if(CanSmashTurfs(T)) T.attack_animal(src) return for(var/obj/O in T.contents) - if(!O.Adjacent(targets_from)) + if(!O.Adjacent(target_from)) continue if((ismachinery(O) || isstructure(O)) && O.density && environment_smash >= ENVIRONMENT_SMASH_STRUCTURES && !O.IsObscured()) O.attack_animal(src) @@ -459,7 +463,8 @@ /mob/living/simple_animal/hostile/proc/DestroyPathToTarget() if(environment_smash) EscapeConfinement() - var/dir_to_target = get_dir(targets_from, target) + var/atom/target_from = GET_TARGETS_FROM(src) + var/dir_to_target = get_dir(target_from, target) var/dir_list = list() if(dir_to_target in GLOB.diagonals) //it's diagonal, so we need two directions to hit for(var/direction in GLOB.cardinals) @@ -479,18 +484,19 @@ /mob/living/simple_animal/hostile/proc/EscapeConfinement() + var/atom/target_from = GET_TARGETS_FROM(src) if(buckled) buckled.attack_animal(src) - if(!isturf(targets_from.loc) && targets_from.loc != null)//Did someone put us in something? - var/atom/A = targets_from.loc + if(!isturf(target_from.loc) && target_from.loc != null)//Did someone put us in something? + var/atom/A = target_from.loc A.attack_animal(src)//Bang on it till we get out - /mob/living/simple_animal/hostile/proc/FindHidden() if(istype(target.loc, /obj/structure/closet) || istype(target.loc, /obj/machinery/disposal) || istype(target.loc, /obj/machinery/sleeper)) var/atom/A = target.loc + var/atom/target_from = GET_TARGETS_FROM(src) Goto(A,move_to_delay,minimum_distance) - if(A.Adjacent(targets_from)) + if(A.Adjacent(target_from)) A.attack_animal(src) return 1 @@ -576,6 +582,7 @@ else if (M.loc.type in hostile_machines) . += M.loc +<<<<<<< HEAD /mob/living/simple_animal/hostile/proc/set_targets_from(atom/target_from) if(targets_from) UnregisterSignal(targets_from, COMSIG_PARENT_QDELETING) @@ -587,6 +594,14 @@ SIGNAL_HANDLER if(targets_from != src) set_targets_from(src) +======= +/mob/living/simple_animal/hostile/proc/get_targets_from() + var/atom/target_from = targets_from.resolve() + if(!target_from) + targets_from = null + return src + return target_from +>>>>>>> e260143132 (Port harddel fixes, as well as "Fixes stasis bed runtimes" (#4598)) /mob/living/simple_animal/hostile/proc/handle_target_del(datum/source) SIGNAL_HANDLER diff --git a/code/modules/mob/living/simple_animal/hostile/jungle/mook.dm b/code/modules/mob/living/simple_animal/hostile/jungle/mook.dm index 229bd68907e..27ebb186ef1 100644 --- a/code/modules/mob/living/simple_animal/hostile/jungle/mook.dm +++ b/code/modules/mob/living/simple_animal/hostile/jungle/mook.dm @@ -90,9 +90,10 @@ if(target && !stat && attack_state == MOOK_ATTACK_ACTIVE) melee_damage = 15 var/mob_direction = get_dir(src,target) + var/atom/target_from = GET_TARGETS_FROM(src) if(get_dist(src,target) > 1) step(src,mob_direction) - if(targets_from && isturf(targets_from.loc) && target.Adjacent(targets_from) && isliving(target)) + if(isturf(target_from.loc) && target.Adjacent(target_from) && isliving(target)) var/mob/living/L = target L.attack_animal(src) return diff --git a/code/modules/mob/living/simple_animal/hostile/mecha_pilot.dm b/code/modules/mob/living/simple_animal/hostile/mecha_pilot.dm index 9c99dc54be9..7568e3702b1 100644 --- a/code/modules/mob/living/simple_animal/hostile/mecha_pilot.dm +++ b/code/modules/mob/living/simple_animal/hostile/mecha_pilot.dm @@ -73,7 +73,7 @@ return 0 LoseTarget() //Target was our mecha, so null it out M.aimob_enter_mech(src) - set_targets_from(M) + targets_from = WEAKREF(M) allow_movement_on_non_turfs = TRUE //duh var/do_ranged = 0 for(var/equip in mecha.equipment) @@ -99,7 +99,7 @@ mecha.aimob_exit_mech(src) allow_movement_on_non_turfs = FALSE - set_targets_from(src) + targets_from = null //Find a new mecha wanted_objects = typecacheof(/obj/mecha/combat, TRUE) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm index 8c58c8a835f..8cb95163c30 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm @@ -526,7 +526,7 @@ Difficulty: Hard true_spawn = FALSE /mob/living/simple_animal/hostile/megafauna/bubblegum/hallucination/Initialize() - ..() + . = ..() toggle_ai(AI_OFF) /mob/living/simple_animal/hostile/megafauna/bubblegum/hallucination/charge(var/atom/chargeat = target, var/delay = 3, var/chargepast = 2) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm index d0277a81135..9f5e597658d 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm @@ -261,6 +261,9 @@ Difficulty: Very Hard SSexplosions.medturf += target +//There can only ever be one blackbox, and we want to know if there already is one when we spawn +GLOBAL_DATUM(blackbox, /obj/machinery/smartfridge/black_box) + //Black Box /obj/machinery/smartfridge/black_box @@ -290,11 +293,9 @@ Difficulty: Very Hard /obj/machinery/smartfridge/black_box/Initialize() . = ..() - var/static/obj/machinery/smartfridge/black_box/current - if(current && current != src) - qdel(src, force=TRUE) - return - current = src + if(GLOB.blackbox != src) + return INITIALIZE_HINT_QDEL_FORCE + GLOB.blackbox = src ReadMemory() /obj/machinery/smartfridge/black_box/process() @@ -339,6 +340,8 @@ Difficulty: Very Hard /obj/machinery/smartfridge/black_box/Destroy(force = FALSE) if(force) + if(GLOB.blackbox == src) + GLOB.blackbox = null for(var/thing in src) qdel(thing) return ..() diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm index 1d5f27b9004..332eafa8772 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm @@ -79,7 +79,6 @@ Difficulty: Hard var/did_reset = TRUE //if we timed out, returned to our beacon, and healed some var/list/kill_phrases = list("Wsyvgi sj irivkc xettih. Vitemvmrk...", "Irivkc wsyvgi jsyrh. Vitemvmrk...", "Jyip jsyrh. Egxmzexmrk vitemv gcgpiw...", "Kix fiex. Liepmrk...") var/list/target_phrases = list("Xevkix psgexih.", "Iriqc jsyrh.", "Eguymvih xevkix.") - var/list/stored_nearby = list() // stores people nearby the hierophant when it enters the death animation mobchatspan = "hierosay" @@ -406,6 +405,7 @@ Difficulty: Hard blinking = TRUE //we do a fancy animation, release a huge burst(), and leave our staff. visible_message("\"Mrmxmexmrk wipj-hiwxvygx wiuyirgi...\"") visible_message("[src] shrinks, releasing a massive burst of energy!") + var/list/stored_nearby = list() for(var/mob/living/L in oviewers(7,src)) stored_nearby += L // store the people to grant the achievements to once we die hierophant_burst(null, get_turf(src), 10) diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/basilisk.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/basilisk.dm index 297583db771..4ffbb0d0d43 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/basilisk.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/basilisk.dm @@ -44,7 +44,8 @@ /mob/living/simple_animal/hostile/asteroid/basilisk/GiveTarget(new_target) if(..()) //we have a target - if(isliving(target) && !target.Adjacent(targets_from) && ranged_cooldown <= world.time)//No more being shot at point blank or spammed with RNG beams + var/atom/target_from = GET_TARGETS_FROM(src) + if(isliving(target) && !target.Adjacent(target_from) && ranged_cooldown <= world.time)//No more being shot at point blank or spammed with RNG beams OpenFire(target) /mob/living/simple_animal/hostile/asteroid/basilisk/ex_act(severity, target) diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm index 497957994c2..11008b4c1b3 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm @@ -69,19 +69,18 @@ While using this makes the system rely on OnFire, it still gives options for tim icon_icon = 'icons/mob/actions/actions_elites.dmi' button_icon_state = "" background_icon_state = "bg_default" - var/mob/living/simple_animal/hostile/asteroid/elite/M var/chosen_message var/chosen_attack_num = 0 /datum/action/innate/elite_attack/Grant(mob/living/L) if(istype(L, /mob/living/simple_animal/hostile/asteroid/elite)) - M = L return ..() return FALSE /datum/action/innate/elite_attack/Activate() - M.chosen_attack = chosen_attack_num - to_chat(M, chosen_message) + var/mob/living/simple_animal/hostile/asteroid/elite/elite_owner = owner + elite_owner.chosen_attack = chosen_attack_num + to_chat(elite_owner, chosen_message) /mob/living/simple_animal/hostile/asteroid/elite/updatehealth() . = ..() diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/herald.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/herald.dm index 65b42ec8c83..99bf3ec3f15 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/herald.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/herald.dm @@ -200,7 +200,7 @@ var/mob/living/simple_animal/hostile/asteroid/elite/herald/my_master = null /mob/living/simple_animal/hostile/asteroid/elite/herald/mirror/Initialize() - ..() + . = ..() toggle_ai(AI_OFF) /mob/living/simple_animal/hostile/asteroid/elite/herald/mirror/Destroy() 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 eb438442e07..dfb54ec7586 100644 --- a/code/modules/mob/living/simple_animal/hostile/retaliate/retaliate.dm +++ b/code/modules/mob/living/simple_animal/hostile/retaliate/retaliate.dm @@ -7,7 +7,7 @@ if(L.is_conscious()) return L else - enemies -= L + remove_enemy(L) else if(ismecha(A)) var/obj/mecha/M = A if(M.occupant) @@ -25,19 +25,38 @@ if(isliving(A)) var/mob/living/M = A if(attack_same || !faction_check_mob(M)) - enemies |= M + add_enemy(M) if(istype(M, /mob/living/simple_animal/hostile/retaliate)) var/mob/living/simple_animal/hostile/retaliate/H = M if(attack_same && H.attack_same) - H.enemies |= enemies + H.add_enemies(enemies) else if(ismecha(A)) var/obj/mecha/M = A if(M.occupant) - enemies |= M - enemies |= M.occupant + add_enemy(M) + add_enemy(M.occupant) return FALSE /mob/living/simple_animal/hostile/retaliate/adjustHealth(amount, updating_health = TRUE, forced = FALSE) . = ..() if(. > 0 && stat == CONSCIOUS) Retaliate() + +/mob/living/simple_animal/hostile/retaliate/proc/add_enemy(new_enemy) + RegisterSignal(new_enemy, COMSIG_PARENT_QDELETING, .proc/remove_enemy, override = TRUE) + enemies |= new_enemy + +/mob/living/simple_animal/hostile/retaliate/proc/add_enemies(new_enemies) + for(var/new_enemy in new_enemies) + RegisterSignal(new_enemy, COMSIG_PARENT_QDELETING, .proc/remove_enemy, override = TRUE) + enemies |= new_enemy + +/mob/living/simple_animal/hostile/retaliate/proc/clear_enemies() + for(var/enemy in enemies) + UnregisterSignal(enemy, COMSIG_PARENT_QDELETING) + enemies.Cut() + +/mob/living/simple_animal/hostile/retaliate/proc/remove_enemy(datum/enemy_to_remove) + SIGNAL_HANDLER + UnregisterSignal(enemy_to_remove, COMSIG_PARENT_QDELETING) + enemies -= enemy_to_remove diff --git a/code/modules/mob/living/simple_animal/slime/life.dm b/code/modules/mob/living/simple_animal/slime/life.dm index 63add9b766f..47e38f95378 100644 --- a/code/modules/mob/living/simple_animal/slime/life.dm +++ b/code/modules/mob/living/simple_animal/slime/life.dm @@ -59,7 +59,7 @@ step_to(src, Target) else special_process = FALSE - Target = null + set_target(null) reset_processing() @@ -154,11 +154,10 @@ if(M.stat == DEAD) if(client) to_chat(src, "This subject does not have a strong enough life energy anymore...") - else if(!rabid && !attacked && M.LAssailant && prob(50)) - if(M.LAssailant in Friends) - ++Friends[M.LAssailant] - else - Friends[M.LAssailant] = 1 + else if(!rabid && !attacked) + var/mob/last_to_hurt = M.LAssailant?.resolve() + if(last_to_hurt && last_to_hurt != M && prob(50)) + add_friendship(last_to_hurt, 1) //we go rabid after finishing to feed on a human with a client. if(M.client && ishuman(M)) rabid = 1 @@ -169,7 +168,7 @@ layer = initial(layer) qdel(M) - Target = null + set_target(null) special_process = FALSE Feedstop() return @@ -250,7 +249,7 @@ --target_patience if (target_patience <= 0 || SStun > world.time || Discipline || attacked || docile) target_patience = 0 - Target = null + set_target(null) special_process = FALSE var/hungry = 0 @@ -263,7 +262,7 @@ if(hungry == 2) if(Friends.len > 0 && prob(1)) var/mob/nofriend = pick(Friends) - --Friends[nofriend] + add_friendship(nofriend, -1) if(!Target) if(will_hunt() && hungry || attacked || rabid) @@ -279,9 +278,9 @@ if(ishuman(L)) if(!Discipline && prob(5) || attacked || rabid) - Target = L + set_target(L) else - Target = L + set_target(L) if(Target) target_patience = rand(5,7) @@ -353,13 +352,13 @@ if (Leader == who) // Already following him to_say = pick("Yes...", "Lead...", "Follow...") else if (Friends[who] > Friends[Leader]) // VIVA - Leader = who + set_leader(who) to_say = "Yes... I follow [who]..." else to_say = "No... I follow [Leader]..." else if (Friends[who] >= SLIME_FRIENDSHIP_FOLLOW) - Leader = who + set_leader(who) to_say = "I follow..." else // Not friendly enough to_say = pick("No...", "I no follow...") @@ -367,27 +366,27 @@ if (buckled) // We are asked to stop feeding if (Friends[who] >= SLIME_FRIENDSHIP_STOPEAT) Feedstop() - Target = null + set_target(null) if (Friends[who] < SLIME_FRIENDSHIP_STOPEAT_NOANGRY) - --Friends[who] + add_friendship(who, -1) to_say = "Grrr..." // I'm angry but I do it else to_say = "Fine..." else if (Target) // We are asked to stop chasing if (Friends[who] >= SLIME_FRIENDSHIP_STOPCHASE) - Target = null + set_target(null) if (Friends[who] < SLIME_FRIENDSHIP_STOPCHASE_NOANGRY) - --Friends[who] + add_friendship(who, -1) to_say = "Grrr..." // I'm angry but I do it else to_say = "Fine..." else if (Leader) // We are asked to stop following if (Leader == who) to_say = "Yes... I stay..." - Leader = null + set_leader(null) else if (Friends[who] > Friends[Leader]) - Leader = null + set_leader(null) to_say = "Yes... I stop..." else to_say = "No... keep follow..." @@ -409,7 +408,7 @@ to_say = "No... won't stay..." else if (findtext(phrase, "attack")) if (rabid && prob(20)) - Target = who + set_target(who) special_process = TRUE to_say = "ATTACK!?!?" else if (Friends[who] >= SLIME_FRIENDSHIP_ATTACK) @@ -417,14 +416,14 @@ if (findtext(phrase, lowertext(L.name))) if (isslime(L)) to_say = "NO... [L] slime friend" - --Friends[who] //Don't ask a slime to attack its friend + add_friendship(who, -1) //Don't ask a slime to attack its friend else if(!Friends[L] || Friends[L] < 1) - Target = L + set_target(L) special_process = TRUE to_say = "Ok... I attack [Target]" else to_say = "No... like [L] ..." - --Friends[who] //Don't ask a slime to attack its friend + add_friendship(who, -1) //Don't ask a slime to attack its friend break else to_say = "No... no listen" diff --git a/code/modules/mob/living/simple_animal/slime/powers.dm b/code/modules/mob/living/simple_animal/slime/powers.dm index 8d0bd5c1758..f2b091c3098 100644 --- a/code/modules/mob/living/simple_animal/slime/powers.dm +++ b/code/modules/mob/living/simple_animal/slime/powers.dm @@ -253,7 +253,7 @@ GLOB.poi_list |= M M.master = master LAZYADD(GLOB.mob_spawners["[master.real_name]'s slime"], M) - M.Friends = Friends.Copy() + M.set_friends(Friends) if(step_away) step_away(M,src) M.mutation_chance = clamp(mutation_chance+(rand(5,-5)),0,100) diff --git a/code/modules/mob/living/simple_animal/slime/slime.dm b/code/modules/mob/living/simple_animal/slime/slime.dm index cfabb085abc..f5a3220cb94 100644 --- a/code/modules/mob/living/simple_animal/slime/slime.dm +++ b/code/modules/mob/living/simple_animal/slime/slime.dm @@ -1,3 +1,4 @@ +#define SLIME_CARES_ABOUT(to_check) (to_check && (to_check == Target || to_check == Leader || (to_check in Friends))) /mob/living/simple_animal/slime name = "grey baby slime (123)" icon = 'icons/mob/slimes.dmi' @@ -112,6 +113,12 @@ if(transformeffects & SLIME_EFFECT_LIGHT_PINK) set_playable() +/mob/living/simple_animal/slime/Destroy() + set_target(null) + set_leader(null) + clear_friends() + return ..() + /mob/living/simple_animal/slime/proc/set_colour(new_colour) colour = new_colour update_name() @@ -356,10 +363,7 @@ if(S.next_step(user,user.a_intent)) return 1 if(istype(W, /obj/item/stack/sheet/mineral/plasma) && !stat) //Let's you feed slimes plasma. - if (user in Friends) - ++Friends[user] - else - Friends[user] = 1 + add_friendship(user, 1) to_chat(user, "You feed the slime the plasma. It chirps happily.") var/obj/item/stack/sheet/mineral/plasma/S = W S.use(1) @@ -430,7 +434,7 @@ adjustBruteLoss(new_damage) if(!client) if(Target) // Like cats - Target = null + set_target(null) ++Discipline return @@ -475,8 +479,7 @@ if(Discipline == 1) attacked = 0 - if(Target) - Target = null + set_target(null) if(buckled) Feedstop(silent = TRUE) //we unbuckle the slime from the mob it latched onto. bucklestrength = initial(bucklestrength) @@ -537,3 +540,55 @@ /mob/living/simple_animal/slime/rainbow/Initialize(mapload, new_colour="rainbow", new_is_adult) . = ..(mapload, new_colour, new_is_adult) + +/mob/living/simple_animal/slime/proc/set_target(new_target) + var/old_target = Target + Target = new_target + if(old_target && !SLIME_CARES_ABOUT(old_target)) + UnregisterSignal(old_target, COMSIG_PARENT_QDELETING) + if(Target) + RegisterSignal(Target, COMSIG_PARENT_QDELETING, .proc/clear_memories_of, override = TRUE) + +/mob/living/simple_animal/slime/proc/set_leader(new_leader) + var/old_leader = Leader + Leader = new_leader + if(old_leader && !SLIME_CARES_ABOUT(old_leader)) + UnregisterSignal(old_leader, COMSIG_PARENT_QDELETING) + if(Leader) + RegisterSignal(Leader, COMSIG_PARENT_QDELETING, .proc/clear_memories_of, override = TRUE) + +/mob/living/simple_animal/slime/proc/add_friendship(new_friend, amount = 1) + if(!Friends[new_friend]) + Friends[new_friend] = 0 + Friends[new_friend] += amount + if(new_friend) + RegisterSignal(new_friend, COMSIG_PARENT_QDELETING, .proc/clear_memories_of, override = TRUE) + +/mob/living/simple_animal/slime/proc/set_friendship(new_friend, amount = 1) + Friends[new_friend] = amount + if(new_friend) + RegisterSignal(new_friend, COMSIG_PARENT_QDELETING, .proc/clear_memories_of, override = TRUE) + +/mob/living/simple_animal/slime/proc/remove_friend(friend) + Friends -= friend + if(friend && !SLIME_CARES_ABOUT(friend)) + UnregisterSignal(friend, COMSIG_PARENT_QDELETING) + +/mob/living/simple_animal/slime/proc/set_friends(new_buds) + clear_friends() + for(var/mob/friend as anything in new_buds) + set_friendship(friend, new_buds[friend]) + +/mob/living/simple_animal/slime/proc/clear_friends() + for(var/mob/friend as anything in Friends) + remove_friend(friend) + +/mob/living/simple_animal/slime/proc/clear_memories_of(datum/source) + SIGNAL_HANDLER + if(source == Target) + set_target(null) + if(source == Leader) + set_leader(null) + remove_friend(source) + +#undef SLIME_CARES_ABOUT diff --git a/code/modules/mob/logout.dm b/code/modules/mob/logout.dm index 18dd11f1bb9..0f21607b201 100644 --- a/code/modules/mob/logout.dm +++ b/code/modules/mob/logout.dm @@ -3,10 +3,7 @@ SStgui.on_logout(src) unset_machine() remove_from_player_list() - if(client?.movingmob) //In the case the client was transferred to another mob and not deleted. - client.movingmob.client_mobs_in_contents -= src - UNSETEMPTY(client.movingmob.client_mobs_in_contents) - client.movingmob = null + clear_client_in_contents() ..() if(loc) diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 1254db09f05..2852907f22a 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -16,14 +16,19 @@ * * qdels any client colours in place on this mob * + * Clears any refs to the mob inside its current location + * * Ghostizes the client attached to this mob * + * If our mind still exists, clear its current var to prevent harddels + * * Parent call */ /mob/Destroy()//This makes sure that mobs with clients/keys are not just deleted from the game. remove_from_mob_list() remove_from_dead_mob_list() remove_from_alive_mob_list() + remove_from_mob_suicide_list() focus = null for (var/alert in alerts) clear_alert(alert, TRUE) @@ -35,7 +40,10 @@ for(var/cc in client_colours) qdel(cc) client_colours = null + clear_client_in_contents() //Gotta do this here as well as Logout, since client will be null by the time it gets there, cause of that ghostize ghostize() + if(mind?.current == src) //Let's just be safe yeah? This will occasionally be cleared, but not always. Can't do it with ghostize without changing behavior + mind.set_current(null) QDEL_LIST(mob_spell_list) for(var/datum/action/A as() in actions) if(istype(A.target, /obj/effect/proc_holder)) @@ -1271,3 +1279,21 @@ SEND_SIGNAL(src, COMSIG_MOB_STATCHANGE, new_stat) . = stat stat = new_stat + +/mob/proc/set_active_storage(new_active_storage) + if(active_storage) + UnregisterSignal(active_storage, COMSIG_PARENT_QDELETING) + active_storage = new_active_storage + if(active_storage) + RegisterSignal(active_storage, COMSIG_PARENT_QDELETING, .proc/active_storage_deleted) + +/mob/proc/active_storage_deleted(datum/source) + SIGNAL_HANDLER + set_active_storage(null) + +///Clears the client in contents list of our current "eye". Prevents hard deletes +/mob/proc/clear_client_in_contents() + if(client?.movingmob) //In the case the client was transferred to another mob and not deleted. + client.movingmob.client_mobs_in_contents -= src + UNSETEMPTY(client.movingmob.client_mobs_in_contents) + client.movingmob = null diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index 51a980849f5..ac4a4052601 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -150,8 +150,8 @@ /// Can this mob enter shuttles var/move_on_shuttle = 1 - ///The last mob/living/carbon to push/drag/grab this mob (exclusively used by slimes friend recognition) - var/mob/living/carbon/LAssailant = null + ///A weakref to the last mob/living/carbon to push/drag/grab this mob (exclusively used by slimes friend recognition) + var/datum/weakref/LAssailant = null /** * construct spells and mime spells. diff --git a/code/modules/mob/mob_lists.dm b/code/modules/mob/mob_lists.dm index bd47d511e1d..e09f2a5e523 100644 --- a/code/modules/mob/mob_lists.dm +++ b/code/modules/mob/mob_lists.dm @@ -22,6 +22,13 @@ if(client) remove_from_current_living_players() +///Adds a mob reference to the list of all suicided mobs +/mob/proc/add_to_mob_suicide_list() + GLOB.suicided_mob_list += src + +///Removes a mob references from the list of all suicided mobs +/mob/proc/remove_from_mob_suicide_list() + GLOB.suicided_mob_list -= src ///Adds the mob reference to the list of all the dead mobs. If mob is cliented, it adds it to the list of all dead player-mobs. /mob/proc/add_to_dead_mob_list() diff --git a/code/modules/modular_computers/NTNet/NTNRC/conversation.dm b/code/modules/modular_computers/NTNet/NTNRC/conversation.dm index 20ad05b8e37..cf1b9bb28cd 100644 --- a/code/modules/modular_computers/NTNet/NTNRC/conversation.dm +++ b/code/modules/modular_computers/NTNet/NTNRC/conversation.dm @@ -16,6 +16,8 @@ /datum/ntnet_conversation/Destroy() if(SSnetworks.station_network) SSnetworks.station_network.chat_channels.Remove(src) + for(var/datum/computer_file/program/chatclient/chatterbox in clients) + purge_client(chatterbox) return ..() /datum/ntnet_conversation/proc/add_message(message, username) @@ -35,12 +37,18 @@ /datum/ntnet_conversation/proc/add_client(datum/computer_file/program/chatclient/C) if(!istype(C)) return + C.conversations |= src clients.Add(C) add_status_message("[C.username] has joined the channel.") // No operator, so we assume the channel was empty. Assign this user as operator. if(!operator) changeop(C) +//Clear all of our references to a client, used for client deletion +/datum/ntnet_conversation/proc/purge_client(datum/computer_file/program/chatclient/forget) + remove_client(forget) + forget.conversations -= src + /datum/ntnet_conversation/proc/remove_client(datum/computer_file/program/chatclient/C) if(!istype(C) || !(C in clients)) return diff --git a/code/modules/modular_computers/computers/machinery/console_presets.dm b/code/modules/modular_computers/computers/machinery/console_presets.dm index 4b09436796c..3e40d5a686a 100644 --- a/code/modules/modular_computers/computers/machinery/console_presets.dm +++ b/code/modules/modular_computers/computers/machinery/console_presets.dm @@ -25,8 +25,6 @@ /obj/machinery/modular_computer/console/preset/proc/install_programs() return - - // ===== ENGINEERING CONSOLE ===== /obj/machinery/modular_computer/console/preset/engineering console_department = "Engineering" diff --git a/code/modules/modular_computers/file_system/programs/ntnrc_client.dm b/code/modules/modular_computers/file_system/programs/ntnrc_client.dm index 9422788afed..76dd8039e6f 100644 --- a/code/modules/modular_computers/file_system/programs/ntnrc_client.dm +++ b/code/modules/modular_computers/file_system/programs/ntnrc_client.dm @@ -19,10 +19,18 @@ var/list/channel_history = list() var/operator_mode = FALSE // Channel operator mode var/netadmin_mode = FALSE // Administrator mode (invisible to other users + bypasses passwords) + //A list of all the converstations we're a part of + var/list/datum/ntnet_conversation/conversations = list() /datum/computer_file/program/chatclient/New() username = "DefaultUser[rand(100, 999)]" +/datum/computer_file/program/chatclient/Destroy() + for(var/datum/ntnet_conversation/discussion as anything in conversations) + discussion.purge_client(src) + conversations.Cut() + return ..() + /datum/computer_file/program/chatclient/ui_act(action, params) if(..()) return diff --git a/code/modules/modular_computers/file_system/programs/sm_monitor.dm b/code/modules/modular_computers/file_system/programs/sm_monitor.dm index b7c5be50425..e814aff4fdd 100644 --- a/code/modules/modular_computers/file_system/programs/sm_monitor.dm +++ b/code/modules/modular_computers/file_system/programs/sm_monitor.dm @@ -31,12 +31,15 @@ refresh() /datum/computer_file/program/supermatter_monitor/kill_program(forced = FALSE) - active = null + for(var/supermatter in supermatters) + clear_supermatter(supermatter) supermatters = null ..() // Refreshes list of active supermatter crystals /datum/computer_file/program/supermatter_monitor/proc/refresh() + for(var/supermatter in supermatters) + clear_supermatter(supermatter) supermatters = list() var/turf/T = get_turf(ui_host()) if(!T) @@ -46,9 +49,7 @@ if (!isturf(S.loc) || !(is_station_level(S.z) || is_mining_level(S.z) || S.get_virtual_z_level() == T.get_virtual_z_level())) continue supermatters.Add(S) - - if(!(active in supermatters)) - active = null + RegisterSignal(S, COMSIG_PARENT_QDELETING, .proc/react_to_del) /datum/computer_file/program/supermatter_monitor/proc/get_status() . = SUPERMATTER_INACTIVE @@ -124,3 +125,13 @@ if(S.uid == newuid) active = S return TRUE + +/datum/computer_file/program/supermatter_monitor/proc/react_to_del(datum/source) + SIGNAL_HANDLER + clear_supermatter(source) + +/datum/computer_file/program/supermatter_monitor/proc/clear_supermatter(matter) + supermatters -= matter + if(matter == active) + active = null + UnregisterSignal(matter, COMSIG_PARENT_QDELETING) diff --git a/code/modules/modular_computers/hardware/hard_drive.dm b/code/modules/modular_computers/hardware/hard_drive.dm index e03ace05a5e..8577827dc7a 100644 --- a/code/modules/modular_computers/hardware/hard_drive.dm +++ b/code/modules/modular_computers/hardware/hard_drive.dm @@ -117,7 +117,7 @@ return null /obj/item/computer_hardware/hard_drive/Destroy() - stored_files = null + QDEL_LIST(stored_files) return ..() /obj/item/computer_hardware/hard_drive/Initialize() diff --git a/code/modules/ninja/suit/suit.dm b/code/modules/ninja/suit/suit.dm index 75f7604717f..d79742c99fe 100644 --- a/code/modules/ninja/suit/suit.dm +++ b/code/modules/ninja/suit/suit.dm @@ -76,6 +76,11 @@ Contents: cell.name = "black power cell" cell.icon_state = "bscell" +/obj/item/clothing/suit/space/space_ninja/Destroy() + QDEL_NULL(spark_system) + QDEL_NULL(cell) + return ..() + //Simply deletes all the attachments and self, killing all related procs. /obj/item/clothing/suit/space/space_ninja/proc/terminate() qdel(n_hood) diff --git a/code/modules/projectiles/ammunition/energy/portal.dm b/code/modules/projectiles/ammunition/energy/portal.dm index ec1f067080d..3d560158a7a 100644 --- a/code/modules/projectiles/ammunition/energy/portal.dm +++ b/code/modules/projectiles/ammunition/energy/portal.dm @@ -4,7 +4,8 @@ harmful = FALSE fire_sound = 'sound/weapons/pulse3.ogg' select_name = "blue" - var/obj/item/gun/energy/wormhole_projector/gun + //Weakref to the gun that shot us + var/datum/weakref/gun /obj/item/ammo_casing/energy/wormhole/orange projectile_type = /obj/item/projectile/beam/wormhole/orange @@ -12,7 +13,7 @@ /obj/item/ammo_casing/energy/wormhole/Initialize(mapload, obj/item/gun/energy/wormhole_projector/wh) . = ..() - gun = wh + gun = WEAKREF(wh) /obj/item/ammo_casing/energy/wormhole/throw_proj() . = ..() diff --git a/code/modules/projectiles/guns/energy/laser_gatling.dm b/code/modules/projectiles/guns/energy/laser_gatling.dm index 3ff4c1b5684..bf852f7b1af 100644 --- a/code/modules/projectiles/guns/energy/laser_gatling.dm +++ b/code/modules/projectiles/guns/energy/laser_gatling.dm @@ -23,6 +23,9 @@ START_PROCESSING(SSobj, src) /obj/item/minigunpack/Destroy() + if(!QDELETED(gun)) + qdel(gun) + gun = null STOP_PROCESSING(SSobj, src) return ..() @@ -133,6 +136,12 @@ return ..() +/obj/item/gun/energy/minigun/Destroy() + if(!QDELETED(ammo_pack)) + qdel(ammo_pack) + ammo_pack = null + return ..() + /obj/item/gun/energy/minigun/attack_self(mob/living/user) return diff --git a/code/modules/projectiles/guns/energy/special.dm b/code/modules/projectiles/guns/energy/special.dm index 8976f200b3d..00faa65624f 100644 --- a/code/modules/projectiles/guns/energy/special.dm +++ b/code/modules/projectiles/guns/energy/special.dm @@ -258,10 +258,10 @@ for(var/i in 1 to ammo_type.len) var/obj/item/ammo_casing/energy/wormhole/W = ammo_type[i] if(istype(W)) - W.gun = src + W.gun = WEAKREF(src) var/obj/item/projectile/beam/wormhole/WH = W.BB if(istype(WH)) - WH.gun = src + WH.gun = WEAKREF(src) /obj/item/gun/energy/wormhole_projector/process_chamber() ..() diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 42257883f5c..d25d25bcd28 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -553,6 +553,8 @@ else if(T != loc) step_towards(src, T) hitscan_last = loc + if(QDELETED(src)) + return if(!hitscanning && !forcemoved) pixel_x = trajectory.return_px() - trajectory.mpx * trajectory_multiplier * SSprojectiles.global_iterations_per_move pixel_y = trajectory.return_py() - trajectory.mpy * trajectory_multiplier * SSprojectiles.global_iterations_per_move @@ -685,13 +687,14 @@ finalize_hitscan_and_generate_tracers() STOP_PROCESSING(SSprojectiles, src) cleanup_beam_segments() - qdel(trajectory) + if(trajectory) + QDEL_NULL(trajectory) return ..() /obj/item/projectile/proc/cleanup_beam_segments() QDEL_LIST_ASSOC(beam_segments) beam_segments = list() - qdel(beam_index) + QDEL_NULL(beam_index) /obj/item/projectile/proc/finalize_hitscan_and_generate_tracers(impacting = TRUE) if(trajectory && beam_index) diff --git a/code/modules/projectiles/projectile/special/curse.dm b/code/modules/projectiles/projectile/special/curse.dm index 2598c439706..0e0eaa1f21a 100644 --- a/code/modules/projectiles/projectile/special/curse.dm +++ b/code/modules/projectiles/projectile/special/curse.dm @@ -36,7 +36,7 @@ /obj/item/projectile/curse_hand/Destroy() if(arm) arm.End() - arm = null + QDEL_NULL(arm) if(CHECK_BITFIELD(movement_type, UNSTOPPABLE)) playsound(src, 'sound/effects/curse3.ogg', 25, 1, -1) var/turf/T = get_step(src, dir) diff --git a/code/modules/projectiles/projectile/special/wormhole.dm b/code/modules/projectiles/projectile/special/wormhole.dm index c7fa6c644ff..075db9472c9 100644 --- a/code/modules/projectiles/projectile/special/wormhole.dm +++ b/code/modules/projectiles/projectile/special/wormhole.dm @@ -5,7 +5,8 @@ damage = 0 nodamage = TRUE pass_flags = PASSGLASS | PASSTABLE | PASSGRILLE | PASSMOB - var/obj/item/gun/energy/wormhole_projector/gun + //Weakref to the thing that shot us + var/datum/weakref/gun color = "#33CCFF" tracer_type = /obj/effect/projectile/tracer/wormhole impact_type = /obj/effect/projectile/impact/wormhole @@ -24,7 +25,8 @@ /obj/item/projectile/beam/wormhole/on_hit(atom/target) - if(!gun) + var/obj/item/gun/energy/wormhole_projector/projector = gun.resolve() + if(!projector) qdel(src) return - gun.create_portal(src, get_turf(src)) + projector.create_portal(src, get_turf(src)) diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index ce858ec91e0..53245185a7b 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -1,5 +1,5 @@ /datum/reagent/blood - data = list("donor"=null,"viruses"=null,"blood_DNA"=null,"blood_type"=null,"resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null,"quirks"=null) + data = list("viruses"=null,"blood_DNA"=null,"blood_type"=null,"resistances"=null,"trace_chem"=null,"mind"=null,"ckey"=null,"gender"=null,"real_name"=null,"cloneable"=null,"factions"=null,"quirks"=null) name = "Blood" color = "#C80000" // rgb: 200, 0, 0 metabolization_rate = 5 //fast rate so it disappears fast. diff --git a/code/modules/reagents/reagent_containers.dm b/code/modules/reagents/reagent_containers.dm index 311e04d7b80..683e9e54772 100644 --- a/code/modules/reagents/reagent_containers.dm +++ b/code/modules/reagents/reagent_containers.dm @@ -87,12 +87,14 @@ /obj/item/reagent_containers/proc/bartender_check(atom/target) . = FALSE - if(target.CanPass(src, get_turf(src)) && thrownby && HAS_TRAIT(thrownby, TRAIT_BOOZE_SLIDER)) + var/mob/thrown_by = thrownby?.resolve() + if(target.CanPass(src, get_turf(src)) && thrown_by && HAS_TRAIT(thrown_by, TRAIT_BOOZE_SLIDER)) . = TRUE /obj/item/reagent_containers/proc/SplashReagents(atom/target, thrown = FALSE) if(!reagents || !reagents.total_volume || !spillable) return + var/mob/thrown_by = thrownby?.resolve() if(ismob(target) && target.reagents) if(thrown) @@ -105,7 +107,7 @@ R += "[A.type] ([num2text(A.volume)])," if(thrownby) - log_combat(thrownby, M, "splashed", R) + log_combat(thrown_by, M, "splashed", R) reagents.reaction(target, TOUCH) else if(bartender_check(target) && thrown) @@ -113,10 +115,10 @@ return else - if(isturf(target) && reagents.reagent_list.len && thrownby) - log_combat(thrownby, target, "splashed (thrown) [english_list(reagents.reagent_list)]", "in [AREACOORD(target)]") - log_game("[key_name(thrownby)] splashed (thrown) [english_list(reagents.reagent_list)] on [target] in [AREACOORD(target)].") - message_admins("[ADMIN_LOOKUPFLW(thrownby)] splashed (thrown) [english_list(reagents.reagent_list)] on [target] in [ADMIN_VERBOSEJMP(target)].") + if(isturf(target) && reagents.reagent_list.len && thrown_by) + log_combat(thrown_by, target, "splashed (thrown) [english_list(reagents.reagent_list)]", "in [AREACOORD(target)]") + log_game("[key_name(thrown_by)] splashed (thrown) [english_list(reagents.reagent_list)] on [target] in [AREACOORD(target)].") + message_admins("[ADMIN_LOOKUPFLW(thrown_by)] splashed (thrown) [english_list(reagents.reagent_list)] on [target] in [ADMIN_VERBOSEJMP(target)].") visible_message("[src] spills its contents all over [target].") reagents.reaction(target, TOUCH) if(QDELETED(src)) diff --git a/code/modules/reagents/reagent_containers/blood_pack.dm b/code/modules/reagents/reagent_containers/blood_pack.dm index bce6ebeb4d4..3a686b76958 100644 --- a/code/modules/reagents/reagent_containers/blood_pack.dm +++ b/code/modules/reagents/reagent_containers/blood_pack.dm @@ -12,7 +12,7 @@ /obj/item/reagent_containers/blood/Initialize() . = ..() if(blood_type != null) - reagents.add_reagent(unique_blood ? unique_blood : /datum/reagent/blood, 200, list("donor"=null,"viruses"=null,"blood_DNA"=null,"blood_type"=blood_type,"resistances"=null,"trace_chem"=null)) + reagents.add_reagent(unique_blood ? unique_blood : /datum/reagent/blood, 200, list("viruses"=null,"blood_DNA"=null,"blood_type"=blood_type,"resistances"=null,"trace_chem"=null)) update_icon() /obj/item/reagent_containers/blood/on_reagent_change(changetype) diff --git a/code/modules/reagents/reagent_containers/borghydro.dm b/code/modules/reagents/reagent_containers/borghydro.dm index 9175fd650cc..7011be0db7b 100644 --- a/code/modules/reagents/reagent_containers/borghydro.dm +++ b/code/modules/reagents/reagent_containers/borghydro.dm @@ -44,9 +44,9 @@ Borg Hypospray /obj/item/reagent_containers/borghypo/Destroy() STOP_PROCESSING(SSobj, src) + QDEL_LIST(reagent_list) return ..() - /obj/item/reagent_containers/borghypo/process(delta_time) //Every [recharge_time] seconds, recharge some reagents for the cyborg charge_timer += delta_time if(charge_timer >= recharge_time) diff --git a/code/modules/recycling/disposal/bin.dm b/code/modules/recycling/disposal/bin.dm index d276c339317..b09a2235ebe 100644 --- a/code/modules/recycling/disposal/bin.dm +++ b/code/modules/recycling/disposal/bin.dm @@ -137,7 +137,7 @@ else target.visible_message("[user] has placed [target] in [src].", "[user] has placed you in [src].") log_combat(user, target, "stuffed", addition="into [src]") - target.LAssailant = user + target.LAssailant = WEAKREF(user) update_icon() /obj/machinery/disposal/relaymove(mob/user) diff --git a/code/modules/research/nanites/nanite_chamber.dm b/code/modules/research/nanites/nanite_chamber.dm index 13b50c6b0fc..ece40e19773 100644 --- a/code/modules/research/nanites/nanite_chamber.dm +++ b/code/modules/research/nanites/nanite_chamber.dm @@ -11,7 +11,6 @@ idle_power_usage = 300 active_power_usage = 1200 - var/obj/machinery/computer/nanite_chamber_control/console var/locked = FALSE var/breakout_time = 1200 var/scan_level diff --git a/code/modules/research/nanites/nanite_chamber_computer.dm b/code/modules/research/nanites/nanite_chamber_computer.dm index b73c6253ab6..d6caf584aac 100644 --- a/code/modules/research/nanites/nanite_chamber_computer.dm +++ b/code/modules/research/nanites/nanite_chamber_computer.dm @@ -2,7 +2,6 @@ name = "nanite chamber control console" desc = "Controls a connected nanite chamber. Can inoculate nanites, load programs, and analyze existing nanite swarms." var/obj/machinery/nanite_chamber/chamber - var/obj/item/disk/nanite_program/disk icon_screen = "nanite_chamber_control" circuit = /obj/item/circuitboard/computer/nanite_chamber_control @@ -17,8 +16,7 @@ var/C = locate(/obj/machinery/nanite_chamber, get_step(src, direction)) if(C) var/obj/machinery/nanite_chamber/NC = C - chamber = NC - NC.console = src + set_connected_chamber(NC) /obj/machinery/computer/nanite_chamber_control/interact() if(!chamber) @@ -102,3 +100,14 @@ log_combat(usr, chamber.occupant, "injected", null, "with nanites via [src]") chamber.occupant.investigate_log("was injected with nanites by [key_name(usr)] via [src] at [AREACOORD(src)].", INVESTIGATE_NANITES) . = TRUE + +/obj/machinery/computer/nanite_chamber_control/proc/set_connected_chamber(new_chamber) + if(chamber) + UnregisterSignal(chamber, COMSIG_PARENT_QDELETING) + chamber = new_chamber + if(chamber) + RegisterSignal(chamber, COMSIG_PARENT_QDELETING, .proc/react_to_chamber_del) + +/obj/machinery/computer/nanite_chamber_control/proc/react_to_chamber_del(datum/source) + SIGNAL_HANDLER + set_connected_chamber(null) diff --git a/code/modules/research/nanites/nanite_programs.dm b/code/modules/research/nanites/nanite_programs.dm index 7c6d64e9b2b..2a4142bb35c 100644 --- a/code/modules/research/nanites/nanite_programs.dm +++ b/code/modules/research/nanites/nanite_programs.dm @@ -77,6 +77,9 @@ on_mob_remove() if(nanites) nanites.programs -= src + for(var/datum/nanite_rule/rule as anything in rules) + rule.remove() + rules.Cut() return ..() /datum/nanite_program/proc/copy() diff --git a/code/modules/research/nanites/nanite_programs/utility.dm b/code/modules/research/nanites/nanite_programs/utility.dm index 8eccc0d481b..66c041d6628 100644 --- a/code/modules/research/nanites/nanite_programs/utility.dm +++ b/code/modules/research/nanites/nanite_programs/utility.dm @@ -326,7 +326,7 @@ /datum/nanite_program/dermal_button/on_mob_remove() . = ..() - qdel(button) + QDEL_NULL(button) /datum/nanite_program/dermal_button/proc/press() if(activated) diff --git a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm index 3eea59c696d..c5bc034cba4 100644 --- a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm +++ b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm @@ -467,7 +467,7 @@ for(var/mob/living/simple_animal/slime/S in viewers(1, owner)) if(!(owner in S.Friends)) to_chat(owner, "[linked_extract] pulses gently as it communicates with [S].") - S.Friends[owner] = 1 + S.set_friendship(owner, 1) return ..() /datum/status_effect/stabilized/orange diff --git a/code/modules/research/xenobiology/crossbreeding/burning.dm b/code/modules/research/xenobiology/crossbreeding/burning.dm index 948e5bbaa6a..e817d7b84e4 100644 --- a/code/modules/research/xenobiology/crossbreeding/burning.dm +++ b/code/modules/research/xenobiology/crossbreeding/burning.dm @@ -34,7 +34,7 @@ Burning extracts: /obj/item/slimecross/burning/grey/do_effect(mob/user) var/mob/living/simple_animal/slime/S = new(get_turf(user),"grey") S.visible_message("A baby slime emerges from [src], and it nuzzles [user] before burbling hungrily!") - S.Friends[user] = 20 //Gas, gas, gas + S.set_friendship(user, 20) //Gas, gas, gas S.bodytemperature = T0C + 400 //We gonna step on the gas. S.set_nutrition(S.get_hunger_nutrition()) //Tonight, we fight! ..() @@ -198,10 +198,10 @@ Burning extracts: for(var/mob/living/simple_animal/slime/S in hearers(7, get_turf(user))) if(user in S.Friends) var/friendliness = S.Friends[user] - S.Friends = list() - S.Friends[user] = friendliness + S.clear_friends() + S.set_friendship(user, friendliness) else - S.Friends = list() + S.clear_friends() S.rabid = 1 S.visible_message("The [S] is driven into a dangerous frenzy!") ..() diff --git a/code/modules/research/xenobiology/xenobio_camera.dm b/code/modules/research/xenobiology/xenobio_camera.dm index cf3cb3d240a..5459617ef65 100644 --- a/code/modules/research/xenobiology/xenobio_camera.dm +++ b/code/modules/research/xenobiology/xenobio_camera.dm @@ -238,7 +238,7 @@ if(X.monkeys >= 1) var/mob/living/carbon/monkey/food = new /mob/living/carbon/monkey(remote_eye.loc, TRUE, owner) if (!QDELETED(food)) - food.LAssailant = C + food.LAssailant = WEAKREF(C) X.monkeys-- X.monkeys = round(X.monkeys, 0.1) //Prevents rounding errors to_chat(owner, "[X] now has [X.monkeys] monkeys stored.") @@ -440,7 +440,7 @@ if(X.monkeys >= 1) var/mob/living/carbon/monkey/food = new /mob/living/carbon/monkey(T, TRUE, C) if (!QDELETED(food)) - food.LAssailant = C + food.LAssailant = WEAKREF(C) X.monkeys-- X.monkeys = round(X.monkeys, 0.1) //Prevents rounding errors to_chat(C, "[X] now has [X.monkeys] monkeys stored.") diff --git a/code/modules/ruins/objects_and_mobs/ash_walker_den.dm b/code/modules/ruins/objects_and_mobs/ash_walker_den.dm index 30d03404ebf..7024ed91772 100644 --- a/code/modules/ruins/objects_and_mobs/ash_walker_den.dm +++ b/code/modules/ruins/objects_and_mobs/ash_walker_den.dm @@ -17,17 +17,26 @@ var/faction = list("ashwalker") var/meat_counter = 6 var/datum/team/ashwalkers/ashies + var/datum/linked_objective /obj/structure/lavaland/ash_walker/Initialize() .=..() ashies = new /datum/team/ashwalkers() var/datum/objective/protect_object/objective = new objective.set_target(src) + linked_objective = objective ashies.objectives += objective for(var/datum/mind/M in ashies.members) log_objective(M, objective.explanation_text) START_PROCESSING(SSprocessing, src) +/obj/structure/lavaland/ash_walker/Destroy() + ashies.objectives -= linked_objective + ashies = null + QDEL_NULL(linked_objective) + STOP_PROCESSING(SSprocessing, src) + return ..() + /obj/structure/lavaland/ash_walker/deconstruct(disassembled) new /obj/item/assembly/signaler/anomaly (get_step(loc, pick(GLOB.alldirs))) new /obj/effect/collapse(loc) diff --git a/code/modules/shuttle/emergency.dm b/code/modules/shuttle/emergency.dm index 31ac823bbf0..955c6e69896 100644 --- a/code/modules/shuttle/emergency.dm +++ b/code/modules/shuttle/emergency.dm @@ -737,6 +737,11 @@ SSshuttle.emergency = current_emergency SSshuttle.backup_shuttle = src +/obj/docking_port/mobile/emergency/backup/Destroy(force) + if(SSshuttle.backup_shuttle == src) + SSshuttle.backup_shuttle = null + return ..() + /obj/docking_port/mobile/emergency/shuttle_build/register() . = ..() initiate_docking(SSshuttle.getDock("emergency_home")) diff --git a/code/modules/shuttle/shuttle.dm b/code/modules/shuttle/shuttle.dm index a25963393e3..efc273c04f7 100644 --- a/code/modules/shuttle/shuttle.dm +++ b/code/modules/shuttle/shuttle.dm @@ -783,8 +783,16 @@ var/range = (engine_coeff * max(width, height)) var/long_range = range * 2.5 var/atom/distant_source - if(LAZYLEN(engine_list)) - distant_source = engine_list[1] + var/list/engines = list() + for(var/datum/weakref/engine in engine_list) + var/obj/structure/shuttle/engine/real_engine = engine.resolve() + if(!real_engine) + engine_list -= engine + continue + engines += real_engine + + if(LAZYLEN(engines)) + distant_source = engines[1] else for(var/A in areas) distant_source = locate(/obj/machinery/door) in A @@ -798,11 +806,11 @@ M.playsound_local(distant_source, "sound/effects/[selected_sound]_distance.ogg", 100, falloff = 20) else if(dist_far <= range) var/source - if(engine_list.len == 0) + if(engines.len == 0) source = distant_source else var/closest_dist = 10000 - for(var/obj/O in engine_list) + for(var/obj/O in engines) var/dist_near = get_dist(M, O) if(dist_near < closest_dist) source = O @@ -828,7 +836,7 @@ var/area/shuttle/areaInstance = thing for(var/obj/structure/shuttle/engine/E in areaInstance.contents) if(!QDELETED(E)) - engine_list += E + engine_list += WEAKREF(E) . += E.engine_power for(var/obj/machinery/shuttle/engine/E in areaInstance.contents) if(!QDELETED(E)) diff --git a/code/modules/spells/spell.dm b/code/modules/spells/spell.dm index 309b6ec7060..1bcf9306d68 100644 --- a/code/modules/spells/spell.dm +++ b/code/modules/spells/spell.dm @@ -20,6 +20,12 @@ if(has_action) action = new base_action(src) +/obj/effect/proc_holder/Destroy() + if(!QDELETED(action)) + qdel(action) + action = null + return ..() + /obj/effect/proc_holder/proc/on_gain(mob/living/user) return diff --git a/code/modules/surgery/organs/augments_arms.dm b/code/modules/surgery/organs/augments_arms.dm index ea5468ea9a1..8cce69a6fae 100644 --- a/code/modules/surgery/organs/augments_arms.dm +++ b/code/modules/surgery/organs/augments_arms.dm @@ -211,7 +211,7 @@ . = ..() if(locate(/obj/item/assembly/flash/armimplant) in items_list) var/obj/item/assembly/flash/armimplant/F = locate(/obj/item/assembly/flash/armimplant) in items_list - F.I = src + F.arm = WEAKREF(src) /obj/item/organ/cyberimp/arm/baton name = "arm electrification implant" @@ -227,7 +227,7 @@ . = ..() if(locate(/obj/item/assembly/flash/armimplant) in items_list) var/obj/item/assembly/flash/armimplant/F = locate(/obj/item/assembly/flash/armimplant) in items_list - F.I = src + F.arm = WEAKREF(src) /obj/item/organ/cyberimp/arm/surgery name = "surgical toolset implant" diff --git a/code/modules/vending/_vending.dm b/code/modules/vending/_vending.dm index 581ed62a95a..00f444d16bd 100644 --- a/code/modules/vending/_vending.dm +++ b/code/modules/vending/_vending.dm @@ -64,7 +64,7 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C var/vend_ready = TRUE ///Next world time to send a purchase message var/purchase_message_cooldown - ///Last mob to shop with us + ///The ref of the last mob to shop with us var/last_shopper var/tilted = FALSE var/tiltable = TRUE @@ -777,10 +777,11 @@ GLOBAL_LIST_EMPTY(vending_products) var/datum/bank_account/D = SSeconomy.get_dep_account(payment_department) if(D) D.adjust_money(price_to_use) - if(last_shopper != usr || purchase_message_cooldown < world.time) + if(last_shopper != REF(usr) || purchase_message_cooldown < world.time) say("Thank you for shopping with [src]!") purchase_message_cooldown = world.time + 5 SECONDS - last_shopper = usr + //This is not the best practice, but it's safe enough here since the chances of two people using a machine with the same ref in 5 seconds is fuck low + last_shopper = REF(usr) use_power(5) if(icon_vend) //Show the vending animation if needed flick(icon_vend,src) @@ -1025,10 +1026,10 @@ GLOBAL_LIST_EMPTY(vending_products) S.forceMove(drop_location()) loaded_items-- use_power(5) - if(last_shopper != usr || purchase_message_cooldown < world.time) + if(last_shopper != REF(usr) || purchase_message_cooldown < world.time) say("Thank you for buying local and purchasing [S]!") purchase_message_cooldown = world.time + 5 SECONDS - last_shopper = usr + last_shopper = REF(usr) vend_ready = TRUE updateUsrDialog() return diff --git a/code/modules/zombie/organs.dm b/code/modules/zombie/organs.dm index fd5b3b71c5e..01439476699 100644 --- a/code/modules/zombie/organs.dm +++ b/code/modules/zombie/organs.dm @@ -30,7 +30,7 @@ /obj/item/organ/zombie_infection/Remove(mob/living/carbon/M, special = 0) . = ..() STOP_PROCESSING(SSobj, src) - if(iszombie(M) && old_species) + if(iszombie(M) && old_species && !QDELETED(M)) M.set_species(old_species) if(timer_id) deltimer(timer_id)