From 99950517aaa92d4236b4ec084a5f624728ba072d Mon Sep 17 00:00:00 2001 From: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com> Date: Wed, 27 Sep 2023 18:05:55 -0700 Subject: [PATCH] Quick Harddel Fixeees (#78253) --- code/__HELPERS/_lists.dm | 11 ++++ code/_globalvars/lists/mobs.dm | 2 +- code/controllers/subsystem/economy.dm | 4 +- code/datums/records/manifest.dm | 20 ++++--- code/datums/records/record.dm | 12 ++-- code/game/gamemodes/dynamic/dynamic.dm | 4 ++ .../gamemodes/dynamic/dynamic_rulesets.dm | 8 +++ .../dynamic/dynamic_rulesets_midround.dm | 34 ++++++++++- .../dynamic/dynamic_rulesets_roundstart.dm | 4 ++ .../game/gamemodes/dynamic/ruleset_picking.dm | 3 +- .../telecomms/computers/telemonitor.dm | 56 +++++++++++-------- code/game/objects/items/mail.dm | 5 +- code/modules/admin/verbs/admingame.dm | 2 +- .../objectives/abstract/target_player.dm | 15 +++++ .../traitor/objectives/assassination.dm | 17 ++---- .../traitor/objectives/demoralise_assault.dm | 12 ++-- .../traitor/objectives/eyesnatching.dm | 2 +- .../antagonists/traitor/objectives/infect.dm | 8 +-- .../traitor/objectives/kidnapping.dm | 13 +++-- .../mob/living/simple_animal/bot/bot.dm | 21 +++---- .../hostile/mining_mobs/elites/herald.dm | 3 +- .../mob/living/simple_animal/parrot.dm | 37 +++++++----- code/modules/paperwork/filingcabinet.dm | 6 +- 23 files changed, 193 insertions(+), 106 deletions(-) diff --git a/code/__HELPERS/_lists.dm b/code/__HELPERS/_lists.dm index 34512b95952..fb1603d650d 100644 --- a/code/__HELPERS/_lists.dm +++ b/code/__HELPERS/_lists.dm @@ -408,6 +408,17 @@ list_to_clear -= new_list return list_to_clear.len < start_len +/** + * Removes any empty weakrefs from the list + * Returns TRUE if the list had empty refs, FALSE otherwise +**/ +/proc/list_clear_empty_weakrefs(list/list_to_clear) + var/start_len = list_to_clear.len + for(var/datum/weakref/entry in list_to_clear) + if(!entry.resolve()) + list_to_clear -= entry + return list_to_clear.len < start_len + /* * Returns list containing all the entries from first list that are not present in second. * If skiprep = 1, repeated elements are treated as one. diff --git a/code/_globalvars/lists/mobs.dm b/code/_globalvars/lists/mobs.dm index 146a83fa8d2..5fc93a2494e 100644 --- a/code/_globalvars/lists/mobs.dm +++ b/code/_globalvars/lists/mobs.dm @@ -116,7 +116,7 @@ GLOBAL_LIST_INIT(construct_radial_images, list( /proc/get_crewmember_minds() var/list/minds = list() for(var/datum/record/locked/target in GLOB.manifest.locked) - var/datum/mind/mind = target.mind_ref + var/datum/mind/mind = target.mind_ref.resolve() if(mind) minds += mind return minds diff --git a/code/controllers/subsystem/economy.dm b/code/controllers/subsystem/economy.dm index 73224333978..b560f12ee20 100644 --- a/code/controllers/subsystem/economy.dm +++ b/code/controllers/subsystem/economy.dm @@ -203,9 +203,9 @@ SUBSYSTEM_DEF(economy) CRASH("Track purchases was missing an argument! (Account, Price, or Vendor.)") audit_log += list(list( - "account" = account.account_holder, + "account" = "[account.account_holder]", "cost" = price_to_use, - "vendor" = vendor, + "vendor" = "[vendor]", )) /** diff --git a/code/datums/records/manifest.dm b/code/datums/records/manifest.dm index d94c53620b0..225da0e0c04 100644 --- a/code/datums/records/manifest.dm +++ b/code/datums/records/manifest.dm @@ -109,35 +109,37 @@ GLOBAL_DATUM_INIT(manifest, /datum/manifest, new) person_gender = "Male" if(person.gender == "female") person_gender = "Female" + var/datum/dna/record_dna = new() + person.dna.copy_dna(record_dna) var/datum/record/locked/lockfile = new( age = person.age, - blood_type = person.dna.blood_type, + blood_type = record_dna.blood_type, character_appearance = character_appearance, - dna_string = person.dna.unique_enzymes, - fingerprint = md5(person.dna.unique_identity), + dna_string = record_dna.unique_enzymes, + fingerprint = md5(record_dna.unique_identity), gender = person_gender, initial_rank = assignment, name = person.real_name, rank = assignment, - species = person.dna.species.name, + species = record_dna.species.name, trim = assignment, // Locked specifics - dna_ref = person.dna, + locked_dna = record_dna, mind_ref = person.mind, ) new /datum/record/crew( age = person.age, - blood_type = person.dna.blood_type, + blood_type = record_dna.blood_type, character_appearance = character_appearance, - dna_string = person.dna.unique_enzymes, - fingerprint = md5(person.dna.unique_identity), + dna_string = record_dna.unique_enzymes, + fingerprint = md5(record_dna.unique_identity), gender = person_gender, initial_rank = assignment, name = person.real_name, rank = assignment, - species = person.dna.species.name, + species = record_dna.species.name, trim = assignment, // Crew specific lock_ref = REF(lockfile), diff --git a/code/datums/records/record.dm b/code/datums/records/record.dm index debb70a813c..167f227fc3a 100644 --- a/code/datums/records/record.dm +++ b/code/datums/records/record.dm @@ -127,9 +127,9 @@ */ /datum/record/locked /// Mob's dna - var/datum/dna/dna_ref + var/datum/dna/locked_dna /// Mind datum - var/datum/mind/mind_ref + var/datum/weakref/mind_ref /// Typepath of species used by player, for usage in respawning via records var/species_type @@ -146,13 +146,13 @@ species = "Human", trim = "Unassigned", /// Locked specific - datum/dna/dna_ref, + datum/dna/locked_dna, datum/mind/mind_ref, ) . = ..() - src.dna_ref = dna_ref - src.mind_ref = mind_ref - species_type = dna_ref.species.type + src.locked_dna = locked_dna + src.mind_ref = WEAKREF(mind_ref) + species_type = locked_dna.species.type GLOB.manifest.locked += src diff --git a/code/game/gamemodes/dynamic/dynamic.dm b/code/game/gamemodes/dynamic/dynamic.dm index e42cefab193..5a86050b13e 100644 --- a/code/game/gamemodes/dynamic/dynamic.dm +++ b/code/game/gamemodes/dynamic/dynamic.dm @@ -634,8 +634,10 @@ GLOBAL_LIST_EMPTY(dynamic_station_traits) if(rule.persistent) current_rules += rule new_snapshot(rule) + rule.forget_startup() return TRUE rule.clean_up() // Refund threat, delete teams and so on. + rule.forget_startup() executed_rules -= rule stack_trace("The starting rule \"[rule.name]\" failed to execute.") return FALSE @@ -683,9 +685,11 @@ GLOBAL_LIST_EMPTY(dynamic_station_traits) executed_rules += new_rule if (new_rule.persistent) current_rules += new_rule + new_rule.forget_startup() return TRUE else if (forced) log_dynamic("The ruleset [new_rule.name] couldn't be executed due to lack of elligible players.") + new_rule.forget_startup() return FALSE /datum/game_mode/dynamic/process() diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets.dm b/code/game/gamemodes/dynamic/dynamic_rulesets.dm index 87147e6cd35..945c7e4ed01 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets.dm @@ -167,6 +167,14 @@ GLOB.pre_setup_antags -= M return TRUE +/// Rulesets can be reused, so when we're done setting one up we want to wipe its memory of the people it was selecting over +/// This isn't Destroy we aren't deleting it here, rulesets free when nothing holds a ref. This is just to prevent hung refs. +/datum/dynamic_ruleset/proc/forget_startup() + SHOULD_CALL_PARENT(TRUE) + candidates = list() + assigned = list() + antag_datum = null + /// Here you can perform any additional checks you want. (such as checking the map etc) /// Remember that on roundstart no one knows what their job is at this point. /// IMPORTANT: If ready() returns TRUE, that means pre_execute() or execute() should never fail! diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm index a9f125e8885..169c914f846 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm @@ -21,6 +21,13 @@ /// Abstract root value var/abstract_type = /datum/dynamic_ruleset/midround +/datum/dynamic_ruleset/midround/forget_startup() + living_players = list() + living_antags = list() + dead_players = list() + list_observers = list() + return ..() + /datum/dynamic_ruleset/midround/from_ghosts weight = 0 required_type = /mob/dead/observer @@ -364,8 +371,6 @@ flags = HIGH_IMPACT_RULESET var/list/operative_cap = list(2,2,3,3,4,5,5,5,5,5) - /// The nuke ops team datum. - var/datum/team/nuclear/nuke_team /datum/dynamic_ruleset/midround/from_ghosts/nuclear/acceptable(population=0, threat=0) if (locate(/datum/dynamic_ruleset/roundstart/nuclear) in mode.executed_rules) @@ -391,7 +396,6 @@ new_character.mind.special_role = ROLE_NUCLEAR_OPERATIVE if(index == 1) var/datum/antagonist/nukeop/leader/leader_antag_datum = new() - nuke_team = leader_antag_datum.nuke_team new_character.mind.add_antag_datum(leader_antag_datum) return return ..() @@ -477,6 +481,10 @@ repeatable = TRUE var/list/vents = list() +/datum/dynamic_ruleset/midround/from_ghosts/xenomorph/forget_startup() + vents = list() + return ..() + /datum/dynamic_ruleset/midround/from_ghosts/xenomorph/execute() // 50% chance of being incremented by one required_candidates += prob(50) @@ -556,6 +564,10 @@ repeatable = TRUE var/list/spawn_locs = list() +/datum/dynamic_ruleset/midround/from_ghosts/space_dragon/forget_startup() + spawn_locs = list() + return ..() + /datum/dynamic_ruleset/midround/from_ghosts/space_dragon/execute() for(var/obj/effect/landmark/carpspawn/C in GLOB.landmarks_list) spawn_locs += (C.loc) @@ -594,6 +606,10 @@ var/datum/team/abductor_team/new_team +/datum/dynamic_ruleset/midround/from_ghosts/abductors/forget_startup() + new_team = null + return ..() + /datum/dynamic_ruleset/midround/from_ghosts/abductors/ready(forced = FALSE) if (required_candidates > (dead_players.len + list_observers.len)) return FALSE @@ -626,6 +642,10 @@ var/list/spawn_locs = list() +/datum/dynamic_ruleset/midround/from_ghosts/space_ninja/forget_startup() + spawn_locs = list() + return ..() + /datum/dynamic_ruleset/midround/from_ghosts/space_ninja/execute() for(var/obj/effect/landmark/carpspawn/carp_spawn in GLOB.landmarks_list) if(!isturf(carp_spawn.loc)) @@ -680,6 +700,10 @@ var/need_extra_spawns_value = 15 var/list/spawn_locs = list() +/datum/dynamic_ruleset/midround/from_ghosts/revenant/forget_startup() + spawn_locs = list() + return ..() + /datum/dynamic_ruleset/midround/from_ghosts/revenant/acceptable(population=0, threat=0) if(GLOB.dead_mob_list.len < dead_mobs_required) return FALSE @@ -851,6 +875,10 @@ repeatable = TRUE var/list/possible_spawns = list() ///places the antag can spawn +/datum/dynamic_ruleset/midround/from_ghosts/paradox_clone/forget_startup() + possible_spawns = list() + return ..() + /datum/dynamic_ruleset/midround/from_ghosts/paradox_clone/execute() possible_spawns += find_maintenance_spawn(atmos_sensitive = TRUE, require_darkness = FALSE) if(!possible_spawns.len) diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm index df078c462d9..a90eba738c1 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets_roundstart.dm @@ -121,6 +121,10 @@ GLOBAL_VAR_INIT(revolutionary_win, FALSE) var/list/datum/team/brother_team/pre_brother_teams = list() var/const/min_team_size = 2 +/datum/dynamic_ruleset/roundstart/traitorbro/forget_startup() + pre_brother_teams = list() + return ..() + /datum/dynamic_ruleset/roundstart/traitorbro/pre_execute(population) . = ..() var/num_teams = (get_antag_cap(population)/min_team_size) * (scaled_times + 1) // 1 team per scaling diff --git a/code/game/gamemodes/dynamic/ruleset_picking.dm b/code/game/gamemodes/dynamic/ruleset_picking.dm index 5d907e6580c..0ef6299e159 100644 --- a/code/game/gamemodes/dynamic/ruleset_picking.dm +++ b/code/game/gamemodes/dynamic/ruleset_picking.dm @@ -98,11 +98,12 @@ message_admins("[key_name(M)] joined the station, and was selected by the [rule.name] ruleset.") log_dynamic("[key_name(M)] joined the station, and was selected by the [rule.name] ruleset.") executed_rules += rule - rule.candidates.Cut() if (rule.persistent) current_rules += rule new_snapshot(rule) + rule.forget_startup() return TRUE + rule.forget_startup() rule.clean_up() stack_trace("The [rule.ruletype] rule \"[rule.name]\" failed to execute.") return FALSE diff --git a/code/game/machinery/telecomms/computers/telemonitor.dm b/code/game/machinery/telecomms/computers/telemonitor.dm index b862a6372b7..400d827f618 100644 --- a/code/game/machinery/telecomms/computers/telemonitor.dm +++ b/code/game/machinery/telecomms/computers/telemonitor.dm @@ -14,10 +14,10 @@ /// Current screen the user is viewing var/screen = MAIN_VIEW - /// The machines located by the computer - var/list/machinelist = list() - /// the currently selected machine - var/obj/machinery/telecomms/SelectedMachine + /// Weakrefs of the machines located by the computer + var/list/machine_list = list() + /// Weakref of the currently selected tcomms machine + var/datum/weakref/selected_machine_ref /// The network to probe var/network = "NULL" /// Error message to show @@ -35,20 +35,26 @@ // --- Main Menu --- if(MAIN_VIEW) var/list/found_machinery = list() - for(var/obj/machinery/telecomms/telecomms in machinelist) + for(var/datum/weakref/tcomms_ref in machine_list) + var/obj/machinery/telecomms/telecomms = tcomms_ref.resolve() + if(!telecomms) + machine_list -= tcomms_ref + continue found_machinery += list(list("ref" = REF(telecomms), "name" = telecomms.name, "id" = telecomms.id)) data["machinery"] = found_machinery // --- Viewing Machine --- if(MACHINE_VIEW) // Send selected machinery data var/list/machine_out = list() - machine_out["name"] = SelectedMachine.name - // Get the linked machinery - var/list/linked_machinery = list() - for(var/obj/machinery/telecomms/T in SelectedMachine.links) - linked_machinery += list(list("ref" = REF(T.id), "name" = T.name, "id" = T.id)) - machine_out["linked_machinery"] = linked_machinery - data["machine"] = machine_out + var/obj/machinery/telecomms/selected = selected_machine_ref.resolve() + if(selected) + machine_out["name"] = selected.name + // Get the linked machinery + var/list/linked_machinery = list() + for(var/obj/machinery/telecomms/T in selected.links) + linked_machinery += list(list("ref" = REF(T.id), "name" = T.name, "id" = T.id)) + machine_out["linked_machinery"] = linked_machinery + data["machine"] = machine_out return data /obj/machinery/computer/telecomms/monitor/ui_act(action, params) @@ -67,7 +73,9 @@ error_message = "OPERATION FAILED: NETWORK ID TOO LONG." return TRUE - if(machinelist.len > 0) + list_clear_empty_weakrefs(machine_list) + + if(machine_list.len > 0) error_message = "OPERATION FAILED: CANNOT PROBE WHEN BUFFER FULL." return TRUE @@ -75,26 +83,30 @@ for(var/obj/machinery/telecomms/T in urange(25, src)) if(T.network == network) - machinelist.Add(T) - if(machinelist.len == 0) + machine_list += WEAKREF(T) + if(machine_list.len == 0) error_message = "OPERATION FAILED: UNABLE TO LOCATE NETWORK ENTITIES IN [network]." return TRUE - error_message = "[machinelist.len] ENTITIES LOCATED & BUFFERED"; + error_message = "[machine_list.len] ENTITIES LOCATED & BUFFERED"; return TRUE if("flush_buffer") - machinelist = list() + machine_list = list() network = "" return TRUE if("view_machine") - for(var/obj/machinery/telecomms/T in machinelist) - if(T.id == params["id"]) - SelectedMachine = T - if(!SelectedMachine) + for(var/datum/weakref/tcomms_ref in machine_list) + var/obj/machinery/telecomms/tcomms = tcomms_ref.resolve() + if(!tcomms) + machine_list -= tcomms_ref + continue + if(tcomms.id == params["id"]) + selected_machine_ref = tcomms_ref + if(!selected_machine_ref) error_message = "OPERATION FAILED: UNABLE TO LOCATE MACHINERY." screen = MACHINE_VIEW return TRUE if("return_home") - SelectedMachine = null + selected_machine_ref = null screen = MAIN_VIEW return TRUE return TRUE diff --git a/code/game/objects/items/mail.dm b/code/game/objects/items/mail.dm index 9c82720a8e8..3c75a708f9c 100644 --- a/code/game/objects/items/mail.dm +++ b/code/game/objects/items/mail.dm @@ -450,9 +450,10 @@ var/list/mail_recipients_for_input = list("Anyone") var/list/used_names = list() for(var/datum/record/locked/person in sort_record(GLOB.manifest.locked)) - if(isnull(person.mind_ref)) + var/datum/mind/locked_mind = person.mind_ref.resolve() + if(isnull(locked_mind)) continue - mail_recipients += person.mind_ref + mail_recipients += locked_mind mail_recipients_for_input += avoid_assoc_duplicate_keys(person.name, used_names) var/recipient = tgui_input_list(user, "Choose a recipient", "Mail Counterfeiting", mail_recipients_for_input) diff --git a/code/modules/admin/verbs/admingame.dm b/code/modules/admin/verbs/admingame.dm index d8abd0ea5ad..8430fe76fe8 100644 --- a/code/modules/admin/verbs/admingame.dm +++ b/code/modules/admin/verbs/admingame.dm @@ -215,7 +215,7 @@ Traitors and the like can also be revived with the previous role mostly intact. new_character.real_name = record_found.name new_character.gender = lowertext(record_found.gender) new_character.age = record_found.age - var/datum/dna/found_dna = record_found.dna_ref + var/datum/dna/found_dna = record_found.locked_dna new_character.hardset_dna(found_dna.unique_identity, found_dna.mutation_index, null, record_found.name, record_found.blood_type, new record_found.species_type, found_dna.features) else new_character.randomize_human_appearance() diff --git a/code/modules/antagonists/traitor/objectives/abstract/target_player.dm b/code/modules/antagonists/traitor/objectives/abstract/target_player.dm index 76471eb244a..c08f8cd46ee 100644 --- a/code/modules/antagonists/traitor/objectives/abstract/target_player.dm +++ b/code/modules/antagonists/traitor/objectives/abstract/target_player.dm @@ -16,3 +16,18 @@ /// The target that we need to target. var/mob/living/target + +/datum/traitor_objective/target_player/Destroy(force) + set_target(null) + return ..() + +/datum/traitor_objective/target_player/proc/set_target(mob/living/new_target) + if(target) + UnregisterSignal(target, COMSIG_QDELETING) + target = new_target + if(target) + RegisterSignal(target, COMSIG_QDELETING, PROC_REF(target_deleted)) + +/datum/traitor_objective/target_player/proc/target_deleted(datum/source) + SIGNAL_HANDLER + set_target(null) diff --git a/code/modules/antagonists/traitor/objectives/assassination.dm b/code/modules/antagonists/traitor/objectives/assassination.dm index 4efcbb111be..ab3211aedd8 100644 --- a/code/modules/antagonists/traitor/objectives/assassination.dm +++ b/code/modules/antagonists/traitor/objectives/assassination.dm @@ -107,20 +107,13 @@ return //in their pockets please succeed_objective() -/datum/traitor_objective/target_player/assassinate/calling_card/generate_objective(datum/mind/generating_for, list/possible_duplicates) - . = ..() - if(!.) //didn't generate - return FALSE - RegisterSignal(target, COMSIG_QDELETING, PROC_REF(on_target_qdeleted)) - /datum/traitor_objective/target_player/assassinate/calling_card/ungenerate_objective() - UnregisterSignal(target, COMSIG_QDELETING) . = ..() //unsets kill target if(card) UnregisterSignal(card, COMSIG_ITEM_EQUIPPED) card = null -/datum/traitor_objective/target_player/assassinate/calling_card/on_target_qdeleted() +/datum/traitor_objective/target_player/assassinate/calling_card/target_deleted() //you cannot plant anything on someone who is gone gone, so even if this happens after you're still liable to fail fail_objective(penalty_cost = telecrystal_penalty) @@ -228,7 +221,7 @@ return FALSE //MISSION FAILED, WE'LL GET EM NEXT TIME var/datum/mind/target_mind = pick(possible_targets) - target = target_mind.current + set_target(target_mind.current) replace_in_name("%TARGET%", target.real_name) replace_in_name("%JOB TITLE%", target_mind.assigned_role.title) RegisterSignal(target, COMSIG_LIVING_DEATH, PROC_REF(on_target_death)) @@ -236,17 +229,17 @@ /datum/traitor_objective/target_player/assassinate/ungenerate_objective() UnregisterSignal(target, COMSIG_LIVING_DEATH) - target = null + set_target(null) ///proc for checking for special states that invalidate a target /datum/traitor_objective/target_player/assassinate/proc/special_target_filter(list/possible_targets) return -/datum/traitor_objective/target_player/assassinate/proc/on_target_qdeleted() - SIGNAL_HANDLER +/datum/traitor_objective/target_player/assassinate/target_deleted() if(objective_state == OBJECTIVE_STATE_INACTIVE) //don't take an objective target of someone who is already obliterated fail_objective() + return ..() /datum/traitor_objective/target_player/assassinate/proc/on_target_death() SIGNAL_HANDLER diff --git a/code/modules/antagonists/traitor/objectives/demoralise_assault.dm b/code/modules/antagonists/traitor/objectives/demoralise_assault.dm index 095c646cb99..fe26864e4fc 100644 --- a/code/modules/antagonists/traitor/objectives/demoralise_assault.dm +++ b/code/modules/antagonists/traitor/objectives/demoralise_assault.dm @@ -55,9 +55,7 @@ /datum/traitor_objective/target_player/assault/ungenerate_objective() UnregisterSignal(target, COMSIG_ATOM_WAS_ATTACKED) UnregisterSignal(target, COMSIG_LIVING_DEATH) - UnregisterSignal(target, COMSIG_QDELETING) - - target = null + set_target(null) /datum/traitor_objective/target_player/assault/generate_objective(datum/mind/generating_for, list/possible_duplicates) var/list/already_targeting = list() //List of minds we're already targeting. The possible_duplicates is a list of objectives, so let's not mix things @@ -102,7 +100,7 @@ var/datum/mind/target_mind = pick(possible_targets) - target = target_mind.current + set_target(target_mind.current) replace_in_name("%TARGET%", target.real_name) replace_in_name("%JOB TITLE%", target_mind.assigned_role.title) @@ -110,7 +108,6 @@ replace_in_name("%COUNT%", attacks_required) RegisterSignal(target, COMSIG_LIVING_DEATH, PROC_REF(on_target_death)) - RegisterSignal(target, COMSIG_QDELETING, PROC_REF(on_target_qdeleted)) return TRUE @@ -120,11 +117,10 @@ buttons += add_ui_button("[attacks_required - attacks_inflicted]", "This tells you how many more times you have to attack the target player to succeed.", "hand-rock-o", "none") return buttons -/datum/traitor_objective/target_player/assault/proc/on_target_qdeleted() - SIGNAL_HANDLER - +/datum/traitor_objective/target_player/assault/target_deleted() //don't take an objective target of someone who is already obliterated fail_objective() + return ..() /datum/traitor_objective/target_player/assault/proc/on_target_death() SIGNAL_HANDLER diff --git a/code/modules/antagonists/traitor/objectives/eyesnatching.dm b/code/modules/antagonists/traitor/objectives/eyesnatching.dm index 0540d83601c..4a307f8d8e0 100644 --- a/code/modules/antagonists/traitor/objectives/eyesnatching.dm +++ b/code/modules/antagonists/traitor/objectives/eyesnatching.dm @@ -102,7 +102,7 @@ return FALSE //MISSION FAILED, WE'LL GET EM NEXT TIME var/datum/mind/target_mind = pick(possible_targets) - target = target_mind.current + set_target(target_mind.current) replace_in_name("%TARGET%", target_mind.name) replace_in_name("%JOB TITLE%", target_mind.assigned_role.title) diff --git a/code/modules/antagonists/traitor/objectives/infect.dm b/code/modules/antagonists/traitor/objectives/infect.dm index 8dd5e5c7619..2671a615fa8 100644 --- a/code/modules/antagonists/traitor/objectives/infect.dm +++ b/code/modules/antagonists/traitor/objectives/infect.dm @@ -121,7 +121,7 @@ return FALSE //MISSION FAILED, WE'LL GET EM NEXT TIME var/datum/mind/target_mind = pick(possible_targets) - target = target_mind.current + set_target(target_mind.current) replace_in_name("%TARGET%", target.real_name) replace_in_name("%JOB TITLE%", target_mind.assigned_role.title) RegisterSignal(target, COMSIG_LIVING_DEATH, PROC_REF(on_target_death)) @@ -129,17 +129,17 @@ /datum/traitor_objective/target_player/infect/ungenerate_objective() UnregisterSignal(target, COMSIG_LIVING_DEATH) - target = null + set_target(null) ///proc for checking for special states that invalidate a target /datum/traitor_objective/target_player/infect/proc/special_target_filter(list/possible_targets) return -/datum/traitor_objective/target_player/infect/proc/on_target_qdeleted() - SIGNAL_HANDLER +/datum/traitor_objective/target_player/infect/target_deleted() if(objective_state == OBJECTIVE_STATE_INACTIVE) //don't take an objective target of someone who is already obliterated fail_objective() + return ..() /datum/traitor_objective/target_player/infect/proc/on_target_death() SIGNAL_HANDLER diff --git a/code/modules/antagonists/traitor/objectives/kidnapping.dm b/code/modules/antagonists/traitor/objectives/kidnapping.dm index 55d633ced94..4a463b2b616 100644 --- a/code/modules/antagonists/traitor/objectives/kidnapping.dm +++ b/code/modules/antagonists/traitor/objectives/kidnapping.dm @@ -13,7 +13,7 @@ var/pod_called = FALSE /// How much TC do we get from sending the target alive var/alive_bonus = 0 - /// All stripped targets belongings + /// All stripped targets belongings (weakrefs) var/list/target_belongings = list() duplicate_type = /datum/traitor_objective/target_player @@ -157,7 +157,7 @@ return FALSE var/datum/mind/target_mind = pick(possible_targets) - target = target_mind.current + set_target(target_mind.current) AddComponent(/datum/component/traitor_objective_register, target, fail_signals = list(COMSIG_QDELETING)) var/list/possible_areas = GLOB.the_station_areas.Copy() for(var/area/possible_area as anything in possible_areas) @@ -172,7 +172,7 @@ return TRUE /datum/traitor_objective/target_player/kidnapping/ungenerate_objective() - target = null + set_target(null) dropoff_area = null /datum/traitor_objective/target_player/kidnapping/on_objective_taken(mob/user) @@ -234,7 +234,7 @@ var/unequipped = sent_mob.transferItemToLoc(belonging) if (!unequipped) continue - target_belongings.Add(belonging) + target_belongings.Add(WEAKREF(belonging)) var/datum/bank_account/cargo_account = SSeconomy.get_dep_account(ACCOUNT_CAR) @@ -303,7 +303,10 @@ continue sent_mob.dropItemToGround(belonging) // No souvenirs, except shoes and t-shirts - for(var/obj/item/belonging in target_belongings) + for(var/datum/weakref/belonging_ref in target_belongings) + var/obj/item/belonging = belonging_ref.resolve() + if(!belonging) + continue belonging.forceMove(return_pod) sent_mob.forceMove(return_pod) diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm index bf785954fe7..7bd48ab62fb 100644 --- a/code/modules/mob/living/simple_animal/bot/bot.dm +++ b/code/modules/mob/living/simple_animal/bot/bot.dm @@ -104,8 +104,6 @@ var/reset_access_timer_id var/ignorelistcleanuptimer = 1 // This ticks up every automated action, at 300 we clean the ignore list - /// Component which allows ghosts to take over this bot - var/datum/component/ghost_direct_control/personality_download /// If true we will allow ghosts to control this mob var/can_be_possessed = FALSE /// If true we will offer this @@ -212,7 +210,6 @@ GLOB.bots_list -= src QDEL_NULL(paicard) QDEL_NULL(pa_system) - QDEL_NULL(personality_download) QDEL_NULL(internal_radio) QDEL_NULL(access_card) QDEL_NULL(path_hud) @@ -225,14 +222,14 @@ return can_be_possessed = TRUE var/can_announce = !mapload && COOLDOWN_FINISHED(src, offer_ghosts_cooldown) - personality_download = AddComponent(\ - /datum/component/ghost_direct_control,\ - ban_type = ROLE_BOT,\ - poll_candidates = can_announce,\ - poll_ignore_key = POLL_IGNORE_BOTS,\ - assumed_control_message = (bot_cover_flags & BOT_COVER_EMAGGED) ? get_emagged_message() : possessed_message,\ - extra_control_checks = CALLBACK(src, PROC_REF(check_possession)),\ - after_assumed_control = CALLBACK(src, PROC_REF(post_possession)),\ + AddComponent( + /datum/component/ghost_direct_control, \ + ban_type = ROLE_BOT, \ + poll_candidates = can_announce, \ + poll_ignore_key = POLL_IGNORE_BOTS, \ + assumed_control_message = (bot_cover_flags & BOT_COVER_EMAGGED) ? get_emagged_message() : possessed_message, \ + extra_control_checks = CALLBACK(src, PROC_REF(check_possession)), \ + after_assumed_control = CALLBACK(src, PROC_REF(post_possession)), \ ) if (can_announce) COOLDOWN_START(src, offer_ghosts_cooldown, 30 SECONDS) @@ -240,7 +237,7 @@ /// Disables this bot from being possessed by ghosts /mob/living/simple_animal/bot/proc/disable_possession(mob/user) can_be_possessed = FALSE - QDEL_NULL(personality_download) + qdel(GetComponent(/datum/component/ghost_direct_control)) if (isnull(key)) return if (user) 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 4cb4d97f38f..bf4d33a10ed 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 @@ -249,7 +249,8 @@ /obj/projectile/herald/teleshot/on_hit(atom/target, blocked = FALSE) . = ..() - firer.forceMove(get_turf(src)) + if(!QDELETED(firer)) + firer.forceMove(get_turf(src)) //Herald's loot: Cloak of the Prophet diff --git a/code/modules/mob/living/simple_animal/parrot.dm b/code/modules/mob/living/simple_animal/parrot.dm index d857a12c6cb..75950478edc 100644 --- a/code/modules/mob/living/simple_animal/parrot.dm +++ b/code/modules/mob/living/simple_animal/parrot.dm @@ -311,7 +311,7 @@ GLOBAL_LIST_INIT(strippable_parrot_items, create_strippable_list(list( if(parrot_state == PARROT_PERCH) parrot_sleep_dur = parrot_sleep_max //Reset it's sleep timer if it was perched - parrot_interest = user + set_parrot_interest(user) parrot_state = PARROT_SWOOP //The parrot just got hit, it WILL move, now to pick a direction.. if(health > 30) //Let's get in there and squawk it up! @@ -340,7 +340,7 @@ GLOBAL_LIST_INIT(strippable_parrot_items, create_strippable_list(list( parrot_sleep_dur = parrot_sleep_max //Reset it's sleep timer if it was perched if(user.melee_damage_upper > 0 && !stat) - parrot_interest = user + set_parrot_interest(user) parrot_state = PARROT_SWOOP | PARROT_ATTACK //Attack other animals regardless icon_state = icon_living @@ -351,7 +351,7 @@ GLOBAL_LIST_INIT(strippable_parrot_items, create_strippable_list(list( if(parrot_state == PARROT_PERCH) parrot_sleep_dur = parrot_sleep_max //Reset it's sleep timer if it was perched - parrot_interest = user + set_parrot_interest(user) parrot_state = PARROT_SWOOP if(health > 30) //Let's get in there and squawk it up! parrot_state |= PARROT_ATTACK @@ -376,7 +376,7 @@ GLOBAL_LIST_INIT(strippable_parrot_items, create_strippable_list(list( if(parrot_state == PARROT_PERCH) parrot_sleep_dur = parrot_sleep_max //Reset it's sleep timer if it was perched - parrot_interest = null + set_parrot_interest(null) parrot_state = PARROT_WANDER | PARROT_FLEE //Been shot and survived! RUN LIKE HELL! //parrot_been_shot += 5 icon_state = icon_living @@ -471,7 +471,7 @@ GLOBAL_LIST_INIT(strippable_parrot_items, create_strippable_list(list( speak = newspeak //Search for item to steal - parrot_interest = search_for_item() + set_parrot_interest(search_for_item()) if(parrot_interest) manual_emote("looks in [parrot_interest]'s direction and takes flight.") parrot_state = PARROT_SWOOP | PARROT_STEAL @@ -482,7 +482,7 @@ GLOBAL_LIST_INIT(strippable_parrot_items, create_strippable_list(list( else if(parrot_state == PARROT_WANDER) //Stop movement, we'll set it later SSmove_manager.stop_looping(src) - parrot_interest = null + set_parrot_interest(null) //Wander around aimlessly. This will help keep the loops from searches down //and possibly move the mob into a new are in view of something they can use @@ -494,7 +494,7 @@ GLOBAL_LIST_INIT(strippable_parrot_items, create_strippable_list(list( var/atom/movable/AM = search_for_perch_and_item() //This handles checking through lists so we know it's either a perch or stealable item if(AM) if(isitem(AM) || isliving(AM)) //If stealable item - parrot_interest = AM + set_parrot_interest(AM) manual_emote("turns and flies towards [parrot_interest].") parrot_state = PARROT_SWOOP | PARROT_STEAL return @@ -539,7 +539,7 @@ GLOBAL_LIST_INIT(strippable_parrot_items, create_strippable_list(list( parrot_interest.forceMove(src) visible_message(span_notice("[src] grabs [held_item]!"), span_notice("You grab [held_item]!"), span_hear("You hear the sounds of wings flapping furiously.")) - parrot_interest = null + set_parrot_interest(null) parrot_state = PARROT_SWOOP | PARROT_RETURN return @@ -587,7 +587,7 @@ GLOBAL_LIST_INIT(strippable_parrot_items, create_strippable_list(list( //If we're attacking a nothing, an object, a turf or a ghost for some stupid reason, switch to wander if(!parrot_interest || !isliving(parrot_interest)) - parrot_interest = null + set_parrot_interest(null) parrot_state = PARROT_WANDER return @@ -601,7 +601,7 @@ GLOBAL_LIST_INIT(strippable_parrot_items, create_strippable_list(list( //If the mob we've been chasing/attacking dies or falls into crit, check for loot! if(L.stat) - parrot_interest = null + set_parrot_interest(null) if(!held_item) held_item = steal_from_ground() if(!held_item) @@ -625,7 +625,7 @@ GLOBAL_LIST_INIT(strippable_parrot_items, create_strippable_list(list( //-----STATE MISHAP else //This should not happen. If it does lets reset everything and try again SSmove_manager.stop_looping(src) - parrot_interest = null + set_parrot_interest(null) parrot_perch = null drop_held_item() parrot_state = PARROT_WANDER @@ -635,6 +635,17 @@ GLOBAL_LIST_INIT(strippable_parrot_items, create_strippable_list(list( * Procs */ +/mob/living/simple_animal/parrot/proc/set_parrot_interest(atom/movable/shiny) + if(parrot_interest) + UnregisterSignal(parrot_interest, COMSIG_QDELETING) + parrot_interest = shiny + if(parrot_interest) + RegisterSignal(parrot_interest, COMSIG_QDELETING, PROC_REF(shiny_deleted)) + +/mob/living/simple_animal/parrot/proc/shiny_deleted(datum/source) + SIGNAL_HANDLER + set_parrot_interest(null) + /mob/living/simple_animal/parrot/proc/isStuck() //Check to see if the parrot is stuck due to things like windows or doors or windowdoors if(parrot_lastmove) @@ -1035,7 +1046,7 @@ GLOBAL_LIST_INIT(strippable_parrot_items, create_strippable_list(list( /mob/living/simple_animal/parrot/poly/ghost/handle_automated_movement() if(isliving(parrot_interest)) if(!ishuman(parrot_interest)) - parrot_interest = null + set_parrot_interest(null) else if(parrot_state == (PARROT_SWOOP | PARROT_ATTACK) && Adjacent(parrot_interest)) SSmove_manager.move_to(src, parrot_interest, 0, parrot_speed) Possess(parrot_interest) @@ -1048,7 +1059,7 @@ GLOBAL_LIST_INIT(strippable_parrot_items, create_strippable_list(list( P.parrot = src forceMove(H) H.ForceContractDisease(P, FALSE) - parrot_interest = null + set_parrot_interest(null) H.visible_message(span_danger("[src] dive bombs into [H]'s chest and vanishes!"), span_userdanger("[src] dive bombs into your chest, vanishing! This can't be good!")) #undef PARROT_PERCH diff --git a/code/modules/paperwork/filingcabinet.dm b/code/modules/paperwork/filingcabinet.dm index cb6aae768fa..ed99e7ea179 100644 --- a/code/modules/paperwork/filingcabinet.dm +++ b/code/modules/paperwork/filingcabinet.dm @@ -193,9 +193,9 @@ GLOBAL_LIST_EMPTY(employmentCabinets) /obj/structure/filingcabinet/employment/proc/fillCurrent() //This proc fills the cabinet with the current crew. for(var/datum/record/locked/target in GLOB.manifest.locked) - var/datum/mind/mind_ref = target.mind_ref - if(mind_ref && ishuman(mind_ref.current)) - addFile(mind_ref.current) + var/datum/mind/filed_mind = target.mind_ref.resolve() + if(filed_mind && ishuman(filed_mind.current)) + addFile(filed_mind.current) /obj/structure/filingcabinet/employment/proc/addFile(mob/living/carbon/human/employee) new /obj/item/paper/employment_contract(src, employee.mind.name)