mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-13 17:14:47 +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:
@@ -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
|
||||
|
||||
|
||||
@@ -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])
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user