diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm index 36ef596098d..2aba4b44b75 100644 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm @@ -334,3 +334,6 @@ #define FAIL_PROB_INDEX 1 /// Index in modifiers containing the modifer to surgery speed #define SPEED_MOD_INDEX 2 + +///from mob/living/befriend() +#define COMSIG_LIVING_MADE_NEW_FRIEND "made_new_friend" diff --git a/code/datums/ai/basic_mobs/base_basic_controller.dm b/code/datums/ai/basic_mobs/base_basic_controller.dm index 4fe208667af..26d3e39e5a4 100644 --- a/code/datums/ai/basic_mobs/base_basic_controller.dm +++ b/code/datums/ai/basic_mobs/base_basic_controller.dm @@ -7,7 +7,8 @@ var/mob/living/basic/basic_mob = new_pawn update_speed(basic_mob) - + RegisterSignal(basic_mob, COMSIG_LIVING_BEFRIENDED, PROC_REF(on_tamed)) + RegisterSignal(basic_mob, COMSIG_LIVING_UNFRIENDED, PROC_REF(on_untamed)) RegisterSignals(basic_mob, list(POST_BASIC_MOB_UPDATE_VARSPEED, COMSIG_MOB_MOVESPEED_UPDATED), PROC_REF(update_speed)) RegisterSignal(basic_mob, COMSIG_MOB_ATE, PROC_REF(on_mob_eat)) @@ -56,3 +57,29 @@ SIGNAL_HANDLER var/food_cooldown = blackboard[BB_EAT_FOOD_COOLDOWN] || EAT_FOOD_COOLDOWN set_blackboard_key(BB_NEXT_FOOD_EAT, world.time + food_cooldown) + + +/datum/ai_controller/proc/on_tamed(datum/source, mob/living/new_friend) + SIGNAL_HANDLER + forgive_target(new_friend) + clear_blackboard_key(BB_BASIC_MOB_CURRENT_TARGET) + clear_blackboard_key(BB_BASIC_MOB_RETALIATE_LIST) //we have just been tamed by a new party, clean slate for everyone! + RegisterSignal(new_friend, COMSIG_LIVING_MADE_NEW_FRIEND, PROC_REF(on_master_tame)) + +/datum/ai_controller/proc/on_untamed(datum/source, mob/living/old_friend) + SIGNAL_HANDLER + UnregisterSignal(old_friend, COMSIG_LIVING_MADE_NEW_FRIEND) + +/datum/ai_controller/proc/on_master_tame(datum/master, mob/living/master_new_friend) + SIGNAL_HANDLER + forgive_target(master_new_friend) + +/datum/ai_controller/proc/forgive_target(atom/target) + var/static/list/keys_to_check = list( + BB_BASIC_MOB_CURRENT_TARGET, + BB_CURRENT_PET_TARGET, + ) + for(var/key in keys_to_check) + if(target == blackboard[key]) + clear_blackboard_key(key) + remove_from_blackboard_lazylist_key(BB_BASIC_MOB_RETALIATE_LIST, target) //make peace with our friend's new pet! diff --git a/code/datums/ai/basic_mobs/basic_subtrees/target_retaliate.dm b/code/datums/ai/basic_mobs/basic_subtrees/target_retaliate.dm index 775fd3367d1..6893bad6f6a 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/target_retaliate.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/target_retaliate.dm @@ -46,7 +46,7 @@ if (!check_faction) controller.set_blackboard_key(BB_TEMPORARILY_IGNORE_FACTION, TRUE) - if (!QDELETED(existing_target) && (locate(existing_target) in shitlist) && targeting_strategy.can_attack(living_mob, existing_target, vision_range)) + if (!QDELETED(existing_target) && targeting_strategy.can_attack(living_mob, existing_target, vision_range)) return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED var/list/enemies_list = list() diff --git a/code/datums/components/pet_commands/pet_commands_basic.dm b/code/datums/components/pet_commands/pet_commands_basic.dm index bd544a47295..2269f760ba4 100644 --- a/code/datums/components/pet_commands/pet_commands_basic.dm +++ b/code/datums/components/pet_commands/pet_commands_basic.dm @@ -277,6 +277,9 @@ var/mob/living/victim = controller.blackboard[BB_CURRENT_PET_TARGET] if(QDELETED(victim)) return + var/datum/targeting_strategy/targeter = GET_TARGETING_STRATEGY(controller.blackboard[targeting_strategy_key]) + if(!targeter.can_attack(controller.pawn, victim)) + return // cancel the action if they're below our given crit stat, OR if we're trying to attack ourselves (this can happen on tamed mobs w/ protect subtree rarely) if(victim.stat > controller.blackboard[BB_TARGET_MINIMUM_STAT] || victim == controller.pawn) controller.clear_blackboard_key(BB_ACTIVE_PET_COMMAND) diff --git a/code/datums/components/tameable.dm b/code/datums/components/tameable.dm index 747d729ee1d..6c64bfde0e0 100644 --- a/code/datums/components/tameable.dm +++ b/code/datums/components/tameable.dm @@ -56,7 +56,6 @@ /datum/component/tameable/proc/on_tame(atom/source, mob/living/tamer, obj/item/food, inform_tamer = FALSE) SIGNAL_HANDLER source.tamed(tamer, food)//Run custom behavior if needed - if(isliving(parent) && isliving(tamer)) INVOKE_ASYNC(source, TYPE_PROC_REF(/mob/living, befriend), tamer) if(inform_tamer) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index db52d09d486..c181ceaca9e 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -2767,6 +2767,7 @@ GLOBAL_LIST_EMPTY(fire_appearances) /// Proc for giving a mob a new 'friend', generally used for AI control and targeting. Returns false if already friends or null if qdeleted. /mob/living/proc/befriend(mob/living/new_friend) SHOULD_CALL_PARENT(TRUE) + SEND_SIGNAL(new_friend, COMSIG_LIVING_MADE_NEW_FRIEND, src) if(QDELETED(new_friend)) return var/friend_ref = REF(new_friend)