From a62838fcc811172ffd562189d500285185639ff9 Mon Sep 17 00:00:00 2001 From: AnturK Date: Thu, 4 Jun 2026 20:29:22 +0200 Subject: [PATCH] Polar bear basic mob conversion (#96295) Straightforward conversion to basic mob. Only effective change is slight increase in movement speed. They're still walking punching bags. :cl: balance: polar bears are tiny bit faster /:cl: --- ...cemoon_underground_abandoned_homestead.dmm | 2 +- ..._underground_abandoned_plasma_facility.dmm | 2 +- .../map_files/IceBoxStation/IceBoxStation.dmm | 6 +- code/__DEFINES/ai/ai_blackboard.dm | 5 ++ .../ai/basic_mobs/basic_subtrees/enrage.dm | 44 ++++++++++++ code/datums/mapgen/Cavegens/IcemoonCaves.dm | 2 +- .../structures/icemoon/cave_entrance.dm | 2 +- .../objects/structures/lavaland/ore_vent.dm | 4 +- .../basic/icemoon/polar_bear/polar_bear.dm | 72 +++++++++++++++++++ .../hostile/mining_mobs/polarbear.dm | 67 ----------------- .../spell_types/shapeshift/polar_bear.dm | 2 +- .../unit_tests/simple_animal_freeze.dm | 2 - tgstation.dme | 3 +- tools/UpdatePaths/Scripts/96295_polarbear.txt | 1 + 14 files changed, 134 insertions(+), 80 deletions(-) create mode 100644 code/datums/ai/basic_mobs/basic_subtrees/enrage.dm create mode 100644 code/modules/mob/living/basic/icemoon/polar_bear/polar_bear.dm delete mode 100644 code/modules/mob/living/simple_animal/hostile/mining_mobs/polarbear.dm create mode 100644 tools/UpdatePaths/Scripts/96295_polarbear.txt diff --git a/_maps/RandomRuins/IceRuins/icemoon_underground_abandoned_homestead.dmm b/_maps/RandomRuins/IceRuins/icemoon_underground_abandoned_homestead.dmm index 80e245fa11b..b6f057ca94d 100644 --- a/_maps/RandomRuins/IceRuins/icemoon_underground_abandoned_homestead.dmm +++ b/_maps/RandomRuins/IceRuins/icemoon_underground_abandoned_homestead.dmm @@ -4,7 +4,7 @@ /turf/open/misc/asteroid/snow/icemoon, /area/icemoon/surface/outdoors/nospawn) "cP" = ( -/mob/living/simple_animal/hostile/asteroid/polarbear, +/mob/living/basic/mining/polarbear, /turf/open/floor/wood/large{ initial_gas_mix = "ICEMOON_ATMOS" }, diff --git a/_maps/RandomRuins/IceRuins/icemoon_underground_abandoned_plasma_facility.dmm b/_maps/RandomRuins/IceRuins/icemoon_underground_abandoned_plasma_facility.dmm index fad279c0710..df600c338fa 100644 --- a/_maps/RandomRuins/IceRuins/icemoon_underground_abandoned_plasma_facility.dmm +++ b/_maps/RandomRuins/IceRuins/icemoon_underground_abandoned_plasma_facility.dmm @@ -204,7 +204,7 @@ /turf/open/floor/iron, /area/ruin/plasma_facility/operations) "dB" = ( -/mob/living/simple_animal/hostile/asteroid/polarbear{ +/mob/living/basic/mining/polarbear{ name = "Baloo" }, /turf/open/misc/asteroid/snow/icemoon, diff --git a/_maps/map_files/IceBoxStation/IceBoxStation.dmm b/_maps/map_files/IceBoxStation/IceBoxStation.dmm index 04bda8da1f3..51b0e5c781c 100644 --- a/_maps/map_files/IceBoxStation/IceBoxStation.dmm +++ b/_maps/map_files/IceBoxStation/IceBoxStation.dmm @@ -17519,7 +17519,7 @@ /turf/open/floor/iron/white, /area/station/medical/surgery/aft) "eUO" = ( -/mob/living/simple_animal/hostile/asteroid/polarbear{ +/mob/living/basic/mining/polarbear{ move_force = 999; name = "Dewey" }, @@ -23561,7 +23561,7 @@ /turf/open/floor/iron/white, /area/station/medical/treatment_center) "gHA" = ( -/mob/living/simple_animal/hostile/asteroid/polarbear{ +/mob/living/basic/mining/polarbear{ move_force = 999; name = "Louie" }, @@ -56844,7 +56844,7 @@ /turf/open/floor/plating, /area/station/maintenance/port/aft) "pZY" = ( -/mob/living/simple_animal/hostile/asteroid/polarbear{ +/mob/living/basic/mining/polarbear{ move_force = 999; name = "Huey" }, diff --git a/code/__DEFINES/ai/ai_blackboard.dm b/code/__DEFINES/ai/ai_blackboard.dm index fdd8de59206..21ed0c47aa1 100644 --- a/code/__DEFINES/ai/ai_blackboard.dm +++ b/code/__DEFINES/ai/ai_blackboard.dm @@ -243,3 +243,8 @@ // Used to hold state without making bigass lists /// For /datum/ai_behavior/find_potential_targets, what if any field are we using currently #define BB_FIND_TARGETS_FIELD(type) "bb_find_targets_field_[type]" + +///Currently enraged +#define BB_BASIC_MOB_ENRAGE "BB_enraged" +///Previous melee cooldown +#define BB_BASIC_MOB_PREVIOUS_MELEE_COOLDOWN "BB_previous_melee_cooldown" diff --git a/code/datums/ai/basic_mobs/basic_subtrees/enrage.dm b/code/datums/ai/basic_mobs/basic_subtrees/enrage.dm new file mode 100644 index 00000000000..cf3a922a5a4 --- /dev/null +++ b/code/datums/ai/basic_mobs/basic_subtrees/enrage.dm @@ -0,0 +1,44 @@ +// Performs the enrage behavior when health is below given threshold, and calm down behavior if above that value afterwards +/datum/ai_planning_subtree/enrage + var/health_threshold = 0.5 + var/enrage_behavior = /datum/ai_behavior/enrage + +/datum/ai_planning_subtree/enrage/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) + if(!isbasicmob(controller.pawn)) + return + var/mob/living/basic/basic_pawn = controller.pawn + var/low_health = (basic_pawn.health / basic_pawn.maxHealth) <= health_threshold + + var/is_enraged = controller.blackboard_key_exists(BB_BASIC_MOB_ENRAGE) + if(low_health && !is_enraged) + controller.queue_behavior(enrage_behavior, FALSE) + else if(!low_health && is_enraged) + controller.queue_behavior(enrage_behavior, TRUE) + + +/// Cuts down basic mob's melee attack cooldown in half +/datum/ai_behavior/enrage + +/datum/ai_behavior/enrage/perform(seconds_per_tick, datum/ai_controller/controller, calm_down) + var/mob/living/basic/basic_pawn = controller.pawn + if(calm_down) + var/previous_delay = controller.blackboard[BB_BASIC_MOB_PREVIOUS_MELEE_COOLDOWN] + // Technically something else could have modified the cooldown before/after but that requires further consideration so don't use this behavior in these scenarios + basic_pawn.melee_attack_cooldown = previous_delay + controller.clear_blackboard_key(BB_BASIC_MOB_PREVIOUS_MELEE_COOLDOWN) + controller.clear_blackboard_key(BB_BASIC_MOB_ENRAGE) + return AI_BEHAVIOR_SUCCEEDED + + var/current_cooldown = basic_pawn.melee_attack_cooldown + var/new_attack_cooldown = current_cooldown / 2 + + controller.set_blackboard_key(BB_BASIC_MOB_ENRAGE, TRUE) + controller.set_blackboard_key(BB_BASIC_MOB_PREVIOUS_MELEE_COOLDOWN, current_cooldown) + basic_pawn.melee_attack_cooldown = new_attack_cooldown + + if(controller.blackboard_key_exists(BB_BASIC_MOB_CURRENT_TARGET)) + var/current_target = controller.blackboard[BB_BASIC_MOB_CURRENT_TARGET] + controller.pawn.visible_message(span_danger("\The [controller.pawn] gets an enraged look at [current_target]!")) + else + controller.pawn.visible_message(span_danger("\The [controller.pawn] gets an enraged look!")) + return AI_BEHAVIOR_SUCCEEDED diff --git a/code/datums/mapgen/Cavegens/IcemoonCaves.dm b/code/datums/mapgen/Cavegens/IcemoonCaves.dm index 153b0c22e80..91efa9988be 100644 --- a/code/datums/mapgen/Cavegens/IcemoonCaves.dm +++ b/code/datums/mapgen/Cavegens/IcemoonCaves.dm @@ -11,7 +11,7 @@ /mob/living/basic/mining/lobstrosity = 15, /mob/living/basic/mining/wolf = 50, /obj/effect/spawner/random/lavaland_mob/raptor = 15, - /mob/living/simple_animal/hostile/asteroid/polarbear = 30, + /mob/living/basic/mining/polarbear = 30, /obj/structure/spawner/ice_moon = 3, /obj/structure/spawner/ice_moon/polarbear = 3, ) diff --git a/code/game/objects/structures/icemoon/cave_entrance.dm b/code/game/objects/structures/icemoon/cave_entrance.dm index 408e409e557..b58fff6bb70 100644 --- a/code/game/objects/structures/icemoon/cave_entrance.dm +++ b/code/game/objects/structures/icemoon/cave_entrance.dm @@ -66,7 +66,7 @@ GLOBAL_LIST_INIT(ore_probability, list( /obj/structure/spawner/ice_moon/polarbear max_mobs = 1 spawn_time = 60 SECONDS - mob_types = list(/mob/living/simple_animal/hostile/asteroid/polarbear) + mob_types = list(/mob/living/basic/mining/polarbear) mob_gps_id = "BR" // bear /obj/structure/spawner/ice_moon/polarbear/clear_rock() diff --git a/code/game/objects/structures/lavaland/ore_vent.dm b/code/game/objects/structures/lavaland/ore_vent.dm index 244e88102be..3ab9542f630 100644 --- a/code/game/objects/structures/lavaland/ore_vent.dm +++ b/code/game/objects/structures/lavaland/ore_vent.dm @@ -677,7 +677,7 @@ /mob/living/basic/mining/lobstrosity, /mob/living/basic/mining/legion/snow/spawner_made, /mob/living/basic/mining/wolf, - /mob/living/simple_animal/hostile/asteroid/polarbear, + /mob/living/basic/mining/polarbear, ) ore_vent_options = list( SMALL_VENT_TYPE, @@ -690,7 +690,7 @@ /mob/living/basic/mining/legion/snow/spawner_made, /mob/living/basic/mining/ice_demon, /mob/living/basic/mining/wolf, - /mob/living/simple_animal/hostile/asteroid/polarbear, + /mob/living/basic/mining/polarbear, ) ore_vent_options = list( SMALL_VENT_TYPE = 3, diff --git a/code/modules/mob/living/basic/icemoon/polar_bear/polar_bear.dm b/code/modules/mob/living/basic/icemoon/polar_bear/polar_bear.dm new file mode 100644 index 00000000000..b1dc69d06bf --- /dev/null +++ b/code/modules/mob/living/basic/icemoon/polar_bear/polar_bear.dm @@ -0,0 +1,72 @@ +// The taxonomy of polar vs space bear left to imagination of the reader +/mob/living/basic/mining/polarbear + name = "polar bear" + desc = "An aggressive animal that defends its territory with incredible power. These beasts don't run from their enemies." + icon = 'icons/mob/simple/icemoon/icemoon_monsters.dmi' + icon_state = "polarbear" + icon_living = "polarbear" + icon_dead = "polarbear_dead" + mob_biotypes = MOB_ORGANIC|MOB_BEAST|MOB_MINING + + friendly_verb_continuous = "growls at" + friendly_verb_simple = "growl at" + response_help_continuous = "pets" + response_help_simple = "pet" + response_disarm_continuous = "gently pushes aside" + response_disarm_simple = "gently push aside" + attack_verb_continuous = "claws" + attack_verb_simple = "claw" + attack_sound = 'sound/items/weapons/bladeslice.ogg' + attack_vis_effect = ATTACK_EFFECT_CLAW + + habitable_atmos = null + speed = 2 + maxHealth = 300 + health = 300 + obj_damage = 40 + melee_damage_lower = 25 + melee_damage_upper = 25 + wound_bonus = -5 + exposed_wound_bonus = 10 + sharpness = SHARP_EDGED + + move_force = MOVE_FORCE_VERY_STRONG + move_resist = MOVE_FORCE_VERY_STRONG + pull_force = MOVE_FORCE_VERY_STRONG + butcher_results = list(/obj/item/food/meat/slab/bear = 3, /obj/item/stack/sheet/bone = 2) + guaranteed_butcher_results = list(/obj/item/stack/sheet/animalhide/goliath_hide/polar_bear_hide = 1) + crusher_loot = /obj/item/crusher_trophy/bear_paw + + ai_controller = /datum/ai_controller/basic_controller/polar + +/mob/living/basic/mining/polarbear/Initialize(mapload) + . = ..() + + add_traits(list(TRAIT_SPACEWALK, TRAIT_SWIMMER, TRAIT_FENCE_CLIMBER, TRAIT_SNOWSTORM_IMMUNE), INNATE_TRAIT) + AddElement(/datum/element/ai_retaliate) + AddElement(/datum/element/swabable, CELL_LINE_TABLE_BEAR, CELL_VIRUS_TABLE_GENERIC_MOB, 1, 5) + AddElement(/datum/element/change_force_on_death, move_force = MOVE_FORCE_DEFAULT, move_resist = MOVE_RESIST_DEFAULT, pull_force = PULL_FORCE_DEFAULT) + AddElement(/datum/element/footstep, footstep_type = FOOTSTEP_MOB_CLAW) + +/mob/living/basic/mining/polarbear/lesser + name = "magic polar bear" + desc = "It seems sentient somehow." + faction = list(FACTION_NEUTRAL) + +/datum/ai_controller/basic_controller/polar + blackboard = list( + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, + BB_TARGET_MINIMUM_STAT = HARD_CRIT, + BB_AGGRO_RANGE = 2, + ) + + ai_movement = /datum/ai_movement/basic_avoidance + idle_behavior = /datum/idle_behavior/idle_random_walk + planning_subtrees = list( + /datum/ai_planning_subtree/enrage, + /datum/ai_planning_subtree/escape_captivity, + /datum/ai_planning_subtree/target_retaliate, + /datum/ai_planning_subtree/simple_find_target, + /datum/ai_planning_subtree/basic_melee_attack_subtree, + /datum/ai_planning_subtree/random_speech/bear, + ) diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/polarbear.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/polarbear.dm deleted file mode 100644 index 8a73d146596..00000000000 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/polarbear.dm +++ /dev/null @@ -1,67 +0,0 @@ -/mob/living/simple_animal/hostile/asteroid/polarbear - name = "polar bear" - desc = "An aggressive animal that defends its territory with incredible power. These beasts don't run from their enemies." - icon = 'icons/mob/simple/icemoon/icemoon_monsters.dmi' - icon_state = "polarbear" - icon_living = "polarbear" - icon_dead = "polarbear_dead" - mob_biotypes = MOB_ORGANIC|MOB_BEAST|MOB_MINING - mouse_opacity = MOUSE_OPACITY_ICON - friendly_verb_continuous = "growls at" - friendly_verb_simple = "growl at" - speak_emote = list("growls") - speed = 3 - move_to_delay = 8 - maxHealth = 300 - health = 300 - obj_damage = 40 - melee_damage_lower = 25 - melee_damage_upper = 25 - attack_verb_continuous = "claws" - attack_verb_simple = "claw" - attack_sound = 'sound/items/weapons/bladeslice.ogg' - attack_vis_effect = ATTACK_EFFECT_CLAW - vision_range = 2 // don't aggro unless you basically antagonize it, though they will kill you worse than a goliath will - aggro_vision_range = 9 - move_force = MOVE_FORCE_VERY_STRONG - move_resist = MOVE_FORCE_VERY_STRONG - pull_force = MOVE_FORCE_VERY_STRONG - butcher_results = list(/obj/item/food/meat/slab/bear = 3, /obj/item/stack/sheet/bone = 2) - guaranteed_butcher_results = list(/obj/item/stack/sheet/animalhide/goliath_hide/polar_bear_hide = 1) - loot = list() - crusher_loot = /obj/item/crusher_trophy/bear_paw - stat_attack = HARD_CRIT - robust_searching = TRUE - footstep_type = FOOTSTEP_MOB_CLAW - /// Message for when the polar bear starts to attack faster - var/aggressive_message_said = FALSE - -/mob/living/simple_animal/hostile/asteroid/polarbear/Initialize(mapload) - . = ..() - AddElement(\ - /datum/element/change_force_on_death,\ - move_force = MOVE_FORCE_DEFAULT,\ - move_resist = MOVE_RESIST_DEFAULT,\ - pull_force = PULL_FORCE_DEFAULT,\ - ) - -/mob/living/simple_animal/hostile/asteroid/polarbear/adjustHealth(amount, updating_health = TRUE, forced = FALSE) - . = ..() - if(health > maxHealth*0.5) - rapid_melee = initial(rapid_melee) - return - if(!aggressive_message_said && target) - visible_message(span_danger("\The [src] gets an enraged look at [target]!")) - aggressive_message_said = TRUE - rapid_melee = 2 - -/mob/living/simple_animal/hostile/asteroid/polarbear/Life(seconds_per_tick = SSMOBS_DT) - . = ..() - if(!. || target) - return - aggressive_message_said = FALSE - -/mob/living/simple_animal/hostile/asteroid/polarbear/lesser - name = "magic polar bear" - desc = "It seems sentient somehow." - faction = list(FACTION_NEUTRAL) diff --git a/code/modules/spells/spell_types/shapeshift/polar_bear.dm b/code/modules/spells/spell_types/shapeshift/polar_bear.dm index 93e1f6cea91..65a7342054f 100644 --- a/code/modules/spells/spell_types/shapeshift/polar_bear.dm +++ b/code/modules/spells/spell_types/shapeshift/polar_bear.dm @@ -6,4 +6,4 @@ invocation_type = INVOCATION_EMOTE spell_requirements = NONE - possible_shapes = list(/mob/living/simple_animal/hostile/asteroid/polarbear/lesser) + possible_shapes = list(/mob/living/basic/mining/polarbear/lesser) diff --git a/code/modules/unit_tests/simple_animal_freeze.dm b/code/modules/unit_tests/simple_animal_freeze.dm index 72e12016030..5b1794ef33b 100644 --- a/code/modules/unit_tests/simple_animal_freeze.dm +++ b/code/modules/unit_tests/simple_animal_freeze.dm @@ -18,8 +18,6 @@ /mob/living/simple_animal/hostile/asteroid/elite/legionnaire, /mob/living/simple_animal/hostile/asteroid/elite/legionnairehead, /mob/living/simple_animal/hostile/asteroid/elite/pandora, - /mob/living/simple_animal/hostile/asteroid/polarbear, - /mob/living/simple_animal/hostile/asteroid/polarbear/lesser, /mob/living/simple_animal/hostile/megafauna, /mob/living/simple_animal/hostile/megafauna/bubblegum, /mob/living/simple_animal/hostile/megafauna/bubblegum/hallucination, diff --git a/tgstation.dme b/tgstation.dme index 9d443c4f779..526f84801f6 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -1000,6 +1000,7 @@ #include "code\datums\ai\basic_mobs\basic_subtrees\capricious_retaliate.dm" #include "code\datums\ai\basic_mobs\basic_subtrees\climb_tree.dm" #include "code\datums\ai\basic_mobs\basic_subtrees\drag_items.dm" +#include "code\datums\ai\basic_mobs\basic_subtrees\enrage.dm" #include "code\datums\ai\basic_mobs\basic_subtrees\escape_captivity.dm" #include "code\datums\ai\basic_mobs\basic_subtrees\express_happiness.dm" #include "code\datums\ai\basic_mobs\basic_subtrees\find_food.dm" @@ -5312,6 +5313,7 @@ #include "code\modules\mob\living\basic\icemoon\ice_whelp\ice_whelp.dm" #include "code\modules\mob\living\basic\icemoon\ice_whelp\ice_whelp_abilities.dm" #include "code\modules\mob\living\basic\icemoon\ice_whelp\ice_whelp_ai.dm" +#include "code\modules\mob\living\basic\icemoon\polar_bear\polar_bear.dm" #include "code\modules\mob\living\basic\icemoon\wolf\wolf.dm" #include "code\modules\mob\living\basic\icemoon\wolf\wolf_ai.dm" #include "code\modules\mob\living\basic\icemoon\wolf\wolf_extras.dm" @@ -5725,7 +5727,6 @@ #include "code\modules\mob\living\simple_animal\hostile\megafauna\legion.dm" #include "code\modules\mob\living\simple_animal\hostile\megafauna\wendigo.dm" #include "code\modules\mob\living\simple_animal\hostile\mining_mobs\mining_mobs.dm" -#include "code\modules\mob\living\simple_animal\hostile\mining_mobs\polarbear.dm" #include "code\modules\mob\living\simple_animal\hostile\mining_mobs\elites\elite.dm" #include "code\modules\mob\living\simple_animal\hostile\mining_mobs\elites\goliath_broodmother.dm" #include "code\modules\mob\living\simple_animal\hostile\mining_mobs\elites\herald.dm" diff --git a/tools/UpdatePaths/Scripts/96295_polarbear.txt b/tools/UpdatePaths/Scripts/96295_polarbear.txt new file mode 100644 index 00000000000..c3b0c19872f --- /dev/null +++ b/tools/UpdatePaths/Scripts/96295_polarbear.txt @@ -0,0 +1 @@ +/mob/living/simple_animal/hostile/asteroid/polarbear : /mob/living/basic/mining/polarbear{@OLD}