[MIRROR] Canonise passive carp (#29510)

* Canonise passive carp (#85939)

## About The Pull Request

The other day someone posted a story on the tgstation forums about being
spawned as a sentient "passive carp" from slime gold cores and then
biting someone to death which mildly annoyed me because "passive carp"
is a mob which exists purely for a shuttle event, to make them less
dangerous when passing through the area.

And _also_ because once sapient the passive carp was, of course, not
passive at all. If it was a passive carp they wouldn't have had to
appeal a note, because they wouldn't have been able to bite that guy.

There were two solutions for this.
The obvious one is "remove this mob from the gold slime core pool".
The one I chose instead was "give this mob more divergent behaviour".

Now instead of "passive carp" it is called a "false carp", which is a
carp-like creature that is incapable of harming humans (it has the
pacifist trait and does no damage).
It is spawned from the _friendly_ gold core reaction instead of the
hostile one.
It will be chill until someone attacks it or it sees someone attack
another false carp, then all of them will run away from that person.

Additionally I fixed a bug where its teeth reappeared in some animation
states.
And another bug where crab AI just didn't work.

## Why It's Good For The Game

If you see a mob called "passive carp" it should do what it says in the
name.

## Changelog

🆑
balance: Pacifist carp can now be spawned from the friendly gold core
reaction, and no longer appear from the hostile one.
fix: The teeth of toothless carp will not occasionally reappear
fix: Crabs will now run from attackers larger than them and attack
things smaller than them, as intended.
/🆑

* Canonise passive carp

---------

Co-authored-by: Jacquerel <hnevard@gmail.com>
This commit is contained in:
SkyratBot
2024-08-22 08:15:57 +07:00
committed by GitHub
co-authored by Jacquerel
parent 90388767c8
commit f77fcc6907
9 changed files with 60 additions and 21 deletions
+3
View File
@@ -133,6 +133,9 @@
///Range for a MOD AI controller.
#define MOD_AI_RANGE 200
///Only target mobs with these traits
#define BB_TARGET_ONLY_WITH_TRAITS "BB_target_only_with_traits"
///should we skip the faction check for the targeting strategy?
#define BB_ALWAYS_IGNORE_FACTION "BB_always_ignore_factions"
///are we in some kind of temporary state of ignoring factions when targeting? can result in volatile results if multiple behaviours touch this
@@ -21,4 +21,5 @@
controller.queue_behavior(/datum/ai_behavior/target_from_retaliate_list/nearest, BB_BASIC_MOB_RETALIATE_LIST, target_key, targeting_key, BB_BASIC_MOB_CURRENT_TARGET_HIDING_LOCATION)
/datum/ai_planning_subtree/find_nearest_thing_which_attacked_me_to_flee/from_flee_key
target_key = BB_BASIC_MOB_FLEE_TARGET
targeting_key = BB_FLEE_TARGETING_STRATEGY
@@ -1,8 +1,10 @@
/datum/ai_planning_subtree/simple_find_target
/// Variable to store target in
var/target_key = BB_BASIC_MOB_CURRENT_TARGET
/datum/ai_planning_subtree/simple_find_target/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick)
. = ..()
controller.queue_behavior(/datum/ai_behavior/find_potential_targets, BB_BASIC_MOB_CURRENT_TARGET, BB_TARGETING_STRATEGY, BB_BASIC_MOB_CURRENT_TARGET_HIDING_LOCATION)
controller.queue_behavior(/datum/ai_behavior/find_potential_targets, target_key, BB_TARGETING_STRATEGY, BB_BASIC_MOB_CURRENT_TARGET_HIDING_LOCATION)
// Prevents finding a target if a human is nearby
/datum/ai_planning_subtree/simple_find_target/not_while_observed
@@ -12,3 +14,6 @@
if(watcher.stat != DEAD)
return
return ..()
/datum/ai_planning_subtree/simple_find_target/to_flee
target_key = BB_BASIC_MOB_FLEE_TARGET
@@ -88,6 +88,21 @@
// trust fall exercise
return TRUE
/datum/targeting_strategy/basic/require_traits
/datum/targeting_strategy/basic/require_traits/can_attack(mob/living/living_mob, atom/the_target, vision_range)
. = ..()
if (!.)
return FALSE
var/list/required_traits = living_mob.ai_controller.blackboard[BB_TARGET_ONLY_WITH_TRAITS]
if (!length(required_traits))
return TRUE
for (var/trait as anything in required_traits)
if (HAS_TRAIT(the_target, trait))
return TRUE
return FALSE
/// Subtype which searches for mobs of a size relative to ours
/datum/targeting_strategy/basic/of_size
/// If true, we will return mobs which are smaller than us. If false, larger.
@@ -44,6 +44,8 @@
minimum_survivable_temperature = 0
maximum_survivable_temperature = 1500
/// If true we will run away from attackers even at full health
var/cowardly = FALSE
/// Cytology cells you can swab from this creature
var/cell_line = CELL_LINE_TABLE_CARP
/// What colour is our 'healing' outline?
@@ -88,7 +90,8 @@
if (cell_line)
AddElement(/datum/element/swabable, cell_line, CELL_VIRUS_TABLE_GENERIC_MOB, 1, 5)
AddElement(/datum/element/simple_flying)
AddElement(/datum/element/ai_flee_while_injured)
if (!cowardly)
AddElement(/datum/element/ai_flee_while_injured)
setup_eating()
AddComponent(/datum/component/aggro_emote, emote_list = string_list(list("gnashes")))
@@ -267,8 +270,8 @@
///Wild carp that just vibe ya know
/mob/living/basic/carp/passive
name = "passive carp"
desc = "A timid, sucker-bearing creature that resembles a fish. "
name = "false carp"
desc = "A close relative of the space carp which is entirely toothless and feeds by stealing its cousin's leftovers."
icon_state = "base_friend"
icon_living = "base_friend"
@@ -278,11 +281,19 @@
attack_verb_continuous = "suckers"
attack_verb_simple = "suck"
melee_damage_lower = 4
melee_damage_upper = 4
melee_damage_lower = 0
melee_damage_upper = 0
cowardly = TRUE
ai_controller = /datum/ai_controller/basic_controller/carp/passive
gold_core_spawnable = FRIENDLY_SPAWN
/mob/living/basic/carp/passive/Initialize(mapload)
. = ..()
AddElement(/datum/element/ai_retaliate)
AddComponent(/datum/component/ai_retaliate_advanced, CALLBACK(src, PROC_REF(on_attacked)))
AddElement(/datum/element/pet_bonus, "bloops happily!")
ADD_TRAIT(src, TRAIT_PACIFISM, INNATE_TRAIT)
/// If someone slaps one of the school, scatter
/mob/living/basic/carp/passive/proc/on_attacked(mob/living/attacker)
for(var/mob/living/basic/carp/passive/schoolmate in oview(src, 9))
schoolmate.ai_controller?.insert_blackboard_key_lazylist(BB_BASIC_MOB_RETALIATE_LIST, attacker)
@@ -7,18 +7,20 @@
var/datum/ai_behavior/rift_behaviour
/// If true we finish planning after this
var/finish_planning = FALSE
/// Key to read for flee target
var/target_key = BB_BASIC_MOB_CURRENT_TARGET
/datum/ai_planning_subtree/make_carp_rift/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick)
if (!rift_behaviour)
CRASH("Forgot to specify rift behaviour for [src]")
if (!controller.blackboard_key_exists(BB_BASIC_MOB_CURRENT_TARGET))
if (!controller.blackboard_key_exists(target_key))
return
var/datum/action/cooldown/using_action = controller.blackboard[BB_CARP_RIFT]
if (!using_action?.IsAvailable())
return
controller.queue_behavior(rift_behaviour, BB_CARP_RIFT, BB_BASIC_MOB_CURRENT_TARGET)
controller.queue_behavior(rift_behaviour, BB_CARP_RIFT, target_key)
if (finish_planning)
return SUBTREE_RETURN_FINISH_PLANNING
@@ -31,13 +33,17 @@
finish_planning = TRUE
/datum/ai_planning_subtree/make_carp_rift/panic_teleport/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick)
var/atom/movable/fleeing_from = controller.blackboard[BB_BASIC_MOB_CURRENT_TARGET]
var/atom/movable/fleeing_from = controller.blackboard[target_key]
if(!QDELETED(fleeing_from) && controller.blackboard[BB_CARPS_FEAR_FISHERMAN] && HAS_TRAIT(fleeing_from, TRAIT_SCARY_FISHERMAN))
return ..()
if (controller.blackboard[BB_BASIC_MOB_STOP_FLEEING])
return
return ..()
/datum/ai_planning_subtree/make_carp_rift/panic_teleport/flee_key
target_key = BB_BASIC_MOB_FLEE_TARGET
/**
* # Make carp rift (aggressive)
* Plan to teleport towards our target so we can fuck them up
@@ -46,7 +52,7 @@
rift_behaviour = /datum/ai_behavior/make_carp_rift/towards/aggressive
/datum/ai_planning_subtree/make_carp_rift/aggressive_teleport/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick)
var/atom/movable/target = controller.blackboard[BB_BASIC_MOB_CURRENT_TARGET]
var/atom/movable/target = controller.blackboard[target_key]
if(!QDELETED(target) && controller.blackboard[BB_CARPS_FEAR_FISHERMAN] && HAS_TRAIT(target, TRAIT_SCARY_FISHERMAN))
return
return ..()
@@ -106,22 +106,21 @@
*/
/datum/ai_controller/basic_controller/carp/passive
blackboard = list(
BB_BASIC_MOB_STOP_FLEEING = TRUE,
BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic,
BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic/require_traits,
BB_FLEE_TARGETING_STRATEGY = /datum/targeting_strategy/basic,
BB_PET_TARGETING_STRATEGY = /datum/targeting_strategy/basic/not_friends,
BB_TARGET_PRIORITY_TRAIT = TRAIT_SCARY_FISHERMAN,
BB_CARPS_FEAR_FISHERMAN = TRUE,
BB_TARGET_ONLY_WITH_TRAITS = list(TRAIT_SCARY_FISHERMAN),
)
ai_traits = STOP_MOVING_WHEN_PULLED
planning_subtrees = list(
/datum/ai_planning_subtree/pet_planning,
/datum/ai_planning_subtree/simple_find_nearest_target_to_flee,
/datum/ai_planning_subtree/make_carp_rift/panic_teleport,
/datum/ai_planning_subtree/flee_target/from_fisherman,
/datum/ai_planning_subtree/simple_find_target/to_flee, // This should only find master fishermen because of the targeting strategy
/datum/ai_planning_subtree/find_nearest_thing_which_attacked_me_to_flee/from_flee_key,
/datum/ai_planning_subtree/make_carp_rift/panic_teleport/flee_key,
/datum/ai_planning_subtree/flee_target/from_flee_key,
/datum/ai_planning_subtree/find_food,
/datum/ai_planning_subtree/attack_obstacle_in_path/carp,
/datum/ai_planning_subtree/shortcut_to_target_through_carp_rift,
/datum/ai_planning_subtree/make_carp_rift/aggressive_teleport,
/datum/ai_planning_subtree/basic_melee_attack_subtree/no_fisherman,
/datum/ai_planning_subtree/basic_melee_attack_subtree,
/datum/ai_planning_subtree/carp_migration,
)
@@ -89,7 +89,6 @@
planning_subtrees = list(
/datum/ai_planning_subtree/find_nearest_thing_which_attacked_me_to_flee/from_flee_key,
/datum/ai_planning_subtree/flee_target/from_flee_key,
/datum/ai_planning_subtree/target_retaliate/to_flee,
/datum/ai_planning_subtree/simple_find_target,
/datum/ai_planning_subtree/basic_melee_attack_subtree,
/datum/ai_planning_subtree/random_speech/crab,
Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 35 KiB