Experiment with replacing weakrefs in AI blackboard with deleting signals, ideally making it easier to work with and harder to cause hard deletes (#74791)

## About The Pull Request

Replaces weakref usage in AI blackboards with deleting signals

All blackboard var setting must go through setters rather than directly

## Why It's Good For The Game

This both makes it a ton easier to develop AI for, and also makes it
harder for hard deletes to sneak in, as has been seen with recent 515
prs showing hard deletes in AI blackboards

(To quantify "making it easier to develop AI", I found multiple bugs in
existing AI code due to the usage of weakrefs.)

I'm looking for `@Jacquerel` `@tralezab` 's opinions on the matter, also
maybe `@LemonInTheDark` if they're interested

## Changelog

🆑 Melbert
refactor: Mob ai refactored once again
/🆑
This commit is contained in:
MrMelbert
2023-04-23 18:07:17 -05:00
committed by GitHub
parent 23b09f8a14
commit ed2f04f486
92 changed files with 688 additions and 592 deletions
@@ -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)
+5 -7
View File
@@ -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)
+1 -7
View File
@@ -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)
+1 -1
View File
@@ -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))