mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-24 05:30:05 +01:00
[MIRROR] Experiment with replacing weakrefs in AI blackboard with deleting signals, ideally making it easier to work with and harder to cause hard deletes [MDB IGNORE] (#20719)
* 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 /🆑 * Experiment with replacing weakrefs in AI blackboard with deleting signals, ideally making it easier to work with and harder to cause hard deletes --------- Co-authored-by: MrMelbert <51863163+MrMelbert@users.noreply.github.com>
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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()
|
||||
. = ..()
|
||||
|
||||
@@ -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 ..()
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -380,8 +380,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 ..()
|
||||
|
||||
@@ -2517,12 +2517,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
|
||||
|
||||
@@ -2533,12 +2529,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
|
||||
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user