diff --git a/code/__DEFINES/ai.dm b/code/__DEFINES/ai.dm index 6bb160969e2..d9a52bbb3b2 100644 --- a/code/__DEFINES/ai.dm +++ b/code/__DEFINES/ai.dm @@ -165,6 +165,7 @@ #define BB_DOG_PLAYING_DEAD "BB_DOG_PLAYING_DEAD" #define BB_DOG_HARASS_TARGET "BB_DOG_HARASS_TARGET" #define BB_DOG_HARASS_FRUSTRATION "BB_DOG_HARASS_FRUSTRATION" +#define BB_DOG_HARASS_HARM "BB_DOG_HARASS_HARM" #define BB_DOG_IS_SLOW "BB_DOG_IS_SLOW" /// Basically, what is our vision/hearing range for picking up on things to fetch/ diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index fbf40de05a5..97b36905235 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -441,6 +441,9 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai /// If the mob has this trait and die, their bomb implant doesn't detonate automatically. It must be consciously activated. #define TRAIT_PREVENT_IMPLANT_AUTO_EXPLOSION "prevent_implant_auto_explosion" +/// If applied to a mob, nearby dogs will have a small chance to nonharmfully harass said mob +#define TRAIT_HATED_BY_DOGS "hated_by_dogs" + // METABOLISMS // Various jobs on the station have historically had better reactions // to various drinks and foodstuffs. Security liking donuts is a classic diff --git a/code/datums/ai/dog/dog_behaviors.dm b/code/datums/ai/dog/dog_behaviors.dm index 358ae968be4..8c16ca5e52f 100644 --- a/code/datums/ai/dog/dog_behaviors.dm +++ b/code/datums/ai/dog/dog_behaviors.dm @@ -163,7 +163,7 @@ /// This behavior involves either eating a snack we can reach, or begging someone holding a snack /datum/ai_behavior/harass behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT | AI_BEHAVIOR_MOVE_AND_PERFORM - required_distance = 1 + required_distance = 3 /datum/ai_behavior/harass/perform(delta_time, datum/ai_controller/controller) . = ..() @@ -215,13 +215,19 @@ controller.blackboard[BB_DOG_HARASS_FRUSTRATION] = world.time - // make sure the pawn gets some temporary strength boost to actually attack the target instead of pathetically nuzzling them. - var/old_melee_lower = living_pawn.melee_damage_lower - var/old_melee_upper = living_pawn.melee_damage_upper - living_pawn.melee_damage_lower = max(5, old_melee_lower) - living_pawn.melee_damage_upper = max(10, old_melee_upper) + if(controller.blackboard[BB_DOG_HARASS_HARM]) + // make sure the pawn gets some temporary strength boost to actually attack the target instead of pathetically nuzzling them. + var/old_melee_lower = living_pawn.melee_damage_lower + var/old_melee_upper = living_pawn.melee_damage_upper + living_pawn.melee_damage_lower = max(5, old_melee_lower) + living_pawn.melee_damage_upper = max(10, old_melee_upper) - living_pawn.UnarmedAttack(living_target, FALSE) + living_pawn.UnarmedAttack(living_target, FALSE) - living_pawn.melee_damage_lower = old_melee_lower - living_pawn.melee_damage_upper = old_melee_upper + living_pawn.melee_damage_lower = old_melee_lower + living_pawn.melee_damage_upper = old_melee_upper + else + if(prob(20)) + living_pawn.do_attack_animation(living_target, ATTACK_EFFECT_DISARM) + playsound(living_target, 'sound/weapons/thudswoosh.ogg', 50, TRUE, -1) + living_target.visible_message(span_danger("[living_pawn] paws ineffectually at [living_target]!"), span_danger("[living_pawn] paws ineffectually at you!")) diff --git a/code/datums/ai/dog/dog_controller.dm b/code/datums/ai/dog/dog_controller.dm index 84e9f621a27..c06902426ad 100644 --- a/code/datums/ai/dog/dog_controller.dm +++ b/code/datums/ai/dog/dog_controller.dm @@ -9,6 +9,7 @@ BB_DOG_PLAYING_DEAD = FALSE, BB_DOG_HARASS_TARGET = null, BB_DOG_HARASS_FRUSTRATION = null, + BB_DOG_HARASS_HARM = TRUE, BB_VISION_RANGE = AI_DOG_VISION_RANGE, ) ai_movement = /datum/ai_movement/jps @@ -280,6 +281,7 @@ pawn.visible_message(span_notice("[pawn] follows [pointing_friend]'s gesture towards [pointed_movable] and growls intensely!")) set_movement_target(pointed_movable) blackboard[BB_DOG_HARASS_TARGET] = WEAKREF(pointed_movable) + blackboard[BB_DOG_HARASS_HARM] = TRUE if(living_pawn.buckled) queue_behavior(/datum/ai_behavior/resist)//in case they are in bed or something queue_behavior(/datum/ai_behavior/harass) @@ -299,6 +301,7 @@ BB_DOG_PLAYING_DEAD = FALSE, BB_DOG_HARASS_TARGET = null, BB_DOG_HARASS_FRUSTRATION = null, + BB_DOG_HARASS_HARM = TRUE, BB_VISION_RANGE = AI_DOG_VISION_RANGE, BB_BABIES_PARTNER_TYPES = list(/mob/living/basic/pet/dog), diff --git a/code/datums/ai/dog/dog_subtrees.dm b/code/datums/ai/dog/dog_subtrees.dm index e31106f0a8c..ac1eca95d95 100644 --- a/code/datums/ai/dog/dog_subtrees.dm +++ b/code/datums/ai/dog/dog_subtrees.dm @@ -38,3 +38,15 @@ controller.set_movement_target(type, return_target) controller.queue_behavior(/datum/ai_behavior/deliver_item) return + + if(DT_PROB(10, delta_time)) + for(var/mob/living/iter_living in oview(2, living_pawn)) + if(iter_living.stat != CONSCIOUS || !HAS_TRAIT(iter_living, TRAIT_HATED_BY_DOGS)) + continue + + living_pawn.audible_message(span_warning("[living_pawn] growls at [iter_living], seemingly annoyed by [iter_living.p_their()] presence."), hearing_distance = COMBAT_MESSAGE_RANGE) + controller.set_movement_target(iter_living) + controller.blackboard[BB_DOG_HARASS_TARGET] = WEAKREF(iter_living) + controller.blackboard[BB_DOG_HARASS_HARM] = FALSE + controller.queue_behavior(/datum/ai_behavior/harass) + return diff --git a/code/modules/clothing/head/hat.dm b/code/modules/clothing/head/hat.dm index 58c048f7672..a0d0d12924a 100644 --- a/code/modules/clothing/head/hat.dm +++ b/code/modules/clothing/head/hat.dm @@ -49,6 +49,7 @@ name = "mailman's hat" icon_state = "mailman" desc = "'Right-on-time' mail service head wear." + clothing_traits = list(TRAIT_HATED_BY_DOGS) /obj/item/clothing/head/bio_hood/plague name = "plague doctor's hat" diff --git a/code/modules/clothing/under/miscellaneous.dm b/code/modules/clothing/under/miscellaneous.dm index eb99f4efc7a..6a2b7d4c69c 100644 --- a/code/modules/clothing/under/miscellaneous.dm +++ b/code/modules/clothing/under/miscellaneous.dm @@ -26,6 +26,7 @@ desc = "'Special delivery!'" icon_state = "mailman" inhand_icon_state = "b_suit" + clothing_traits = list(TRAIT_HATED_BY_DOGS) /obj/item/clothing/under/misc/psyche name = "psychedelic jumpsuit" diff --git a/code/modules/mob/living/carbon/human/species_types/felinid.dm b/code/modules/mob/living/carbon/human/species_types/felinid.dm index 6e3a6e7ce48..58b3ccd8fe1 100644 --- a/code/modules/mob/living/carbon/human/species_types/felinid.dm +++ b/code/modules/mob/living/carbon/human/species_types/felinid.dm @@ -10,6 +10,7 @@ external_organs = list( /obj/item/organ/external/tail/cat = "Cat", ) + inherent_traits = list(TRAIT_CAN_USE_FLIGHT_POTION, TRAIT_HATED_BY_DOGS) changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC | RACE_SWAP | ERT_SPAWN | SLIME_EXTRACT species_language_holder = /datum/language_holder/felinid disliked_food = GROSS | CLOTH | RAW