mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-13 09:05:11 +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,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
|
||||
|
||||
@@ -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 ..()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 ..()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
. = ..()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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("<b>[pawn]</b> 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)
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 ..()
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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