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.
/🆑
This commit is contained in:
Jacquerel
2024-08-21 10:34:42 +02:00
committed by GitHub
parent 5ec6fd132d
commit 828d807464
9 changed files with 60 additions and 21 deletions
@@ -45,6 +45,8 @@
maximum_survivable_temperature = 1500
death_offset_y = -10
/// 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?
@@ -89,7 +91,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")))
@@ -268,8 +271,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"
@@ -279,11 +282,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,