diff --git a/_maps/RandomZLevels/caves.dmm b/_maps/RandomZLevels/caves.dmm index a4c071a17d0..e3025fc7faf 100644 --- a/_maps/RandomZLevels/caves.dmm +++ b/_maps/RandomZLevels/caves.dmm @@ -1331,7 +1331,7 @@ /turf/open/floor/iron, /area/awaymission/caves/listeningpost) "ml" = ( -/mob/living/simple_animal/hostile/asteroid/fugu, +/mob/living/basic/wumborian_fugu, /turf/open/misc/asteroid/basalt{ initial_gas_mix = "n2=23;o2=14;TEMP=2.7" }, diff --git a/code/__DEFINES/ai.dm b/code/__DEFINES/ai.dm index e7dc62a72c4..f6d1768d725 100644 --- a/code/__DEFINES/ai.dm +++ b/code/__DEFINES/ai.dm @@ -243,3 +243,7 @@ #define BB_BILEWORM_SPEW_BILE "BB_bileworm_spew_bile" #define BB_BILEWORM_RESURFACE "BB_bileworm_resurface" #define BB_BILEWORM_DEVOUR "BB_bileworm_devour" + +/// Fugu AI Keys + +#define BB_FUGU_INFLATE "BB_fugu_inflate" diff --git a/code/datums/ai/basic_mobs/base_basic_controller.dm b/code/datums/ai/basic_mobs/base_basic_controller.dm index 93e9e795d57..b4f7c27c2f9 100644 --- a/code/datums/ai/basic_mobs/base_basic_controller.dm +++ b/code/datums/ai/basic_mobs/base_basic_controller.dm @@ -8,7 +8,7 @@ update_speed(basic_mob) - RegisterSignal(basic_mob, POST_BASIC_MOB_UPDATE_VARSPEED, PROC_REF(update_speed)) + RegisterSignals(basic_mob, list(POST_BASIC_MOB_UPDATE_VARSPEED, COMSIG_MOB_MOVESPEED_UPDATED), PROC_REF(update_speed)) return ..() //Run parent at end diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/basic_attacking.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/basic_attacking.dm index 7c457d143c3..1fa012fc466 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/basic_attacking.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/basic_attacking.dm @@ -1,5 +1,5 @@ /datum/ai_behavior/basic_melee_attack - action_cooldown = 0.6 SECONDS + action_cooldown = 2 SECONDS behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT | AI_BEHAVIOR_CAN_PLAN_DURING_EXECUTION /datum/ai_behavior/basic_melee_attack/setup(datum/ai_controller/controller, target_key, targetting_datum_key, hiding_location_key) diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/try_mob_ability.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/targeted_mob_ability.dm similarity index 62% rename from code/datums/ai/basic_mobs/basic_ai_behaviors/try_mob_ability.dm rename to code/datums/ai/basic_mobs/basic_ai_behaviors/targeted_mob_ability.dm index aad52b924bb..5e366c0f4fd 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/try_mob_ability.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/targeted_mob_ability.dm @@ -1,11 +1,13 @@ /** - * # Try Mob Ability + * # Targeted Mob Ability * Attempts to use a mob's cooldown ability on a target */ -/datum/ai_behavior/try_mob_ability +/datum/ai_behavior/targeted_mob_ability + +/datum/ai_behavior/targeted_mob_ability/perform(delta_time, datum/ai_controller/controller, ability_key, target_key) + var/datum/weakref/weak_ability = controller.blackboard[ability_key] + var/datum/action/cooldown/ability = weak_ability?.resolve() -/datum/ai_behavior/try_mob_ability/perform(delta_time, datum/ai_controller/controller, ability_key, target_key) - var/datum/action/cooldown/mob_cooldown/ability = controller.blackboard[ability_key] var/datum/weakref/weak_target = controller.blackboard[target_key] var/mob/living/target = weak_target?.resolve() if(!ability || QDELETED(target)) @@ -15,7 +17,7 @@ var/result = ability.InterceptClickOn(pawn, null, target) finish_action(controller, result, ability_key, target_key) -/datum/ai_behavior/try_mob_ability/finish_action(datum/ai_controller/controller, succeeded, ability_key, target_key) +/datum/ai_behavior/targeted_mob_ability/finish_action(datum/ai_controller/controller, succeeded, ability_key, target_key) . = ..() var/datum/weakref/weak_target = controller.blackboard[target_key] var/atom/target = weak_target?.resolve() @@ -33,9 +35,9 @@ * Attempts to use a mob's cooldown ability on a target and then move the target into a special target blackboard datum * Doesn't need another subtype to clear BB_BASIC_MOB_EXECUTION_TARGET because it will be the target key for the normal action */ -/datum/ai_behavior/try_mob_ability/and_plan_execute +/datum/ai_behavior/targeted_mob_ability/and_plan_execute -/datum/ai_behavior/try_mob_ability/and_plan_execute/finish_action(datum/ai_controller/controller, succeeded, ability_key, target_key) +/datum/ai_behavior/targeted_mob_ability/and_plan_execute/finish_action(datum/ai_controller/controller, succeeded, ability_key, target_key) controller.blackboard[BB_BASIC_MOB_EXECUTION_TARGET] = controller.blackboard[target_key] return ..() @@ -43,8 +45,8 @@ * # Try Mob Ability and clear target * Attempts to use a mob's cooldown ability on a target and releases the target when the action completes */ -/datum/ai_behavior/try_mob_ability/and_clear_target +/datum/ai_behavior/targeted_mob_ability/and_clear_target -/datum/ai_behavior/try_mob_ability/and_clear_target/finish_action(datum/ai_controller/controller, succeeded, ability_key, target_key) +/datum/ai_behavior/targeted_mob_ability/and_clear_target/finish_action(datum/ai_controller/controller, succeeded, ability_key, target_key) . = ..() controller.blackboard[target_key] = null diff --git a/code/datums/ai/basic_mobs/basic_subtrees/attack_obstacle_in_path.dm b/code/datums/ai/basic_mobs/basic_subtrees/attack_obstacle_in_path.dm index b2496b15e2f..151a4125bf6 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/attack_obstacle_in_path.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/attack_obstacle_in_path.dm @@ -22,7 +22,7 @@ /// Something is in our way, get it outta here /datum/ai_behavior/attack_obstructions - action_cooldown = 1 SECONDS + action_cooldown = 2 SECONDS /// If we should attack walls, be prepared for complaints about breaches var/can_attack_turfs = FALSE /// Tries to bump open airlocks with an attack diff --git a/code/datums/ai/basic_mobs/basic_subtrees/targetted_mob_ability.dm b/code/datums/ai/basic_mobs/basic_subtrees/targeted_mob_ability.dm similarity index 59% rename from code/datums/ai/basic_mobs/basic_subtrees/targetted_mob_ability.dm rename to code/datums/ai/basic_mobs/basic_subtrees/targeted_mob_ability.dm index 4450f9fa331..f748a877f05 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/targetted_mob_ability.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/targeted_mob_ability.dm @@ -1,13 +1,13 @@ /// Attempts to use a mob ability on a target -/datum/ai_planning_subtree/targetted_mob_ability +/datum/ai_planning_subtree/targeted_mob_ability /// Blackboard key for the ability var/ability_key /// Blackboard key for where the target ref is stored var/target_key = BB_BASIC_MOB_CURRENT_TARGET /// Behaviour to perform using ability - var/use_ability_behaviour = /datum/ai_behavior/try_mob_ability + var/use_ability_behaviour = /datum/ai_behavior/targeted_mob_ability -/datum/ai_planning_subtree/targetted_mob_ability/SelectBehaviors(datum/ai_controller/controller, delta_time) +/datum/ai_planning_subtree/targeted_mob_ability/SelectBehaviors(datum/ai_controller/controller, delta_time) if (!ability_key) CRASH("You forgot to tell this mob where to find its ability") @@ -16,10 +16,9 @@ if (QDELETED(target)) return - var/datum/action/cooldown/using_action = controller.blackboard[ability_key] - if (QDELETED(using_action)) - return - if (!using_action.IsAvailable()) + var/datum/weakref/weak_ability = controller.blackboard[ability_key] + var/datum/action/cooldown/using_action = weak_ability?.resolve() + if (!using_action || !using_action.IsAvailable()) return controller.queue_behavior(use_ability_behaviour, ability_key, target_key) diff --git a/code/datums/ai/basic_mobs/basic_subtrees/use_mob_ability.dm b/code/datums/ai/basic_mobs/basic_subtrees/use_mob_ability.dm new file mode 100644 index 00000000000..c7eaf4a996f --- /dev/null +++ b/code/datums/ai/basic_mobs/basic_subtrees/use_mob_ability.dm @@ -0,0 +1,35 @@ +/** + * Simple behaviours which simply try to use an ability whenever it is available. + * For something which wants a target try `targetted_mob_ability`. + */ +/datum/ai_planning_subtree/use_mob_ability + /// Blackboard key for the ability + var/ability_key + /// Behaviour to perform using ability + var/use_ability_behaviour = /datum/ai_behavior/use_mob_ability + /// If true we terminate planning after trying to use the ability. + var/finish_planning = FALSE + +/datum/ai_planning_subtree/use_mob_ability/SelectBehaviors(datum/ai_controller/controller, delta_time) + if (!ability_key) + CRASH("You forgot to tell this mob where to find its ability") + + var/datum/weakref/weak_ability = controller.blackboard[ability_key] + var/datum/action/cooldown/using_action = weak_ability?.resolve() + if (!using_action || !using_action.IsAvailable()) + return + + controller.queue_behavior(use_ability_behaviour, ability_key) + if (finish_planning) + return SUBTREE_RETURN_FINISH_PLANNING + +/datum/ai_behavior/use_mob_ability + +/datum/ai_behavior/use_mob_ability/perform(delta_time, datum/ai_controller/controller, ability_key) + var/datum/weakref/weak_ability = controller.blackboard[ability_key] + var/datum/action/cooldown/using_action = weak_ability?.resolve() + if (!using_action) + finish_action(controller, FALSE, ability_key) + return + var/result = using_action.Trigger() + finish_action(controller, result, ability_key) diff --git a/code/datums/elements/wall_smasher.dm b/code/datums/elements/wall_smasher.dm index b9f764e66ac..3c6c1d92da7 100644 --- a/code/datums/elements/wall_smasher.dm +++ b/code/datums/elements/wall_smasher.dm @@ -20,13 +20,13 @@ RegisterSignals(target, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_HUMAN_EARLY_UNARMED_ATTACK), PROC_REF(on_unarm_attack)) // Players RegisterSignal(target, COMSIG_HOSTILE_PRE_ATTACKINGTARGET, PROC_REF(on_pre_attackingtarget)) // AI - if (isanimal(target)) + if (isanimal_or_basicmob(target)) var/mob/living/simple_animal/animal_target = target animal_target.environment_smash = strength_flag /datum/element/wall_smasher/Detach(datum/target) UnregisterSignal(target, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_HUMAN_EARLY_UNARMED_ATTACK, COMSIG_HOSTILE_PRE_ATTACKINGTARGET)) - if (isanimal(target)) + if (isanimal_or_basicmob(target)) var/mob/living/simple_animal/animal_target = target animal_target.environment_smash = initial(animal_target.environment_smash) diff --git a/code/game/objects/structures/spawner.dm b/code/game/objects/structures/spawner.dm index e1f17470ef1..a505952666b 100644 --- a/code/game/objects/structures/spawner.dm +++ b/code/game/objects/structures/spawner.dm @@ -65,7 +65,7 @@ max_mobs = 3 icon = 'icons/mob/simple/lavaland/nest.dmi' spawn_text = "crawls out of" - mob_types = list(/mob/living/simple_animal/hostile/asteroid/goldgrub, /mob/living/simple_animal/hostile/asteroid/goliath, /mob/living/simple_animal/hostile/asteroid/hivelord, /mob/living/simple_animal/hostile/asteroid/basilisk, /mob/living/simple_animal/hostile/asteroid/fugu) + mob_types = list(/mob/living/simple_animal/hostile/asteroid/goldgrub, /mob/living/simple_animal/hostile/asteroid/goliath, /mob/living/simple_animal/hostile/asteroid/hivelord, /mob/living/simple_animal/hostile/asteroid/basilisk, /mob/living/basic/wumborian_fugu) faction = list("mining") /obj/structure/spawner/mining/goldgrub @@ -91,7 +91,7 @@ /obj/structure/spawner/mining/wumborian name = "wumborian fugu den" desc = "A den housing a nest of wumborian fugus, how do they all even fit in there?" - mob_types = list(/mob/living/simple_animal/hostile/asteroid/fugu) + mob_types = list(/mob/living/basic/wumborian_fugu) /obj/structure/spawner/nether name = "netherworld link" diff --git a/code/modules/antagonists/wizard/grand_ritual/grand_side_effect.dm b/code/modules/antagonists/wizard/grand_ritual/grand_side_effect.dm index 41fc69b4089..0643b73ead9 100644 --- a/code/modules/antagonists/wizard/grand_ritual/grand_side_effect.dm +++ b/code/modules/antagonists/wizard/grand_ritual/grand_side_effect.dm @@ -352,7 +352,7 @@ abstract = FALSE /// Typepaths of mobs to create var/static/list/permitted_mobs = list( - /mob/living/simple_animal/hostile/asteroid/fugu, + /mob/living/basic/wumborian_fugu, /mob/living/simple_animal/hostile/skeleton, /mob/living/simple_animal/hostile/killertomato, /mob/living/simple_animal/hostile/ooze, diff --git a/code/modules/mob/living/basic/basic.dm b/code/modules/mob/living/basic/basic.dm index 7018361cff9..8fab34ad903 100644 --- a/code/modules/mob/living/basic/basic.dm +++ b/code/modules/mob/living/basic/basic.dm @@ -35,8 +35,8 @@ ///Played when someone punches the creature. var/attacked_sound = SFX_PUNCH //This should be an element - ///What kind of objects this mob can smash. - var/environment_smash = ENVIRONMENT_SMASH_NONE + /// Variable maintained for compatibility with attack_animal procs until simple animals can be refactored away. Use element instead of setting manually. + var/environment_smash = ENVIRONMENT_SMASH_STRUCTURES /// 1 for full damage, 0 for none, -1 for 1:1 heal from that source. var/list/damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1) diff --git a/code/modules/mob/living/basic/farm_animals/cow/cow_moonicorn.dm b/code/modules/mob/living/basic/farm_animals/cow/cow_moonicorn.dm index 0c0c7047bdd..5f065ec53e4 100644 --- a/code/modules/mob/living/basic/farm_animals/cow/cow_moonicorn.dm +++ b/code/modules/mob/living/basic/farm_animals/cow/cow_moonicorn.dm @@ -56,16 +56,9 @@ /datum/ai_planning_subtree/simple_find_target, //...or something to eat, possibly. both types of target handled by melee attack subtree /datum/ai_planning_subtree/find_food, - /datum/ai_planning_subtree/basic_melee_attack_subtree/moonicorn, + /datum/ai_planning_subtree/basic_melee_attack_subtree, ) -/datum/ai_planning_subtree/basic_melee_attack_subtree/moonicorn - melee_attack_behavior = /datum/ai_behavior/basic_melee_attack/moonicorn - -/datum/ai_behavior/basic_melee_attack/moonicorn - //it's a fairly strong attack and it applies pax, so they do not attack often - action_cooldown = 2 SECONDS - ///moonicorns will not attack people holding something that could tame them. /datum/targetting_datum/basic/allow_items/moonicorn diff --git a/code/modules/mob/living/basic/farm_animals/pig.dm b/code/modules/mob/living/basic/farm_animals/pig.dm index bf9831db0f7..09cc2fdf722 100644 --- a/code/modules/mob/living/basic/farm_animals/pig.dm +++ b/code/modules/mob/living/basic/farm_animals/pig.dm @@ -59,11 +59,5 @@ /datum/ai_planning_subtree/find_nearest_thing_which_attacked_me_to_flee, /datum/ai_planning_subtree/flee_target, /datum/ai_planning_subtree/target_retaliate, - /datum/ai_planning_subtree/basic_melee_attack_subtree/pig, + /datum/ai_planning_subtree/basic_melee_attack_subtree, ) - -/datum/ai_planning_subtree/basic_melee_attack_subtree/pig - melee_attack_behavior = /datum/ai_behavior/basic_melee_attack/pig - -/datum/ai_behavior/basic_melee_attack/pig - action_cooldown = 2 SECONDS diff --git a/code/modules/mob/living/basic/lavaland/bileworm/_bileworm.dm b/code/modules/mob/living/basic/lavaland/bileworm/_bileworm.dm index cfc1cd2db0b..16615169f48 100644 --- a/code/modules/mob/living/basic/lavaland/bileworm/_bileworm.dm +++ b/code/modules/mob/living/basic/lavaland/bileworm/_bileworm.dm @@ -56,6 +56,6 @@ devour.Grant(src) var/datum/action/adjust_vision/adjust_vision = new(src) adjust_vision.Grant(src) - ai_controller.blackboard[BB_BILEWORM_SPEW_BILE] = spew_bile - ai_controller.blackboard[BB_BILEWORM_RESURFACE] = resurface - ai_controller.blackboard[BB_BILEWORM_DEVOUR] = devour + ai_controller.blackboard[BB_BILEWORM_SPEW_BILE] = WEAKREF(spew_bile) + ai_controller.blackboard[BB_BILEWORM_RESURFACE] = WEAKREF(resurface) + ai_controller.blackboard[BB_BILEWORM_DEVOUR] = WEAKREF(devour) diff --git a/code/modules/mob/living/basic/lavaland/bileworm/bileworm_ai.dm b/code/modules/mob/living/basic/lavaland/bileworm/bileworm_ai.dm index 3abfc0430b6..f6205a341bd 100644 --- a/code/modules/mob/living/basic/lavaland/bileworm/bileworm_ai.dm +++ b/code/modules/mob/living/basic/lavaland/bileworm/bileworm_ai.dm @@ -18,14 +18,15 @@ if(QDELETED(target)) return - var/datum/action/cooldown/mob_cooldown/resurface = controller.blackboard[BB_BILEWORM_RESURFACE] + var/datum/weakref/weak_action = controller.blackboard[BB_BILEWORM_RESURFACE] + var/datum/action/cooldown/mob_cooldown/resurface = weak_action?.resolve() //because one ability is always INFINITY cooldown, this actually works to check which ability should be used //sometimes it will try to spew bile on infinity cooldown, but that's okay because as soon as resurface is ready it will attempt that - if(resurface.next_use_time <= world.time) - controller.queue_behavior(/datum/ai_behavior/try_mob_ability/and_plan_execute, BB_BILEWORM_RESURFACE, BB_BASIC_MOB_CURRENT_TARGET) + if(resurface && resurface.next_use_time <= world.time) + controller.queue_behavior(/datum/ai_behavior/targeted_mob_ability/and_plan_execute, BB_BILEWORM_RESURFACE, BB_BASIC_MOB_CURRENT_TARGET) else - controller.queue_behavior(/datum/ai_behavior/try_mob_ability/and_plan_execute, BB_BILEWORM_SPEW_BILE, BB_BASIC_MOB_CURRENT_TARGET) + controller.queue_behavior(/datum/ai_behavior/targeted_mob_ability/and_plan_execute, BB_BILEWORM_SPEW_BILE, BB_BASIC_MOB_CURRENT_TARGET) return SUBTREE_RETURN_FINISH_PLANNING //focus on the fight /datum/ai_planning_subtree/bileworm_execute @@ -37,5 +38,5 @@ if(QDELETED(target) || target.stat < UNCONSCIOUS) return - controller.queue_behavior(/datum/ai_behavior/try_mob_ability, BB_BILEWORM_DEVOUR, BB_BASIC_MOB_EXECUTION_TARGET) + controller.queue_behavior(/datum/ai_behavior/targeted_mob_ability, BB_BILEWORM_DEVOUR, BB_BASIC_MOB_EXECUTION_TARGET) return SUBTREE_RETURN_FINISH_PLANNING //focus on devouring this fool diff --git a/code/modules/mob/living/basic/space_fauna/carp/carp.dm b/code/modules/mob/living/basic/space_fauna/carp/carp.dm index f506d77f7de..169eaa77ce9 100644 --- a/code/modules/mob/living/basic/space_fauna/carp/carp.dm +++ b/code/modules/mob/living/basic/space_fauna/carp/carp.dm @@ -105,7 +105,7 @@ teleport = new(src) teleport.Grant(src) - ai_controller.blackboard[BB_CARP_RIFT] = teleport + ai_controller.blackboard[BB_CARP_RIFT] = WEAKREF(teleport) /mob/living/basic/carp/Destroy() QDEL_NULL(teleport) diff --git a/code/modules/mob/living/basic/space_fauna/carp/carp_ai_actions.dm b/code/modules/mob/living/basic/space_fauna/carp/carp_ai_actions.dm index abda57a55ed..2eea1f3edfb 100644 --- a/code/modules/mob/living/basic/space_fauna/carp/carp_ai_actions.dm +++ b/code/modules/mob/living/basic/space_fauna/carp/carp_ai_actions.dm @@ -42,7 +42,8 @@ /datum/ai_planning_subtree/find_nearest_magicarp_spell_target /datum/ai_planning_subtree/find_nearest_magicarp_spell_target/SelectBehaviors(datum/ai_controller/controller, delta_time) - var/datum/action/cooldown/using_action = controller.blackboard[BB_MAGICARP_SPELL] + var/datum/weakref/weak_action = controller.blackboard[BB_MAGICARP_SPELL] + var/datum/action/cooldown/using_action = weak_action?.resolve() if (QDELETED(using_action)) return if (!using_action.IsAvailable()) @@ -68,7 +69,7 @@ /datum/ai_behavior/find_potential_targets/nearest/magicarp /// Then use it on that target -/datum/ai_planning_subtree/targetted_mob_ability/magicarp +/datum/ai_planning_subtree/targeted_mob_ability/magicarp ability_key = BB_MAGICARP_SPELL target_key = BB_MAGICARP_SPELL_TARGET - use_ability_behaviour = /datum/ai_behavior/try_mob_ability/and_clear_target + use_ability_behaviour = /datum/ai_behavior/targeted_mob_ability/and_clear_target diff --git a/code/modules/mob/living/basic/space_fauna/carp/carp_ai_rift_actions.dm b/code/modules/mob/living/basic/space_fauna/carp/carp_ai_rift_actions.dm index 4f8cf327e75..71be65aadd7 100644 --- a/code/modules/mob/living/basic/space_fauna/carp/carp_ai_rift_actions.dm +++ b/code/modules/mob/living/basic/space_fauna/carp/carp_ai_rift_actions.dm @@ -17,10 +17,9 @@ if (!target) return - var/datum/action/cooldown/using_action = controller.blackboard[BB_CARP_RIFT] - if (isnull(using_action)) - return - if (!using_action.IsAvailable()) + var/datum/weakref/weak_action = controller.blackboard[BB_CARP_RIFT] + var/datum/action/cooldown/using_action = weak_action?.resolve() + if (isnull(using_action) || !using_action.IsAvailable()) return controller.queue_behavior(rift_behaviour, BB_CARP_RIFT, BB_BASIC_MOB_CURRENT_TARGET) @@ -54,7 +53,8 @@ /datum/ai_behavior/make_carp_rift /datum/ai_behavior/make_carp_rift/setup(datum/ai_controller/controller, ability_key, target_key) - var/datum/action/cooldown/mob_cooldown/lesser_carp_rift/ability = controller.blackboard[ability_key] + var/datum/weakref/weak_action = controller.blackboard[ability_key] + var/datum/action/cooldown/mob_cooldown/lesser_carp_rift/ability = weak_action?.resolve() if (!ability) return FALSE var/datum/weakref/weak_target = controller.blackboard[target_key] @@ -63,7 +63,8 @@ /datum/ai_behavior/make_carp_rift/perform(delta_time, datum/ai_controller/controller, ability_key, target_key) . = ..() - var/datum/action/cooldown/mob_cooldown/lesser_carp_rift/ability = controller.blackboard[ability_key] + var/datum/weakref/weak_action = controller.blackboard[ability_key] + var/datum/action/cooldown/mob_cooldown/lesser_carp_rift/ability = weak_action?.resolve() var/datum/weakref/weak_target = controller.blackboard[target_key] var/atom/target = weak_target?.resolve() diff --git a/code/modules/mob/living/basic/space_fauna/carp/carp_controllers.dm b/code/modules/mob/living/basic/space_fauna/carp/carp_controllers.dm index 4210853c02a..75c915c16a1 100644 --- a/code/modules/mob/living/basic/space_fauna/carp/carp_controllers.dm +++ b/code/modules/mob/living/basic/space_fauna/carp/carp_controllers.dm @@ -63,7 +63,7 @@ /datum/ai_planning_subtree/flee_target, /datum/ai_planning_subtree/find_food, /datum/ai_planning_subtree/find_nearest_magicarp_spell_target, - /datum/ai_planning_subtree/targetted_mob_ability/magicarp, + /datum/ai_planning_subtree/targeted_mob_ability/magicarp, /datum/ai_planning_subtree/simple_find_target, /datum/ai_planning_subtree/attack_obstacle_in_path/carp, /datum/ai_planning_subtree/shortcut_to_target_through_carp_rift, diff --git a/code/modules/mob/living/basic/space_fauna/carp/magicarp.dm b/code/modules/mob/living/basic/space_fauna/carp/magicarp.dm index 3ee5c35c5e7..90418d7e467 100644 --- a/code/modules/mob/living/basic/space_fauna/carp/magicarp.dm +++ b/code/modules/mob/living/basic/space_fauna/carp/magicarp.dm @@ -88,7 +88,7 @@ GLOBAL_LIST_INIT(magicarp_spell_colours, list( spell.projectile_type = spell_type spell.button_icon_state = initial(spell_type.icon_state) spell.Grant(src) - ai_controller.blackboard[BB_MAGICARP_SPELL] = spell + ai_controller.blackboard[BB_MAGICARP_SPELL] = WEAKREF(spell) assign_spell_ai(spell_type) /// If you have certain spells, use a different targetting datum diff --git a/code/modules/mob/living/basic/space_fauna/ghost.dm b/code/modules/mob/living/basic/space_fauna/ghost.dm index e8f65ae4737..c20903e2773 100644 --- a/code/modules/mob/living/basic/space_fauna/ghost.dm +++ b/code/modules/mob/living/basic/space_fauna/ghost.dm @@ -99,17 +99,10 @@ planning_subtrees = list( /datum/ai_planning_subtree/target_retaliate, - /datum/ai_planning_subtree/basic_melee_attack_subtree/ghost, + /datum/ai_planning_subtree/basic_melee_attack_subtree, ) -/datum/ai_planning_subtree/basic_melee_attack_subtree/ghost - melee_attack_behavior = /datum/ai_behavior/basic_melee_attack/ghost - -/datum/ai_behavior/basic_melee_attack/ghost - action_cooldown = 2 SECONDS - - -/// Weaker variant of ghosts that can smash structures. Meant to be summoned in swarms via the ectoplasmic anomaly and associated ghost portal. +/// Weaker variant of ghosts. Meant to be summoned in swarms via the ectoplasmic anomaly and associated ghost portal. /mob/living/basic/ghost/swarm name = "vengeful spirit" desc = "Back from the grave, and not happy about it." @@ -121,4 +114,3 @@ melee_damage_upper = 10 death_message = "wails as it is torn back to the realm from which it came!" random_identity = FALSE - environment_smash = ENVIRONMENT_SMASH_STRUCTURES diff --git a/code/modules/mob/living/basic/space_fauna/giant_spider/giant_spider_ai.dm b/code/modules/mob/living/basic/space_fauna/giant_spider/giant_spider_ai.dm index 826982e491d..ca7b8cce21c 100644 --- a/code/modules/mob/living/basic/space_fauna/giant_spider/giant_spider_ai.dm +++ b/code/modules/mob/living/basic/space_fauna/giant_spider/giant_spider_ai.dm @@ -1,5 +1,3 @@ -#define SPIDER_ATTACK_COOLDOWN (2 SECONDS) - /// For now, essentially just a Simple Hostile but room for expansion /datum/ai_controller/basic_controller/giant_spider blackboard = list( @@ -12,11 +10,18 @@ planning_subtrees = list( /datum/ai_planning_subtree/simple_find_target, - /datum/ai_planning_subtree/attack_obstacle_in_path/giant_spider, - /datum/ai_planning_subtree/basic_melee_attack_subtree/giant_spider, + /datum/ai_planning_subtree/attack_obstacle_in_path, + /datum/ai_planning_subtree/basic_melee_attack_subtree, /datum/ai_planning_subtree/random_speech/insect, // Space spiders are taxonomically insects not arachnids, don't DM me ) +/// Giant spider which won't attack structures +/datum/ai_controller/basic_controller/giant_spider/weak + planning_subtrees = list( + /datum/ai_planning_subtree/simple_find_target, + /datum/ai_planning_subtree/basic_melee_attack_subtree, + /datum/ai_planning_subtree/random_speech/insect, + ) /// Used by Araneus, who only attacks those who attack first /datum/ai_controller/basic_controller/giant_spider/retaliate @@ -26,21 +31,7 @@ planning_subtrees = list( /datum/ai_planning_subtree/target_retaliate, - /datum/ai_planning_subtree/attack_obstacle_in_path/giant_spider, - /datum/ai_planning_subtree/basic_melee_attack_subtree/giant_spider, + /datum/ai_planning_subtree/attack_obstacle_in_path, + /datum/ai_planning_subtree/basic_melee_attack_subtree, /datum/ai_planning_subtree/random_speech/insect, ) - -/datum/ai_planning_subtree/attack_obstacle_in_path/giant_spider - attack_behaviour = /datum/ai_behavior/attack_obstructions/giant_spider - -/datum/ai_behavior/attack_obstructions/giant_spider - action_cooldown = SPIDER_ATTACK_COOLDOWN - -/datum/ai_planning_subtree/basic_melee_attack_subtree/giant_spider - melee_attack_behavior = /datum/ai_behavior/basic_melee_attack/giant_spider - -/datum/ai_behavior/basic_melee_attack/giant_spider - action_cooldown = SPIDER_ATTACK_COOLDOWN - -#undef SPIDER_ATTACK_COOLDOWN diff --git a/code/modules/mob/living/basic/space_fauna/giant_spider/spider_variants.dm b/code/modules/mob/living/basic/space_fauna/giant_spider/spider_variants.dm index 2eacd437ecf..1cdc1828372 100644 --- a/code/modules/mob/living/basic/space_fauna/giant_spider/spider_variants.dm +++ b/code/modules/mob/living/basic/space_fauna/giant_spider/spider_variants.dm @@ -212,13 +212,13 @@ */ /mob/living/basic/giant_spider/hunter/scrawny name = "scrawny spider" - environment_smash = ENVIRONMENT_SMASH_NONE health = 60 maxHealth = 60 melee_damage_lower = 5 melee_damage_upper = 10 desc = "Furry and black, it makes you shudder to look at it. This one has sparkling purple eyes, and looks abnormally thin and frail." menu_description = "Fast spider variant specializing in catching running prey and toxin injection, but has less damage than a normal hunter spider at the cost of a little more health." + ai_controller = /datum/ai_controller/basic_controller/giant_spider/weak /** * # Scrawny Tarantula @@ -228,13 +228,13 @@ */ /mob/living/basic/giant_spider/tarantula/scrawny name = "scrawny tarantula" - environment_smash = ENVIRONMENT_SMASH_NONE health = 150 maxHealth = 150 melee_damage_lower = 20 melee_damage_upper = 25 desc = "Furry and black, it makes you shudder to look at it. This one has abyssal red eyes, and looks abnormally thin and frail." menu_description = "A weaker variant of the tarantula with reduced amount of health and damage, very slow when not on webbing. It also has a charge ability to close distance with a target after a small windup." + ai_controller = /datum/ai_controller/basic_controller/giant_spider/weak /** * # Scrawny Nurse Spider @@ -245,11 +245,11 @@ */ /mob/living/basic/giant_spider/nurse/scrawny name = "scrawny nurse spider" - environment_smash = ENVIRONMENT_SMASH_NONE health = 30 maxHealth = 30 desc = "Furry and black, it makes you shudder to look at it. This one has brilliant green eyes, and looks abnormally thin and frail." menu_description = "Weaker version of the nurse spider, specializing in healing their brethren and placing webbings very swiftly, but has very low amount of health and deals low damage." + ai_controller = /datum/ai_controller/basic_controller/giant_spider/weak /** * # Flesh Spider diff --git a/code/modules/mob/living/basic/space_fauna/wumborian_fugu/fugu_gland.dm b/code/modules/mob/living/basic/space_fauna/wumborian_fugu/fugu_gland.dm new file mode 100644 index 00000000000..485343c0a49 --- /dev/null +++ b/code/modules/mob/living/basic/space_fauna/wumborian_fugu/fugu_gland.dm @@ -0,0 +1,42 @@ +/// Item you use on a mob to make it bigger and stronger +/obj/item/fugu_gland + name = "wumborian fugu gland" + desc = "The key to the wumborian fugu's ability to increase its mass arbitrarily, this disgusting remnant can apply the same effect to other creatures, giving them great strength." + icon = 'icons/obj/medical/organs/organs.dmi' + icon_state = "fugu_gland" + item_flags = NOBLUDGEON + w_class = WEIGHT_CLASS_NORMAL + layer = MOB_LAYER + /// List of mob types which you can't apply the gland to + var/static/list/fugu_blacklist + +/obj/item/fugu_gland/Initialize(mapload) + . = ..() + if(fugu_blacklist) + return + fugu_blacklist = typecacheof(list( + /mob/living/simple_animal/hostile/guardian, + )) + +/obj/item/fugu_gland/afterattack(atom/target, mob/user, proximity_flag) + . = ..() + if(!proximity_flag || !isanimal_or_basicmob(target) || fugu_blacklist[target.type]) + return + var/mob/living/animal = target + + if(animal.stat == DEAD || HAS_TRAIT(animal, TRAIT_FAKEDEATH)) + balloon_alert(user, "it's dead!") + return + if(HAS_TRAIT(animal, TRAIT_FUGU_GLANDED)) + balloon_alert(user, "already large!") + return + + ADD_TRAIT(animal, TRAIT_FUGU_GLANDED, type) + animal.maxHealth *= 1.5 + animal.health = min(animal.maxHealth, animal.health * 1.5) + animal.melee_damage_lower = max((animal.melee_damage_lower * 2), 10) + animal.melee_damage_upper = max((animal.melee_damage_upper * 2), 10) + animal.transform *= 2 + animal.AddElement(/datum/element/wall_smasher, strength_flag = ENVIRONMENT_SMASH_RWALLS) + to_chat(user, span_info("You increase the size of [animal], giving [animal.p_them()] a surge of strength!")) + qdel(src) diff --git a/code/modules/mob/living/basic/space_fauna/wumborian_fugu/inflation.dm b/code/modules/mob/living/basic/space_fauna/wumborian_fugu/inflation.dm new file mode 100644 index 00000000000..e6e3d2200d7 --- /dev/null +++ b/code/modules/mob/living/basic/space_fauna/wumborian_fugu/inflation.dm @@ -0,0 +1,94 @@ +/** + * Action which inflates you, making you larger and stronger for the duration. Also invulnerable. + * This is pretty much all just handled by a status effect. + * Unfortunately the requirements here are specific enough that it kind of only works for the mob it is designed for. + */ +/datum/action/cooldown/fugu_expand + name = "Inflate" + desc = "Temporarily increases your size, making you significantly more dangerous and durable!" + button_icon = 'icons/mob/actions/actions_animal.dmi' + button_icon_state = "expand" + background_icon_state = "bg_fugu" + overlay_icon_state = "bg_fugu_border" + cooldown_time = 16 SECONDS + melee_cooldown_time = 0 SECONDS + +/datum/action/cooldown/fugu_expand/IsAvailable(feedback) + . = ..() + if (!.) + return FALSE + if(!istype(owner, /mob/living/basic/wumborian_fugu)) // A shame but there's not any good way to make this work on other mobs + if (feedback) + owner.balloon_alert(owner, "not stretchy enough!") + return FALSE + if(HAS_TRAIT(owner, TRAIT_FUGU_GLANDED)) + if (feedback) + owner.balloon_alert(owner, "already large!") + return FALSE + return TRUE + +/datum/action/cooldown/fugu_expand/Activate(atom/target) + . = ..() + var/mob/living/living_owner = owner + living_owner.apply_status_effect(/datum/status_effect/inflated) + +/** + * Status effect from the Expand action, makes you big and round and strong. + */ +/datum/status_effect/inflated + id = "wumbo_inflated" + duration = 10 SECONDS + alert_type = /atom/movable/screen/alert/status_effect/inflated + +/atom/movable/screen/alert/status_effect/inflated + name = "WUMBO" + desc = "You feel big and strong!" + icon_state = "gross" + +/datum/status_effect/inflated/on_creation(mob/living/new_owner, ...) + if (!istype(new_owner, /mob/living/basic/wumborian_fugu)) + return FALSE + return ..() + +/datum/status_effect/inflated/on_apply() + . = ..() + var/mob/living/basic/wumborian_fugu/fugu = owner + if (!istype(fugu)) + return FALSE + RegisterSignal(fugu, COMSIG_MOB_STATCHANGE, PROC_REF(check_death)) + fugu.add_movespeed_modifier(/datum/movespeed_modifier/status_effect/inflated) + ADD_TRAIT(fugu, TRAIT_FUGU_GLANDED, TRAIT_STATUS_EFFECT(id)) + fugu.AddElement(/datum/element/wall_smasher) + fugu.mob_size = MOB_SIZE_LARGE + fugu.icon_state = "Fugu1" + fugu.melee_damage_lower = 15 + fugu.melee_damage_upper = 20 + fugu.status_flags |= GODMODE + fugu.obj_damage = 60 + fugu.ai_controller.blackboard[BB_BASIC_MOB_FLEEING] = FALSE + fugu.ai_controller.CancelActions() + +/datum/status_effect/inflated/on_remove() + . = ..() + var/mob/living/basic/wumborian_fugu/fugu = owner + if (!istype(fugu)) + return // Check again in case you changed mob after application but somehow kept the status effect + UnregisterSignal(fugu, COMSIG_MOB_STATCHANGE) + fugu.remove_movespeed_modifier(/datum/movespeed_modifier/status_effect/inflated) + REMOVE_TRAIT(fugu, TRAIT_FUGU_GLANDED, TRAIT_STATUS_EFFECT(id)) + fugu.RemoveElement(/datum/element/wall_smasher) + fugu.mob_size = MOB_SIZE_SMALL + fugu.melee_damage_lower = 0 + fugu.melee_damage_upper = 0 + fugu.status_flags &= ~GODMODE + if (fugu.stat != DEAD) + fugu.icon_state = "Fugu0" + fugu.obj_damage = 0 + fugu.ai_controller.blackboard[BB_BASIC_MOB_FLEEING] = TRUE + fugu.ai_controller.CancelActions() + +/// Remove status effect if we die +/datum/status_effect/inflated/proc/check_death(mob/living/source, new_stat) + SIGNAL_HANDLER + if (new_stat == DEAD) + qdel(src) diff --git a/code/modules/mob/living/basic/space_fauna/wumborian_fugu/wumborian_ai.dm b/code/modules/mob/living/basic/space_fauna/wumborian_fugu/wumborian_ai.dm new file mode 100644 index 00000000000..f632a38dc1b --- /dev/null +++ b/code/modules/mob/living/basic/space_fauna/wumborian_fugu/wumborian_ai.dm @@ -0,0 +1,37 @@ +#define WUMBO_ATTACK_COOLDOWN 2.5 SECONDS + +/// Cowardly when small, aggressive when big. Tries to transform whenever possible. +/datum/ai_controller/basic_controller/wumborian_fugu + blackboard = list( + BB_TARGETTING_DATUM = new /datum/targetting_datum/basic(), + BB_BASIC_MOB_FLEEING = TRUE, + ) + + ai_movement = /datum/ai_movement/basic_avoidance + idle_behavior = /datum/idle_behavior/idle_random_walk + + planning_subtrees = list( + /datum/ai_planning_subtree/simple_find_target, + /datum/ai_planning_subtree/targeted_mob_ability/inflate, + /datum/ai_planning_subtree/flee_target, + /datum/ai_planning_subtree/attack_obstacle_in_path/wumborian_fugu, + /datum/ai_planning_subtree/basic_melee_attack_subtree/wumborian_fugu, + ) + +/datum/ai_planning_subtree/basic_melee_attack_subtree/wumborian_fugu + melee_attack_behavior = /datum/ai_behavior/basic_melee_attack/wumborian_fugu + +/datum/ai_behavior/basic_melee_attack/wumborian_fugu + action_cooldown = WUMBO_ATTACK_COOLDOWN + +/datum/ai_planning_subtree/attack_obstacle_in_path/wumborian_fugu + attack_behaviour = /datum/ai_behavior/attack_obstructions/wumborian_fugu + +/datum/ai_behavior/attack_obstructions/wumborian_fugu + can_attack_turfs = TRUE + action_cooldown = WUMBO_ATTACK_COOLDOWN + +/datum/ai_planning_subtree/targeted_mob_ability/inflate + ability_key = BB_FUGU_INFLATE + +#undef WUMBO_ATTACK_COOLDOWN diff --git a/code/modules/mob/living/basic/space_fauna/wumborian_fugu/wumborian_fugu.dm b/code/modules/mob/living/basic/space_fauna/wumborian_fugu/wumborian_fugu.dm new file mode 100644 index 00000000000..93516eddcf5 --- /dev/null +++ b/code/modules/mob/living/basic/space_fauna/wumborian_fugu/wumborian_fugu.dm @@ -0,0 +1,58 @@ +/** + * # Wumborian Fugu + * + * A strange alien creature capable of increasing its mass when threatened, when not inflated it is virtually defenceless. + * Mostly only appears from xenobiology, or the occasional wizard. + * On death, the "fugu gland" is dropped, which can be used on mobs to increase their size, health, strength, and lets them smash walls. + */ +/mob/living/basic/wumborian_fugu + name = "wumborian fugu" + desc = "The wumborian fugu rapidly increases its body mass in order to ward off its prey. Great care should be taken to avoid it while it's in this state as it is nearly invincible, but it cannot maintain its form forever." + icon = 'icons/mob/simple/lavaland/64x64megafauna.dmi' + icon_state = "Fugu0" + icon_living = "Fugu0" + icon_dead = "Fugu_dead" + icon_gib = "syndicate_gib" + health_doll_icon = "Fugu0" + pixel_x = -16 + base_pixel_x = -16 + status_flags = NONE + gold_core_spawnable = HOSTILE_SPAWN + mob_biotypes = MOB_ORGANIC | MOB_BEAST + mob_size = MOB_SIZE_SMALL + speed = 0 + maxHealth = 50 + health = 50 + combat_mode = TRUE + obj_damage = 0 + melee_damage_lower = 0 + melee_damage_upper = 0 + attack_sound = 'sound/weapons/punch1.ogg' + attack_vis_effect = ATTACK_EFFECT_BITE + attack_verb_continuous = "chomps" + attack_verb_simple = "chomp" + friendly_verb_continuous = "floats near" + friendly_verb_simple = "float near" + speak_emote = list("puffs") + faction = list("mining") + see_in_dark = 8 + lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE + habitable_atmos = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) + minimum_survivable_temperature = 0 + maximum_survivable_temperature = INFINITY + ai_controller = /datum/ai_controller/basic_controller/wumborian_fugu + /// Ability used by the mob to become large, dangerous, and invulnerable + var/datum/action/cooldown/fugu_expand/expand + +/mob/living/basic/wumborian_fugu/Initialize(mapload) + . = ..() + AddElement(/datum/element/death_drops, loot = list(/obj/item/fugu_gland)) + ADD_TRAIT(src, TRAIT_LAVA_IMMUNE, ROUNDSTART_TRAIT) + ADD_TRAIT(src, TRAIT_ASHSTORM_IMMUNE, ROUNDSTART_TRAIT) + expand = new(src) + expand.Grant(src) + ai_controller.blackboard[BB_FUGU_INFLATE] = WEAKREF(expand) + +/mob/living/basic/wumborian_fugu/Destroy() + QDEL_NULL(expand) + return ..() diff --git a/code/modules/mob/living/basic/syndicate/syndicate.dm b/code/modules/mob/living/basic/syndicate/syndicate.dm index ea503fcd694..6fd1f6217df 100644 --- a/code/modules/mob/living/basic/syndicate/syndicate.dm +++ b/code/modules/mob/living/basic/syndicate/syndicate.dm @@ -10,7 +10,6 @@ health = 100 basic_mob_flags = DEL_ON_DEATH speed = 1.1 - environment_smash = ENVIRONMENT_SMASH_STRUCTURES melee_damage_lower = 10 melee_damage_upper = 10 attack_verb_continuous = "punches" @@ -253,7 +252,7 @@ bubble_icon = "syndibot" gold_core_spawnable = HOSTILE_SPAWN death_message = "is smashed into pieces!" - ai_controller = /datum/ai_controller/basic_controller/viscerator + ai_controller = /datum/ai_controller/basic_controller/syndicate/viscerator /mob/living/basic/viscerator/Initialize(mapload) . = ..() diff --git a/code/modules/mob/living/basic/syndicate/syndicate_ai.dm b/code/modules/mob/living/basic/syndicate/syndicate_ai.dm index 151e10017af..9e2c86e3602 100644 --- a/code/modules/mob/living/basic/syndicate/syndicate_ai.dm +++ b/code/modules/mob/living/basic/syndicate/syndicate_ai.dm @@ -7,6 +7,7 @@ idle_behavior = /datum/idle_behavior/idle_random_walk planning_subtrees = list( /datum/ai_planning_subtree/simple_find_target, + /datum/ai_planning_subtree/attack_obstacle_in_path/syndicate, /datum/ai_planning_subtree/basic_melee_attack_subtree/syndicate ) @@ -19,6 +20,12 @@ /datum/ai_behavior/basic_melee_attack/syndicate action_cooldown = 1.2 SECONDS +/datum/ai_planning_subtree/attack_obstacle_in_path/syndicate + attack_behaviour = /datum/ai_behavior/attack_obstructions/syndicate + +/datum/ai_behavior/attack_obstructions/syndicate + action_cooldown = 1.2 SECONDS + /datum/ai_controller/basic_controller/syndicate/ranged planning_subtrees = list( /datum/ai_planning_subtree/simple_find_target, @@ -58,14 +65,7 @@ action_cooldown = 3 SECONDS required_distance = 1 -/datum/ai_controller/basic_controller/viscerator +/datum/ai_controller/basic_controller/syndicate/viscerator blackboard = list( BB_TARGETTING_DATUM = new /datum/targetting_datum/basic() ) - - ai_movement = /datum/ai_movement/dumb - idle_behavior = /datum/idle_behavior/idle_random_walk - planning_subtrees = list( - /datum/ai_planning_subtree/simple_find_target, - /datum/ai_planning_subtree/basic_melee_attack_subtree/syndicate - ) diff --git a/code/modules/mob/living/basic/vermin/mouse.dm b/code/modules/mob/living/basic/vermin/mouse.dm index 9e8cea68791..6d9fe51dd56 100644 --- a/code/modules/mob/living/basic/vermin/mouse.dm +++ b/code/modules/mob/living/basic/vermin/mouse.dm @@ -407,21 +407,9 @@ planning_subtrees = list( /datum/ai_planning_subtree/pet_planning, /datum/ai_planning_subtree/simple_find_target, - /datum/ai_planning_subtree/attack_obstacle_in_path/rat, - /datum/ai_planning_subtree/basic_melee_attack_subtree/rat, + /datum/ai_planning_subtree/attack_obstacle_in_path, + /datum/ai_planning_subtree/basic_melee_attack_subtree, /datum/ai_planning_subtree/find_and_hunt_target/look_for_cheese, /datum/ai_planning_subtree/random_speech/mouse, /datum/ai_planning_subtree/find_and_hunt_target/look_for_cables, ) - -/datum/ai_planning_subtree/basic_melee_attack_subtree/rat - melee_attack_behavior = /datum/ai_behavior/basic_melee_attack/rat - -/datum/ai_behavior/basic_melee_attack/rat - action_cooldown = 2 SECONDS - -/datum/ai_planning_subtree/attack_obstacle_in_path/rat - attack_behaviour = /datum/ai_behavior/attack_obstructions/rat - -/datum/ai_behavior/attack_obstructions/rat - action_cooldown = 2 SECONDS diff --git a/code/modules/mob/living/simple_animal/hostile/regalrat.dm b/code/modules/mob/living/simple_animal/hostile/regalrat.dm index b7021115496..0ee8a7d3038 100644 --- a/code/modules/mob/living/simple_animal/hostile/regalrat.dm +++ b/code/modules/mob/living/simple_animal/hostile/regalrat.dm @@ -388,7 +388,7 @@ command_feedback = "squeak!" // Frogs and roaches can squeak too it's fine pointed_reaction = "and squeaks aggressively" refuse_reaction = "quivers" - attack_behaviour = /datum/ai_behavior/basic_melee_attack/rat + attack_behaviour = /datum/ai_behavior/basic_melee_attack // Command you can give to a mouse to make it kill someone /datum/pet_command/point_targetting/attack/glockroach diff --git a/code/modules/mob/living/simple_animal/hostile/wumborian_fugu.dm b/code/modules/mob/living/simple_animal/hostile/wumborian_fugu.dm deleted file mode 100644 index 56c308e7565..00000000000 --- a/code/modules/mob/living/simple_animal/hostile/wumborian_fugu.dm +++ /dev/null @@ -1,177 +0,0 @@ -/** - * - * # Wumborian Fugu - * - * A strange alien creature capable of increasing its mass when threatened, - * giving it unmatched defensive capabilities temporarily. The rest of the - * time, it is quite fragile. - * - * On death, the "fugu gland" is dropped, which can be used on simple mobs - * to increase their size, health, strength, and lets them smash walls. - */ -/mob/living/simple_animal/hostile/asteroid/fugu - name = "wumborian fugu" - desc = "The wumborian fugu rapidly increases its body mass in order to ward off its prey. Great care should be taken to avoid it while it's in this state as it is nearly invincible, but it cannot maintain its form forever." - icon = 'icons/mob/simple/lavaland/64x64megafauna.dmi' - icon_state = "Fugu0" - icon_living = "Fugu0" - icon_aggro = "Fugu0" - icon_dead = "Fugu_dead" - icon_gib = "syndicate_gib" - health_doll_icon = "Fugu0" - mob_biotypes = MOB_ORGANIC|MOB_BEAST - mouse_opacity = MOUSE_OPACITY_ICON - move_to_delay = 5 - friendly_verb_continuous = "floats near" - friendly_verb_simple = "float near" - speak_emote = list("puffs") - vision_range = 5 - speed = 0 - maxHealth = 50 - health = 50 - pixel_x = -16 - base_pixel_x = -16 - harm_intent_damage = 5 - obj_damage = 0 - melee_damage_lower = 0 - melee_damage_upper = 0 - attack_verb_continuous = "chomps" - attack_verb_simple = "chomp" - attack_sound = 'sound/weapons/punch1.ogg' - attack_vis_effect = ATTACK_EFFECT_BITE - throw_message = "is avoided by the" - aggro_vision_range = 9 - mob_size = MOB_SIZE_SMALL - environment_smash = ENVIRONMENT_SMASH_NONE - gold_core_spawnable = HOSTILE_SPAWN - var/wumbo = 0 - var/inflate_cooldown = 0 - var/datum/action/innate/fugu/expand/E - loot = list(/obj/item/fugu_gland{layer = ABOVE_MOB_LAYER}) - -/mob/living/simple_animal/hostile/asteroid/fugu/Initialize(mapload) - . = ..() - E = new - E.Grant(src) - -/mob/living/simple_animal/hostile/asteroid/fugu/Destroy() - QDEL_NULL(E) - return ..() - -/mob/living/simple_animal/hostile/asteroid/fugu/Life(delta_time = SSMOBS_DT, times_fired) - if(!wumbo) - inflate_cooldown = max((inflate_cooldown - (0.5 * delta_time)), 0) - if(target && AIStatus == AI_ON) - E.Activate() - ..() - -/mob/living/simple_animal/hostile/asteroid/fugu/adjustHealth(amount, updating_health = TRUE, forced = FALSE) - if(!forced && wumbo) - return FALSE - . = ..() - -/mob/living/simple_animal/hostile/asteroid/fugu/Aggro() - ..() - E.Activate() - -/datum/action/innate/fugu - button_icon = 'icons/mob/actions/actions_animal.dmi' - background_icon_state = "bg_fugu" - overlay_icon_state = "bg_fugu_border" - -/datum/action/innate/fugu/expand - name = "Inflate" - desc = "Temporarily increases your size, and makes you significantly more dangerous and tough! Do not bully the fugu!" - button_icon_state = "expand" - -/datum/action/innate/fugu/expand/Activate() - var/mob/living/simple_animal/hostile/asteroid/fugu/F = owner - if(F.wumbo) - to_chat(F, span_warning("YOU'RE ALREADY WUMBO!")) - return - if(F.inflate_cooldown) - to_chat(F, span_warning("You need time to gather your strength!")) - return - if(HAS_TRAIT(F, TRAIT_FUGU_GLANDED)) - to_chat(F, span_warning("Something is interfering with your growth!")) - return - F.wumbo = 1 - F.icon_state = "Fugu1" - F.obj_damage = 60 - F.melee_damage_lower = 15 - F.melee_damage_upper = 20 - F.harm_intent_damage = 0 - F.throw_message = "is absorbed by the girth of the" - F.retreat_distance = null - F.minimum_distance = 1 - F.move_to_delay = 6 - F.AddElement(/datum/element/wall_smasher) - F.mob_size = MOB_SIZE_LARGE - F.speed = 1 - addtimer(CALLBACK(F, TYPE_PROC_REF(/mob/living/simple_animal/hostile/asteroid/fugu, Deflate)), 100) - -// Why is half of this in an action and the other hand a proc on the mob? -/mob/living/simple_animal/hostile/asteroid/fugu/proc/Deflate() - if(wumbo) - SSmove_manager.stop_looping(src) - wumbo = 0 - icon_state = "Fugu0" - obj_damage = 0 - melee_damage_lower = 0 - melee_damage_upper = 0 - harm_intent_damage = 5 - throw_message = "is avoided by the" - retreat_distance = 9 - minimum_distance = 9 - move_to_delay = 2 - inflate_cooldown = 4 - RemoveElement(/datum/element/wall_smasher) - mob_size = MOB_SIZE_SMALL - speed = 0 - -/mob/living/simple_animal/hostile/asteroid/fugu/death(gibbed) - Deflate() - ..(gibbed) - -/obj/item/fugu_gland - name = "wumborian fugu gland" - desc = "The key to the wumborian fugu's ability to increase its mass arbitrarily, this disgusting remnant can apply the same effect to other creatures, giving them great strength." - icon = 'icons/obj/medical/organs/organs.dmi' - icon_state = "fugu_gland" - item_flags = NOBLUDGEON - w_class = WEIGHT_CLASS_NORMAL - layer = MOB_LAYER - var/static/list/fugu_blacklist - -/obj/item/fugu_gland/Initialize(mapload) - . = ..() - if(!fugu_blacklist) - fugu_blacklist = typecacheof(list( - /mob/living/simple_animal/hostile/guardian, - )) - -/obj/item/fugu_gland/afterattack(atom/target, mob/user, proximity_flag) - . = ..() - if(!proximity_flag) - return - if(!isanimal(target) || fugu_blacklist[target.type]) - return - var/mob/living/simple_animal/animal = target - - if(animal.stat == DEAD || HAS_TRAIT(animal, TRAIT_FAKEDEATH)) - to_chat(user, span_warning("[src] can only multiply strength, not grant it to the dead.")) - return - if(HAS_TRAIT(animal, TRAIT_FUGU_GLANDED)) - to_chat(user, span_warning("[animal] has already been affected by \a [src].")) - return - - ADD_TRAIT(animal, TRAIT_FUGU_GLANDED, type) - - animal.maxHealth *= 1.5 - animal.health = min(animal.maxHealth, animal.health * 1.5) - animal.melee_damage_lower = max((animal.melee_damage_lower * 2), 10) - animal.melee_damage_upper = max((animal.melee_damage_upper * 2), 10) - animal.transform *= 2 - animal.AddElement(/datum/element/wall_smasher, strength_flag = ENVIRONMENT_SMASH_RWALLS) - to_chat(user, span_info("You increase the size of [animal], giving [animal.p_them()] a surge of strength!")) - qdel(src) diff --git a/code/modules/movespeed/modifiers/status_effects.dm b/code/modules/movespeed/modifiers/status_effects.dm index a201a2363cd..d2120541cfa 100644 --- a/code/modules/movespeed/modifiers/status_effects.dm +++ b/code/modules/movespeed/modifiers/status_effects.dm @@ -28,3 +28,6 @@ /datum/movespeed_modifier/status_effect/brimdust_concussion multiplicative_slowdown = 1.5 + +/datum/movespeed_modifier/status_effect/inflated + multiplicative_slowdown = 3.5 diff --git a/code/modules/unit_tests/simple_animal_freeze.dm b/code/modules/unit_tests/simple_animal_freeze.dm index 823483f7251..4fefba1d285 100644 --- a/code/modules/unit_tests/simple_animal_freeze.dm +++ b/code/modules/unit_tests/simple_animal_freeze.dm @@ -78,7 +78,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/fugu, /mob/living/simple_animal/hostile/asteroid/goldgrub, /mob/living/simple_animal/hostile/asteroid/goliath, /mob/living/simple_animal/hostile/asteroid/goliath/beast, diff --git a/tgstation.dme b/tgstation.dme index 83009d722bb..a5bb7b66c5e 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -735,10 +735,10 @@ #include "code\datums\ai\basic_mobs\basic_ai_behaviors\pick_up_item.dm" #include "code\datums\ai\basic_mobs\basic_ai_behaviors\run_away_from_target.dm" #include "code\datums\ai\basic_mobs\basic_ai_behaviors\step_towards_turf.dm" +#include "code\datums\ai\basic_mobs\basic_ai_behaviors\targeted_mob_ability.dm" #include "code\datums\ai\basic_mobs\basic_ai_behaviors\targetting.dm" #include "code\datums\ai\basic_mobs\basic_ai_behaviors\tipped_reaction.dm" #include "code\datums\ai\basic_mobs\basic_ai_behaviors\travel_towards.dm" -#include "code\datums\ai\basic_mobs\basic_ai_behaviors\try_mob_ability.dm" #include "code\datums\ai\basic_mobs\basic_subtrees\attack_obstacle_in_path.dm" #include "code\datums\ai\basic_mobs\basic_subtrees\find_food.dm" #include "code\datums\ai\basic_mobs\basic_subtrees\flee_target.dm" @@ -747,8 +747,9 @@ #include "code\datums\ai\basic_mobs\basic_subtrees\simple_find_target.dm" #include "code\datums\ai\basic_mobs\basic_subtrees\speech_subtree.dm" #include "code\datums\ai\basic_mobs\basic_subtrees\target_retaliate.dm" -#include "code\datums\ai\basic_mobs\basic_subtrees\targetted_mob_ability.dm" +#include "code\datums\ai\basic_mobs\basic_subtrees\targeted_mob_ability.dm" #include "code\datums\ai\basic_mobs\basic_subtrees\tipped_subtree.dm" +#include "code\datums\ai\basic_mobs\basic_subtrees\use_mob_ability.dm" #include "code\datums\ai\basic_mobs\pet_commands\fetch.dm" #include "code\datums\ai\basic_mobs\pet_commands\pet_command_planning.dm" #include "code\datums\ai\basic_mobs\pet_commands\pet_follow_friend.dm" @@ -3789,6 +3790,10 @@ #include "code\modules\mob\living\basic\space_fauna\netherworld\creature.dm" #include "code\modules\mob\living\basic\space_fauna\netherworld\migo.dm" #include "code\modules\mob\living\basic\space_fauna\statue\statue.dm" +#include "code\modules\mob\living\basic\space_fauna\wumborian_fugu\fugu_gland.dm" +#include "code\modules\mob\living\basic\space_fauna\wumborian_fugu\inflation.dm" +#include "code\modules\mob\living\basic\space_fauna\wumborian_fugu\wumborian_ai.dm" +#include "code\modules\mob\living\basic\space_fauna\wumborian_fugu\wumborian_fugu.dm" #include "code\modules\mob\living\basic\syndicate\syndicate.dm" #include "code\modules\mob\living\basic\syndicate\syndicate_ai.dm" #include "code\modules\mob\living\basic\vermin\axolotl.dm" @@ -4025,7 +4030,6 @@ #include "code\modules\mob\living\simple_animal\hostile\vatbeast.dm" #include "code\modules\mob\living\simple_animal\hostile\venus_human_trap.dm" #include "code\modules\mob\living\simple_animal\hostile\wizard.dm" -#include "code\modules\mob\living\simple_animal\hostile\wumborian_fugu.dm" #include "code\modules\mob\living\simple_animal\hostile\zombie.dm" #include "code\modules\mob\living\simple_animal\hostile\bosses\boss.dm" #include "code\modules\mob\living\simple_animal\hostile\bosses\paperwizard.dm" diff --git a/tools/UpdatePaths/Scripts/73415_simple_fugu_to_basic.txt b/tools/UpdatePaths/Scripts/73415_simple_fugu_to_basic.txt new file mode 100644 index 00000000000..a884cb3d370 --- /dev/null +++ b/tools/UpdatePaths/Scripts/73415_simple_fugu_to_basic.txt @@ -0,0 +1,3 @@ +# replace simple animal fugu with basic animal + +/mob/living/simple_animal/hostile/asteroid/fugu : /mob/living/basic/wumborian_fugu{@OLD}