diff --git a/code/datums/ai/_ai_controller.dm b/code/datums/ai/_ai_controller.dm index f75cdab46b8..0640b6472f9 100644 --- a/code/datums/ai/_ai_controller.dm +++ b/code/datums/ai/_ai_controller.dm @@ -7,6 +7,16 @@ multiple modular subtrees with behaviors /datum/ai_controller ///The atom this controller is controlling var/atom/pawn + /** + * This is a list of variables the AI uses and can be mutated by actions. + * + * When an action is performed you pass this list and any relevant keys for the variables it can mutate. + * + * DO NOT set values in the blackboard directly, and especially not if you're adding a datum reference to this! + * Use the setters, this is important for reference handing. + */ + var/list/blackboard = list() + ///Bitfield of traits for this AI to handle extra behavior var/ai_traits = NONE ///Current actions planned to be performed by the AI in the upcoming plan @@ -21,8 +31,6 @@ multiple modular subtrees with behaviors var/atom/current_movement_target ///Identifier for what last touched our movement target, so it can be cleared conditionally var/movement_target_source - ///This is a list of variables the AI uses and can be mutated by actions. When an action is performed you pass this list and any relevant keys for the variables it can mutate. - var/list/blackboard = list() ///Stored arguments for behaviors given during their initial creation var/list/behavior_args = list() ///Tracks recent pathing attempts, if we fail too many in a row we fail our current plans. @@ -336,3 +344,248 @@ multiple modular subtrees with behaviors if(iter_behavior.required_distance < minimum_distance) minimum_distance = iter_behavior.required_distance return minimum_distance + +/** + * Used to manage references to datum by AI controllers + * + * * tracked_datum - something being added to an ai blackboard + * * key - the associated key + */ +#define TRACK_AI_DATUM_TARGET(tracked_datum, key) do { \ + if(isweakref(tracked_datum)) { \ + var/datum/weakref/_bad_weakref = tracked_datum; \ + stack_trace("Weakref (Actual datum: [_bad_weakref.resolve()]) found in ai datum blackboard! \ + This is an outdated method of ai reference handling, please remove it."); \ + }; \ + else if(isdatum(tracked_datum)) { \ + var/datum/_tracked_datum = tracked_datum; \ + if(!HAS_TRAIT_FROM(_tracked_datum, TRAIT_AI_TRACKING, "[REF(src)]_[key]")) { \ + RegisterSignal(_tracked_datum, COMSIG_PARENT_QDELETING, PROC_REF(sig_remove_from_blackboard), override = TRUE); \ + ADD_TRAIT(_tracked_datum, TRAIT_AI_TRACKING, "[REF(src)]_[key]"); \ + }; \ + }; \ +} while(FALSE) + +/** + * Used to clear previously set reference handing by AI controllers + * + * * tracked_datum - something being removed from an ai blackboard + * * key - the associated key + */ +#define CLEAR_AI_DATUM_TARGET(tracked_datum, key) do { \ + if(isdatum(tracked_datum)) { \ + var/datum/_tracked_datum = tracked_datum; \ + REMOVE_TRAIT(_tracked_datum, TRAIT_AI_TRACKING, "[REF(src)]_[key]"); \ + if(!HAS_TRAIT(_tracked_datum, TRAIT_AI_TRACKING)) { \ + UnregisterSignal(_tracked_datum, COMSIG_PARENT_QDELETING); \ + }; \ + }; \ +} while(FALSE) + +/// Used for above to track all the keys that have registered a signal +#define TRAIT_AI_TRACKING "tracked_by_ai" + +/** + * Sets the key to the passed "thing". + * + * * key - A blackboard key + * * thing - a value to set the blackboard key to. + */ +/datum/ai_controller/proc/set_blackboard_key(key, thing) + // Assume it is an error when trying to set a value overtop a list + if(islist(blackboard[key])) + CRASH("set_blackboard_key attempting to set a blackboard value to key [key] when it's a list!") + + // Clear existing values + if(!isnull(blackboard[key])) + clear_blackboard_key(key) + + TRACK_AI_DATUM_TARGET(thing, key) + blackboard[key] = thing + +/** + * Sets the key at index thing to the passed value + * + * Assumes the key value is already a list, if not throws an error. + * + * * key - A blackboard key, with its value set to a list + * * thing - a value which becomes the inner list value's key + * * value - what to set the inner list's value to + */ +/datum/ai_controller/proc/set_blackboard_key_assoc(key, thing, value) + if(!islist(blackboard[key])) + CRASH("set_blackboard_key_assoc called on non-list key [key]!") + TRACK_AI_DATUM_TARGET(thing, key) + TRACK_AI_DATUM_TARGET(value, key) + blackboard[key][thing] = value + +/** + * Similar to [proc/set_blackboard_key_assoc] but operates under the assumption the key is a lazylist (so it will create a list) + * More dangerous / easier to override values, only use when you want to use a lazylist + * + * * key - A blackboard key, with its value set to a list + * * thing - a value which becomes the inner list value's key + * * value - what to set the inner list's value to + */ +/datum/ai_controller/proc/set_blackboard_key_assoc_lazylist(key, thing, value) + LAZYINITLIST(blackboard[key]) + TRACK_AI_DATUM_TARGET(thing, key) + TRACK_AI_DATUM_TARGET(value, key) + blackboard[key][thing] = value + +/** + * Adds the passed "thing" to the associated key + * + * Works with lists or numbers, but not lazylists. + * + * * key - A blackboard key + * * thing - a value to set the blackboard key to. + */ +/datum/ai_controller/proc/add_blackboard_key(key, thing) + TRACK_AI_DATUM_TARGET(thing, key) + blackboard[key] += thing + +/** + * Similar to [proc/add_blackboard_key], but performs an insertion rather than an add + * Throws an error if the key is not a list already, intended only for use with lists + * + * * key - A blackboard key, with its value set to a list + * * thing - a value to set the blackboard key to. + */ +/datum/ai_controller/proc/insert_blackboard_key(key, thing) + if(!islist(blackboard[key])) + CRASH("insert_blackboard_key called on non-list key [key]!") + TRACK_AI_DATUM_TARGET(thing, key) + blackboard[key] |= thing + +/** + * Adds the passed "thing" to the associated key, assuming key is intended to be a lazylist (so it will create a list) + * More dangerous / easier to override values, only use when you want to use a lazylist + * + * * key - A blackboard key + * * thing - a value to set the blackboard key to. + */ +/datum/ai_controller/proc/add_blackboard_key_lazylist(key, thing) + LAZYINITLIST(blackboard[key]) + TRACK_AI_DATUM_TARGET(thing, key) + blackboard[key] += thing + +/** + * Similar to [proc/insert_blackboard_key_lazylist], but performs an insertion / or rather than an add + * + * * key - A blackboard key + * * thing - a value to set the blackboard key to. + */ +/datum/ai_controller/proc/insert_blackboard_key_lazylist(key, thing) + LAZYINITLIST(blackboard[key]) + TRACK_AI_DATUM_TARGET(thing, key) + blackboard[key] |= thing + +/** + * Adds the value to the inner list at key with the inner key set to "thing" + * Throws an error if the key is not a list already, intended only for use with lists + * + * * key - A blackboard key, with its value set to a list + * * thing - a value which becomes the inner list value's key + * * value - what to set the inner list's value to + */ +/datum/ai_controller/proc/add_blackboard_key_assoc(key, thing, value) + if(!islist(blackboard[key])) + CRASH("add_blackboard_key_assoc called on non-list key [key]!") + TRACK_AI_DATUM_TARGET(thing, key) + TRACK_AI_DATUM_TARGET(value, key) + blackboard[key][thing] += value + + +/** + * Similar to [proc/add_blackboard_key_assoc], assuming key is intended to be a lazylist (so it will create a list) + * More dangerous / easier to override values, only use when you want to use a lazylist + * + * * key - A blackboard key, with its value set to a list + * * thing - a value which becomes the inner list value's key + * * value - what to set the inner list's value to + */ +/datum/ai_controller/proc/add_blackboard_key_assoc_lazylist(key, thing, value) + LAZYINITLIST(blackboard[key]) + TRACK_AI_DATUM_TARGET(thing, key) + TRACK_AI_DATUM_TARGET(value, key) + blackboard[key][thing] += value + +/** + * Clears the passed key, resetting it to null + * + * Not intended for use with list keys - use [proc/remove_thing_from_blackboard_key] if you are removing a value from a list at a key + * + * * key - A blackboard key + */ +/datum/ai_controller/proc/clear_blackboard_key(key) + CLEAR_AI_DATUM_TARGET(blackboard[key], key) + blackboard[key] = null + +/** + * Remove the passed thing from the associated blackboard key + * + * Intended for use with lists, if you're just clearing a reference from a key use [proc/clear_blackboard_key] + * + * * key - A blackboard key + * * thing - a value to set the blackboard key to. + */ +/datum/ai_controller/proc/remove_thing_from_blackboard_key(key, thing) + var/associated_value = blackboard[key] + if(thing == associated_value) + stack_trace("remove_thing_from_blackboard_key was called un-necessarily in a situation where clear_blackboard_key would suffice. ") + clear_blackboard_key(key) + return + + if(!islist(associated_value)) + CRASH("remove_thing_from_blackboard_key called with an invalid \"thing\" argument ([thing]). \ + (The associated value of the passed key is not a list and is also not the passed thing, meaning it is clearing an unintended value.)") + + for(var/inner_key in associated_value) + if(inner_key == thing) + // flat list + CLEAR_AI_DATUM_TARGET(thing, key) + associated_value -= thing + return + else if(associated_value[inner_key] == thing) + // assoc list + CLEAR_AI_DATUM_TARGET(thing, key) + associated_value -= inner_key + return + + CRASH("remove_thing_from_blackboard_key called with an invalid \"thing\" argument ([thing]). \ + (The passed value is not tracked in the passed list.)") + +/// Signal proc to go through every key and remove the datum from all keys it finds +/datum/ai_controller/proc/sig_remove_from_blackboard(datum/source) + SIGNAL_HANDLER + + var/list/list/remove_queue = list(blackboard) + var/index = 1 + while(index <= length(remove_queue)) + var/list/next_to_clear = remove_queue[index] + for(var/inner_value in next_to_clear) + var/associated_value = next_to_clear[inner_value] + // We are a lists of lists, add the next value to the queue so we can handle references in there + // (But we only need to bother checking the list if it's not empty.) + if(islist(inner_value) && length(inner_value)) + UNTYPED_LIST_ADD(remove_queue, inner_value) + + // We found the value that's been deleted. Clear it out from this list + else if(inner_value == source) + next_to_clear -= inner_value + + // We are an assoc lists of lists, the list at the next value so we can handle references in there + // (But again, we only need to bother checking the list if it's not empty.) + if(islist(associated_value) && length(associated_value)) + UNTYPED_LIST_ADD(remove_queue, associated_value) + + // We found the value that's been deleted, it was an assoc value. Clear it out entirely + else if(associated_value == source) + next_to_clear -= inner_value + + index += 1 + +#undef TRACK_AI_DATUM_TARGET +#undef CLEAR_AI_DATUM_TARGET +#undef TRAIT_AI_TRACKING diff --git a/code/datums/ai/_item_behaviors.dm b/code/datums/ai/_item_behaviors.dm index cfd55c05c49..6cfb539f7a0 100644 --- a/code/datums/ai/_item_behaviors.dm +++ b/code/datums/ai/_item_behaviors.dm @@ -24,8 +24,7 @@ /datum/ai_behavior/item_move_close_and_attack/setup(datum/ai_controller/controller, target_key, throw_count_key) . = ..() - var/datum/weakref/target_ref = controller.blackboard[target_key] - var/atom/target = target_ref?.resolve() + var/atom/target = controller.blackboard[target_key] if (isnull(target)) return FALSE set_movement_target(controller, target) @@ -33,13 +32,12 @@ /datum/ai_behavior/item_move_close_and_attack/perform(seconds_per_tick, datum/ai_controller/controller, target_key, throw_count_key) . = ..() var/obj/item/item_pawn = controller.pawn - var/datum/weakref/target_ref = controller.blackboard[target_key] - var/atom/throw_target = target_ref?.resolve() + var/atom/throw_target = controller.blackboard[target_key] item_pawn.visible_message(span_warning("[item_pawn] hurls towards [throw_target]!")) item_pawn.throw_at(throw_target, rand(4,5), 9) playsound(item_pawn.loc, attack_sound, 100, TRUE) - controller.blackboard[throw_count_key]++ + controller.add_blackboard_key(throw_count_key, 1) if(controller.blackboard[throw_count_key] >= max_attempts) finish_action(controller, TRUE, target_key, throw_count_key) @@ -48,8 +46,8 @@ reset_blackboard(controller, succeeded, target_key, throw_count_key) /datum/ai_behavior/item_move_close_and_attack/proc/reset_blackboard(datum/ai_controller/controller, succeeded, target_key, throw_count_key) - controller.blackboard -= target_key - controller.blackboard[throw_count_key] = 0 + controller.clear_blackboard_key(target_key) + controller.set_blackboard_key(throw_count_key, 0) /datum/ai_behavior/item_move_close_and_attack/ghostly attack_sound = 'sound/items/haunted/ghostitemattack.ogg' @@ -58,6 +56,5 @@ /datum/ai_behavior/item_move_close_and_attack/ghostly/haunted /datum/ai_behavior/item_move_close_and_attack/ghostly/haunted/finish_action(datum/ai_controller/controller, succeeded, target_key, throw_count_key) - var/datum/weakref/target_ref = controller.blackboard[target_key] - controller.blackboard[BB_TO_HAUNT_LIST][target_ref]-- + controller.add_blackboard_key_assoc(BB_TO_HAUNT_LIST, controller.blackboard[target_key], -1) return ..() diff --git a/code/datums/ai/babies/babies_behaviors.dm b/code/datums/ai/babies/babies_behaviors.dm index 569d271d675..aeb295ff220 100644 --- a/code/datums/ai/babies/babies_behaviors.dm +++ b/code/datums/ai/babies/babies_behaviors.dm @@ -37,7 +37,7 @@ return if(partner && children < max_children) - controller.blackboard[target_key] = WEAKREF(partner) + controller.set_blackboard_key(target_key, partner) finish_action(controller, TRUE) @@ -49,8 +49,7 @@ behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT /datum/ai_behavior/make_babies/setup(datum/ai_controller/controller, target_key, child_types_key) - var/datum/weakref/weak_target = controller.blackboard[target_key] - var/atom/target = weak_target?.resolve() + var/atom/target = controller.blackboard[target_key] if(!target) return FALSE set_movement_target(controller, target) @@ -58,8 +57,7 @@ /datum/ai_behavior/make_babies/perform(seconds_per_tick, datum/ai_controller/controller, target_key, child_types_key) . = ..() - var/datum/weakref/weak_target = controller.blackboard[target_key] - var/mob/target = weak_target?.resolve() + var/mob/target = controller.blackboard[target_key] if(!target || target.stat != CONSCIOUS) finish_action(controller, FALSE, target_key) return @@ -74,4 +72,4 @@ /datum/ai_behavior/make_babies/finish_action(datum/ai_controller/controller, succeeded, target_key) . = ..() - controller.blackboard -= target_key + controller.clear_blackboard_key(target_key) diff --git a/code/datums/ai/babies/babies_subtrees.dm b/code/datums/ai/babies/babies_subtrees.dm index 49db0181315..0c71b6d757b 100644 --- a/code/datums/ai/babies/babies_subtrees.dm +++ b/code/datums/ai/babies/babies_subtrees.dm @@ -20,15 +20,13 @@ if(is_type_in_list(controller.pawn, baby_types)) return - var/datum/weakref/weak_target = controller.blackboard[BB_BABIES_TARGET] - var/atom/target = weak_target?.resolve() + var/atom/target = controller.blackboard[BB_BABIES_TARGET] // Find target - if(!target || QDELETED(target)) + if(QDELETED(target)) controller.queue_behavior(/datum/ai_behavior/find_partner, BB_BABIES_TARGET, BB_BABIES_PARTNER_TYPES, BB_BABIES_CHILD_TYPES) return // Do target - if(target) - controller.queue_behavior(/datum/ai_behavior/make_babies, BB_BABIES_TARGET, BB_BABIES_CHILD_TYPES) - return SUBTREE_RETURN_FINISH_PLANNING + controller.queue_behavior(/datum/ai_behavior/make_babies, BB_BABIES_TARGET, BB_BABIES_CHILD_TYPES) + return SUBTREE_RETURN_FINISH_PLANNING diff --git a/code/datums/ai/bane/bane_behaviors.dm b/code/datums/ai/bane/bane_behaviors.dm index 93b1f278426..d36c110f0c3 100644 --- a/code/datums/ai/bane/bane_behaviors.dm +++ b/code/datums/ai/bane/bane_behaviors.dm @@ -1,6 +1,7 @@ -/datum/ai_behavior/break_spine/bane/finish_action(datum/ai_controller/controller, succeeded) - var/list/bane_quotes = strings("bane.json", "bane") - var/mob/living/bane = controller.pawn - bane.say(pick(bane_quotes)) - . = ..() +/datum/ai_behavior/break_spine/bane/finish_action(datum/ai_controller/controller, succeeded, target_key) + if(succeeded) + var/list/bane_quotes = strings("bane.json", "bane") + var/mob/living/bane = controller.pawn + bane.say(pick(bane_quotes)) + return ..() diff --git a/code/datums/ai/bane/bane_subtrees.dm b/code/datums/ai/bane/bane_subtrees.dm index b75df3004c9..e7f651737bf 100644 --- a/code/datums/ai/bane/bane_subtrees.dm +++ b/code/datums/ai/bane/bane_subtrees.dm @@ -1,13 +1,16 @@ ///The bat is broken! /datum/ai_planning_subtree/bane_hunting/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) var/mob/living/batman = controller.blackboard[BB_BANE_BATMAN] - if(!batman) + if(QDELETED(batman)) for(var/mob/living/possibly_the_dark_knight in oview(7, controller.pawn)) if(IS_DEAD_OR_INCAP(possibly_the_dark_knight)) //I HAVE BROKEN THE BAT continue - controller.blackboard[BB_BANE_BATMAN] = possibly_the_dark_knight + controller.set_blackboard_key(BB_BANE_BATMAN, possibly_the_dark_knight) batman = possibly_the_dark_knight break - if(batman) - controller.queue_behavior(/datum/ai_behavior/break_spine/bane, BB_BANE_BATMAN) - return SUBTREE_RETURN_FINISH_PLANNING + + if(isnull(batman)) + return + + controller.queue_behavior(/datum/ai_behavior/break_spine/bane, BB_BANE_BATMAN) + return SUBTREE_RETURN_FINISH_PLANNING diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/basic_attacking.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/basic_attacking.dm index 58f53e21a99..cfd53164bb2 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/basic_attacking.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/basic_attacking.dm @@ -4,22 +4,22 @@ /datum/ai_behavior/basic_melee_attack/setup(datum/ai_controller/controller, target_key, targetting_datum_key, hiding_location_key) . = ..() - //Hiding location is priority - var/datum/weakref/weak_target = controller.blackboard[hiding_location_key] || controller.blackboard[target_key] - var/atom/target = weak_target?.resolve() - if(!target) - return FALSE var/datum/targetting_datum/targetting_datum = controller.blackboard[targetting_datum_key] - if (!targetting_datum) - return + if(isnull(targetting_datum)) + CRASH("No target datum was supplied in the blackboard for [controller.pawn]") + + //Hiding location is priority + var/atom/target = controller.blackboard[hiding_location_key] || controller.blackboard[target_key] + if(QDELETED(target)) + return FALSE + set_movement_target(controller, target) /datum/ai_behavior/basic_melee_attack/perform(seconds_per_tick, datum/ai_controller/controller, target_key, targetting_datum_key, hiding_location_key) . = ..() var/mob/living/basic/basic_mob = controller.pawn //targetting datum will kill the action if not real anymore - var/datum/weakref/weak_target = controller.blackboard[target_key] - var/atom/target = weak_target?.resolve() + var/atom/target = controller.blackboard[target_key] var/datum/targetting_datum/targetting_datum = controller.blackboard[targetting_datum_key] if(!targetting_datum.can_attack(basic_mob, target)) @@ -28,7 +28,7 @@ var/hiding_target = targetting_datum.find_hidden_mobs(basic_mob, target) //If this is valid, theyre hidden in something! - controller.blackboard[hiding_location_key] = hiding_target + controller.set_blackboard_key(hiding_location_key, hiding_target) if(hiding_target) //Slap it! basic_mob.melee_attack(hiding_target) @@ -39,7 +39,7 @@ /datum/ai_behavior/basic_melee_attack/finish_action(datum/ai_controller/controller, succeeded, target_key, targetting_datum_key, hiding_location_key) . = ..() if(!succeeded) - controller.blackboard -= target_key + controller.clear_blackboard_key(target_key) /datum/ai_behavior/basic_melee_attack/average_speed action_cooldown = 1 SECONDS @@ -55,9 +55,8 @@ /datum/ai_behavior/basic_ranged_attack/setup(datum/ai_controller/controller, target_key, targetting_datum_key, hiding_location_key) . = ..() - var/datum/weakref/weak_target = controller.blackboard[hiding_location_key] || controller.blackboard[target_key] - var/atom/target = weak_target?.resolve() - if(!target) + var/atom/target = controller.blackboard[hiding_location_key] || controller.blackboard[target_key] + if(QDELETED(target)) return FALSE set_movement_target(controller, target) @@ -65,8 +64,7 @@ . = ..() var/mob/living/basic/basic_mob = controller.pawn //targetting datum will kill the action if not real anymore - var/datum/weakref/weak_target = controller.blackboard[target_key] - var/atom/target = weak_target?.resolve() + var/atom/target = controller.blackboard[target_key] var/datum/targetting_datum/targetting_datum = controller.blackboard[targetting_datum_key] if(!targetting_datum.can_attack(basic_mob, target)) @@ -80,7 +78,7 @@ finish_action(controller, FALSE, target_key) return - controller.blackboard[hiding_location_key] = WEAKREF(hiding_target) + controller.set_blackboard_key(hiding_location_key, hiding_target) if(shots>1) var/atom/burst_target = final_target @@ -94,4 +92,4 @@ /datum/ai_behavior/basic_ranged_attack/finish_action(datum/ai_controller/controller, succeeded, target_key, targetting_datum_key, hiding_location_key) . = ..() if(!succeeded) - controller.blackboard -= target_key + controller.clear_blackboard_key(target_key) diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/pick_up_item.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/pick_up_item.dm index 2d5dccea049..e81c9f95751 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/pick_up_item.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/pick_up_item.dm @@ -7,18 +7,16 @@ /datum/ai_behavior/pick_up_item/setup(datum/ai_controller/controller, target_key, storage_key) . = ..() - var/datum/weakref/weak_target = controller.blackboard[target_key] - var/obj/item/target = weak_target?.resolve() + var/obj/item/target = controller.blackboard[target_key] return isitem(target) && isturf(target.loc) && !target.anchored /datum/ai_behavior/pick_up_item/perform(seconds_per_tick, datum/ai_controller/controller, target_key, storage_key) . = ..() - var/datum/weakref/weak_target = controller.blackboard[target_key] - var/obj/item/target = weak_target?.resolve() - if(!isturf(target?.loc)) // Someone picked it up or it got deleted + var/obj/item/target = controller.blackboard[target_key] + if(QDELETED(target) || !isturf(target.loc)) // Someone picked it up or it got deleted finish_action(controller, FALSE, target_key) return - if(!in_range(controller.pawn, target)) // It teleported + if(!controller.pawn.Adjacent(target)) // It teleported finish_action(controller, FALSE, target_key) return pickup_item(controller, target, storage_key) @@ -26,22 +24,21 @@ /datum/ai_behavior/pick_up_item/finish_action(datum/ai_controller/controller, success, target_key, storage_key) . = ..() - controller.blackboard[target_key] = null + controller.clear_blackboard_key(target_key) /datum/ai_behavior/pick_up_item/proc/pickup_item(datum/ai_controller/controller, obj/item/target, storage_key) var/atom/pawn = controller.pawn drop_existing_item(controller, storage_key) pawn.visible_message(span_notice("[pawn] picks up [target].")) target.forceMove(pawn) - controller.blackboard[storage_key] = WEAKREF(target) + controller.set_blackboard_key(storage_key, target) return TRUE /datum/ai_behavior/pick_up_item/proc/drop_existing_item(datum/ai_controller/controller, storage_key) - var/datum/weakref/carried_ref = controller.blackboard[storage_key] - var/obj/item/carried_item = carried_ref?.resolve() + var/obj/item/carried_item = controller.blackboard[storage_key] if(!carried_item) return - controller.blackboard[storage_key] = null + controller.clear_blackboard_key(storage_key) var/atom/pawn = controller.pawn if(carried_item.loc != pawn) return diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/run_away_from_target.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/run_away_from_target.dm index 1a3f9abcc80..c082817f4fb 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/run_away_from_target.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/run_away_from_target.dm @@ -7,9 +7,8 @@ var/run_distance = 9 /datum/ai_behavior/run_away_from_target/setup(datum/ai_controller/controller, target_key, hiding_location_key) - var/datum/weakref/weak_target = controller.blackboard[hiding_location_key] || controller.blackboard[target_key] - var/atom/target = weak_target?.resolve() - if(!target) + var/atom/target = controller.blackboard[hiding_location_key] || controller.blackboard[target_key] + if(QDELETED(target)) return FALSE if(!plot_path_away_from(controller, target)) return FALSE @@ -17,9 +16,8 @@ /datum/ai_behavior/run_away_from_target/perform(seconds_per_tick, datum/ai_controller/controller, target_key, hiding_location_key) . = ..() - var/datum/weakref/weak_target = controller.blackboard[hiding_location_key] || controller.blackboard[target_key] - var/atom/target = weak_target?.resolve() - var/escaped = !target || !can_see(controller.pawn, target, run_distance) // If we can't see it we got away + var/atom/target = controller.blackboard[hiding_location_key] || controller.blackboard[target_key] + var/escaped = QDELETED(target) || !can_see(controller.pawn, target, run_distance) // If we can't see it we got away if (escaped) finish_action(controller, succeeded = TRUE, target_key = target_key, hiding_location_key = hiding_location_key) return @@ -43,4 +41,4 @@ /datum/ai_behavior/run_away_from_target/finish_action(datum/ai_controller/controller, succeeded, target_key, hiding_location_key) . = ..() - controller.blackboard[target_key] = null + controller.clear_blackboard_key(target_key) diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/step_towards_turf.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/step_towards_turf.dm index d82a0d17a05..f941b2eb95d 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/step_towards_turf.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/step_towards_turf.dm @@ -11,13 +11,12 @@ var/step_distance = 3 /datum/ai_behavior/step_towards_turf/setup(datum/ai_controller/controller, turf_key) - var/datum/weakref/weak_turf = controller.blackboard[turf_key] - var/turf/target_turf = weak_turf?.resolve() - if (!target_turf || target_turf.is_blocked_turf(exclude_mobs = TRUE)) + var/turf/target_turf = controller.blackboard[turf_key] + if (QDELETED(target_turf) || target_turf.is_blocked_turf(exclude_mobs = TRUE)) target_turf = find_destination_turf(args) if (!target_turf) return FALSE - controller.blackboard[turf_key] = WEAKREF(target_turf) + controller.set_blackboard_key(turf_key, target_turf) if (target_turf.z != controller.pawn.z) return FALSE diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/stop_and_stare.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/stop_and_stare.dm index 989837cf88d..cc02528262d 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/stop_and_stare.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/stop_and_stare.dm @@ -4,16 +4,14 @@ /datum/ai_behavior/stop_and_stare/setup(datum/ai_controller/controller, target_key) . = ..() - var/datum/weakref/weak_target = controller.blackboard[target_key] - var/atom/movable/target = weak_target?.resolve() + var/atom/movable/target = controller.blackboard[target_key] return ismovable(target) && isturf(target.loc) && ismob(controller.pawn) /datum/ai_behavior/stop_and_stare/perform(seconds_per_tick, datum/ai_controller/controller, target_key) // i don't really like doing this but we wanna make sure that the cooldown is pertinent to what we need for this specific controller before we invoke parent action_cooldown = controller.blackboard[BB_STATIONARY_COOLDOWN] . = ..() - var/datum/weakref/weak_target = controller.blackboard[target_key] - var/atom/movable/target = weak_target?.resolve() + var/atom/movable/target = controller.blackboard[target_key] if(!ismovable(target) || !isturf(target.loc)) // just to make sure that nothing funky happened between setup and perform return diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/targeted_mob_ability.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/targeted_mob_ability.dm index dc3b3a5ccaf..b737a8bcdd2 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/targeted_mob_ability.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/targeted_mob_ability.dm @@ -5,12 +5,9 @@ /datum/ai_behavior/targeted_mob_ability /datum/ai_behavior/targeted_mob_ability/perform(seconds_per_tick, datum/ai_controller/controller, ability_key, target_key) - var/datum/weakref/weak_ability = controller.blackboard[ability_key] - var/datum/action/cooldown/ability = weak_ability?.resolve() - - var/datum/weakref/weak_target = controller.blackboard[target_key] - var/mob/living/target = weak_target?.resolve() - if(!ability || QDELETED(target)) + var/datum/action/cooldown/ability = controller.blackboard[ability_key] + var/mob/living/target = controller.blackboard[target_key] + if(QDELETED(ability) || QDELETED(target)) finish_action(controller, FALSE, ability_key, target_key) return var/mob/pawn = controller.pawn @@ -19,16 +16,15 @@ /datum/ai_behavior/targeted_mob_ability/finish_action(datum/ai_controller/controller, succeeded, ability_key, target_key) . = ..() - var/datum/weakref/weak_target = controller.blackboard[target_key] - var/atom/target = weak_target?.resolve() + var/atom/target = controller.blackboard[target_key] if (QDELETED(target)) - controller.blackboard[target_key] = null + controller.clear_blackboard_key(target_key) return if (!isliving(target)) return var/mob/living/living_target = target if(living_target.stat >= UNCONSCIOUS) - controller.blackboard[target_key] = null + controller.clear_blackboard_key(target_key) /** * # Try Mob Ability and plan execute @@ -38,7 +34,7 @@ /datum/ai_behavior/targeted_mob_ability/and_plan_execute /datum/ai_behavior/targeted_mob_ability/and_plan_execute/finish_action(datum/ai_controller/controller, succeeded, ability_key, target_key) - controller.blackboard[BB_BASIC_MOB_EXECUTION_TARGET] = controller.blackboard[target_key] + controller.set_blackboard_key(BB_BASIC_MOB_EXECUTION_TARGET, controller.blackboard[target_key]) return ..() /** @@ -49,4 +45,4 @@ /datum/ai_behavior/targeted_mob_ability/and_clear_target/finish_action(datum/ai_controller/controller, succeeded, ability_key, target_key) . = ..() - controller.blackboard[target_key] = null + controller.clear_blackboard_key(target_key) diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/targetting.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/targetting.dm index ec6362cee31..a5dba85febc 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/targetting.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/targetting.dm @@ -13,13 +13,12 @@ if(!targetting_datum) CRASH("No target datum was supplied in the blackboard for [controller.pawn]") - var/datum/weakref/weak_target = controller.blackboard[target_key] - var/atom/current_target = weak_target?.resolve() + var/atom/current_target = controller.blackboard[target_key] if (targetting_datum.can_attack(living_mob, current_target)) finish_action(controller, succeeded = FALSE) return - controller.blackboard[target_key] = null + controller.clear_blackboard_key(target_key) var/list/potential_targets = hearers(vision_range, controller.pawn) - living_mob //Remove self, so we don't suicide for(var/HM in typecache_filter_list(range(vision_range, living_mob), hostile_machines)) //Can we see any hostile machines? @@ -42,12 +41,12 @@ return var/atom/target = pick_final_target(controller, filtered_targets) - controller.blackboard[target_key] = WEAKREF(target) + controller.set_blackboard_key(target_key, target) var/atom/potential_hiding_location = targetting_datum.find_hidden_mobs(living_mob, target) if(potential_hiding_location) //If they're hiding inside of something, we need to know so we can go for that instead initially. - controller.blackboard[hiding_location_key] = WEAKREF(potential_hiding_location) + controller.set_blackboard_key(hiding_location_key, potential_hiding_location) finish_action(controller, succeeded = TRUE) diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/tipped_reaction.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/tipped_reaction.dm index ff36fa4c415..643bb9ced5a 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/tipped_reaction.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/tipped_reaction.dm @@ -33,5 +33,5 @@ /datum/ai_behavior/tipped_reaction/finish_action(datum/ai_controller/controller, succeeded, tipper_key, reacting_key) . = ..() //I'VE SAID MY PEACE... - controller.blackboard[reacting_key] = FALSE - controller.blackboard[tipper_key] = null + controller.set_blackboard_key(reacting_key, FALSE) + controller.clear_blackboard_key(tipper_key) diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/travel_towards.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/travel_towards.dm index 058797e04fc..bbc1a43e322 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/travel_towards.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/travel_towards.dm @@ -9,9 +9,8 @@ /datum/ai_behavior/travel_towards/setup(datum/ai_controller/controller, target_key) . = ..() - var/datum/weakref/weak_target = controller.blackboard[target_key] - var/atom/target = weak_target?.resolve() - if(isnull(target)) + var/atom/target = controller.blackboard[target_key] + if(QDELETED(target)) return FALSE set_movement_target(controller, target) diff --git a/code/datums/ai/basic_mobs/basic_subtrees/attack_obstacle_in_path.dm b/code/datums/ai/basic_mobs/basic_subtrees/attack_obstacle_in_path.dm index 4df1fb38307..9f1053f29d3 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/attack_obstacle_in_path.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/attack_obstacle_in_path.dm @@ -7,10 +7,8 @@ /datum/ai_planning_subtree/attack_obstacle_in_path/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) . = ..() - var/datum/weakref/weak_target = controller.blackboard[target_key] - var/atom/target = weak_target?.resolve() - - if(isnull(target)) + var/atom/target = controller.blackboard[target_key] + if(QDELETED(target)) return var/turf/next_step = get_step_towards(controller.pawn, target) @@ -31,10 +29,9 @@ /datum/ai_behavior/attack_obstructions/perform(seconds_per_tick, datum/ai_controller/controller, target_key) . = ..() var/mob/living/basic/basic_mob = controller.pawn - var/datum/weakref/weak_target = controller.blackboard[target_key] - var/atom/target = weak_target?.resolve() + var/atom/target = controller.blackboard[target_key] - if (!target) + if (QDELETED(target)) finish_action(controller, succeeded = FALSE) return diff --git a/code/datums/ai/basic_mobs/basic_subtrees/find_food.dm b/code/datums/ai/basic_mobs/basic_subtrees/find_food.dm index ac03aee7154..8d20df7b9c7 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/find_food.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/find_food.dm @@ -1,10 +1,11 @@ -/// similar to finding a target but looks for food types in the +/// similar to finding a target but looks for food types in the // the what? /datum/ai_planning_subtree/find_food /datum/ai_planning_subtree/find_food/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) . = ..() var/atom/target = controller.blackboard[BB_BASIC_MOB_CURRENT_TARGET] - if(target && !QDELETED(target)) + if(!QDELETED(target)) + // Busy with something return - var/list/wanted = controller.blackboard[BB_BASIC_FOODS] - controller.queue_behavior(/datum/ai_behavior/find_and_set/in_list, BB_BASIC_MOB_CURRENT_TARGET, wanted) + + controller.queue_behavior(/datum/ai_behavior/find_and_set/in_list, BB_BASIC_MOB_CURRENT_TARGET, controller.blackboard[BB_BASIC_FOODS]) diff --git a/code/datums/ai/basic_mobs/basic_subtrees/flee_target.dm b/code/datums/ai/basic_mobs/basic_subtrees/flee_target.dm index 8490f0dd1c0..6ae7885618b 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/flee_target.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/flee_target.dm @@ -11,9 +11,8 @@ . = ..() if (!controller.blackboard[BB_BASIC_MOB_FLEEING]) return - var/datum/weakref/weak_target = controller.blackboard[target_key] - var/atom/target = weak_target?.resolve() - if(!target || QDELETED(target)) + var/atom/target = controller.blackboard[target_key] + if(QDELETED(target)) return controller.queue_behavior(flee_behaviour, target_key, hiding_place_key) return SUBTREE_RETURN_FINISH_PLANNING //we gotta get out of here. diff --git a/code/datums/ai/basic_mobs/basic_subtrees/simple_attack_target.dm b/code/datums/ai/basic_mobs/basic_subtrees/simple_attack_target.dm index 5489d7c1545..5db0486a43a 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/simple_attack_target.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/simple_attack_target.dm @@ -3,10 +3,8 @@ /datum/ai_planning_subtree/basic_melee_attack_subtree/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) . = ..() - var/datum/weakref/weak_target = controller.blackboard[BB_BASIC_MOB_CURRENT_TARGET] - var/atom/target = weak_target?.resolve() - - if(!target || QDELETED(target)) + var/atom/target = controller.blackboard[BB_BASIC_MOB_CURRENT_TARGET] + if(QDELETED(target)) return controller.queue_behavior(melee_attack_behavior, BB_BASIC_MOB_CURRENT_TARGET, BB_TARGETTING_DATUM, BB_BASIC_MOB_CURRENT_TARGET_HIDING_LOCATION) return SUBTREE_RETURN_FINISH_PLANNING //we are going into battle...no distractions. @@ -20,9 +18,8 @@ /datum/ai_planning_subtree/basic_ranged_attack_subtree/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) . = ..() - var/datum/weakref/weak_target = controller.blackboard[BB_BASIC_MOB_CURRENT_TARGET] - var/atom/target = weak_target?.resolve() - if(!target || QDELETED(target)) + var/atom/target = controller.blackboard[BB_BASIC_MOB_CURRENT_TARGET] + if(QDELETED(target)) return controller.queue_behavior(ranged_attack_behavior, BB_BASIC_MOB_CURRENT_TARGET, BB_TARGETTING_DATUM, BB_BASIC_MOB_CURRENT_TARGET_HIDING_LOCATION) return SUBTREE_RETURN_FINISH_PLANNING //we are going into battle...no distractions. diff --git a/code/datums/ai/basic_mobs/basic_subtrees/sleep_with_no_target.dm b/code/datums/ai/basic_mobs/basic_subtrees/sleep_with_no_target.dm index de04c7e224d..ccd67d6d1e7 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/sleep_with_no_target.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/sleep_with_no_target.dm @@ -15,16 +15,15 @@ var/time_to_wait = 10 /datum/ai_behavior/sleep_after_targetless_time/perform(seconds_per_tick, datum/ai_controller/controller, target_key) - var/datum/weakref/weak_target = controller.blackboard[target_key] - var/atom/target = weak_target?.resolve() + var/atom/target = controller.blackboard[target_key] finish_action(controller, succeeded = !target, seconds_per_tick = seconds_per_tick) /datum/ai_behavior/sleep_after_targetless_time/finish_action(datum/ai_controller/controller, succeeded, seconds_per_tick) . = ..() if (!succeeded) - controller.blackboard[BB_TARGETLESS_TIME] = 0 + controller.set_blackboard_key(BB_TARGETLESS_TIME, 0) return - controller.blackboard[BB_TARGETLESS_TIME] += seconds_per_tick + controller.add_blackboard_key(BB_TARGETLESS_TIME, seconds_per_tick) if (controller.blackboard[BB_TARGETLESS_TIME] > time_to_wait) enter_sleep(controller) diff --git a/code/datums/ai/basic_mobs/basic_subtrees/stare_at_thing.dm b/code/datums/ai/basic_mobs/basic_subtrees/stare_at_thing.dm index 1beb70f710c..5263c8f82c6 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/stare_at_thing.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/stare_at_thing.dm @@ -2,8 +2,7 @@ /datum/ai_planning_subtree/stare_at_thing /datum/ai_planning_subtree/stare_at_thing/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) - var/datum/weakref/weak_target = controller.blackboard[BB_STATIONARY_CAUSE] - var/atom/target = weak_target?.resolve() + var/atom/target = controller.blackboard[BB_STATIONARY_CAUSE] if(isnull(target)) // No target? Time to locate one using the list we set in this mob's blackboard. var/list/potential_scares = controller.blackboard[BB_STATIONARY_TARGETS] @@ -11,4 +10,3 @@ return controller.queue_behavior(/datum/ai_behavior/stop_and_stare, BB_STATIONARY_CAUSE) - diff --git a/code/datums/ai/basic_mobs/basic_subtrees/target_retaliate.dm b/code/datums/ai/basic_mobs/basic_subtrees/target_retaliate.dm index 8e5e922820c..ccb740c9980 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/target_retaliate.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/target_retaliate.dm @@ -35,36 +35,22 @@ if(!targetting_datum) CRASH("No target datum was supplied in the blackboard for [controller.pawn]") - var/list/enemy_refs = controller.blackboard[shitlist_key] - if (!length(enemy_refs)) - finish_action(controller, succeeded = FALSE) - return - - var/list/enemies_list = list() - for (var/datum/weakref/enemy_ref as anything in enemy_refs) - var/atom/enemy = enemy_ref.resolve() - if (!can_attack_target(living_mob, enemy, targetting_datum)) - controller.blackboard[shitlist_key] -= enemy_ref - continue - enemies_list += enemy - + var/list/enemies_list = controller.blackboard[shitlist_key] if (!length(enemies_list)) finish_action(controller, succeeded = FALSE) return - var/datum/weakref/weak_target = controller.blackboard[target_key] - var/atom/target = weak_target?.resolve() - if (target && (locate(target) in enemies_list)) // Don't bother changing + if (controller.blackboard[target_key] in enemies_list) // Don't bother changing finish_action(controller, succeeded = FALSE) return var/atom/new_target = pick_final_target(controller, enemies_list) - controller.blackboard[target_key] = WEAKREF(new_target) + controller.set_blackboard_key(target_key, new_target) var/atom/potential_hiding_location = targetting_datum.find_hidden_mobs(living_mob, new_target) if(potential_hiding_location) //If they're hiding inside of something, we need to know so we can go for that instead initially. - controller.blackboard[hiding_location_key] = WEAKREF(potential_hiding_location) + controller.set_blackboard_key(hiding_location_key, potential_hiding_location) finish_action(controller, succeeded = TRUE) diff --git a/code/datums/ai/basic_mobs/basic_subtrees/targeted_mob_ability.dm b/code/datums/ai/basic_mobs/basic_subtrees/targeted_mob_ability.dm index 67ca10b4c28..0f53d53b618 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/targeted_mob_ability.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/targeted_mob_ability.dm @@ -13,14 +13,9 @@ if (!ability_key) CRASH("You forgot to tell this mob where to find its ability") - var/datum/weakref/weak_target = controller.blackboard[target_key] - var/mob/living/target = weak_target?.resolve() - if (QDELETED(target)) - return - - var/datum/weakref/weak_ability = controller.blackboard[ability_key] - var/datum/action/cooldown/using_action = weak_ability?.resolve() - if (!using_action || !using_action.IsAvailable()) + var/mob/living/target = controller.blackboard[target_key] + var/datum/action/cooldown/using_action = controller.blackboard[ability_key] + if (QDELETED(target) || QDELETED(using_action) || !using_action.IsAvailable()) return controller.queue_behavior(use_ability_behaviour, ability_key, target_key) diff --git a/code/datums/ai/basic_mobs/basic_subtrees/use_mob_ability.dm b/code/datums/ai/basic_mobs/basic_subtrees/use_mob_ability.dm index a94e7dc2b32..2c618e98e72 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/use_mob_ability.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/use_mob_ability.dm @@ -14,9 +14,8 @@ if (!ability_key) CRASH("You forgot to tell this mob where to find its ability") - var/datum/weakref/weak_ability = controller.blackboard[ability_key] - var/datum/action/cooldown/using_action = weak_ability?.resolve() - if (!using_action || !using_action.IsAvailable()) + var/datum/action/cooldown/using_action = controller.blackboard[ability_key] + if (QDELETED(using_action) || !using_action.IsAvailable()) return controller.queue_behavior(use_ability_behaviour, ability_key) @@ -26,9 +25,8 @@ /datum/ai_behavior/use_mob_ability /datum/ai_behavior/use_mob_ability/perform(seconds_per_tick, datum/ai_controller/controller, ability_key) - var/datum/weakref/weak_ability = controller.blackboard[ability_key] - var/datum/action/cooldown/using_action = weak_ability?.resolve() - if (!using_action) + var/datum/action/cooldown/using_action = controller.blackboard[ability_key] + if (QDELETED(using_action)) finish_action(controller, FALSE, ability_key) return var/result = using_action.Trigger() diff --git a/code/datums/ai/basic_mobs/pet_commands/fetch.dm b/code/datums/ai/basic_mobs/pet_commands/fetch.dm index 5f697170b20..ce018b55f7e 100644 --- a/code/datums/ai/basic_mobs/pet_commands/fetch.dm +++ b/code/datums/ai/basic_mobs/pet_commands/fetch.dm @@ -7,21 +7,18 @@ /datum/ai_behavior/fetch_seek/setup(datum/ai_controller/controller, target_key, delivery_key) . = ..() - var/datum/weakref/thing_ref = controller.blackboard[target_key] - var/obj/item/fetch_thing = thing_ref?.resolve() - + var/obj/item/fetch_thing = controller.blackboard[target_key] // It stopped existing - if (!fetch_thing) + if (QDELETED(fetch_thing)) return FALSE set_movement_target(controller, fetch_thing) /datum/ai_behavior/fetch_seek/perform(seconds_per_tick, datum/ai_controller/controller, target_key, delivery_key) . = ..() - var/datum/weakref/thing_ref = controller.blackboard[target_key] - var/obj/item/fetch_thing = thing_ref?.resolve() + var/obj/item/fetch_thing = controller.blackboard[target_key] // It stopped existing - if (!fetch_thing) + if (QDELETED(fetch_thing)) finish_action(controller, FALSE, target_key, delivery_key) return var/mob/living/living_pawn = controller.pawn @@ -37,12 +34,11 @@ if (success) return // Blacklist item if we failed - var/datum/weakref/thing_ref = controller.blackboard[target_key] - var/obj/item/target = thing_ref?.resolve() + var/obj/item/target = controller.blackboard[target_key] if (target) - controller.blackboard[BB_FETCH_IGNORE_LIST][thing_ref] = TRUE - controller.blackboard[target_key] = null - controller.blackboard[delivery_key] = null + controller.set_blackboard_key_assoc_lazylist(BB_FETCH_IGNORE_LIST, target, TRUE) + controller.clear_blackboard_key(target_key) + controller.clear_blackboard_key(delivery_key) /** * The second half of fetching, deliver the item to a target. @@ -52,17 +48,15 @@ /datum/ai_behavior/deliver_fetched_item/setup(datum/ai_controller/controller, delivery_key, storage_key) . = ..() - var/datum/weakref/return_ref = controller.blackboard[delivery_key] - var/mob/living/return_target = return_ref?.resolve() - if(!return_target) // Guess it's mine now + var/mob/living/return_target = controller.blackboard[delivery_key] + if(QDELETED(return_target)) // Guess it's mine now return FALSE set_movement_target(controller, return_target) /datum/ai_behavior/deliver_fetched_item/perform(seconds_per_tick, datum/ai_controller/controller, delivery_key, storage_key) . = ..() - var/datum/weakref/return_ref = controller.blackboard[delivery_key] - var/mob/living/return_target = return_ref?.resolve() - if(!return_target) + var/mob/living/return_target = controller.blackboard[delivery_key] + if(QDELETED(return_target)) finish_action(controller, FALSE, delivery_key) return @@ -71,22 +65,21 @@ /datum/ai_behavior/deliver_fetched_item/finish_action(datum/ai_controller/controller, success, delivery_key) . = ..() - controller.blackboard[delivery_key] = null - controller.blackboard[BB_ACTIVE_PET_COMMAND] = null + controller.clear_blackboard_key(delivery_key) + controller.clear_blackboard_key(BB_ACTIVE_PET_COMMAND) /// Actually deliver the fetched item to the target, if we still have it /datum/ai_behavior/deliver_fetched_item/proc/deliver_item(datum/ai_controller/controller, return_target, storage_key) var/mob/pawn = controller.pawn - var/datum/weakref/carried_ref = controller.blackboard[storage_key] - var/obj/item/carried_item = carried_ref?.resolve() - if(!carried_item || carried_item.loc != pawn) + var/obj/item/carried_item = controller.blackboard[storage_key] + if(QDELETED(carried_item) || carried_item.loc != pawn) pawn.visible_message(span_notice("[pawn] looks around as if [pawn.p_they()] [pawn.p_have()] lost something.")) finish_action(controller, FALSE) return pawn.visible_message(span_notice("[pawn] delivers [carried_item] to [return_target].")) carried_item.forceMove(get_turf(return_target)) - controller.blackboard[storage_key] = null + controller.clear_blackboard_key(storage_key) return TRUE /** @@ -101,19 +94,15 @@ /datum/ai_behavior/eat_fetched_snack/setup(datum/ai_controller/controller, target_key, delivery_key) . = ..() - var/datum/weakref/thing_ref = controller.blackboard[target_key] - var/obj/item/snack = thing_ref?.resolve() - + var/obj/item/snack = controller.blackboard[target_key] if(!istype(snack) || !IS_EDIBLE(snack) || !(isturf(snack.loc) || ishuman(snack.loc))) return FALSE // This isn't food at all! set_movement_target(controller, snack) /datum/ai_behavior/eat_fetched_snack/perform(seconds_per_tick, datum/ai_controller/controller, target_key, delivery_key) . = ..() - var/datum/weakref/thing_ref = controller.blackboard[target_key] - var/obj/item/snack = thing_ref?.resolve() - - if(!(isturf(snack.loc) || ishuman(snack.loc))) + var/obj/item/snack = controller.blackboard[target_key] + if(QDELETED(snack) || !isturf(snack.loc) || ishuman(snack.loc)) finish_action(controller, FALSE) // Where did it go? var/mob/living/basic/basic_pawn = controller.pawn @@ -130,9 +119,9 @@ /datum/ai_behavior/eat_fetched_snack/finish_action(datum/ai_controller/controller, succeeded, target_key, delivery_key) . = ..() - controller.blackboard[target_key] = null - controller.blackboard[delivery_key] = null - controller.blackboard[BB_ACTIVE_PET_COMMAND] = null + controller.clear_blackboard_key(target_key) + controller.clear_blackboard_key(delivery_key) + controller.clear_blackboard_key(BB_ACTIVE_PET_COMMAND) /** * Clear our failed fetch list every so often @@ -153,5 +142,5 @@ /datum/ai_behavior/forget_failed_fetches/perform(seconds_per_tick, datum/ai_controller/controller) . = ..() COOLDOWN_START(src, reset_ignore_cooldown, cooldown_duration) - controller.blackboard[BB_FETCH_IGNORE_LIST] = list() + controller.clear_blackboard_key(BB_FETCH_IGNORE_LIST) finish_action(controller, TRUE) diff --git a/code/datums/ai/basic_mobs/pet_commands/pet_command_planning.dm b/code/datums/ai/basic_mobs/pet_commands/pet_command_planning.dm index caa4073b699..bf4885b817b 100644 --- a/code/datums/ai/basic_mobs/pet_commands/pet_command_planning.dm +++ b/code/datums/ai/basic_mobs/pet_commands/pet_command_planning.dm @@ -8,8 +8,7 @@ /datum/ai_planning_subtree/pet_planning /datum/ai_planning_subtree/pet_planning/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) - var/datum/weakref/weak_command = controller.blackboard[BB_ACTIVE_PET_COMMAND] - var/datum/pet_command/command = weak_command?.resolve() + var/datum/pet_command/command = controller.blackboard[BB_ACTIVE_PET_COMMAND] if (!command) return // Do something else return command.execute_action(controller) diff --git a/code/datums/ai/basic_mobs/pet_commands/pet_follow_friend.dm b/code/datums/ai/basic_mobs/pet_commands/pet_follow_friend.dm index 59d3aaad79a..397021818aa 100644 --- a/code/datums/ai/basic_mobs/pet_commands/pet_follow_friend.dm +++ b/code/datums/ai/basic_mobs/pet_commands/pet_follow_friend.dm @@ -4,16 +4,14 @@ /datum/ai_behavior/pet_follow_friend/setup(datum/ai_controller/controller, target_key) . = ..() - var/datum/weakref/weak_target = controller.blackboard[target_key] - var/atom/target = weak_target?.resolve() - if (!target) + var/atom/target = controller.blackboard[target_key] + if (QDELETED(target)) return FALSE set_movement_target(controller, target) /datum/ai_behavior/pet_follow_friend/perform(seconds_per_tick, datum/ai_controller/controller, target_key) . = ..() - var/datum/weakref/weak_target = controller.blackboard[target_key] - var/atom/target = weak_target?.resolve() - if (!target) + var/atom/target = controller.blackboard[target_key] + if (QDELETED(target)) finish_action(controller, FALSE, target_key) return diff --git a/code/datums/ai/basic_mobs/pet_commands/pet_use_targetted_ability.dm b/code/datums/ai/basic_mobs/pet_commands/pet_use_targetted_ability.dm index f86f0a481fc..584fb984839 100644 --- a/code/datums/ai/basic_mobs/pet_commands/pet_use_targetted_ability.dm +++ b/code/datums/ai/basic_mobs/pet_commands/pet_use_targetted_ability.dm @@ -4,17 +4,15 @@ /datum/ai_behavior/pet_use_ability/setup(datum/ai_controller/controller, ability_key, target_key) . = ..() - var/datum/weakref/weak_target = controller.blackboard[target_key] - var/mob/living/target = weak_target?.resolve() + var/mob/living/target = controller.blackboard[target_key] if (QDELETED(target)) return FALSE set_movement_target(controller, target) /datum/ai_behavior/pet_use_ability/perform(seconds_per_tick, datum/ai_controller/controller, ability_key, target_key) var/datum/action/cooldown/mob_cooldown/ability = controller.blackboard[ability_key] - var/datum/weakref/weak_target = controller.blackboard[target_key] - var/mob/living/target = weak_target?.resolve() - if (!ability || QDELETED(target)) + var/mob/living/target = controller.blackboard[target_key] + if (QDELETED(ability) || QDELETED(target)) finish_action(controller, FALSE, ability_key, target_key) return var/mob/pawn = controller.pawn @@ -23,4 +21,4 @@ /datum/ai_behavior/pet_use_ability/finish_action(datum/ai_controller/controller, succeeded, ability_key, target_key) . = ..() - controller.blackboard[target_key] = null + controller.clear_blackboard_key(target_key) diff --git a/code/datums/ai/basic_mobs/pet_commands/play_dead.dm b/code/datums/ai/basic_mobs/pet_commands/play_dead.dm index d788402de7f..a84310cb9ab 100644 --- a/code/datums/ai/basic_mobs/pet_commands/play_dead.dm +++ b/code/datums/ai/basic_mobs/pet_commands/play_dead.dm @@ -21,4 +21,4 @@ return basic_pawn.visible_message(span_notice("[basic_pawn] miraculously springs back to life!")) basic_pawn.look_alive() - controller.blackboard[BB_ACTIVE_PET_COMMAND] = null + controller.clear_blackboard_key(BB_ACTIVE_PET_COMMAND) diff --git a/code/datums/ai/basic_mobs/targetting_datums/dont_target_friends.dm b/code/datums/ai/basic_mobs/targetting_datums/dont_target_friends.dm index d7985ab9d62..8e6c79fda3f 100644 --- a/code/datums/ai/basic_mobs/targetting_datums/dont_target_friends.dm +++ b/code/datums/ai/basic_mobs/targetting_datums/dont_target_friends.dm @@ -30,11 +30,10 @@ if (!living_mob.ai_controller) // How did you get here? return FALSE - var/list/friends_list = living_mob.ai_controller.blackboard[BB_FRIENDS_LIST] - if (!friends_list) - return TRUE // We don't have any friends, anything's fair game - if (!friends_list[WEAKREF(target)]) - return TRUE // This is not our friend, fire at will + if (!(target in living_mob.ai_controller.blackboard[BB_FRIENDS_LIST])) + // We don't have any friends, anything's fair game + // OR This is not our friend, fire at will + return TRUE return FALSE diff --git a/code/datums/ai/cursed/cursed_behaviors.dm b/code/datums/ai/cursed/cursed_behaviors.dm index be04d534c92..63e7310f968 100644 --- a/code/datums/ai/cursed/cursed_behaviors.dm +++ b/code/datums/ai/cursed/cursed_behaviors.dm @@ -1,8 +1,7 @@ /datum/ai_behavior/item_move_close_and_attack/ghostly/cursed /datum/ai_behavior/item_move_close_and_attack/ghostly/cursed/reset_blackboard(datum/ai_controller/controller, succeeded, target_key, throw_count_key) - var/datum/weakref/target_ref = controller.blackboard[target_key] - var/atom/throw_target = target_ref?.resolve() + var/atom/throw_target = controller.blackboard[target_key] //dropping our target from the blackboard if they are no longer a valid target after the attack behavior if(get_dist(throw_target, controller.pawn) > CURSED_VIEW_RANGE) - controller.blackboard[target_key] = null + controller.clear_blackboard_key(target_key) diff --git a/code/datums/ai/cursed/cursed_subtrees.dm b/code/datums/ai/cursed/cursed_subtrees.dm index b9edac290f3..dd33312900a 100644 --- a/code/datums/ai/cursed/cursed_subtrees.dm +++ b/code/datums/ai/cursed/cursed_subtrees.dm @@ -2,13 +2,12 @@ var/obj/item/item_pawn = controller.pawn //make sure we have a target - var/datum/weakref/target_ref = controller.blackboard[BB_CURSE_TARGET] - var/mob/living/carbon/curse_target = target_ref?.resolve() + var/mob/living/carbon/curse_target = controller.blackboard[BB_CURSE_TARGET] if(!curse_target) controller.queue_behavior(/datum/ai_behavior/find_and_set, BB_CURSE_TARGET, /mob/living/carbon, CURSED_VIEW_RANGE) return //make sure attack is valid if(get_dist(curse_target, item_pawn) > CURSED_VIEW_RANGE) - controller.blackboard[BB_CURSE_TARGET] = null + controller.clear_blackboard_key(BB_CURSE_TARGET) return controller.queue_behavior(/datum/ai_behavior/item_move_close_and_attack/ghostly/cursed, BB_CURSE_TARGET) diff --git a/code/datums/ai/dog/dog_behaviors.dm b/code/datums/ai/dog/dog_behaviors.dm index 5c6a81a2676..2f6ae2d9720 100644 --- a/code/datums/ai/dog/dog_behaviors.dm +++ b/code/datums/ai/dog/dog_behaviors.dm @@ -16,8 +16,7 @@ return // Unfortunately going to repeat this check in parent call but what can you do - var/datum/weakref/weak_target = controller.blackboard[target_key] - var/atom/target = weak_target?.resolve() + var/atom/target = controller.blackboard[target_key] var/datum/targetting_datum/targetting_datum = controller.blackboard[targetting_datum_key] if (!targetting_datum.can_attack(living_pawn, target)) finish_action(controller, FALSE, target_key, targetting_datum_key, hiding_location_key) diff --git a/code/datums/ai/dog/dog_subtrees.dm b/code/datums/ai/dog/dog_subtrees.dm index fdadd3a9869..66198b61ac3 100644 --- a/code/datums/ai/dog/dog_subtrees.dm +++ b/code/datums/ai/dog/dog_subtrees.dm @@ -5,8 +5,7 @@ if(!SPT_PROB(10, seconds_per_tick)) return controller.queue_behavior(/datum/ai_behavior/find_hated_dog_target, BB_DOG_HARASS_TARGET, BB_PET_TARGETTING_DATUM) - var/datum/weakref/weak_target = controller.blackboard[BB_DOG_HARASS_TARGET] - var/atom/harass_target = weak_target?.resolve() + var/atom/harass_target = controller.blackboard[BB_DOG_HARASS_TARGET] if (isnull(harass_target)) return @@ -29,11 +28,11 @@ continue dog.audible_message(span_warning("[dog] growls at [iter_living], seemingly annoyed by [iter_living.p_their()] presence."), hearing_distance = COMBAT_MESSAGE_RANGE) - controller.blackboard[target_key] = WEAKREF(iter_living) - controller.blackboard[BB_DOG_HARASS_HARM] = FALSE + controller.set_blackboard_key(target_key, iter_living) + controller.set_blackboard_key(BB_DOG_HARASS_HARM, FALSE) return TRUE - controller.blackboard[target_key] = null + controller.clear_blackboard_key(target_key) /datum/ai_behavior/find_hated_dog_target/perform(seconds_per_tick, datum/ai_controller/controller, target_key) . = ..() diff --git a/code/datums/ai/generic/find_and_set.dm b/code/datums/ai/generic/find_and_set.dm index 5d33516d6a6..02f2980dd72 100644 --- a/code/datums/ai/generic/find_and_set.dm +++ b/code/datums/ai/generic/find_and_set.dm @@ -10,7 +10,7 @@ . = ..() var/find_this_thing = search_tactic(controller, locate_path, search_range) if(find_this_thing) - controller.blackboard[set_key] = WEAKREF(find_this_thing) + controller.set_blackboard_key(set_key, find_this_thing) finish_action(controller, TRUE) else finish_action(controller, FALSE) diff --git a/code/datums/ai/generic/generic_behaviors.dm b/code/datums/ai/generic/generic_behaviors.dm index ac2846ef684..75370e54d26 100644 --- a/code/datums/ai/generic/generic_behaviors.dm +++ b/code/datums/ai/generic/generic_behaviors.dm @@ -31,20 +31,25 @@ /datum/ai_behavior/break_spine/setup(datum/ai_controller/controller, target_key) . = ..() - set_movement_target(controller, controller.blackboard[target_key]) + var/atom/target = controller.blackboard[target_key] + if(QDELETED(target)) + return FALSE + set_movement_target(controller, target) /datum/ai_behavior/break_spine/perform(seconds_per_tick, datum/ai_controller/controller, target_key) var/mob/living/batman = controller.blackboard[target_key] var/mob/living/big_guy = controller.pawn //he was molded by the darkness - if(batman.stat) - finish_action(controller, TRUE, target_key) - - if(get_dist(batman, big_guy) >= give_up_distance) + if(QDELETED(batman) || get_dist(batman, big_guy) >= give_up_distance) finish_action(controller, FALSE, target_key) + return + + if(batman.stat != CONSCIOUS) + finish_action(controller, TRUE, target_key) + return big_guy.start_pulling(batman) - big_guy.setDir(get_dir(big_guy, batman)) + big_guy.face_atom(batman) batman.visible_message(span_warning("[batman] gets a slightly too tight hug from [big_guy]!"), span_userdanger("You feel your body break as [big_guy] embraces you!")) @@ -61,7 +66,9 @@ /datum/ai_behavior/break_spine/finish_action(datum/ai_controller/controller, succeeded, target_key) if(succeeded) - controller.blackboard -= target_key + var/mob/living/bane = controller.pawn + bane.stop_pulling() + controller.clear_blackboard_key(target_key) return ..() /// Use in hand the currently held item @@ -86,9 +93,8 @@ /datum/ai_behavior/use_on_object/setup(datum/ai_controller/controller, target_key) . = ..() - var/datum/weakref/target_ref = controller.blackboard[target_key] - var/target = target_ref?.resolve() - if(!target) + var/atom/target = controller.blackboard[target_key] + if(QDELETED(target)) return FALSE set_movement_target(controller, target) @@ -96,10 +102,8 @@ . = ..() var/mob/living/pawn = controller.pawn var/obj/item/held_item = pawn.get_item_by_slot(pawn.get_active_hand()) - var/datum/weakref/target_ref = controller.blackboard[target_key] - var/atom/target = target_ref?.resolve() - - if(!target || !pawn.CanReach(target)) + var/atom/target = controller.blackboard[target_key] + if(QDELETED(target) || !pawn.CanReach(target)) finish_action(controller, FALSE) return @@ -118,15 +122,13 @@ /datum/ai_behavior/give/setup(datum/ai_controller/controller, target_key) . = ..() - var/datum/weakref/target_ref = controller.blackboard[target_key] - set_movement_target(controller, target_ref?.resolve()) + set_movement_target(controller, controller.blackboard[target_key]) /datum/ai_behavior/give/perform(seconds_per_tick, datum/ai_controller/controller, target_key) . = ..() var/mob/living/pawn = controller.pawn var/obj/item/held_item = pawn.get_active_held_item() - var/datum/weakref/target_ref = controller.blackboard[target_key] - var/atom/target = target_ref?.resolve() + var/atom/target = controller.blackboard[target_key] if(!held_item) //if held_item is null, we pretend that action was succesful finish_action(controller, TRUE) @@ -185,14 +187,14 @@ /datum/ai_behavior/consume/setup(datum/ai_controller/controller, target_key) . = ..() - var/datum/weakref/target_ref = controller.blackboard[target_key] - set_movement_target(controller, target_ref?.resolve()) + set_movement_target(controller, controller.blackboard[target_key]) /datum/ai_behavior/consume/perform(seconds_per_tick, datum/ai_controller/controller, target_key, hunger_timer_key) . = ..() var/mob/living/living_pawn = controller.pawn - var/datum/weakref/target_ref = controller.blackboard[target_key] - var/obj/item/target = target_ref.resolve() + var/obj/item/target = controller.blackboard[target_key] + if(QDELETED(target)) + return if(!(target in living_pawn.held_items)) if(!living_pawn.get_empty_held_indexes() || !living_pawn.put_in_hands(target)) @@ -207,7 +209,7 @@ /datum/ai_behavior/consume/finish_action(datum/ai_controller/controller, succeeded, target_key, hunger_timer_key) . = ..() if(succeeded) - controller.blackboard[hunger_timer_key] = world.time + rand(12 SECONDS, 60 SECONDS) + controller.set_blackboard_key(hunger_timer_key, world.time + rand(12 SECONDS, 60 SECONDS)) /** * Drops items in hands, very important for future behaviors that require the pawn to grab stuff @@ -234,9 +236,8 @@ if(!istype(living_pawn) || !isturf(living_pawn.loc)) return - var/datum/weakref/attack_ref = controller.blackboard[BB_ATTACK_TARGET] - var/atom/movable/attack_target = attack_ref?.resolve() - if(!attack_target || !can_see(living_pawn, attack_target, length=controller.blackboard[BB_VISION_RANGE])) + var/atom/movable/attack_target = controller.blackboard[BB_ATTACK_TARGET] + if(!attack_target || !can_see(living_pawn, attack_target, length = controller.blackboard[BB_VISION_RANGE])) finish_action(controller, FALSE) return @@ -250,7 +251,7 @@ /datum/ai_behavior/attack/finish_action(datum/ai_controller/controller, succeeded) . = ..() - controller.blackboard[BB_ATTACK_TARGET] = null + controller.clear_blackboard_key(BB_ATTACK_TARGET) /// A proc representing when the mob is pushed to actually attack the target. Again, subtypes can be used to represent different attacks from different animals, or it can be some other generic behavior /datum/ai_behavior/attack/proc/attack(datum/ai_controller/controller, mob/living/living_target) @@ -270,8 +271,7 @@ if(!istype(living_pawn) || !isturf(living_pawn.loc)) return - var/datum/weakref/follow_ref = controller.blackboard[BB_FOLLOW_TARGET] - var/atom/movable/follow_target = follow_ref?.resolve() + var/atom/movable/follow_target = controller.blackboard[BB_FOLLOW_TARGET] if(!follow_target || get_dist(living_pawn, follow_target) > controller.blackboard[BB_VISION_RANGE]) finish_action(controller, FALSE) return @@ -285,7 +285,7 @@ /datum/ai_behavior/follow/finish_action(datum/ai_controller/controller, succeeded) . = ..() - controller.blackboard[BB_FOLLOW_TARGET] = null + controller.clear_blackboard_key(BB_FOLLOW_TARGET) @@ -316,8 +316,7 @@ /datum/ai_behavior/setup_instrument/perform(seconds_per_tick, datum/ai_controller/controller, song_instrument_key, song_lines_key) . = ..() - var/datum/weakref/instrument_ref = controller.blackboard[song_instrument_key] - var/obj/item/instrument/song_instrument = instrument_ref.resolve() + var/obj/item/instrument/song_instrument = controller.blackboard[song_instrument_key] var/datum/song/song = song_instrument.song var/song_lines = controller.blackboard[song_lines_key] @@ -333,8 +332,7 @@ /datum/ai_behavior/play_instrument/perform(seconds_per_tick, datum/ai_controller/controller, song_instrument_key) . = ..() - var/datum/weakref/instrument_ref = controller.blackboard[song_instrument_key] - var/obj/item/instrument/song_instrument = instrument_ref.resolve() + var/obj/item/instrument/song_instrument = controller.blackboard[song_instrument_key] var/datum/song/song = song_instrument.song song.start_playing(controller.pawn) @@ -354,5 +352,5 @@ possible_targets += thing if(!possible_targets.len) finish_action(controller, FALSE) - controller.blackboard[target_key] = WEAKREF(pick(possible_targets)) + controller.set_blackboard_key(target_key, pick(possible_targets)) finish_action(controller, TRUE) diff --git a/code/datums/ai/generic/generic_subtrees.dm b/code/datums/ai/generic/generic_subtrees.dm index dfb37719ebf..12007a26124 100644 --- a/code/datums/ai/generic/generic_subtrees.dm +++ b/code/datums/ai/generic/generic_subtrees.dm @@ -8,8 +8,7 @@ * * BB_SONG_LINES - not set by this subtree, is the song loaded into the song datum. */ /datum/ai_planning_subtree/generic_play_instrument/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) - var/datum/weakref/player_ref = controller.blackboard[BB_SONG_INSTRUMENT] - var/obj/item/instrument/song_player = player_ref?.resolve() + var/obj/item/instrument/song_player = controller.blackboard[BB_SONG_INSTRUMENT] if(!song_player) controller.queue_behavior(/datum/ai_behavior/find_and_set/in_hands, BB_SONG_INSTRUMENT, /obj/item/instrument) @@ -47,15 +46,16 @@ * * BB_NEXT_HUNGRY - set by this subtree, is when the controller is next hungry */ /datum/ai_planning_subtree/generic_hunger/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) - //inits the blackboard timer - if(!controller.blackboard[BB_NEXT_HUNGRY]) - controller.blackboard[BB_NEXT_HUNGRY] = world.time + rand(0, 30 SECONDS) + var/next_eat = controller.blackboard[BB_NEXT_HUNGRY] + if(!next_eat) + //inits the blackboard timer + next_eat = world.time + rand(0, 30 SECONDS) + controller.set_blackboard_key(BB_NEXT_HUNGRY, next_eat) - if(world.time < controller.blackboard[BB_NEXT_HUNGRY]) + if(world.time < next_eat) return - var/datum/weakref/food_ref = controller.blackboard[BB_FOOD_TARGET] - if(!food_ref?.resolve()) + if(!controller.blackboard[BB_FOOD_TARGET]) controller.queue_behavior(/datum/ai_behavior/find_and_set/edible, BB_FOOD_TARGET, /obj/item, 2) return diff --git a/code/datums/ai/hauntium/haunted_controller.dm b/code/datums/ai/hauntium/haunted_controller.dm index 8783fff5296..e8e80b41607 100644 --- a/code/datums/ai/hauntium/haunted_controller.dm +++ b/code/datums/ai/hauntium/haunted_controller.dm @@ -32,9 +32,9 @@ haunt_equipper = FALSE if(haunt_equipper) //You have now become one of the victims of the HAAAAUNTTIIIINNGGG OOOOOO~~~ - blackboard[BB_TO_HAUNT_LIST][WEAKREF(equipper)] += HAUNTED_ITEM_AGGRO_ADDITION + set_blackboard_key_assoc(BB_TO_HAUNT_LIST, equipper, HAUNTED_ITEM_AGGRO_ADDITION) else - blackboard[BB_LIKES_EQUIPPER] = TRUE + set_blackboard_key(BB_LIKES_EQUIPPER, TRUE) RegisterSignal(pawn, COMSIG_ITEM_DROPPED, PROC_REF(on_dropped)) @@ -42,6 +42,6 @@ /datum/ai_controller/haunted/proc/on_dropped(datum/source, mob/user) SIGNAL_HANDLER + set_blackboard_key(BB_LIKES_EQUIPPER, FALSE) RegisterSignal(pawn, COMSIG_ITEM_EQUIPPED, PROC_REF(on_equip)) - blackboard[BB_LIKES_EQUIPPER] = FALSE UnregisterSignal(pawn, COMSIG_ITEM_DROPPED) diff --git a/code/datums/ai/hauntium/hauntium_subtrees.dm b/code/datums/ai/hauntium/hauntium_subtrees.dm index 0ea459f087a..57b5d2ae7e0 100644 --- a/code/datums/ai/hauntium/hauntium_subtrees.dm +++ b/code/datums/ai/hauntium/hauntium_subtrees.dm @@ -13,17 +13,12 @@ var/list/to_haunt_list = controller.blackboard[BB_TO_HAUNT_LIST] - for(var/datum/weakref/target_ref as anything in to_haunt_list) - if(to_haunt_list[target_ref] <= 0) - to_haunt_list -= target_ref + for(var/mob/living/haunt_target as anything in to_haunt_list) + if(to_haunt_list[haunt_target] <= 0) + controller.remove_thing_from_blackboard_key(BB_TO_HAUNT_LIST, haunt_target) continue - var/mob/living/real_target = target_ref.resolve() - if(QDELETED(real_target)) - to_haunt_list -= target_ref - continue - - if(get_dist(real_target, item_pawn) <= 7) - controller.blackboard[BB_HAUNT_TARGET] = target_ref + if(get_dist(haunt_target, item_pawn) <= 7) + controller.set_blackboard_key(BB_HAUNT_TARGET, haunt_target) controller.queue_behavior(/datum/ai_behavior/item_move_close_and_attack/ghostly/haunted, BB_HAUNT_TARGET, BB_HAUNTED_THROW_ATTEMPT_COUNT) return SUBTREE_RETURN_FINISH_PLANNING diff --git a/code/datums/ai/hunting_behavior/hunting_behaviors.dm b/code/datums/ai/hunting_behavior/hunting_behaviors.dm index cb8c07f95f8..a06f6996569 100644 --- a/code/datums/ai/hunting_behavior/hunting_behaviors.dm +++ b/code/datums/ai/hunting_behavior/hunting_behaviors.dm @@ -31,8 +31,7 @@ if(HAS_TRAIT(controller.pawn, TRAIT_HANDS_BLOCKED) || living_pawn.stat != CONSCIOUS) return - var/datum/weakref/hunting_weakref = controller.blackboard[target_key] - var/atom/hunted = hunting_weakref?.resolve() + var/atom/hunted = controller.blackboard[target_key] // We're not hunting anything, look around for something if(isnull(hunted)) controller.queue_behavior(finding_behavior, target_key, hunt_targets, hunt_range) @@ -56,7 +55,7 @@ for(var/atom/possible_dinner as anything in typecache_filter_list(range(hunt_range, living_mob), types_to_hunt)) if(!valid_dinner(living_mob, possible_dinner, hunt_range)) continue - controller.blackboard[hunting_target_key] = WEAKREF(possible_dinner) + controller.set_blackboard_key(hunting_target_key, possible_dinner) finish_action(controller, TRUE) return @@ -80,8 +79,7 @@ /datum/ai_behavior/hunt_target/setup(datum/ai_controller/controller, hunting_target_key, hunting_cooldown_key) . = ..() - var/datum/weakref/hunting_weakref = controller.blackboard[hunting_target_key] - var/atom/hunt_target = hunting_weakref?.resolve() + var/atom/hunt_target = controller.blackboard[hunting_target_key] if (isnull(hunt_target)) return FALSE set_movement_target(controller, hunt_target) @@ -89,8 +87,7 @@ /datum/ai_behavior/hunt_target/perform(seconds_per_tick, datum/ai_controller/controller, hunting_target_key, hunting_cooldown_key) . = ..() var/mob/living/hunter = controller.pawn - var/datum/weakref/hunting_weakref = controller.blackboard[hunting_target_key] - var/atom/hunted = hunting_weakref?.resolve() + var/atom/hunted = controller.blackboard[hunting_target_key] if(isnull(hunted)) //Target is gone for some reason. forget about this task! @@ -117,11 +114,11 @@ /datum/ai_behavior/hunt_target/finish_action(datum/ai_controller/controller, succeeded, hunting_target_key, hunting_cooldown_key) . = ..() if(succeeded) - controller.blackboard[hunting_cooldown_key] = world.time + hunt_cooldown + controller.set_blackboard_key(hunting_cooldown_key, world.time + hunt_cooldown) else if(hunting_target_key) - controller.blackboard[hunting_target_key] = null + controller.clear_blackboard_key(hunting_target_key) if(always_reset_target && hunting_target_key) - controller.blackboard[hunting_target_key] = null + controller.clear_blackboard_key(hunting_target_key) /datum/ai_behavior/hunt_target/unarmed_attack_target diff --git a/code/datums/ai/idle_behaviors/idle_dog.dm b/code/datums/ai/idle_behaviors/idle_dog.dm index 75ef809e2f8..46e0d040c9d 100644 --- a/code/datums/ai/idle_behaviors/idle_dog.dm +++ b/code/datums/ai/idle_behaviors/idle_dog.dm @@ -4,8 +4,7 @@ if(!isturf(living_pawn.loc) || living_pawn.pulledby) return - var/datum/weakref/weak_item = controller.blackboard[BB_SIMPLE_CARRY_ITEM] - var/obj/item/carry_item = weak_item?.resolve() + var/obj/item/carry_item = controller.blackboard[BB_SIMPLE_CARRY_ITEM] // if we're just ditzing around carrying something, occasionally print a message so people know we have something if(carry_item && SPT_PROB(5, seconds_per_tick)) living_pawn.visible_message(span_notice("[living_pawn] gently teethes on \the [carry_item] in [living_pawn.p_their()] mouth."), vision_distance=COMBAT_MESSAGE_RANGE) diff --git a/code/datums/ai/monkey/monkey_behaviors.dm b/code/datums/ai/monkey/monkey_behaviors.dm index 0ecb7a75bb9..8c69db1c69c 100644 --- a/code/datums/ai/monkey/monkey_behaviors.dm +++ b/code/datums/ai/monkey/monkey_behaviors.dm @@ -8,14 +8,9 @@ . = ..() if(!success) //Don't try again on this item if we failed - var/list/item_blacklist = controller.blackboard[BB_MONKEY_BLACKLISTITEMS] - var/obj/item/target = controller.blackboard[BB_MONKEY_PICKUPTARGET] + controller.set_blackboard_key_assoc(BB_MONKEY_BLACKLISTITEMS, controller.blackboard[BB_MONKEY_PICKUPTARGET], TRUE) - item_blacklist[target] = TRUE - if(istype(controller, /datum/ai_controller/monkey)) //What the fuck - controller.RegisterSignal(target, COMSIG_PARENT_QDELETING, TYPE_PROC_REF(/datum/ai_controller/monkey,target_del)) - - controller.blackboard[BB_MONKEY_PICKUPTARGET] = null + controller.clear_blackboard_key(BB_MONKEY_PICKUPTARGET) /datum/ai_behavior/monkey_equip/proc/equip_item(datum/ai_controller/controller) var/mob/living/living_pawn = controller.pawn @@ -39,7 +34,7 @@ else if(target.force > best_force) living_pawn.drop_all_held_items() living_pawn.put_in_hands(target) - controller.blackboard[BB_MONKEY_BEST_FORCE_FOUND] = target.force + controller.set_blackboard_key(BB_MONKEY_BEST_FORCE_FOUND, target.force) finish_action(controller, TRUE) return @@ -77,7 +72,6 @@ /datum/ai_behavior/monkey_equip/pickpocket/proc/attempt_pickpocket(datum/ai_controller/controller) var/obj/item/target = controller.blackboard[BB_MONKEY_PICKUPTARGET] - var/mob/living/victim = target.loc var/mob/living/living_pawn = controller.pawn @@ -89,7 +83,7 @@ victim.visible_message(span_warning("[living_pawn] starts trying to take [target] from [victim]!"), span_danger("[living_pawn] tries to take [target]!")) - controller.blackboard[BB_MONKEY_PICKPOCKETING] = TRUE + controller.set_blackboard_key(BB_MONKEY_PICKPOCKETING, TRUE) var/success = FALSE @@ -110,8 +104,8 @@ /datum/ai_behavior/monkey_equip/pickpocket/finish_action(datum/ai_controller/controller, success) . = ..() - controller.blackboard[BB_MONKEY_PICKPOCKETING] = FALSE - controller.blackboard[BB_MONKEY_PICKUPTARGET] = null + controller.set_blackboard_key(BB_MONKEY_PICKPOCKETING, FALSE) + controller.clear_blackboard_key(BB_MONKEY_PICKUPTARGET) /datum/ai_behavior/monkey_flee @@ -128,7 +122,7 @@ // flee from anyone who attacked us and we didn't beat down for(var/mob/living/L in view(living_pawn, MONKEY_FLEE_VISION)) - if(controller.blackboard[BB_MONKEY_ENEMIES][WEAKREF(L)] && L.stat == CONSCIOUS) + if(controller.blackboard[BB_MONKEY_ENEMIES][L] && L.stat == CONSCIOUS) target = L break @@ -142,14 +136,12 @@ /datum/ai_behavior/monkey_attack_mob/setup(datum/ai_controller/controller, target_key) . = ..() - var/datum/weakref/target_ref = controller.blackboard[target_key] - set_movement_target(controller, target_ref?.resolve()) + set_movement_target(controller, controller.blackboard[target_key]) /datum/ai_behavior/monkey_attack_mob/perform(seconds_per_tick, datum/ai_controller/controller, target_key) . = ..() - var/datum/weakref/target_ref = controller.blackboard[target_key] - var/mob/living/target = target_ref?.resolve() + var/mob/living/target = controller.blackboard[target_key] var/mob/living/living_pawn = controller.pawn if(!target || target.stat != CONSCIOUS) @@ -175,7 +167,7 @@ . = ..() var/mob/living/living_pawn = controller.pawn SSmove_manager.stop_looping(living_pawn) - controller.blackboard[target_key] = null + controller.clear_blackboard_key(target_key) /// attack using a held weapon otherwise bite the enemy, then if we are angry there is a chance we might calm down a little /datum/ai_behavior/monkey_attack_mob/proc/monkey_attack(datum/ai_controller/controller, mob/living/target, seconds_per_tick, disarm) @@ -193,7 +185,7 @@ living_pawn.set_combat_mode(TRUE) if(isnull(controller.blackboard[BB_MONKEY_GUN_WORKED])) - controller.blackboard[BB_MONKEY_GUN_WORKED] = TRUE + controller.set_blackboard_key(BB_MONKEY_GUN_WORKED, TRUE) // attack with weapon if we have one if(living_pawn.CanReach(target, weapon)) @@ -201,7 +193,7 @@ weapon.melee_attack_chain(living_pawn, target) else living_pawn.UnarmedAttack(target, null, disarm ? list("right" = TRUE) : null) //Fake a right click if we're disarmin - controller.blackboard[BB_MONKEY_GUN_WORKED] = TRUE // We reset their memory of the gun being 'broken' if they accomplish some other attack + controller.set_blackboard_key(BB_MONKEY_GUN_WORKED, TRUE) // We reset their memory of the gun being 'broken' if they accomplish some other attack else if(weapon) var/atom/real_target = target if(prob(10)) // Artificial miss @@ -212,27 +204,32 @@ if(gun && controller.blackboard[BB_MONKEY_GUN_WORKED] && prob(95)) // We attempt to attack even if we can't shoot so we get the effects of pulling the trigger gun.afterattack(real_target, living_pawn, FALSE) - controller.blackboard[BB_MONKEY_GUN_WORKED] = can_shoot ? TRUE : prob(80) // Only 20% likely to notice it didn't work + controller.set_blackboard_key(BB_MONKEY_GUN_WORKED, can_shoot ? TRUE : prob(80)) // Only 20% likely to notice it didn't work if(can_shoot) - controller.blackboard[BB_MONKEY_GUN_NEURONS_ACTIVATED] = TRUE + controller.set_blackboard_key(BB_MONKEY_GUN_NEURONS_ACTIVATED, TRUE) else living_pawn.throw_item(real_target) - controller.blackboard[BB_MONKEY_GUN_WORKED] = TRUE // 'worked' + controller.set_blackboard_key(BB_MONKEY_GUN_WORKED, TRUE) // 'worked' // no de-aggro if(controller.blackboard[BB_MONKEY_AGGRESSIVE]) return + // we've queued up a monkey attack on a mob which isn't already an enemy, so give them 1 threat to start + // note they might immediately reduce threat and drop from the list. + // this is fine, we're just giving them a love tap then leaving them alone. + // unless they fight back, then we retaliate + if(isnull(controller.blackboard[BB_MONKEY_ENEMIES][target])) + controller.set_blackboard_key_assoc(BB_MONKEY_ENEMIES, target, 1) + /// mob refs are uids, so this is safe - var/datum/weakref/target_ref = WEAKREF(target) if(SPT_PROB(MONKEY_HATRED_REDUCTION_PROB, seconds_per_tick)) - controller.blackboard[BB_MONKEY_ENEMIES][target_ref]-- + controller.add_blackboard_key_assoc(BB_MONKEY_ENEMIES, target, -1) // if we are not angry at our target, go back to idle - if(controller.blackboard[BB_MONKEY_ENEMIES][target_ref] <= 0) - var/list/enemies = controller.blackboard[BB_MONKEY_ENEMIES] - enemies.Remove(target_ref) - if(controller.blackboard[BB_MONKEY_CURRENT_ATTACK_TARGET] == WEAKREF(target)) + if(controller.blackboard[BB_MONKEY_ENEMIES][target] <= 0) + controller.remove_thing_from_blackboard_key(BB_MONKEY_ENEMIES, target) + if(controller.blackboard[BB_MONKEY_CURRENT_ATTACK_TARGET] == target) finish_action(controller, TRUE) /datum/ai_behavior/disposal_mob @@ -240,14 +237,13 @@ /datum/ai_behavior/disposal_mob/setup(datum/ai_controller/controller, attack_target_key, disposal_target_key) . = ..() - var/datum/weakref/target_ref = controller.blackboard[attack_target_key] - set_movement_target(controller, target_ref?.resolve()) + set_movement_target(controller, controller.blackboard[attack_target_key]) /datum/ai_behavior/disposal_mob/finish_action(datum/ai_controller/controller, succeeded, attack_target_key, disposal_target_key) . = ..() - controller.blackboard[attack_target_key] = null //Reset attack target - controller.blackboard[BB_MONKEY_DISPOSING] = FALSE //No longer disposing - controller.blackboard[disposal_target_key] = null //No target disposal + controller.clear_blackboard_key(attack_target_key) //Reset attack target + controller.set_blackboard_key(BB_MONKEY_DISPOSING, FALSE) //No longer disposing + controller.clear_blackboard_key(disposal_target_key) //No target disposal /datum/ai_behavior/disposal_mob/perform(seconds_per_tick, datum/ai_controller/controller, attack_target_key, disposal_target_key) . = ..() @@ -255,8 +251,7 @@ if(controller.blackboard[BB_MONKEY_DISPOSING]) //We are disposing, don't do ANYTHING!!!! return - var/datum/weakref/target_ref = controller.blackboard[attack_target_key] - var/mob/living/target = target_ref?.resolve() + var/mob/living/target = controller.blackboard[attack_target_key] var/mob/living/living_pawn = controller.pawn set_movement_target(controller, target) @@ -270,8 +265,7 @@ target.grabbedby(living_pawn) return //Do the rest next turn - var/datum/weakref/disposal_ref = controller.blackboard[disposal_target_key] - var/obj/machinery/disposal/disposal = disposal_ref.resolve() + var/obj/machinery/disposal/disposal = controller.blackboard[disposal_target_key] set_movement_target(controller, disposal) if(!disposal) @@ -285,12 +279,10 @@ /datum/ai_behavior/disposal_mob/proc/try_disposal_mob(datum/ai_controller/controller, attack_target_key, disposal_target_key) var/mob/living/living_pawn = controller.pawn - var/datum/weakref/target_ref = controller.blackboard[attack_target_key] - var/mob/living/target = target_ref?.resolve() - var/datum/weakref/disposal_ref = controller.blackboard[disposal_target_key] - var/obj/machinery/disposal/disposal = disposal_ref?.resolve() + var/mob/living/target = controller.blackboard[attack_target_key] + var/obj/machinery/disposal/disposal = controller.blackboard[disposal_target_key] - controller.blackboard[BB_MONKEY_DISPOSING] = TRUE + controller.set_blackboard_key(BB_MONKEY_DISPOSING, TRUE) if(target && disposal?.stuff_mob_in(target, living_pawn)) disposal.flush() @@ -300,20 +292,19 @@ /datum/ai_behavior/recruit_monkeys/perform(seconds_per_tick, datum/ai_controller/controller) . = ..() - controller.blackboard[BB_MONKEY_RECRUIT_COOLDOWN] = world.time + MONKEY_RECRUIT_COOLDOWN + controller.set_blackboard_key(BB_MONKEY_RECRUIT_COOLDOWN, world.time + MONKEY_RECRUIT_COOLDOWN) var/mob/living/living_pawn = controller.pawn - for(var/mob/living/L in view(living_pawn, MONKEY_ENEMY_VISION)) - if(!HAS_AI_CONTROLLER_TYPE(L, /datum/ai_controller/monkey)) + for(var/mob/living/nearby_monkey in view(living_pawn, MONKEY_ENEMY_VISION)) + if(!HAS_AI_CONTROLLER_TYPE(nearby_monkey, /datum/ai_controller/monkey)) continue - if(!SPT_PROB(MONKEY_RECRUIT_PROB, seconds_per_tick)) continue - var/datum/ai_controller/monkey/monkey_ai = L.ai_controller - var/datum/weakref/enemy_ref = controller.blackboard[BB_MONKEY_CURRENT_ATTACK_TARGET] - var/list/enemies = L.ai_controller.blackboard[BB_MONKEY_ENEMIES] - enemies[enemy_ref] = MONKEY_RECRUIT_HATED_AMOUNT - monkey_ai.blackboard[BB_MONKEY_RECRUIT_COOLDOWN] = world.time + MONKEY_RECRUIT_COOLDOWN + // Recruited a monkey to our side + controller.set_blackboard_key(BB_MONKEY_RECRUIT_COOLDOWN, world.time + MONKEY_RECRUIT_COOLDOWN) + // Other monkeys now also hate the guy we're currently targeting + nearby_monkey.ai_controller.add_blackboard_key_assoc(BB_MONKEY_ENEMIES, controller.blackboard[BB_MONKEY_CURRENT_ATTACK_TARGET], MONKEY_RECRUIT_HATED_AMOUNT) + finish_action(controller, TRUE) /datum/ai_behavior/monkey_set_combat_target/perform(seconds_per_tick, datum/ai_controller/controller, set_key, enemies_key) @@ -322,16 +313,17 @@ for(var/mob/living/possible_enemy in view(MONKEY_ENEMY_VISION, controller.pawn)) if(possible_enemy == controller.pawn) continue // don't target ourselves - var/datum/weakref/enemy_ref = WEAKREF(possible_enemy) - if(!enemies[enemy_ref]) //We don't hate this creature! But we might still attack it! + if(!enemies[possible_enemy]) //We don't hate this creature! But we might still attack it! if(!controller.blackboard[BB_MONKEY_AGGRESSIVE]) //We are not aggressive either, so we won't attack! continue if(HAS_AI_CONTROLLER_TYPE(possible_enemy, /datum/ai_controller/monkey) && !controller.blackboard[BB_MONKEY_TARGET_MONKEYS]) //Do not target poor monkes continue // Weighted list, so the closer they are the more likely they are to be chosen as the enemy - valids[enemy_ref] = CEILING(100 / (get_dist(controller.pawn, possible_enemy) || 1), 1) + valids[possible_enemy] = CEILING(100 / (get_dist(controller.pawn, possible_enemy) || 1), 1) - if(!valids.len) + if(!length(valids)) finish_action(controller, FALSE) - controller.blackboard[set_key] = pick_weight(valids) + return + + controller.set_blackboard_key(set_key, pick_weight(valids)) finish_action(controller, TRUE) diff --git a/code/datums/ai/monkey/monkey_controller.dm b/code/datums/ai/monkey/monkey_controller.dm index d4877480dd6..e7885aa3014 100644 --- a/code/datums/ai/monkey/monkey_controller.dm +++ b/code/datums/ai/monkey/monkey_controller.dm @@ -52,7 +52,7 @@ have ways of interacting with a specific mob and control it. . = ..() if(. & AI_CONTROLLER_INCOMPATIBLE) return - blackboard[BB_MONKEY_AGGRESSIVE] = TRUE //Angry cunt + set_blackboard_key(BB_MONKEY_AGGRESSIVE, TRUE) //Angry cunt /datum/ai_controller/monkey/TryPossessPawn(atom/new_pawn) if(!isliving(new_pawn)) @@ -103,8 +103,8 @@ have ways of interacting with a specific mob and control it. /datum/ai_controller/monkey/proc/TryFindWeapon() var/mob/living/living_pawn = pawn - if(!locate(/obj/item) in living_pawn.held_items) - blackboard[BB_MONKEY_BEST_FORCE_FOUND] = 0 + if(!(locate(/obj/item) in living_pawn.held_items)) + set_blackboard_key(BB_MONKEY_BEST_FORCE_FOUND, 0) if(blackboard[BB_MONKEY_GUN_NEURONS_ACTIVATED] && (locate(/obj/item/gun) in living_pawn.held_items)) // We have a gun, what could we possibly want? @@ -135,7 +135,7 @@ have ways of interacting with a specific mob and control it. if(weapon.force < 2) // our bite does 2 damage on avarage, no point in settling for anything less return FALSE - blackboard[BB_MONKEY_PICKUPTARGET] = weapon + set_blackboard_key(BB_MONKEY_PICKUPTARGET, weapon) set_movement_target(type, weapon) if(pickpocket) queue_behavior(/datum/ai_behavior/monkey_equip/pickpocket) @@ -145,8 +145,7 @@ have ways of interacting with a specific mob and control it. ///Reactive events to being hit /datum/ai_controller/monkey/proc/retaliate(mob/living/L) - var/list/enemies = blackboard[BB_MONKEY_ENEMIES] - enemies[WEAKREF(L)] += MONKEY_HATRED_AMOUNT + add_blackboard_key_assoc(BB_MONKEY_ENEMIES, L, MONKEY_HATRED_AMOUNT) /datum/ai_controller/monkey/proc/on_attacked(datum/source, mob/attacker) SIGNAL_HANDLER @@ -175,7 +174,3 @@ have ways of interacting with a specific mob and control it. /datum/ai_controller/monkey/proc/update_movespeed(mob/living/pawn) SIGNAL_HANDLER movement_delay = pawn.cached_multiplicative_slowdown - -/datum/ai_controller/monkey/proc/target_del(target) - SIGNAL_HANDLER - blackboard[BB_MONKEY_BLACKLISTITEMS] -= target diff --git a/code/datums/ai/monkey/monkey_subtrees.dm b/code/datums/ai/monkey/monkey_subtrees.dm index 898a0481055..572eeb6b56e 100644 --- a/code/datums/ai/monkey/monkey_subtrees.dm +++ b/code/datums/ai/monkey/monkey_subtrees.dm @@ -37,10 +37,9 @@ living_pawn.set_combat_mode(FALSE) return SUBTREE_RETURN_FINISH_PLANNING - var/datum/weakref/target_ref = controller.blackboard[BB_MONKEY_CURRENT_ATTACK_TARGET] - var/mob/living/selected_enemy = target_ref?.resolve() + var/mob/living/selected_enemy = controller.blackboard[BB_MONKEY_CURRENT_ATTACK_TARGET] - if(!selected_enemy) + if(QDELETED(selected_enemy)) living_pawn.set_combat_mode(FALSE) return diff --git a/code/datums/ai/movement/_ai_movement.dm b/code/datums/ai/movement/_ai_movement.dm index f53fecc528c..2b734ca24a9 100644 --- a/code/datums/ai/movement/_ai_movement.dm +++ b/code/datums/ai/movement/_ai_movement.dm @@ -9,7 +9,7 @@ /datum/ai_movement/proc/start_moving_towards(datum/ai_controller/controller, atom/current_movement_target, min_distance) SHOULD_CALL_PARENT(TRUE) controller.pathing_attempts = 0 - controller.blackboard[BB_CURRENT_MIN_MOVE_DISTANCE] = min_distance + controller.set_blackboard_key(BB_CURRENT_MIN_MOVE_DISTANCE, min_distance) moving_controllers[controller] = current_movement_target /datum/ai_movement/proc/stop_moving_towards(datum/ai_controller/controller) diff --git a/code/datums/ai/objects/mod.dm b/code/datums/ai/objects/mod.dm index c2c3599ddb1..ff3a8c6d169 100644 --- a/code/datums/ai/objects/mod.dm +++ b/code/datums/ai/objects/mod.dm @@ -43,6 +43,6 @@ /datum/ai_behavior/mod_attach/finish_action(datum/ai_controller/controller, succeeded) . = ..() - controller.blackboard[BB_MOD_TARGET] = null + controller.clear_blackboard_key(BB_MOD_TARGET) var/obj/item/implant/mod/implant = controller.blackboard[BB_MOD_IMPLANT] implant.end_recall(succeeded) diff --git a/code/datums/ai/objects/vending_machines/vending_machine_behaviors.dm b/code/datums/ai/objects/vending_machines/vending_machine_behaviors.dm index e5d7f2665e9..5bad78a3515 100644 --- a/code/datums/ai/objects/vending_machines/vending_machine_behaviors.dm +++ b/code/datums/ai/objects/vending_machines/vending_machine_behaviors.dm @@ -9,14 +9,13 @@ . = ..() set_movement_target(controller, controller.blackboard[target_key]) - /datum/ai_behavior/vendor_crush/perform(seconds_per_tick, datum/ai_controller/controller) . = ..() if(controller.blackboard[BB_VENDING_BUSY_TILTING]) return controller.ai_movement.stop_moving_towards(controller) - controller.blackboard[BB_VENDING_BUSY_TILTING] = TRUE + controller.set_blackboard_key(BB_VENDING_BUSY_TILTING, TRUE) var/turf/target_turf = get_turf(controller.blackboard[BB_VENDING_CURRENT_TARGET]) new /obj/effect/temp_visual/telegraphing/vending_machine_tilt(target_turf) addtimer(CALLBACK(src, PROC_REF(tiltonmob), controller, target_turf), time_to_tilt) @@ -25,16 +24,16 @@ var/obj/machinery/vending/vendor_pawn = controller.pawn if(vendor_pawn.tilt(target_turf)) //We hit something vendor_pawn.say(pick("Supersize this!", "Eat my shiny metal ass!", "Want to consume some of my products?", "SMASH!", "Don't you love these smashing prices!")) - controller.blackboard[BB_VENDING_LAST_HIT_SUCCESFUL] = TRUE + controller.set_blackboard_key(BB_VENDING_LAST_HIT_SUCCESFUL, TRUE) else vendor_pawn.say(pick("Get back here!", "Don't you want my well priced love?")) - controller.blackboard[BB_VENDING_LAST_HIT_SUCCESFUL] = FALSE + controller.set_blackboard_key(BB_VENDING_LAST_HIT_SUCCESFUL, FALSE) finish_action(controller, TRUE) /datum/ai_behavior/vendor_crush/finish_action(datum/ai_controller/controller, succeeded) . = ..() - controller.blackboard[BB_VENDING_BUSY_TILTING] = FALSE - controller.blackboard[BB_VENDING_UNTILT_COOLDOWN] = world.time + untilt_cooldown + controller.set_blackboard_key(BB_VENDING_BUSY_TILTING, FALSE) + controller.set_blackboard_key(BB_VENDING_UNTILT_COOLDOWN, world.time + untilt_cooldown) /datum/ai_behavior/vendor_rise_up //what a gamer ///Time before machine can tilt again after untilting if last hit was a success @@ -45,9 +44,6 @@ var/obj/machinery/vending/vendor_pawn = controller.pawn vendor_pawn.visible_message(span_warning("[vendor_pawn] untilts itself!")) if(controller.blackboard[BB_VENDING_LAST_HIT_SUCCESFUL]) - controller.blackboard[BB_VENDING_TILT_COOLDOWN] = world.time + succes_tilt_cooldown + controller.set_blackboard_key(BB_VENDING_TILT_COOLDOWN, world.time + succes_tilt_cooldown) vendor_pawn.untilt() finish_action(controller, TRUE) - - - diff --git a/code/datums/ai/objects/vending_machines/vending_machine_controller.dm b/code/datums/ai/objects/vending_machines/vending_machine_controller.dm index c6b6ea79fa8..cd779b7d691 100644 --- a/code/datums/ai/objects/vending_machines/vending_machine_controller.dm +++ b/code/datums/ai/objects/vending_machines/vending_machine_controller.dm @@ -42,7 +42,7 @@ for(var/mob/living/living_target in oview(vision_range, pawn)) if(living_target.stat || living_target.incorporeal_move) //They're already fucked up or incorporeal continue - blackboard[BB_VENDING_CURRENT_TARGET] = living_target + set_blackboard_key(BB_VENDING_CURRENT_TARGET, living_target) queue_behavior(/datum/ai_behavior/vendor_crush, BB_VENDING_CURRENT_TARGET) return - blackboard[BB_VENDING_TILT_COOLDOWN] = world.time + search_for_enemy_cooldown + set_blackboard_key(BB_VENDING_TILT_COOLDOWN, world.time + search_for_enemy_cooldown) diff --git a/code/datums/ai/oldhostile/hostile_tameable.dm b/code/datums/ai/oldhostile/hostile_tameable.dm index 4291ff8ec98..bfa9f17dffa 100644 --- a/code/datums/ai/oldhostile/hostile_tameable.dm +++ b/code/datums/ai/oldhostile/hostile_tameable.dm @@ -47,7 +47,7 @@ SIGNAL_HANDLER if(force || ai_status == AI_STATUS_OFF) return - if(WEAKREF(buckler) != blackboard[BB_HOSTILE_FRIEND]) + if(buckler != blackboard[BB_HOSTILE_FRIEND]) return COMPONENT_BLOCK_BUCKLE /datum/ai_controller/hostile_friend/able_to_run() @@ -70,36 +70,33 @@ /// Befriends someone /datum/ai_controller/hostile_friend/proc/befriend(mob/living/new_friend) - var/datum/weakref/current_ref = blackboard[BB_HOSTILE_FRIEND] - var/datum/weakref/friend_ref = WEAKREF(new_friend) - var/mob/living/old_friend = current_ref?.resolve() + var/mob/living/old_friend = blackboard[BB_HOSTILE_FRIEND] if(old_friend) unfriend(old_friend) - else - blackboard[BB_HOSTILE_FRIEND] = null if(in_range(pawn, new_friend)) new_friend.visible_message("[pawn] looks at [new_friend] in a friendly manner!", span_notice("[pawn] looks at you in a friendly manner!")) - blackboard[BB_HOSTILE_FRIEND] = friend_ref + set_blackboard_key(BB_HOSTILE_FRIEND, new_friend) RegisterSignal(new_friend, COMSIG_MOB_POINTED, PROC_REF(check_point)) RegisterSignal(new_friend, COMSIG_MOB_SAY, PROC_REF(check_verbal_command)) /// Someone is being mean to us, take them off our friends (add actual enemies behavior later) /datum/ai_controller/hostile_friend/proc/unfriend() - var/datum/weakref/friend_ref = blackboard[BB_HOSTILE_FRIEND] - var/mob/living/old_friend = friend_ref?.resolve() + var/mob/living/old_friend = blackboard[BB_HOSTILE_FRIEND] if(old_friend) UnregisterSignal(old_friend, list(COMSIG_MOB_POINTED, COMSIG_MOB_SAY)) - blackboard[BB_HOSTILE_FRIEND] = null + clear_blackboard_key(BB_HOSTILE_FRIEND) /// Someone is looking at us, if we're currently carrying something then show what it is, and include a message if they're our friend /datum/ai_controller/hostile_friend/proc/on_examined(datum/source, mob/user, list/examine_text) SIGNAL_HANDLER - if(blackboard[BB_HOSTILE_FRIEND] == WEAKREF(user)) - var/mob/living/living_pawn = pawn - if(!IS_DEAD_OR_INCAP(living_pawn)) - examine_text += span_notice("[pawn.p_they(TRUE)] seem[pawn.p_s()] happy to see you!") + if(blackboard[BB_HOSTILE_FRIEND] != user) + return + + var/mob/living/living_pawn = pawn + if(!IS_DEAD_OR_INCAP(living_pawn)) + examine_text += span_notice("[pawn.p_they(TRUE)] seem[pawn.p_s()] happy to see you!") // next section is regarding commands @@ -109,7 +106,7 @@ if(!COOLDOWN_FINISHED(src, command_cooldown)) return - if(!istype(clicker) || blackboard[BB_HOSTILE_FRIEND] == WEAKREF(clicker)) + if(!istype(clicker) || blackboard[BB_HOSTILE_FRIEND] != clicker) return . = COMPONENT_CANCEL_CLICK_ALT INVOKE_ASYNC(src, PROC_REF(command_radial), clicker) @@ -139,7 +136,7 @@ /datum/ai_controller/hostile_friend/proc/check_verbal_command(mob/speaker, speech_args) SIGNAL_HANDLER - if(blackboard[BB_HOSTILE_FRIEND] != WEAKREF(speaker)) + if(blackboard[BB_HOSTILE_FRIEND] != speaker) return if(!COOLDOWN_FINISHED(src, command_cooldown)) @@ -172,14 +169,14 @@ // heel: stop what you're doing, relax and try not to do anything for a little bit if(COMMAND_STOP) pawn.visible_message(span_notice("[pawn] [blackboard[BB_HOSTILE_ATTACK_WORD]] at [commander]'s command, and [pawn.p_they()] stop[pawn.p_s()] obediently, awaiting further orders.")) - blackboard[BB_HOSTILE_ORDER_MODE] = HOSTILE_COMMAND_NONE + set_blackboard_key(BB_HOSTILE_ORDER_MODE, HOSTILE_COMMAND_NONE) CancelActions() // follow: whatever the commander points to, try and bring it back if(COMMAND_FOLLOW) pawn.visible_message(span_notice("[pawn] [blackboard[BB_HOSTILE_ATTACK_WORD]] at [commander]'s command, and [pawn.p_they()] follow[pawn.p_s()] slightly in anticipation.")) CancelActions() - blackboard[BB_HOSTILE_ORDER_MODE] = HOSTILE_COMMAND_FOLLOW - blackboard[BB_FOLLOW_TARGET] = WEAKREF(commander) + set_blackboard_key(BB_HOSTILE_ORDER_MODE, HOSTILE_COMMAND_FOLLOW) + set_blackboard_key(BB_FOLLOW_TARGET, commander) set_movement_target(type, commander) var/mob/living/living_pawn = pawn if(living_pawn.buckled) @@ -189,7 +186,7 @@ if(COMMAND_ATTACK) pawn.visible_message(span_danger("[pawn] [blackboard[BB_HOSTILE_ATTACK_WORD]] at [commander]'s command, and [pawn.p_they()] growl[pawn.p_s()] intensely.")) // imagine getting intimidated by a corgi CancelActions() - blackboard[BB_HOSTILE_ORDER_MODE] = HOSTILE_COMMAND_ATTACK + set_blackboard_key(BB_HOSTILE_ORDER_MODE, HOSTILE_COMMAND_ATTACK) /// Someone we like is pointing at something, see if it's something we might want to interact with (like if they might want us to fetch something for them) /datum/ai_controller/hostile_friend/proc/check_point(mob/pointing_friend, atom/movable/pointed_movable) @@ -201,7 +198,10 @@ if(!COOLDOWN_FINISHED(src, command_cooldown)) return - if(blackboard[BB_HOSTILE_FRIEND] == WEAKREF(pointed_movable) || pointed_movable == pawn || !istype(pointed_movable) || blackboard[BB_HOSTILE_ORDER_MODE] == HOSTILE_COMMAND_NONE) // busy or no command + if(blackboard[BB_HOSTILE_FRIEND] == pointed_movable \ + || pointed_movable == pawn \ + || !istype(pointed_movable) \ + || blackboard[BB_HOSTILE_ORDER_MODE] == HOSTILE_COMMAND_NONE) // busy or no command return if(!can_see(pawn, pointing_friend, length=blackboard[BB_VISION_RANGE]) || !can_see(pawn, pointed_movable, length=blackboard[BB_VISION_RANGE])) return @@ -212,7 +212,7 @@ if(blackboard[BB_HOSTILE_ORDER_MODE] == HOSTILE_COMMAND_ATTACK) pawn.visible_message(span_notice("[pawn] follows [pointing_friend]'s gesture towards [pointed_movable] and [blackboard[BB_HOSTILE_ATTACK_WORD]] intensely!")) set_movement_target(type, pointed_movable) - blackboard[BB_ATTACK_TARGET] = WEAKREF(pointed_movable) + set_blackboard_key(BB_ATTACK_TARGET, pointed_movable) if(living_pawn.buckled) queue_behavior(/datum/ai_behavior/resist)//in case they are in bed or something queue_behavior(/datum/ai_behavior/attack) diff --git a/code/datums/ai/robot_customer/robot_customer_behaviors.dm b/code/datums/ai/robot_customer/robot_customer_behaviors.dm index c78585efc0e..431713b94ca 100644 --- a/code/datums/ai/robot_customer/robot_customer_behaviors.dm +++ b/code/datums/ai/robot_customer/robot_customer_behaviors.dm @@ -26,7 +26,7 @@ if(found_seat) customer_pawn.say(pick(customer_data.found_seat_lines)) - controller.blackboard[BB_CUSTOMER_MY_SEAT] = WEAKREF(found_seat) + controller.set_blackboard_key(BB_CUSTOMER_MY_SEAT, found_seat) attending_venue.linked_seats[found_seat] = customer_pawn finish_action(controller, TRUE) return @@ -34,7 +34,7 @@ // SPT_PROB 1.5 is about a 60% chance that the tourist will have vocalised at least once every minute. if(!controller.blackboard[BB_CUSTOMER_SAID_CANT_FIND_SEAT_LINE] || SPT_PROB(1.5, seconds_per_tick)) customer_pawn.say(pick(customer_data.cant_find_seat_lines)) - controller.blackboard[BB_CUSTOMER_SAID_CANT_FIND_SEAT_LINE] = TRUE + controller.set_blackboard_key(BB_CUSTOMER_SAID_CANT_FIND_SEAT_LINE, TRUE) finish_action(controller, FALSE) @@ -46,9 +46,7 @@ . = ..() var/mob/living/simple_animal/robot_customer/customer_pawn = controller.pawn var/datum/customer_data/customer_data = controller.blackboard[BB_CUSTOMER_CUSTOMERINFO] - - var/datum/weakref/seat_ref = controller.blackboard[BB_CUSTOMER_MY_SEAT] - var/obj/structure/holosign/robot_seat/seat_marker = seat_ref?.resolve() + var/obj/structure/holosign/robot_seat/seat_marker = controller.blackboard[BB_CUSTOMER_MY_SEAT] if(get_turf(seat_marker) == get_turf(customer_pawn)) var/obj/structure/chair/my_seat = locate(/obj/structure/chair) in get_turf(customer_pawn) if(my_seat) @@ -56,7 +54,7 @@ var/datum/venue/attending_venue = controller.blackboard[BB_CUSTOMER_ATTENDING_VENUE] - controller.blackboard[BB_CUSTOMER_CURRENT_ORDER] = attending_venue.order_food(customer_pawn, customer_data) + controller.set_blackboard_key(BB_CUSTOMER_CURRENT_ORDER, attending_venue.order_food(customer_pawn, customer_data)) finish_action(controller, TRUE) @@ -70,7 +68,7 @@ finish_action(controller, TRUE) return - controller.blackboard[BB_CUSTOMER_PATIENCE] -= seconds_per_tick * 10 // Convert seconds_per_tick to a SECONDS equivalent. + controller.add_blackboard_key(BB_CUSTOMER_PATIENCE, seconds_per_tick * -1 SECONDS) // Convert seconds_per_tick to a SECONDS equivalent. if(controller.blackboard[BB_CUSTOMER_PATIENCE] < 0 || controller.blackboard[BB_CUSTOMER_LEAVING]) // Check if we're leaving because sometthing mightve forced us to finish_action(controller, FALSE) return @@ -81,8 +79,7 @@ var/datum/customer_data/customer_data = controller.blackboard[BB_CUSTOMER_CUSTOMERINFO] customer_pawn.say(pick(customer_data.wait_for_food_lines)) - var/datum/weakref/seat_ref = controller.blackboard[BB_CUSTOMER_MY_SEAT] - var/obj/structure/holosign/robot_seat/seat_marker = seat_ref?.resolve() + var/obj/structure/holosign/robot_seat/seat_marker = controller.blackboard[BB_CUSTOMER_MY_SEAT] if(get_turf(seat_marker) == get_turf(controller.pawn)) var/obj/structure/chair/my_seat = locate(/obj/structure/chair) in get_turf(controller.pawn) if(my_seat) @@ -108,7 +105,7 @@ //or are being qdeleted and don't want runtime errors, so don't switch to leaving if(greytider || QDELETED(src)) return - controller.blackboard[BB_CUSTOMER_LEAVING] = TRUE + controller.set_blackboard_key(BB_CUSTOMER_LEAVING, TRUE) customer_pawn.update_icon() //They might have a special leaving accesoiry (french flag) if(succeeded) customer_pawn.say(pick(customer_data.leave_happy_lines)) diff --git a/code/datums/ai/robot_customer/robot_customer_controller.dm b/code/datums/ai/robot_customer/robot_customer_controller.dm index ebbfe31fbed..ca47798726b 100644 --- a/code/datums/ai/robot_customer/robot_customer_controller.dm +++ b/code/datums/ai/robot_customer/robot_customer_controller.dm @@ -13,8 +13,8 @@ /datum/ai_controller/robot_customer/Destroy() // clear possible datum refs - blackboard[BB_CUSTOMER_CURRENT_ORDER] = null - blackboard[BB_CUSTOMER_CUSTOMERINFO] = null + clear_blackboard_key(BB_CUSTOMER_CURRENT_ORDER) + clear_blackboard_key(BB_CUSTOMER_CUSTOMERINFO) return ..() /datum/ai_controller/robot_customer/TryPossessPawn(atom/new_pawn) @@ -51,12 +51,12 @@ if(blackboard[BB_CUSTOMER_EATING]) return - blackboard[BB_CUSTOMER_EATING] = TRUE + set_blackboard_key(BB_CUSTOMER_EATING, TRUE) attending_venue.on_get_order(pawn, order_item) var/our_order = blackboard[BB_CUSTOMER_CURRENT_ORDER] if(isdatum(our_order)) qdel(our_order) - blackboard[BB_CUSTOMER_CURRENT_ORDER] = null + clear_blackboard_key(BB_CUSTOMER_CURRENT_ORDER) ///Called when @@ -101,7 +101,7 @@ return if(3) customer.say(customer_data.self_defense_line) - blackboard[BB_CUSTOMER_CURRENT_TARGET] = greytider + set_blackboard_key(BB_CUSTOMER_CURRENT_TARGET, greytider) CancelActions() diff --git a/code/datums/ai/robot_customer/robot_customer_subtrees.dm b/code/datums/ai/robot_customer/robot_customer_subtrees.dm index b5fb4bd786e..3fd2d8ed547 100644 --- a/code/datums/ai/robot_customer/robot_customer_subtrees.dm +++ b/code/datums/ai/robot_customer/robot_customer_subtrees.dm @@ -8,8 +8,7 @@ controller.queue_behavior(/datum/ai_behavior/break_spine, BB_CUSTOMER_CURRENT_TARGET) return SUBTREE_RETURN_FINISH_PLANNING - var/datum/weakref/seat_ref = controller.blackboard[BB_CUSTOMER_MY_SEAT] - var/obj/structure/holosign/robot_seat/seat_marker = seat_ref?.resolve() + var/obj/structure/holosign/robot_seat/seat_marker = controller.blackboard[BB_CUSTOMER_MY_SEAT] if(!seat_marker) //We havn't got a seat yet! find one! controller.queue_behavior(/datum/ai_behavior/find_seat) diff --git a/code/datums/components/ai_retaliate_advanced.dm b/code/datums/components/ai_retaliate_advanced.dm index 8be84dc5cef..87e7442832d 100644 --- a/code/datums/components/ai_retaliate_advanced.dm +++ b/code/datums/components/ai_retaliate_advanced.dm @@ -25,9 +25,6 @@ if (!victim.ai_controller) return - var/list/enemy_refs = victim.ai_controller.blackboard[BB_BASIC_MOB_RETALIATE_LIST] - if (!enemy_refs) - enemy_refs = list() - enemy_refs |= WEAKREF(attacker) - victim.ai_controller.blackboard[BB_BASIC_MOB_RETALIATE_LIST] = enemy_refs + + victim.ai_controller.insert_blackboard_key_lazylist(BB_BASIC_MOB_RETALIATE_LIST, attacker) post_retaliate_callback?.InvokeAsync(attacker) diff --git a/code/datums/components/pet_commands/fetch.dm b/code/datums/components/pet_commands/fetch.dm index 8898597de2d..a8723f8bd4b 100644 --- a/code/datums/components/pet_commands/fetch.dm +++ b/code/datums/components/pet_commands/fetch.dm @@ -39,7 +39,7 @@ var/list/blackboard = parent.ai_controller.blackboard if (!trigger_on_throw && !blackboard[BB_ACTIVE_PET_COMMAND]) return // We don't have a command and we only listen to commands - if (blackboard[BB_ACTIVE_PET_COMMAND] && blackboard[BB_ACTIVE_PET_COMMAND] != WEAKREF(src)) + if (blackboard[BB_ACTIVE_PET_COMMAND] && blackboard[BB_ACTIVE_PET_COMMAND] != src) return // We have a command and it's not this one if (blackboard[BB_CURRENT_PET_TARGET] || blackboard[BB_FETCH_DELIVER_TO]) return // We're already very fetching @@ -49,7 +49,7 @@ var/obj/item/thrown_thing = thrower.get_active_held_item() if (!isitem(thrown_thing)) return - if (blackboard[BB_FETCH_IGNORE_LIST] && blackboard[BB_FETCH_IGNORE_LIST][WEAKREF(thrown_thing)]) + if (blackboard[BB_FETCH_IGNORE_LIST]?[thrown_thing]) return // We're ignoring it already RegisterSignal(thrown_thing, COMSIG_MOVABLE_THROW_LANDED, PROC_REF(listen_throw_land)) @@ -69,7 +69,7 @@ try_activate_command(throwing_datum.thrower) set_command_target(parent, thrown_thing) - parent.ai_controller.blackboard[BB_FETCH_DELIVER_TO] = WEAKREF(throwing_datum.thrower) + parent.ai_controller.set_blackboard_key(BB_FETCH_DELIVER_TO, throwing_datum.thrower) // Don't try and fetch turfs or anchored objects if someone points at them /datum/pet_command/point_targetting/fetch/look_for_target(mob/living/pointing_friend, obj/item/pointed_atom) @@ -82,16 +82,15 @@ return FALSE var/mob/living/parent = weak_parent.resolve() - parent.ai_controller.blackboard[BB_FETCH_DELIVER_TO] = WEAKREF(pointing_friend) + parent.ai_controller.set_blackboard_key(BB_FETCH_DELIVER_TO, pointing_friend) // Finally, plan our actions /datum/pet_command/point_targetting/fetch/execute_action(datum/ai_controller/controller) controller.queue_behavior(/datum/ai_behavior/forget_failed_fetches) - var/datum/weakref/weak_target = controller.blackboard[BB_CURRENT_PET_TARGET] - var/atom/target = weak_target?.resolve() + var/atom/target = controller.blackboard[BB_CURRENT_PET_TARGET] // We got something to fetch so go fetch it - if (target) + if (!QDELETED(target)) if (get_dist(controller.pawn, target) > 1) // We're not there yet controller.queue_behavior(/datum/ai_behavior/fetch_seek, BB_CURRENT_PET_TARGET, BB_FETCH_DELIVER_TO) return SUBTREE_RETURN_FINISH_PLANNING @@ -99,16 +98,14 @@ controller.queue_behavior(/datum/ai_behavior/pick_up_item, BB_CURRENT_PET_TARGET, BB_SIMPLE_CARRY_ITEM) return SUBTREE_RETURN_FINISH_PLANNING - var/datum/weakref/carried_ref = controller.blackboard[BB_SIMPLE_CARRY_ITEM] - var/obj/item/carried_item = carried_ref?.resolve() - if (!carried_item) + var/obj/item/carried_item = controller.blackboard[BB_SIMPLE_CARRY_ITEM] + if (QDELETED(carried_item)) return - var/datum/weakref/delivery_ref = controller.blackboard[BB_FETCH_DELIVER_TO] - var/atom/delivery_target = delivery_ref?.resolve() - if (!delivery_target || !can_see(controller.pawn, delivery_target, sense_radius)) + var/atom/delivery_target = controller.blackboard[BB_FETCH_DELIVER_TO] + if (QDELETED(delivery_target) || !can_see(controller.pawn, delivery_target, sense_radius)) // We don't know where to return this to so we're just going to keep it - controller.blackboard[BB_ACTIVE_PET_COMMAND] = null + controller.clear_blackboard_key(BB_ACTIVE_PET_COMMAND) return // We got something to deliver and someone to deliver it to diff --git a/code/datums/components/pet_commands/obeys_commands.dm b/code/datums/components/pet_commands/obeys_commands.dm index 3b80bd88eb3..cb516d9502e 100644 --- a/code/datums/components/pet_commands/obeys_commands.dm +++ b/code/datums/components/pet_commands/obeys_commands.dm @@ -57,10 +57,7 @@ if (IS_DEAD_OR_INCAP(source)) return - if (!source.ai_controller) - return - var/list/friends_list = source.ai_controller.blackboard[BB_FRIENDS_LIST] - if (!friends_list || !friends_list[WEAKREF(user)]) + if (!(user in source.ai_controller?.blackboard[BB_FRIENDS_LIST])) return examine_list += span_notice("[source.p_they(capitalized = TRUE)] seem[source.p_s()] happy to see you!") @@ -71,10 +68,7 @@ var/mob/living/living_parent = parent if (IS_DEAD_OR_INCAP(living_parent)) return - if (!living_parent.ai_controller) - return - var/list/friends_list = living_parent.ai_controller.blackboard[BB_FRIENDS_LIST] - if (!friends_list || !friends_list[WEAKREF(clicker)]) + if (!(clicker in living_parent.ai_controller?.blackboard[BB_FRIENDS_LIST])) return // Not our friend, can't boss us around INVOKE_ASYNC(src, PROC_REF(display_radial_menu), clicker) diff --git a/code/datums/components/pet_commands/pet_command.dm b/code/datums/components/pet_commands/pet_command.dm index 97a71b59470..7899ffce40a 100644 --- a/code/datums/components/pet_commands/pet_command.dm +++ b/code/datums/components/pet_commands/pet_command.dm @@ -68,7 +68,7 @@ return if (IS_DEAD_OR_INCAP(parent)) // Probably can't hear them if we're dead return - if (parent.ai_controller.blackboard[BB_ACTIVE_PET_COMMAND] == WEAKREF(src)) // We're already doing it + if (parent.ai_controller.blackboard[BB_ACTIVE_PET_COMMAND] == src) // We're already doing it return set_command_active(parent, commander) @@ -77,13 +77,13 @@ set_command_target(parent, null) parent.ai_controller.CancelActions() // Stop whatever you're doing and do this instead - parent.ai_controller.blackboard[BB_ACTIVE_PET_COMMAND] = WEAKREF(src) + parent.ai_controller.set_blackboard_key(BB_ACTIVE_PET_COMMAND, src) if (command_feedback) parent.balloon_alert_to_viewers("[command_feedback]") // If we get a nicer runechat way to do this, refactor this /// Store the target for the AI blackboard /datum/pet_command/proc/set_command_target(mob/living/parent, atom/target) - parent.ai_controller.blackboard[BB_CURRENT_PET_TARGET] = WEAKREF(target) + parent.ai_controller.set_blackboard_key(BB_CURRENT_PET_TARGET, target) /// Provide information about how to display this command in a radial menu /datum/pet_command/proc/provide_radial_data() @@ -137,9 +137,9 @@ return FALSE if (IS_DEAD_OR_INCAP(parent)) return FALSE - if (parent.ai_controller.blackboard[BB_ACTIVE_PET_COMMAND] != WEAKREF(src)) // We're not listening right now + if (parent.ai_controller.blackboard[BB_ACTIVE_PET_COMMAND] != src) // We're not listening right now return FALSE - if (parent.ai_controller.blackboard[BB_CURRENT_PET_TARGET] == WEAKREF(pointed_atom)) // That's already our target + if (parent.ai_controller.blackboard[BB_CURRENT_PET_TARGET] == pointed_atom) // That's already our target return FALSE if (!can_see(parent, pointed_atom, sense_radius)) return FALSE diff --git a/code/datums/components/pet_commands/pet_commands_basic.dm b/code/datums/components/pet_commands/pet_commands_basic.dm index 674b2b467d8..a562c116843 100644 --- a/code/datums/components/pet_commands/pet_commands_basic.dm +++ b/code/datums/components/pet_commands/pet_commands_basic.dm @@ -28,7 +28,7 @@ command_feedback = "relaxes" /datum/pet_command/free/execute_action(datum/ai_controller/controller) - controller.blackboard[BB_ACTIVE_PET_COMMAND] = null + controller.clear_blackboard_key(BB_ACTIVE_PET_COMMAND) return // Just move on to the next planning subtree. /** @@ -87,7 +87,7 @@ // If we get past this point someone has finally added a non-binary dog /datum/pet_command/good_boy/execute_action(datum/ai_controller/controller) - controller.blackboard[BB_ACTIVE_PET_COMMAND] = null + controller.clear_blackboard_key(BB_ACTIVE_PET_COMMAND) var/mob/living/parent = weak_parent.resolve() if (!parent) return SUBTREE_RETURN_FINISH_PLANNING diff --git a/code/datums/elements/ai_flee_while_injured.dm b/code/datums/elements/ai_flee_while_injured.dm index f990d9d3166..fc1a2e33281 100644 --- a/code/datums/elements/ai_flee_while_injured.dm +++ b/code/datums/elements/ai_flee_while_injured.dm @@ -36,10 +36,10 @@ if (current_health_percentage < stop_fleeing_at) return source.ai_controller.CancelActions() // Stop fleeing go back to whatever you were doing - source.ai_controller.blackboard[BB_BASIC_MOB_FLEEING] = FALSE + source.ai_controller.set_blackboard_key(BB_BASIC_MOB_FLEEING, FALSE) return if (current_health_percentage > start_fleeing_below) return source.ai_controller.CancelActions() - source.ai_controller.blackboard[BB_BASIC_MOB_FLEEING] = TRUE + source.ai_controller.set_blackboard_key(BB_BASIC_MOB_FLEEING, TRUE) diff --git a/code/datums/elements/ai_held_item.dm b/code/datums/elements/ai_held_item.dm index 9fbe9c77c05..6bfb4e43b70 100644 --- a/code/datums/elements/ai_held_item.dm +++ b/code/datums/elements/ai_held_item.dm @@ -20,8 +20,7 @@ /// Returns the item held in a mob's blackboard, if it has one /datum/element/ai_held_item/proc/get_held_item(mob/living/source) - var/datum/weakref/weak_item = source.ai_controller.blackboard[BB_SIMPLE_CARRY_ITEM] - return weak_item?.resolve() + return source.ai_controller.blackboard[BB_SIMPLE_CARRY_ITEM] /// Someone's interacting with us by hand, if we have an item and like them we'll hand it over /datum/element/ai_held_item/proc/on_click(mob/living/source, mob/living/user) @@ -30,8 +29,7 @@ if (user.combat_mode) return - var/list/friends = source.ai_controller.blackboard[BB_FRIENDS_LIST] - if (!friends || !friends[WEAKREF(user)]) + if (!(user in source.ai_controller.blackboard[BB_FRIENDS_LIST])) return // We don't care about this bozo var/obj/item/carried_item = get_held_item(source) if (!carried_item) @@ -39,7 +37,7 @@ source.visible_message(span_danger("[source] drops [carried_item] at [user]'s feet!")) carried_item.forceMove(get_turf(user)) - source.ai_controller.blackboard[BB_SIMPLE_CARRY_ITEM] = null + source.ai_controller.clear_blackboard_key(BB_SIMPLE_CARRY_ITEM) /// If our held item is removed from our atom then take it off the blackboard /datum/element/ai_held_item/proc/atom_exited(mob/living/source, atom/movable/gone) @@ -47,7 +45,7 @@ var/obj/item/carried_item = get_held_item(source) if (carried_item == gone) - source.ai_controller.blackboard[BB_SIMPLE_CARRY_ITEM] = null + source.ai_controller.clear_blackboard_key(BB_SIMPLE_CARRY_ITEM) /// Report that we're holding an item. /datum/element/ai_held_item/proc/on_examined(mob/living/source, mob/user, list/examine_text) @@ -68,4 +66,4 @@ ol_yeller.visible_message(span_danger("[ol_yeller] drops [carried_item] as [ol_yeller.p_they()] die[ol_yeller.p_s()].")) carried_item.forceMove(ol_yeller.drop_location()) - ol_yeller.ai_controller.blackboard[BB_SIMPLE_CARRY_ITEM] = null + ol_yeller.ai_controller.clear_blackboard_key(BB_SIMPLE_CARRY_ITEM) diff --git a/code/datums/elements/ai_retaliate.dm b/code/datums/elements/ai_retaliate.dm index d4e2144f558..3fb8494a99e 100644 --- a/code/datums/elements/ai_retaliate.dm +++ b/code/datums/elements/ai_retaliate.dm @@ -20,10 +20,4 @@ /datum/element/ai_retaliate/proc/on_attacked(mob/victim, atom/attacker) SIGNAL_HANDLER - if (!victim.ai_controller) - return - var/list/enemy_refs = victim.ai_controller.blackboard[BB_BASIC_MOB_RETALIATE_LIST] - if (!enemy_refs) - enemy_refs = list() - enemy_refs |= WEAKREF(attacker) - victim.ai_controller.blackboard[BB_BASIC_MOB_RETALIATE_LIST] = enemy_refs + victim.ai_controller?.insert_blackboard_key_lazylist(BB_BASIC_MOB_RETALIATE_LIST, attacker) diff --git a/code/datums/elements/cursed.dm b/code/datums/elements/cursed.dm index f8742fe61b2..b45693d6526 100644 --- a/code/datums/elements/cursed.dm +++ b/code/datums/elements/cursed.dm @@ -11,7 +11,7 @@ return COMPONENT_INCOMPATIBLE var/obj/item/master = target var/datum/ai_controller/ai = new /datum/ai_controller/cursed(master) - ai.blackboard[BB_TARGET_SLOT] = slot + ai.set_blackboard_key(BB_TARGET_SLOT, slot) master.ai_controller = ai master.AddElement(/datum/element/movetype_handler) ADD_TRAIT(master, TRAIT_MOVE_FLYING, ELEMENT_TRAIT(type)) diff --git a/code/game/machinery/computer/arcade/orion_event.dm b/code/game/machinery/computer/arcade/orion_event.dm index bd800911916..ea81b67532d 100644 --- a/code/game/machinery/computer/arcade/orion_event.dm +++ b/code/game/machinery/computer/arcade/orion_event.dm @@ -526,7 +526,7 @@ playsound(game, 'sound/items/weeoo1.ogg', 100, FALSE) for(var/i in 1 to 3) var/mob/living/basic/syndicate/ranged/smg/orion/spaceport_security = new(get_turf(game)) - spaceport_security.ai_controller.blackboard[BB_BASIC_MOB_CURRENT_TARGET] = REF(usr) + spaceport_security.ai_controller.set_blackboard_key(BB_BASIC_MOB_CURRENT_TARGET, usr) game.fuel += fuel game.food += food diff --git a/code/modules/antagonists/revenant/haunted_item.dm b/code/modules/antagonists/revenant/haunted_item.dm index a9eac99ddc2..a4772912a61 100644 --- a/code/modules/antagonists/revenant/haunted_item.dm +++ b/code/modules/antagonists/revenant/haunted_item.dm @@ -55,7 +55,7 @@ continue // This gives all mobs in view "5" haunt level // For reference picking one up gives "2" - haunted_item.ai_controller.blackboard[BB_TO_HAUNT_LIST][WEAKREF(victim)] = 5 + haunted_item.ai_controller.add_blackboard_key_assoc(BB_TO_HAUNT_LIST, victim, 5) if(haunted_item.throwforce < throw_force_max) pre_haunt_throwforce = haunted_item.throwforce diff --git a/code/modules/clothing/head/mind_monkey_helmet.dm b/code/modules/clothing/head/mind_monkey_helmet.dm index c9520821ce2..83fa277d225 100644 --- a/code/modules/clothing/head/mind_monkey_helmet.dm +++ b/code/modules/clothing/head/mind_monkey_helmet.dm @@ -81,7 +81,7 @@ if(prob(10)) switch(rand(1,4)) if(1) //blood rage - magnification.ai_controller.blackboard[BB_MONKEY_AGGRESSIVE] = TRUE + magnification.ai_controller.set_blackboard_key(BB_MONKEY_AGGRESSIVE, TRUE) if(2) //brain death magnification.apply_damage(500,BRAIN,BODY_ZONE_HEAD,FALSE,FALSE,FALSE) if(3) //primal gene (gorilla) diff --git a/code/modules/food_and_drinks/restaurant/_venue.dm b/code/modules/food_and_drinks/restaurant/_venue.dm index 3565db52163..c42483e6849 100644 --- a/code/modules/food_and_drinks/restaurant/_venue.dm +++ b/code/modules/food_and_drinks/restaurant/_venue.dm @@ -153,7 +153,7 @@ restaurant_portal.update_icon() STOP_PROCESSING(SSobj, src) for(var/mob/living/simple_animal/robot_customer as anything in current_visitors) - robot_customer.ai_controller.blackboard[BB_CUSTOMER_LEAVING] = TRUE //LEAVEEEEEE + robot_customer.ai_controller.set_blackboard_key(BB_CUSTOMER_LEAVING, TRUE) //LEAVEEEEEE /obj/machinery/restaurant_portal name = "restaurant portal" diff --git a/code/modules/mob/living/basic/farm_animals/cow/_cow.dm b/code/modules/mob/living/basic/farm_animals/cow/_cow.dm index 4c80cc4f8b5..949a3cd0c34 100644 --- a/code/modules/mob/living/basic/farm_animals/cow/_cow.dm +++ b/code/modules/mob/living/basic/farm_animals/cow/_cow.dm @@ -45,7 +45,7 @@ udder_component() setup_eating() . = ..() - ai_controller.blackboard[BB_BASIC_FOODS] = food_types + ai_controller.set_blackboard_key(BB_BASIC_FOODS, food_types) ///wrapper for the udder component addition so you can have uniquely uddered cow subtypes /mob/living/basic/cow/proc/udder_component() @@ -86,5 +86,5 @@ /mob/living/basic/cow/proc/set_tip_react_blackboard(mob/living/carbon/tipper) if(!HAS_TRAIT_FROM(src, TRAIT_IMMOBILIZED, TIPPED_OVER) || !ai_controller) return - ai_controller.blackboard[BB_BASIC_MOB_TIP_REACTING] = TRUE - ai_controller.blackboard[BB_BASIC_MOB_TIPPER] = tipper + ai_controller.set_blackboard_key(BB_BASIC_MOB_TIP_REACTING, TRUE) + ai_controller.set_blackboard_key(BB_BASIC_MOB_TIPPER, tipper) diff --git a/code/modules/mob/living/basic/farm_animals/deer.dm b/code/modules/mob/living/basic/farm_animals/deer.dm index a016f8b74a6..9daf27452d4 100644 --- a/code/modules/mob/living/basic/farm_animals/deer.dm +++ b/code/modules/mob/living/basic/farm_animals/deer.dm @@ -28,9 +28,9 @@ . = ..() AddElement(/datum/element/footstep, footstep_type = FOOTSTEP_MOB_SHOE) var/time_to_freeze_for = (rand(5, 10) SECONDS) - ai_controller.blackboard[BB_STATIONARY_SECONDS] = time_to_freeze_for - ai_controller.blackboard[BB_STATIONARY_COOLDOWN] = (time_to_freeze_for * (rand(3, 5))) - ai_controller.blackboard[BB_STATIONARY_TARGETS] = stationary_scary_things + ai_controller.set_blackboard_key(BB_STATIONARY_SECONDS, time_to_freeze_for) + ai_controller.set_blackboard_key(BB_STATIONARY_COOLDOWN, (time_to_freeze_for * (rand(3, 5)))) + ai_controller.set_blackboard_key(BB_STATIONARY_TARGETS, stationary_scary_things) /datum/ai_controller/basic_controller/deer blackboard = list( diff --git a/code/modules/mob/living/basic/festivus_pole.dm b/code/modules/mob/living/basic/festivus_pole.dm index c2c055fc47d..0a453f2c9e6 100644 --- a/code/modules/mob/living/basic/festivus_pole.dm +++ b/code/modules/mob/living/basic/festivus_pole.dm @@ -45,7 +45,7 @@ AddElement(/datum/element/death_drops, list(/obj/item/stack/rods)) var/datum/action/cooldown/mob_cooldown/charge_apc/charge_ability = new(src) charge_ability.Grant(src) - ai_controller.blackboard[BB_FESTIVE_APC] = WEAKREF(charge_ability) + ai_controller.set_blackboard_key(BB_FESTIVE_APC, charge_ability) /datum/ai_controller/basic_controller/festivus_pole blackboard = list( @@ -98,8 +98,7 @@ always_reset_target = TRUE /datum/ai_behavior/hunt_target/apcs/target_caught(mob/living/basic/hunter, obj/machinery/power/apc/hunted) - var/datum/weakref/ability_weakref = hunter.ai_controller.blackboard[BB_FESTIVE_APC] - var/datum/action/cooldown/mob_cooldown/charge_ability = ability_weakref?.resolve() + var/datum/action/cooldown/mob_cooldown/charge_ability = hunter.ai_controller.blackboard[BB_FESTIVE_APC] if(isnull(charge_ability)) return charge_ability.Activate(hunted) diff --git a/code/modules/mob/living/basic/heretic/star_gazer.dm b/code/modules/mob/living/basic/heretic/star_gazer.dm index f6eeb755994..1d3e520c3f7 100644 --- a/code/modules/mob/living/basic/heretic/star_gazer.dm +++ b/code/modules/mob/living/basic/heretic/star_gazer.dm @@ -86,8 +86,7 @@ /datum/ai_behavior/basic_melee_attack/star_gazer/perform(seconds_per_tick, datum/ai_controller/controller, target_key, targetting_datum_key, hiding_location_key) . = ..() - var/datum/weakref/weak_target = controller.blackboard[target_key] - var/atom/target = weak_target?.resolve() + var/atom/target = controller.blackboard[target_key] var/mob/living/living_pawn = controller.pawn if(!isliving(target)) diff --git a/code/modules/mob/living/basic/lavaland/bileworm/_bileworm.dm b/code/modules/mob/living/basic/lavaland/bileworm/_bileworm.dm index c8df6d001f4..c38f2b9e469 100644 --- a/code/modules/mob/living/basic/lavaland/bileworm/_bileworm.dm +++ b/code/modules/mob/living/basic/lavaland/bileworm/_bileworm.dm @@ -56,6 +56,6 @@ devour.Grant(src) var/datum/action/adjust_vision/bileworm/adjust_vision = new(src) adjust_vision.Grant(src) - ai_controller.blackboard[BB_BILEWORM_SPEW_BILE] = WEAKREF(spew_bile) - ai_controller.blackboard[BB_BILEWORM_RESURFACE] = WEAKREF(resurface) - ai_controller.blackboard[BB_BILEWORM_DEVOUR] = WEAKREF(devour) + ai_controller.set_blackboard_key(BB_BILEWORM_SPEW_BILE, spew_bile) + ai_controller.set_blackboard_key(BB_BILEWORM_RESURFACE, resurface) + ai_controller.set_blackboard_key(BB_BILEWORM_DEVOUR, devour) diff --git a/code/modules/mob/living/basic/lavaland/bileworm/bileworm_actions.dm b/code/modules/mob/living/basic/lavaland/bileworm/bileworm_actions.dm index 0be00961bfb..c3e753d992e 100644 --- a/code/modules/mob/living/basic/lavaland/bileworm/bileworm_actions.dm +++ b/code/modules/mob/living/basic/lavaland/bileworm/bileworm_actions.dm @@ -15,7 +15,7 @@ to_chat(burrower, span_warning("Couldn't burrow anywhere near the target!")) if(burrower.ai_controller?.ai_status == AI_STATUS_ON) //this is a valid reason to give up on a target - burrower.ai_controller.blackboard[BB_BASIC_MOB_CURRENT_TARGET] = null + burrower.ai_controller.clear_blackboard_key(BB_BASIC_MOB_CURRENT_TARGET) return playsound(burrower, 'sound/effects/break_stone.ogg', 50, TRUE) new /obj/effect/temp_visual/mook_dust(get_turf(burrower)) diff --git a/code/modules/mob/living/basic/lavaland/bileworm/bileworm_ai.dm b/code/modules/mob/living/basic/lavaland/bileworm/bileworm_ai.dm index 2877dd2909b..28a5b026797 100644 --- a/code/modules/mob/living/basic/lavaland/bileworm/bileworm_ai.dm +++ b/code/modules/mob/living/basic/lavaland/bileworm/bileworm_ai.dm @@ -13,17 +13,15 @@ /datum/ai_planning_subtree/bileworm_attack/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) - var/datum/weakref/weak_target = controller.blackboard[BB_BASIC_MOB_CURRENT_TARGET] - var/mob/living/target = weak_target?.resolve() + var/mob/living/target = controller.blackboard[BB_BASIC_MOB_CURRENT_TARGET] if(QDELETED(target)) return - var/datum/weakref/weak_action = controller.blackboard[BB_BILEWORM_RESURFACE] - var/datum/action/cooldown/mob_cooldown/resurface = weak_action?.resolve() + var/datum/action/cooldown/mob_cooldown/resurface = controller.blackboard[BB_BILEWORM_RESURFACE] //because one ability is always INFINITY cooldown, this actually works to check which ability should be used //sometimes it will try to spew bile on infinity cooldown, but that's okay because as soon as resurface is ready it will attempt that - if(resurface && resurface.next_use_time <= world.time) + if(!QDELETED(resurface) && resurface.next_use_time <= world.time) controller.queue_behavior(/datum/ai_behavior/targeted_mob_ability/and_plan_execute, BB_BILEWORM_RESURFACE, BB_BASIC_MOB_CURRENT_TARGET) else controller.queue_behavior(/datum/ai_behavior/targeted_mob_ability/and_plan_execute, BB_BILEWORM_SPEW_BILE, BB_BASIC_MOB_CURRENT_TARGET) @@ -33,8 +31,7 @@ /datum/ai_planning_subtree/bileworm_execute/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) - var/datum/weakref/weak_target = controller.blackboard[BB_BASIC_MOB_EXECUTION_TARGET] - var/mob/living/target = weak_target?.resolve() + var/mob/living/target = controller.blackboard[BB_BASIC_MOB_EXECUTION_TARGET] if(QDELETED(target) || target.stat < UNCONSCIOUS) return diff --git a/code/modules/mob/living/basic/pets/dog.dm b/code/modules/mob/living/basic/pets/dog.dm index 2fc1132a11a..ac72f782a9c 100644 --- a/code/modules/mob/living/basic/pets/dog.dm +++ b/code/modules/mob/living/basic/pets/dog.dm @@ -14,7 +14,7 @@ /datum/pet_command/point_targetting/attack/dog/set_command_active(mob/living/parent, mob/living/commander) . = ..() - parent.ai_controller.blackboard[BB_DOG_HARASS_HARM] = TRUE + parent.ai_controller.set_blackboard_key(BB_DOG_HARASS_HARM, TRUE) /mob/living/basic/pet/dog mob_biotypes = MOB_ORGANIC|MOB_BEAST @@ -159,7 +159,7 @@ /mob/living/basic/pet/dog/corgi/proc/stop_deadchat_plays() var/controller_type = initial(ai_controller) ai_controller = new controller_type(src) - ai_controller?.blackboard[BB_DOG_IS_SLOW] = is_slow + ai_controller?.set_blackboard_key(BB_DOG_IS_SLOW, is_slow) /mob/living/basic/pet/dog/corgi/handle_atom_del(atom/A) if(A == inventory_head) @@ -556,7 +556,7 @@ GLOBAL_LIST_INIT(strippable_corgi_items, create_strippable_list(list( held_state = "old_corgi" icon_dead = "old_corgi_dead" desc = "At a ripe old age of [record_age], Ian's not as spry as he used to be, but he'll always be the HoP's beloved corgi." //RIP - ai_controller?.blackboard[BB_DOG_IS_SLOW] = TRUE + ai_controller?.set_blackboard_key(BB_DOG_IS_SLOW, TRUE) is_slow = TRUE speed = 2 diff --git a/code/modules/mob/living/basic/space_fauna/carp/carp.dm b/code/modules/mob/living/basic/space_fauna/carp/carp.dm index d25a93b76a2..4d0897647a6 100644 --- a/code/modules/mob/living/basic/space_fauna/carp/carp.dm +++ b/code/modules/mob/living/basic/space_fauna/carp/carp.dm @@ -118,8 +118,9 @@ teleport = new(src) teleport.Grant(src) - ai_controller.blackboard[BB_CARP_RIFT] = WEAKREF(teleport) - ai_controller.blackboard[BB_OBSTACLE_TARGETTING_WHITELIST] = allowed_obstacle_targets + ai_controller.set_blackboard_key(BB_CARP_RIFT, teleport) + ai_controller.set_blackboard_key(BB_OBSTACLE_TARGETTING_WHITELIST, allowed_obstacle_targets) + /mob/living/basic/carp/Destroy() QDEL_NULL(teleport) @@ -129,7 +130,7 @@ /mob/living/basic/carp/proc/setup_eating() AddElement(/datum/element/basic_eating, 10, 0, null, desired_food) AddElement(/datum/element/basic_eating, 0, 10, BRUTE, desired_trash) // We are killing our planet - ai_controller.blackboard[BB_BASIC_FOODS] = desired_food + desired_trash + ai_controller.set_blackboard_key(BB_BASIC_FOODS, desired_food + desired_trash) /// Set a random colour on the carp, override to do something else /mob/living/basic/carp/proc/apply_colour() @@ -151,9 +152,16 @@ /mob/living/basic/carp/ranged_secondary_attack(atom/atom_target, modifiers) teleport.Trigger(target = atom_target) -/// Gives the carp a list of destinations to try and travel between when it has nothing better to do -/mob/living/basic/carp/proc/migrate_to(list/migration_points) - ai_controller.blackboard[BB_CARP_MIGRATION_PATH] = migration_points +/// Gives the carp a list of weakrefs of destinations to try and travel between when it has nothing better to do +/mob/living/basic/carp/proc/migrate_to(list/datum/weakref/migration_points) + var/list/actual_points = list() + for(var/datum/weakref/point_ref as anything in migration_points) + var/turf/point_resolved = point_ref.resolve() + if(QDELETED(point_resolved)) + return // invalid list, we can't migrate to this + actual_points += point_resolved + + ai_controller.set_blackboard_key(BB_CARP_MIGRATION_PATH, actual_points) /** * Holographic carp from the holodeck diff --git a/code/modules/mob/living/basic/space_fauna/carp/carp_ai_actions.dm b/code/modules/mob/living/basic/space_fauna/carp/carp_ai_actions.dm index 0f35ab97625..c0f5143f18c 100644 --- a/code/modules/mob/living/basic/space_fauna/carp/carp_ai_actions.dm +++ b/code/modules/mob/living/basic/space_fauna/carp/carp_ai_actions.dm @@ -42,8 +42,7 @@ /datum/ai_planning_subtree/find_nearest_magicarp_spell_target /datum/ai_planning_subtree/find_nearest_magicarp_spell_target/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) - var/datum/weakref/weak_action = controller.blackboard[BB_MAGICARP_SPELL] - var/datum/action/cooldown/using_action = weak_action?.resolve() + var/datum/action/cooldown/using_action = controller.blackboard[BB_MAGICARP_SPELL] if (QDELETED(using_action)) return if (!using_action.IsAvailable()) diff --git a/code/modules/mob/living/basic/space_fauna/carp/carp_ai_migration.dm b/code/modules/mob/living/basic/space_fauna/carp/carp_ai_migration.dm index ac7bccaa226..c7bee5a36e9 100644 --- a/code/modules/mob/living/basic/space_fauna/carp/carp_ai_migration.dm +++ b/code/modules/mob/living/basic/space_fauna/carp/carp_ai_migration.dm @@ -22,8 +22,7 @@ if (!length(migration_points)) return - var/datum/weakref/weak_target = controller.blackboard[BB_CARP_MIGRATION_TARGET] - var/turf/moving_to = weak_target?.resolve() + var/turf/moving_to = controller.blackboard[BB_CARP_MIGRATION_TARGET] // If we don't have a target or are close enough to it, pick a new one if (isnull(moving_to) || get_dist(controller.pawn, moving_to) <= CARP_DESTINATION_SEARCH_RANGE) @@ -48,13 +47,12 @@ var/list/blackboard_points = controller.blackboard[path_key] var/list/potential_migration_points = blackboard_points.Copy() while (length(potential_migration_points)) - var/datum/weakref/weak_destination = popleft(potential_migration_points) - var/turf/potential_destination = weak_destination.resolve() + var/turf/potential_destination = popleft(potential_migration_points) if (!isnull(potential_destination) && get_dist(controller.pawn, potential_destination) > CARP_DESTINATION_SEARCH_RANGE) - controller.blackboard[target_key] = weak_destination + controller.set_blackboard_key(target_key, potential_destination) finish_action(controller, succeeded = TRUE) return - controller.blackboard[path_key] = potential_migration_points.Copy() + controller.set_blackboard_key(path_key, potential_migration_points.Copy()) finish_action(controller, succeeded = FALSE) diff --git a/code/modules/mob/living/basic/space_fauna/carp/carp_ai_rift_actions.dm b/code/modules/mob/living/basic/space_fauna/carp/carp_ai_rift_actions.dm index d94e480493a..88a9f6706f2 100644 --- a/code/modules/mob/living/basic/space_fauna/carp/carp_ai_rift_actions.dm +++ b/code/modules/mob/living/basic/space_fauna/carp/carp_ai_rift_actions.dm @@ -12,14 +12,9 @@ if (!rift_behaviour) CRASH("Forgot to specify rift behaviour for [src]") - var/datum/weakref/weak_target = controller.blackboard[BB_BASIC_MOB_CURRENT_TARGET] - var/mob/living/target = weak_target?.resolve() - if (!target) - return - - var/datum/weakref/weak_action = controller.blackboard[BB_CARP_RIFT] - var/datum/action/cooldown/using_action = weak_action?.resolve() - if (isnull(using_action) || !using_action.IsAvailable()) + var/mob/living/target = controller.blackboard[BB_BASIC_MOB_CURRENT_TARGET] + var/datum/action/cooldown/using_action = controller.blackboard[BB_CARP_RIFT] + if (QDELETED(target) || QDELETED(using_action) || !using_action.IsAvailable()) return controller.queue_behavior(rift_behaviour, BB_CARP_RIFT, BB_BASIC_MOB_CURRENT_TARGET) @@ -53,20 +48,12 @@ /datum/ai_behavior/make_carp_rift /datum/ai_behavior/make_carp_rift/setup(datum/ai_controller/controller, ability_key, target_key) - var/datum/weakref/weak_action = controller.blackboard[ability_key] - var/datum/action/cooldown/mob_cooldown/lesser_carp_rift/ability = weak_action?.resolve() - if (!ability) - return FALSE - var/datum/weakref/weak_target = controller.blackboard[target_key] - var/atom/target = weak_target?.resolve() - return target + return controller.blackboard[ability_key] && controller.blackboard[target_key] /datum/ai_behavior/make_carp_rift/perform(seconds_per_tick, datum/ai_controller/controller, ability_key, target_key) . = ..() - var/datum/weakref/weak_action = controller.blackboard[ability_key] - var/datum/action/cooldown/mob_cooldown/lesser_carp_rift/ability = weak_action?.resolve() - var/datum/weakref/weak_target = controller.blackboard[target_key] - var/atom/target = weak_target?.resolve() + var/datum/action/cooldown/mob_cooldown/lesser_carp_rift/ability = controller.blackboard[ability_key] + var/atom/target = controller.blackboard[target_key] if (!validate_target(controller, target, ability)) finish_action(controller, FALSE, ability_key, target_key) @@ -187,9 +174,8 @@ var/minimum_distance = 2 /datum/ai_planning_subtree/shortcut_to_target_through_carp_rift/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) - var/datum/weakref/weak_target = controller.blackboard[BB_BASIC_MOB_CURRENT_TARGET] - var/mob/living/target = weak_target?.resolve() - if (isnull(target)) + var/mob/living/target = controller.blackboard[BB_BASIC_MOB_CURRENT_TARGET] + if (QDELETED(target)) return var/distance_to_target = get_dist(controller.pawn, target) diff --git a/code/modules/mob/living/basic/space_fauna/carp/magicarp.dm b/code/modules/mob/living/basic/space_fauna/carp/magicarp.dm index 90418d7e467..5051335a557 100644 --- a/code/modules/mob/living/basic/space_fauna/carp/magicarp.dm +++ b/code/modules/mob/living/basic/space_fauna/carp/magicarp.dm @@ -88,7 +88,7 @@ GLOBAL_LIST_INIT(magicarp_spell_colours, list( spell.projectile_type = spell_type spell.button_icon_state = initial(spell_type.icon_state) spell.Grant(src) - ai_controller.blackboard[BB_MAGICARP_SPELL] = WEAKREF(spell) + ai_controller.set_blackboard_key(BB_MAGICARP_SPELL, spell) assign_spell_ai(spell_type) /// If you have certain spells, use a different targetting datum @@ -99,7 +99,7 @@ GLOBAL_LIST_INIT(magicarp_spell_colours, list( /obj/projectile/magic/resurrection = MAGICARP_SPELL_CORPSES, ) - ai_controller.blackboard[BB_MAGICARP_SPELL_SPECIAL_TARGETTING] = spell_special_targetting[spell_type] + ai_controller.set_blackboard_key(BB_MAGICARP_SPELL_SPECIAL_TARGETTING, spell_special_targetting[spell_type]) /// Shoot when you click away from you /mob/living/basic/carp/magic/RangedAttack(atom/atom_target, modifiers) @@ -123,7 +123,7 @@ GLOBAL_LIST_INIT(magicarp_spell_colours, list( chaos_bolt.permitted_projectiles = allowed_projectile_types chaos_bolt.Grant(src) spell = chaos_bolt - ai_controller.blackboard[BB_MAGICARP_SPELL] = spell + ai_controller.set_blackboard_key(BB_MAGICARP_SPELL, spell) RegisterSignal(spell, COMSIG_ACTION_TRIGGER, PROC_REF(apply_colour)) /// Has a more limited spell pool but can appear from gold slime cores diff --git a/code/modules/mob/living/basic/space_fauna/faithless.dm b/code/modules/mob/living/basic/space_fauna/faithless.dm index 8b0fc1f3cd8..b279856412c 100644 --- a/code/modules/mob/living/basic/space_fauna/faithless.dm +++ b/code/modules/mob/living/basic/space_fauna/faithless.dm @@ -67,8 +67,7 @@ /datum/ai_behavior/basic_melee_attack/faithless/perform(seconds_per_tick, datum/ai_controller/controller, target_key, targetting_datum_key, hiding_location_key) . = ..() - var/datum/weakref/weak_target = controller.blackboard[target_key] - var/atom/target = weak_target?.resolve() + var/atom/target = controller.blackboard[target_key] var/mob/living/living_pawn = controller.pawn if(!isliving(target)) diff --git a/code/modules/mob/living/basic/space_fauna/garden_gnome.dm b/code/modules/mob/living/basic/space_fauna/garden_gnome.dm index f6a9f5a685a..034bf0deb0f 100644 --- a/code/modules/mob/living/basic/space_fauna/garden_gnome.dm +++ b/code/modules/mob/living/basic/space_fauna/garden_gnome.dm @@ -119,13 +119,8 @@ /mob/living/basic/garden_gnome/proc/ai_retaliate_behaviour(mob/living/attacker) if (!istype(attacker)) return - var/list/enemy_refs for (var/mob/living/basic/garden_gnome/potential_gnome in oview(src, 7)) - enemy_refs = potential_gnome.ai_controller.blackboard[BB_BASIC_MOB_RETALIATE_LIST] - if (!enemy_refs) - enemy_refs = list() - enemy_refs |= WEAKREF(attacker) - potential_gnome.ai_controller.blackboard[BB_BASIC_MOB_RETALIATE_LIST] = enemy_refs + potential_gnome.ai_controller.insert_blackboard_key_lazylist(BB_BASIC_MOB_RETALIATE_LIST, attacker) /datum/ai_controller/basic_controller/garden_gnome blackboard = list( diff --git a/code/modules/mob/living/basic/space_fauna/giant_spider/giant_spider.dm b/code/modules/mob/living/basic/space_fauna/giant_spider/giant_spider.dm index 81fc08af989..5cd75f6433b 100644 --- a/code/modules/mob/living/basic/space_fauna/giant_spider/giant_spider.dm +++ b/code/modules/mob/living/basic/space_fauna/giant_spider/giant_spider.dm @@ -73,7 +73,7 @@ var/datum/action/cooldown/lay_web/webbing = new web_type(src) webbing.webbing_time *= web_speed webbing.Grant(src) - ai_controller.blackboard[BB_SPIDER_WEB_ACTION] = WEAKREF(webbing) + ai_controller.set_blackboard_key(BB_SPIDER_WEB_ACTION, webbing) /mob/living/basic/giant_spider/Login() . = ..() diff --git a/code/modules/mob/living/basic/space_fauna/giant_spider/spider_subtrees.dm b/code/modules/mob/living/basic/space_fauna/giant_spider/spider_subtrees.dm index ad9015d8e1a..85d7636ffc9 100644 --- a/code/modules/mob/living/basic/space_fauna/giant_spider/spider_subtrees.dm +++ b/code/modules/mob/living/basic/space_fauna/giant_spider/spider_subtrees.dm @@ -15,16 +15,15 @@ /datum/ai_behavior/find_unwebbed_turf/perform(seconds_per_tick, datum/ai_controller/controller) . = ..() var/mob/living/spider = controller.pawn - var/datum/weakref/weak_target = controller.blackboard[target_key] - var/atom/current_target = weak_target?.resolve() + var/atom/current_target = controller.blackboard[target_key] if (current_target && !(locate(/obj/structure/spider/stickyweb) in current_target)) finish_action(controller, succeeded = FALSE) // Already got a target return - controller.blackboard[target_key] = null + controller.clear_blackboard_key(target_key) var/turf/our_turf = get_turf(spider) if (is_valid_web_turf(our_turf)) - controller.blackboard[target_key] = WEAKREF(our_turf) + controller.set_blackboard_key(target_key, our_turf) finish_action(controller, succeeded = TRUE) return @@ -38,7 +37,7 @@ finish_action(controller, succeeded = FALSE) return - controller.blackboard[target_key] = WEAKREF(get_closest_atom(/turf/, potential_turfs, our_turf)) + controller.set_blackboard_key(target_key, get_closest_atom(/turf/, potential_turfs, our_turf)) finish_action(controller, succeeded = TRUE) /datum/ai_behavior/find_unwebbed_turf/proc/is_valid_web_turf(turf/target_turf, mob/living/spider) @@ -54,11 +53,9 @@ var/target_key = BB_SPIDER_WEB_TARGET /datum/ai_planning_subtree/spin_web/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) - var/datum/weakref/weak_action = controller.blackboard[action_key] - var/datum/action/cooldown/using_action = weak_action?.resolve() - var/datum/weakref/weak_target = controller.blackboard[target_key] - var/turf/target_turf = weak_target?.resolve() - if (!using_action || !target_turf) + var/datum/action/cooldown/using_action = controller.blackboard[action_key] + var/turf/target_turf = controller.blackboard[target_key] + if (QDELETED(using_action) || QDELETED(target_turf)) return controller.queue_behavior(/datum/ai_behavior/spin_web, action_key, target_key) return SUBTREE_RETURN_FINISH_PLANNING @@ -70,10 +67,8 @@ behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT | AI_BEHAVIOR_CAN_PLAN_DURING_EXECUTION /datum/ai_behavior/spin_web/setup(datum/ai_controller/controller, action_key, target_key) - var/datum/weakref/weak_action = controller.blackboard[action_key] - var/datum/action/cooldown/web_action = weak_action?.resolve() - var/datum/weakref/weak_target = controller.blackboard[target_key] - var/turf/target_turf = weak_target?.resolve() + var/datum/action/cooldown/web_action = controller.blackboard[action_key] + var/turf/target_turf = controller.blackboard[target_key] if (!web_action || !target_turf) return FALSE @@ -82,10 +77,9 @@ /datum/ai_behavior/spin_web/perform(seconds_per_tick, datum/ai_controller/controller, action_key, target_key) . = ..() - var/datum/weakref/weak_action = controller.blackboard[action_key] - var/datum/action/cooldown/web_action = weak_action?.resolve() + var/datum/action/cooldown/web_action = controller.blackboard[action_key] finish_action(controller, succeeded = web_action?.Trigger(), action_key = action_key, target_key = target_key) /datum/ai_behavior/spin_web/finish_action(datum/ai_controller/controller, succeeded, action_key, target_key) - controller.blackboard[target_key] = null + controller.clear_blackboard_key(target_key) return ..() diff --git a/code/modules/mob/living/basic/space_fauna/meteor_heart/meteor_heart.dm b/code/modules/mob/living/basic/space_fauna/meteor_heart/meteor_heart.dm index e56bbc4aa84..07c9205de09 100644 --- a/code/modules/mob/living/basic/space_fauna/meteor_heart/meteor_heart.dm +++ b/code/modules/mob/living/basic/space_fauna/meteor_heart/meteor_heart.dm @@ -40,11 +40,11 @@ spikes = new(src) spikes.Grant(src) - ai_controller.blackboard[BB_METEOR_HEART_GROUND_SPIKES] = WEAKREF(spikes) + ai_controller.set_blackboard_key(BB_METEOR_HEART_GROUND_SPIKES, spikes) traps = new(src) traps.Grant(src) - ai_controller.blackboard[BB_METEOR_HEART_SPINE_TRAPS] = WEAKREF(traps) + ai_controller.set_blackboard_key(BB_METEOR_HEART_SPINE_TRAPS, traps) ai_controller.set_ai_status(AI_STATUS_OFF) diff --git a/code/modules/mob/living/basic/space_fauna/wumborian_fugu/inflation.dm b/code/modules/mob/living/basic/space_fauna/wumborian_fugu/inflation.dm index e6e3d2200d7..d459648892b 100644 --- a/code/modules/mob/living/basic/space_fauna/wumborian_fugu/inflation.dm +++ b/code/modules/mob/living/basic/space_fauna/wumborian_fugu/inflation.dm @@ -65,7 +65,7 @@ fugu.melee_damage_upper = 20 fugu.status_flags |= GODMODE fugu.obj_damage = 60 - fugu.ai_controller.blackboard[BB_BASIC_MOB_FLEEING] = FALSE + fugu.ai_controller.set_blackboard_key(BB_BASIC_MOB_FLEEING, FALSE) fugu.ai_controller.CancelActions() /datum/status_effect/inflated/on_remove() @@ -84,7 +84,7 @@ if (fugu.stat != DEAD) fugu.icon_state = "Fugu0" fugu.obj_damage = 0 - fugu.ai_controller.blackboard[BB_BASIC_MOB_FLEEING] = TRUE + fugu.ai_controller.set_blackboard_key(BB_BASIC_MOB_FLEEING, TRUE) fugu.ai_controller.CancelActions() /// Remove status effect if we die diff --git a/code/modules/mob/living/basic/space_fauna/wumborian_fugu/wumborian_fugu.dm b/code/modules/mob/living/basic/space_fauna/wumborian_fugu/wumborian_fugu.dm index e25c7a38643..b36a0916a75 100644 --- a/code/modules/mob/living/basic/space_fauna/wumborian_fugu/wumborian_fugu.dm +++ b/code/modules/mob/living/basic/space_fauna/wumborian_fugu/wumborian_fugu.dm @@ -53,7 +53,7 @@ add_traits(list(TRAIT_LAVA_IMMUNE, TRAIT_ASHSTORM_IMMUNE), ROUNDSTART_TRAIT) expand = new(src) expand.Grant(src) - ai_controller.blackboard[BB_FUGU_INFLATE] = WEAKREF(expand) + ai_controller.set_blackboard_key(BB_FUGU_INFLATE, expand) /mob/living/basic/wumborian_fugu/Destroy() QDEL_NULL(expand) diff --git a/code/modules/mob/living/basic/vermin/mouse.dm b/code/modules/mob/living/basic/vermin/mouse.dm index ca9c76b9456..d8d1dbbc1f7 100644 --- a/code/modules/mob/living/basic/vermin/mouse.dm +++ b/code/modules/mob/living/basic/vermin/mouse.dm @@ -379,8 +379,7 @@ /datum/ai_planning_subtree/flee_target/mouse /datum/ai_planning_subtree/flee_target/mouse/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) - var/datum/weakref/hunting_weakref = controller.blackboard[BB_CURRENT_HUNTING_TARGET] - var/atom/hunted_cheese = hunting_weakref?.resolve() + var/atom/hunted_cheese = controller.blackboard[BB_CURRENT_HUNTING_TARGET] if (!isnull(hunted_cheese)) return // We see some cheese, which is more important than our life return ..() diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 581e8caab5c..f0042e07f45 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -2454,12 +2454,8 @@ GLOBAL_LIST_EMPTY(fire_appearances) if (faction.Find(friend_ref)) return FALSE faction |= friend_ref - if (ai_controller) - var/list/friends = ai_controller.blackboard[BB_FRIENDS_LIST] - if (!friends) - friends = list() - friends[WEAKREF(new_friend)] = TRUE - ai_controller.blackboard[BB_FRIENDS_LIST] = friends + ai_controller?.insert_blackboard_key_lazylist(BB_FRIENDS_LIST, new_friend) + SEND_SIGNAL(src, COMSIG_LIVING_BEFRIENDED, new_friend) return TRUE @@ -2470,12 +2466,8 @@ GLOBAL_LIST_EMPTY(fire_appearances) if (!faction.Find(friend_ref)) return FALSE faction -= friend_ref - if (ai_controller) - var/list/friends = ai_controller.blackboard[BB_FRIENDS_LIST] - if (!friends) - return - friends[WEAKREF(old_friend)] = FALSE - ai_controller.blackboard[BB_FRIENDS_LIST] = friends + ai_controller?.remove_thing_from_blackboard_key(BB_FRIENDS_LIST, old_friend) + SEND_SIGNAL(src, COMSIG_LIVING_UNFRIENDED, old_friend) return TRUE diff --git a/code/modules/mob/living/simple_animal/friendly/robot_customer.dm b/code/modules/mob/living/simple_animal/friendly/robot_customer.dm index ff38ec6e601..baa09c0eb86 100644 --- a/code/modules/mob/living/simple_animal/friendly/robot_customer.dm +++ b/code/modules/mob/living/simple_animal/friendly/robot_customer.dm @@ -29,9 +29,9 @@ clothes_set = pick(customer_info.clothing_sets) ai_controller = customer_info.ai_controller_used . = ..() - ai_controller.blackboard[BB_CUSTOMER_CUSTOMERINFO] = customer_info - ai_controller.blackboard[BB_CUSTOMER_ATTENDING_VENUE] = attending_venue - ai_controller.blackboard[BB_CUSTOMER_PATIENCE] = customer_info.total_patience + ai_controller.set_blackboard_key(BB_CUSTOMER_CUSTOMERINFO, customer_info) + ai_controller.set_blackboard_key(BB_CUSTOMER_ATTENDING_VENUE, attending_venue) + ai_controller.set_blackboard_key(BB_CUSTOMER_PATIENCE, customer_info.total_patience) icon = customer_info.base_icon icon_state = customer_info.base_icon_state name = "[pick(customer_info.name_prefixes)]-bot" @@ -41,9 +41,8 @@ ///Clean up on the mobs seat etc when its deleted (Either by murder or because it left) /mob/living/simple_animal/robot_customer/Destroy() var/datum/venue/attending_venue = ai_controller.blackboard[BB_CUSTOMER_ATTENDING_VENUE] + var/obj/structure/holosign/robot_seat/our_seat = ai_controller.blackboard[BB_CUSTOMER_MY_SEAT] attending_venue.current_visitors -= src - var/datum/weakref/seat_ref = ai_controller.blackboard[BB_CUSTOMER_MY_SEAT] - var/obj/structure/holosign/robot_seat/our_seat = seat_ref?.resolve() if(attending_venue.linked_seats[our_seat]) attending_venue.linked_seats[our_seat] = null QDEL_NULL(hud_to_show_on_hover) @@ -90,6 +89,7 @@ /mob/living/simple_animal/robot_customer/examine(mob/user) . = ..() + // this should be handled by the ai controller if(ai_controller.blackboard[BB_CUSTOMER_CURRENT_ORDER]) var/datum/venue/attending_venue = ai_controller.blackboard[BB_CUSTOMER_ATTENDING_VENUE] var/wanted_item = ai_controller.blackboard[BB_CUSTOMER_CURRENT_ORDER] diff --git a/code/modules/mod/modules/module_pathfinder.dm b/code/modules/mod/modules/module_pathfinder.dm index a86c3ae0421..5f40982e9e9 100644 --- a/code/modules/mod/modules/module_pathfinder.dm +++ b/code/modules/mod/modules/module_pathfinder.dm @@ -110,8 +110,8 @@ var/datum/ai_controller/mod_ai = new /datum/ai_controller/mod(module.mod) module.mod.ai_controller = mod_ai mod_ai.set_movement_target(type, imp_in) - mod_ai.blackboard[BB_MOD_TARGET] = imp_in - mod_ai.blackboard[BB_MOD_IMPLANT] = src + mod_ai.set_blackboard_key(BB_MOD_TARGET, imp_in) + mod_ai.set_blackboard_key(BB_MOD_IMPLANT, src) module.mod.interaction_flags_item &= ~INTERACT_ITEM_ATTACK_HAND_PICKUP module.mod.AddElement(/datum/element/movetype_handler) ADD_TRAIT(module.mod, TRAIT_MOVE_FLYING, MOD_TRAIT) diff --git a/code/modules/surgery/organs/augments_eyes.dm b/code/modules/surgery/organs/augments_eyes.dm index 21422828f24..837b10443f2 100644 --- a/code/modules/surgery/organs/augments_eyes.dm +++ b/code/modules/surgery/organs/augments_eyes.dm @@ -44,6 +44,7 @@ desc = "These cybernetic eye implants will display a security HUD over everything you see." HUD_type = DATA_HUD_SECURITY_ADVANCED HUD_trait = TRAIT_SECURITY_HUD + organ_flags = ALL /obj/item/organ/internal/cyberimp/eyes/hud/diagnostic name = "Diagnostic HUD implant" diff --git a/code/modules/unit_tests/monkey_business.dm b/code/modules/unit_tests/monkey_business.dm index 7c8e4ddcf74..20bfffe6a48 100644 --- a/code/modules/unit_tests/monkey_business.dm +++ b/code/modules/unit_tests/monkey_business.dm @@ -22,5 +22,5 @@ new /datum/ai_controller/monkey/angry(monkey) else new /datum/ai_controller/monkey(monkey) - monkey.ai_controller.blackboard[BB_MONKEY_TARGET_MONKEYS] = TRUE + monkey.ai_controller.set_blackboard_key(BB_MONKEY_TARGET_MONKEYS, TRUE) sleep(monkey_timer) diff --git a/code/modules/unit_tests/mouse_bite_cable.dm b/code/modules/unit_tests/mouse_bite_cable.dm index 0fa72ce0cf1..6d3150d279d 100644 --- a/code/modules/unit_tests/mouse_bite_cable.dm +++ b/code/modules/unit_tests/mouse_bite_cable.dm @@ -24,7 +24,7 @@ // Process behavior - this will execute the "locate the cable" behavior biter.ai_controller.process(fake_dt) // Check that the cable was found - TEST_ASSERT(biter.ai_controller.blackboard[BB_LOW_PRIORITY_HUNTING_TARGET] == WEAKREF(wire), "Mouse, after executing find, did not set the cable as a target.") + TEST_ASSERT(biter.ai_controller.blackboard[BB_LOW_PRIORITY_HUNTING_TARGET] == wire, "Mouse, after executing find, did not set the cable as a target.") // Select behavior - this will queue hunting biter.ai_controller.SelectBehaviors(fake_dt) // Process behavior - this will execute the hunt for the cable and cause a bite (as we're in the min range)