mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-18 19:44:58 +01:00
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:
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user