From 257923e09056075c4eebe49e3ca3b261eb2508e3 Mon Sep 17 00:00:00 2001 From: Jacquerel Date: Mon, 18 Sep 2023 17:10:05 +0100 Subject: [PATCH] Synchronise AI and Player basic mob melee behaviours (#78337) ## About The Pull Request I like for things that mobs do to be consistent regardless of whether they are controlled by a player or by the AI. One big offender of this is the melee behaviour cooldown. Basic mobs piloted by AI have arbitrary melee attack cooldowns which are not reflected when they are controlled by players who can generally attack much faster (but in _two_ instances, slower). To remedy this I added `melee_attack_cooldown` as a var on `living/basic` (sinful) and the ai now uses NextMove to not click too often, meaning that players can only bite things as often as the AI can and also that if you VV the cooldown it can speed the AI up (or slow it down) as well as a player. This also gets rid of a lot of subtypes of that datum, as we mostly made them to change the cooldown. I also hunted down a few places where there was behaviour placed inside an AI behaviour which wasn't easily replicable by a player piloting the same mob, preferably a player should be able to do everything that the AI can. Fixing this was largely a simple case of moving code from `ai_behaviour/melee_attack/perform` to `basic/mob_subtype/melee_attack` and also adding an element for one thing shared by three different mobs. Strictly speaking I didn't need the element that much because a player is perfectly capable of clicking on something they attack to drag it, but it's nice for it to be automatic? ## Why It's Good For The Game If you see a mob do something then you should also be able to do it. Mobs shouldn't have significantly different capabilities when controlled by a player (aside from usually being smarter). ## Changelog :cl: balance: Player-controlled basic mobs attack as fast as those mobs can when controlled by the AI balance: Player-controlled Faithless can paralyse people they attack, like the AI does balance: Player-controlled Star Gazers (if an admin felt like making one) apply the star mark on attack and deal damage to everything around them, like the AI does /:cl: --- .../basic_ai_behaviors/basic_attacking.dm | 10 ++-- .../basic_subtrees/simple_attack_target.dm | 3 -- code/datums/ai/dog/dog_behaviors.dm | 1 - .../components/basic_mob_attack_telegraph.dm | 2 +- .../pet_commands/pet_commands_basic.dm | 2 +- code/datums/elements/content_barfer.dm | 3 +- code/datums/elements/mob_grabber.dm | 30 +++++++++++ code/modules/mob/living/basic/basic.dm | 6 ++- .../mob/living/basic/farm_animals/pony.dm | 2 +- .../mob/living/basic/heretic/star_gazer.dm | 50 ++++++++----------- .../basic/icemoon/ice_whelp/ice_whelp.dm | 3 ++ .../basic/icemoon/ice_whelp/ice_whelp_ai.dm | 1 - .../basic/lavaland/lobstrosity/lobstrosity.dm | 4 +- .../lavaland/lobstrosity/lobstrosity_ai.dm | 8 +-- .../modules/mob/living/basic/pets/dog/_dog.dm | 1 + .../living/basic/ruin_defender/stickman.dm | 9 +--- .../space_fauna/bear/bear_ai_behavior.dm | 3 -- .../basic/space_fauna/bear/bear_ai_subtree.dm | 5 +- .../mob/living/basic/space_fauna/carp/carp.dm | 3 +- .../basic/space_fauna/carp/carp_ai_actions.dm | 15 ++---- .../space_fauna/carp/carp_controllers.dm | 6 +-- .../living/basic/space_fauna/carp/magicarp.dm | 2 +- .../mob/living/basic/space_fauna/faithless.dm | 47 +++++++---------- .../living/basic/space_fauna/garden_gnome.dm | 9 +--- .../living/basic/space_fauna/lightgeist.dm | 15 ++---- .../mob/living/basic/space_fauna/mushroom.dm | 9 +--- .../space_fauna/netherworld/blankbody.dm | 3 +- .../basic/space_fauna/netherworld/creature.dm | 3 +- .../basic/space_fauna/netherworld/migo.dm | 3 +- .../regal_rat/regal_rat_actions.dm | 1 + .../living/basic/space_fauna/statue/statue.dm | 9 +--- .../wumborian_fugu/wumborian_ai.dm | 14 +----- .../wumborian_fugu/wumborian_fugu.dm | 1 + .../mob/living/basic/syndicate/syndicate.dm | 1 + .../living/basic/syndicate/syndicate_ai.dm | 8 +-- code/modules/mob/living/basic/tree.dm | 10 +--- .../mob/living/basic/vermin/cockroach.dm | 17 ++----- code/modules/mob/living/basic/vermin/frog.dm | 11 ++-- .../modules/mob/living/carbon/damage_procs.dm | 2 +- .../mob/living/carbon/human/damage_procs.dm | 2 +- code/modules/mob/living/damage_procs.dm | 2 +- .../mob/living/silicon/damage_procs.dm | 2 +- tgstation.dme | 1 + 43 files changed, 143 insertions(+), 196 deletions(-) create mode 100644 code/datums/elements/mob_grabber.dm 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 480aa68984d..a27d881a437 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 = 2 SECONDS + action_cooldown = 0.2 SECONDS // We gotta check unfortunately often because we're in a race condition with nextmove behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT | AI_BEHAVIOR_REQUIRE_REACH | 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) @@ -16,6 +16,11 @@ set_movement_target(controller, target) /datum/ai_behavior/basic_melee_attack/perform(seconds_per_tick, datum/ai_controller/controller, target_key, targetting_datum_key, hiding_location_key) + if (isliving(controller.pawn)) + var/mob/living/pawn = controller.pawn + if (world.time < pawn.next_move) + return + . = ..() var/mob/living/basic/basic_mob = controller.pawn //targetting datum will kill the action if not real anymore @@ -41,9 +46,6 @@ if(!succeeded) controller.clear_blackboard_key(target_key) -/datum/ai_behavior/basic_melee_attack/average_speed - action_cooldown = 1 SECONDS - /datum/ai_behavior/basic_ranged_attack action_cooldown = 0.6 SECONDS behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT | AI_BEHAVIOR_MOVE_AND_PERFORM diff --git a/code/datums/ai/basic_mobs/basic_subtrees/simple_attack_target.dm b/code/datums/ai/basic_mobs/basic_subtrees/simple_attack_target.dm index 90379fcac0a..ed45de512ac 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/simple_attack_target.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/simple_attack_target.dm @@ -9,9 +9,6 @@ controller.queue_behavior(melee_attack_behavior, BB_BASIC_MOB_CURRENT_TARGET, BB_TARGETTING_DATUM, BB_BASIC_MOB_CURRENT_TARGET_HIDING_LOCATION) return SUBTREE_RETURN_FINISH_PLANNING //we are going into battle...no distractions. -/datum/ai_planning_subtree/basic_melee_attack_subtree/average_speed - melee_attack_behavior = /datum/ai_behavior/basic_melee_attack/average_speed - /datum/ai_planning_subtree/basic_ranged_attack_subtree operational_datums = list(/datum/component/ranged_attacks) var/datum/ai_behavior/basic_ranged_attack/ranged_attack_behavior = /datum/ai_behavior/basic_ranged_attack diff --git a/code/datums/ai/dog/dog_behaviors.dm b/code/datums/ai/dog/dog_behaviors.dm index 7bd0d5824a1..6c9cb779bb3 100644 --- a/code/datums/ai/dog/dog_behaviors.dm +++ b/code/datums/ai/dog/dog_behaviors.dm @@ -4,7 +4,6 @@ * Adds a floor to the melee damage of the dog, as most pet dogs don't actually have any melee strength */ /datum/ai_behavior/basic_melee_attack/dog - action_cooldown = 0.8 SECONDS behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT | AI_BEHAVIOR_MOVE_AND_PERFORM required_distance = 3 diff --git a/code/datums/components/basic_mob_attack_telegraph.dm b/code/datums/components/basic_mob_attack_telegraph.dm index 6467fbd7bbc..5473dbd0fa0 100644 --- a/code/datums/components/basic_mob_attack_telegraph.dm +++ b/code/datums/components/basic_mob_attack_telegraph.dm @@ -73,7 +73,7 @@ return ADD_TRAIT(source, TRAIT_BASIC_ATTACK_FORECAST, REF(src)) forget_target(target) - source.melee_attack(target) + source.melee_attack(target, ignore_cooldown = TRUE) // We already started the cooldown when we triggered the forecast /// The guy we're trying to attack moved, is he still in range? /datum/component/basic_mob_attack_telegraph/proc/target_moved(atom/target) diff --git a/code/datums/components/pet_commands/pet_commands_basic.dm b/code/datums/components/pet_commands/pet_commands_basic.dm index a07a94fff3f..ff29b8f37d2 100644 --- a/code/datums/components/pet_commands/pet_commands_basic.dm +++ b/code/datums/components/pet_commands/pet_commands_basic.dm @@ -111,7 +111,7 @@ pointed_reaction = "and growls" /// Balloon alert to display if providing an invalid target var/refuse_reaction = "shakes head" - /// Attack behaviour to use, generally you will want to override this to add some kind of cooldown + /// Attack behaviour to use var/attack_behaviour = /datum/ai_behavior/basic_melee_attack // Refuse to target things we can't target, chiefly other friends diff --git a/code/datums/elements/content_barfer.dm b/code/datums/elements/content_barfer.dm index 7e26d3f7753..e30294bc08a 100644 --- a/code/datums/elements/content_barfer.dm +++ b/code/datums/elements/content_barfer.dm @@ -4,9 +4,8 @@ * Used for morphs and bileworms! */ /datum/element/content_barfer - argument_hash_start_idx = 2 -/datum/element/content_barfer/Attach(datum/target, tally_string) +/datum/element/content_barfer/Attach(datum/target) . = ..() if(!isliving(target)) diff --git a/code/datums/elements/mob_grabber.dm b/code/datums/elements/mob_grabber.dm new file mode 100644 index 00000000000..a85c5dc48b2 --- /dev/null +++ b/code/datums/elements/mob_grabber.dm @@ -0,0 +1,30 @@ +/// Grab onto mobs we attack +/datum/element/mob_grabber + element_flags = ELEMENT_BESPOKE + argument_hash_start_idx = 2 + /// What state must the mob be in to be grabbed? + var/minimum_stat + /// If someone else is already grabbing this, will we take it? + var/steal_from_others + +/datum/element/mob_grabber/Attach(datum/target, minimum_stat = SOFT_CRIT, steal_from_others = TRUE) + . = ..() + if (!isliving(target)) + return ELEMENT_INCOMPATIBLE + src.minimum_stat = minimum_stat + src.steal_from_others = steal_from_others + RegisterSignals(target, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, COMSIG_HOSTILE_PRE_ATTACKINGTARGET), PROC_REF(grab_mob)) + +/datum/element/mob_grabber/Detach(datum/source) + UnregisterSignal(source, list(COMSIG_LIVING_UNARMED_ATTACK, COMSIG_HUMAN_MELEE_UNARMED_ATTACK, COMSIG_HOSTILE_PRE_ATTACKINGTARGET)) + . = ..() + +/// Try and grab something we attacked +/datum/element/mob_grabber/proc/grab_mob(mob/living/source, mob/living/target) + SIGNAL_HANDLER + if (!isliving(target) || !source.Adjacent(target) || target.stat < minimum_stat) + return + var/atom/currently_pulled = target.pulledby + if (!isnull(currently_pulled) && (!steal_from_others || currently_pulled == source)) + return + INVOKE_ASYNC(target, TYPE_PROC_REF(/mob/living, grabbedby), source) diff --git a/code/modules/mob/living/basic/basic.dm b/code/modules/mob/living/basic/basic.dm index 44c11bdc056..155321805c6 100644 --- a/code/modules/mob/living/basic/basic.dm +++ b/code/modules/mob/living/basic/basic.dm @@ -35,6 +35,8 @@ var/attack_vis_effect ///Played when someone punches the creature. var/attacked_sound = SFX_PUNCH //This should be an element + /// How often can you melee attack? + var/melee_attack_cooldown = 2 SECONDS /// 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 @@ -191,8 +193,10 @@ return . += span_deadsay("Upon closer examination, [p_they()] appear[p_s()] to be [HAS_TRAIT(user.mind, TRAIT_NAIVE) ? "asleep" : "dead"].") -/mob/living/basic/proc/melee_attack(atom/target, list/modifiers) +/mob/living/basic/proc/melee_attack(atom/target, list/modifiers, ignore_cooldown = FALSE) face_atom(target) + if (!ignore_cooldown) + changeNext_move(melee_attack_cooldown) if(SEND_SIGNAL(src, COMSIG_HOSTILE_PRE_ATTACKINGTARGET, target) & COMPONENT_HOSTILE_NO_ATTACK) return FALSE //but more importantly return before attack_animal called var/result = target.attack_basic_mob(src, modifiers) diff --git a/code/modules/mob/living/basic/farm_animals/pony.dm b/code/modules/mob/living/basic/farm_animals/pony.dm index 434caa5ef51..4bc09391cb7 100644 --- a/code/modules/mob/living/basic/farm_animals/pony.dm +++ b/code/modules/mob/living/basic/farm_animals/pony.dm @@ -62,7 +62,7 @@ if (prob(33)) whinny_angrily() -/mob/living/basic/pony/melee_attack(atom/target, list/modifiers) +/mob/living/basic/pony/melee_attack(atom/target, list/modifiers, ignore_cooldown = FALSE) . = ..() if (!.) diff --git a/code/modules/mob/living/basic/heretic/star_gazer.dm b/code/modules/mob/living/basic/heretic/star_gazer.dm index 29b5f16db8f..b739da0831a 100644 --- a/code/modules/mob/living/basic/heretic/star_gazer.dm +++ b/code/modules/mob/living/basic/heretic/star_gazer.dm @@ -22,6 +22,7 @@ attack_verb_simple = "ravage" attack_vis_effect = ATTACK_EFFECT_SLASH attack_sound = 'sound/weapons/bladeslice.ogg' + melee_attack_cooldown = 0.6 SECONDS speak_emote = list("growls") damage_coeff = list(BRUTE = 1, BURN = 0.5, TOX = 0, CLONE = 0, STAMINA = 0, OXY = 0) death_sound = 'sound/magic/cosmic_expansion.ogg' @@ -57,6 +58,24 @@ ADD_TRAIT(src, TRAIT_NO_FLOATING_ANIM, INNATE_TRAIT) set_light(4, l_color = "#dcaa5b") +// Star gazer attacks everything around itself applies a spooky mark +/mob/living/basic/heretic_summon/star_gazer/melee_attack(mob/living/target, list/modifiers, ignore_cooldown) + . = ..() + if (!. || !isliving(target)) + return + + target.apply_status_effect(/datum/status_effect/star_mark) + target.apply_damage(damage = 5, damagetype = CLONE) + var/datum/targetting_datum/target_confirmer = ai_controller.blackboard[BB_TARGETTING_DATUM] + for(var/mob/living/nearby_mob in range(1, src)) + if(target == nearby_mob || !target_confirmer?.can_attack(src, nearby_mob)) + continue + nearby_mob.apply_status_effect(/datum/status_effect/star_mark) + nearby_mob.apply_damage(10) + to_chat(nearby_mob, span_userdanger("\The [src] [attack_verb_continuous] you!")) + do_attack_animation(nearby_mob, ATTACK_EFFECT_SLASH) + log_combat(src, nearby_mob, "slashed") + /datum/ai_controller/basic_controller/star_gazer blackboard = list( BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/star_gazer(), @@ -70,39 +89,12 @@ /datum/ai_planning_subtree/pet_planning, /datum/ai_planning_subtree/simple_find_target, /datum/ai_planning_subtree/attack_obstacle_in_path/star_gazer, - /datum/ai_planning_subtree/basic_melee_attack_subtree/star_gazer, + /datum/ai_planning_subtree/basic_melee_attack_subtree, ) /datum/targetting_datum/basic/star_gazer stat_attack = HARD_CRIT -/datum/ai_planning_subtree/basic_melee_attack_subtree/star_gazer - melee_attack_behavior = /datum/ai_behavior/basic_melee_attack/star_gazer - -/datum/ai_behavior/basic_melee_attack/star_gazer - action_cooldown = 0.6 SECONDS - -/datum/ai_behavior/basic_melee_attack/star_gazer/perform(seconds_per_tick, datum/ai_controller/controller, target_key, targetting_datum_key, hiding_location_key) - . = ..() - var/atom/target = controller.blackboard[target_key] - var/mob/living/living_pawn = controller.pawn - - if(!isliving(target)) - return - var/mob/living/living_target = target - living_target.apply_status_effect(/datum/status_effect/star_mark) - living_target.apply_damage_type(damage = 5, damagetype = CLONE) - if(living_target.pulledby != living_pawn) - if(living_pawn.Adjacent(living_target) && isturf(living_target.loc) && living_target.stat == SOFT_CRIT) - living_target.grabbedby(living_pawn) - for(var/mob/living/nearby_mob in range(1, living_pawn)) - if(nearby_mob.stat == DEAD || living_target == nearby_mob || faction_check(nearby_mob.faction, list(FACTION_HERETIC))) - continue - nearby_mob.apply_status_effect(/datum/status_effect/star_mark) - nearby_mob.adjustBruteLoss(10) - living_pawn.do_attack_animation(nearby_mob, ATTACK_EFFECT_SLASH) - log_combat(living_pawn, nearby_mob, "slashed") - /datum/ai_planning_subtree/attack_obstacle_in_path/star_gazer attack_behaviour = /datum/ai_behavior/attack_obstructions/star_gazer @@ -119,4 +111,4 @@ command_feedback = "stares!" pointed_reaction = "stares intensely!" refuse_reaction = "..." - attack_behaviour = /datum/ai_behavior/basic_melee_attack/star_gazer + attack_behaviour = /datum/ai_behavior/basic_melee_attack diff --git a/code/modules/mob/living/basic/icemoon/ice_whelp/ice_whelp.dm b/code/modules/mob/living/basic/icemoon/ice_whelp/ice_whelp.dm index 465d724944b..292766be07b 100644 --- a/code/modules/mob/living/basic/icemoon/ice_whelp/ice_whelp.dm +++ b/code/modules/mob/living/basic/icemoon/ice_whelp/ice_whelp.dm @@ -69,6 +69,7 @@ INVOKE_ASYNC(src, PROC_REF(cannibalize_victim), victim) return COMPONENT_HOSTILE_NO_ATTACK +/// Carve a stone into a beautiful self-portrait /mob/living/basic/mining/ice_whelp/proc/create_sculpture(atom/target) balloon_alert(src, "sculpting...") if(!do_after(src, 5 SECONDS, target = target)) @@ -80,7 +81,9 @@ dragon_statue.set_anchored(TRUE) qdel(target) +/// Gib and consume our fellow ice drakes /mob/living/basic/mining/ice_whelp/proc/cannibalize_victim(mob/living/target) + start_pulling(target) balloon_alert(src, "devouring...") if(!do_after(src, 5 SECONDS, target)) return diff --git a/code/modules/mob/living/basic/icemoon/ice_whelp/ice_whelp_ai.dm b/code/modules/mob/living/basic/icemoon/ice_whelp/ice_whelp_ai.dm index 08c5fda3fd8..9885ba3da59 100644 --- a/code/modules/mob/living/basic/icemoon/ice_whelp/ice_whelp_ai.dm +++ b/code/modules/mob/living/basic/icemoon/ice_whelp/ice_whelp_ai.dm @@ -58,7 +58,6 @@ finish_action(controller, FALSE) return - living_pawn.start_pulling(target) living_pawn.melee_attack(target) finish_action(controller, TRUE) diff --git a/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity.dm b/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity.dm index 6463fc94979..18cd7321936 100644 --- a/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity.dm +++ b/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity.dm @@ -18,6 +18,7 @@ attack_verb_simple = "snip" attack_sound = 'sound/weapons/bite.ogg' attack_vis_effect = ATTACK_EFFECT_BITE // Closer than a scratch to a crustacean pinching effect + melee_attack_cooldown = 1 SECONDS butcher_results = list( /obj/item/food/meat/crab = 2, /obj/item/stack/sheet/bone = 2, @@ -35,6 +36,7 @@ /mob/living/basic/mining/lobstrosity/Initialize(mapload) . = ..() ADD_TRAIT(src, TRAIT_SNOWSTORM_IMMUNE, INNATE_TRAIT) + AddElement(/datum/element/mob_grabber) AddElement(/datum/element/footstep, FOOTSTEP_MOB_CLAW) AddElement(/datum/element/basic_eating, food_types = target_foods) AddElement(\ @@ -73,7 +75,7 @@ return var/mob/living/basic/basic_source = source var/mob/living/living_target = target - basic_source.melee_attack(living_target) + basic_source.melee_attack(living_target, ignore_cooldown = TRUE) basic_source.ai_controller?.set_blackboard_key(BB_BASIC_MOB_FLEEING, FALSE) basic_source.start_pulling(living_target) diff --git a/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity_ai.dm b/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity_ai.dm index dcbeb1e670c..8e4dfe9e294 100644 --- a/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity_ai.dm +++ b/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity_ai.dm @@ -36,7 +36,6 @@ return ..() /datum/ai_behavior/basic_melee_attack/lobster - action_cooldown = 1 SECONDS /datum/ai_behavior/basic_melee_attack/lobster/perform(seconds_per_tick, datum/ai_controller/controller, target_key, targetting_datum_key, hiding_location_key) var/mob/living/target = controller.blackboard[target_key] @@ -53,9 +52,6 @@ if (controller.blackboard[BB_BASIC_MOB_FLEEING]) finish_action(controller = controller, succeeded = TRUE, target_key = target_key) // We don't want to clear our target return - var/mob/living/living_pawn = controller.pawn - if (target.stat != CONSCIOUS) - living_pawn.start_pulling(target) // No crawling away return ..() /datum/ai_planning_subtree/flee_target/lobster @@ -75,6 +71,10 @@ finish_action(controller, succeeded = FALSE) return + var/mob/living/us = controller.pawn + if (us.pulling == target) + us.stop_pulling() // If we're running away from someone, best not to bring them with us + return ..() /// Don't use charge ability on an adjacent target, and make sure you're visible before you start diff --git a/code/modules/mob/living/basic/pets/dog/_dog.dm b/code/modules/mob/living/basic/pets/dog/_dog.dm index 93947173cd9..dd3b3b3a463 100644 --- a/code/modules/mob/living/basic/pets/dog/_dog.dm +++ b/code/modules/mob/living/basic/pets/dog/_dog.dm @@ -33,6 +33,7 @@ attack_verb_simple = "bite" attack_sound = 'sound/weapons/bite.ogg' attack_vis_effect = ATTACK_EFFECT_BITE + melee_attack_cooldown = 0.8 SECONDS /// Instructions you can give to dogs var/static/list/pet_commands = list( /datum/pet_command/idle, diff --git a/code/modules/mob/living/basic/ruin_defender/stickman.dm b/code/modules/mob/living/basic/ruin_defender/stickman.dm index 8d0a5ab0cde..107973135c7 100644 --- a/code/modules/mob/living/basic/ruin_defender/stickman.dm +++ b/code/modules/mob/living/basic/ruin_defender/stickman.dm @@ -13,6 +13,7 @@ attack_verb_simple = "punch" melee_damage_lower = 10 melee_damage_upper = 10 + melee_attack_cooldown = 1.5 SECONDS attack_sound = 'sound/weapons/punch1.ogg' combat_mode = TRUE faction = list(FACTION_STICKMAN) @@ -39,15 +40,9 @@ 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/stickman + /datum/ai_planning_subtree/basic_melee_attack_subtree ) -/datum/ai_planning_subtree/basic_melee_attack_subtree/stickman - melee_attack_behavior = /datum/ai_behavior/basic_melee_attack/stickman - -/datum/ai_behavior/basic_melee_attack/stickman - action_cooldown = 1.5 SECONDS - /mob/living/basic/stickman/dog name = "Angry Stick Dog" desc = "Stickman's best friend, if he could see him at least." diff --git a/code/modules/mob/living/basic/space_fauna/bear/bear_ai_behavior.dm b/code/modules/mob/living/basic/space_fauna/bear/bear_ai_behavior.dm index 6e716ddf411..7c57349524f 100644 --- a/code/modules/mob/living/basic/space_fauna/bear/bear_ai_behavior.dm +++ b/code/modules/mob/living/basic/space_fauna/bear/bear_ai_behavior.dm @@ -1,6 +1,3 @@ -/datum/ai_behavior/basic_melee_attack/bear - action_cooldown = 2 SECONDS - /datum/ai_behavior/find_hunt_target/find_hive /datum/ai_behavior/find_hunt_target/find_hive/valid_dinner(mob/living/source, obj/structure/beebox/hive, radius) diff --git a/code/modules/mob/living/basic/space_fauna/bear/bear_ai_subtree.dm b/code/modules/mob/living/basic/space_fauna/bear/bear_ai_subtree.dm index 244c600d89f..851c0bb8029 100644 --- a/code/modules/mob/living/basic/space_fauna/bear/bear_ai_subtree.dm +++ b/code/modules/mob/living/basic/space_fauna/bear/bear_ai_subtree.dm @@ -8,16 +8,13 @@ planning_subtrees = list( /datum/ai_planning_subtree/target_retaliate, /datum/ai_planning_subtree/simple_find_target, - /datum/ai_planning_subtree/basic_melee_attack_subtree/bear, + /datum/ai_planning_subtree/basic_melee_attack_subtree, /datum/ai_planning_subtree/climb_trees, /datum/ai_planning_subtree/find_and_hunt_target/find_hive, /datum/ai_planning_subtree/find_and_hunt_target/find_honeycomb, /datum/ai_planning_subtree/random_speech/bear, ) -/datum/ai_planning_subtree/basic_melee_attack_subtree/bear - melee_attack_behavior = /datum/ai_behavior/basic_melee_attack/bear - /datum/ai_planning_subtree/find_and_hunt_target/find_hive target_key = BB_FOUND_HONEY hunting_behavior = /datum/ai_behavior/hunt_target/find_hive 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 6ce40d8c1a3..9a4b149fd1a 100644 --- a/code/modules/mob/living/basic/space_fauna/carp/carp.dm +++ b/code/modules/mob/living/basic/space_fauna/carp/carp.dm @@ -32,6 +32,7 @@ attack_vis_effect = ATTACK_EFFECT_BITE attack_verb_continuous = "bites" attack_verb_simple = "bite" + melee_attack_cooldown = 1.5 SECONDS response_help_continuous = "pets" response_help_simple = "pet" response_disarm_continuous = "gently pushes aside" @@ -57,7 +58,7 @@ /datum/pet_command/idle, /datum/pet_command/free, /datum/pet_command/follow, - /datum/pet_command/point_targetting/attack/carp + /datum/pet_command/point_targetting/attack ) /// Carp want to eat raw meat var/static/list/desired_food = list(/obj/item/food/meat/slab, /obj/item/food/meat/rawcutlet) 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 c0f5143f18c..b2dc866ce7c 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 @@ -1,17 +1,8 @@ #define MAGICARP_SPELL_TARGET_SEEK_RANGE 4 -/datum/pet_command/point_targetting/attack/carp - attack_behaviour = /datum/ai_behavior/basic_melee_attack/carp - /datum/pet_command/point_targetting/use_ability/magicarp pet_ability_key = BB_MAGICARP_SPELL -/datum/ai_planning_subtree/basic_melee_attack_subtree/carp - melee_attack_behavior = /datum/ai_behavior/basic_melee_attack/carp - -/datum/ai_behavior/basic_melee_attack/carp - action_cooldown = 1.5 SECONDS - /datum/ai_planning_subtree/attack_obstacle_in_path/carp attack_behaviour = /datum/ai_behavior/attack_obstructions/carp @@ -20,12 +11,12 @@ /// As basic attack tree but interrupt if your health gets low or if your spell is off cooldown /datum/ai_planning_subtree/basic_melee_attack_subtree/magicarp - melee_attack_behavior = /datum/ai_behavior/basic_melee_attack/carp/magic + melee_attack_behavior = /datum/ai_behavior/basic_melee_attack/magicarp /// Interrupt your attack chain if: you have a spell, it's not on cooldown, and it has a target -/datum/ai_behavior/basic_melee_attack/carp/magic +/datum/ai_behavior/basic_melee_attack/magicarp -/datum/ai_behavior/basic_melee_attack/carp/magic/perform(seconds_per_tick, datum/ai_controller/controller, target_key, targetting_datum_key, hiding_location_key, health_ratio_key) +/datum/ai_behavior/basic_melee_attack/magicarp/perform(seconds_per_tick, datum/ai_controller/controller, target_key, targetting_datum_key, hiding_location_key, health_ratio_key) var/datum/action/cooldown/using_action = controller.blackboard[BB_MAGICARP_SPELL] if (QDELETED(using_action)) return ..() 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 f4c446d088b..b3097014535 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 @@ -25,7 +25,7 @@ /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/carp, + /datum/ai_planning_subtree/basic_melee_attack_subtree, /datum/ai_planning_subtree/carp_migration, ) @@ -48,7 +48,7 @@ /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/carp, + /datum/ai_planning_subtree/basic_melee_attack_subtree, ) /** @@ -91,6 +91,6 @@ /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/carp, + /datum/ai_planning_subtree/basic_melee_attack_subtree, /datum/ai_planning_subtree/carp_migration, ) 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 5051335a557..32f02b880db 100644 --- a/code/modules/mob/living/basic/space_fauna/carp/magicarp.dm +++ b/code/modules/mob/living/basic/space_fauna/carp/magicarp.dm @@ -56,7 +56,7 @@ GLOBAL_LIST_INIT(magicarp_spell_colours, list( /datum/pet_command/idle, /datum/pet_command/free, /datum/pet_command/follow, - /datum/pet_command/point_targetting/attack/carp, + /datum/pet_command/point_targetting/attack, /datum/pet_command/point_targetting/use_ability/magicarp, ) /// List of all projectiles we can fire. diff --git a/code/modules/mob/living/basic/space_fauna/faithless.dm b/code/modules/mob/living/basic/space_fauna/faithless.dm index b279856412c..c1dc297ea46 100644 --- a/code/modules/mob/living/basic/space_fauna/faithless.dm +++ b/code/modules/mob/living/basic/space_fauna/faithless.dm @@ -18,6 +18,7 @@ attack_verb_continuous = "grips" attack_verb_simple = "grip" attack_sound = 'sound/hallucinations/growl1.ogg' + melee_attack_cooldown = 1 SECONDS speak_emote = list("growls") unsuitable_atmos_damage = 0 @@ -29,12 +30,29 @@ ai_controller = /datum/ai_controller/basic_controller/faithless + /// What are the odds we paralyze a target on attack + var/paralyze_chance = 12 + /// How long do we paralyze a target for if we attack them + var/paralyze_duration = 2 SECONDS + /mob/living/basic/faithless/Initialize(mapload) . = ..() ADD_TRAIT(src, TRAIT_SPACEWALK, INNATE_TRAIT) AddElement(/datum/element/footstep, FOOTSTEP_MOB_SHOE) + AddElement(/datum/element/mob_grabber, steal_from_others = FALSE) AddComponent(/datum/component/pry_open_door) +/mob/living/basic/faithless/melee_attack(atom/target, list/modifiers, ignore_cooldown) + . = ..() + if (!. || !isliving(target)) + return + + var/mob/living/living_target = target + if (prob(paralyze_chance)) + living_target.Paralyze(paralyze_duration) + living_target.visible_message(span_danger("\The [src] knocks \the [target] down!"), \ + span_userdanger("\The [src] knocks you down!")) + /datum/ai_controller/basic_controller/faithless blackboard = list( BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/faithless(), @@ -47,37 +65,10 @@ /datum/ai_planning_subtree/simple_find_target, /datum/ai_planning_subtree/attack_obstacle_in_path, /datum/ai_planning_subtree/attack_obstacle_in_path/low_priority_target, - /datum/ai_planning_subtree/basic_melee_attack_subtree/faithless, + /datum/ai_planning_subtree/basic_melee_attack_subtree, /datum/ai_planning_subtree/find_and_hunt_target/look_for_light_fixtures, /datum/ai_planning_subtree/random_speech/faithless, ) /datum/targetting_datum/basic/faithless stat_attack = UNCONSCIOUS - -/datum/ai_planning_subtree/basic_melee_attack_subtree/faithless - melee_attack_behavior = /datum/ai_behavior/basic_melee_attack/faithless - -/datum/ai_behavior/basic_melee_attack/faithless - action_cooldown = 1 SECONDS - /// What are the odds we paralyze a target - var/paralyze_chance = 12 - /// How long do we paralyze a target for if we attack them - var/paralyze_duration = 2 SECONDS - -/datum/ai_behavior/basic_melee_attack/faithless/perform(seconds_per_tick, datum/ai_controller/controller, target_key, targetting_datum_key, hiding_location_key) - . = ..() - var/atom/target = controller.blackboard[target_key] - var/mob/living/living_pawn = controller.pawn - - if(!isliving(target)) - return - var/mob/living/living_target = target - if(living_target.pulledby != living_pawn && !HAS_AI_CONTROLLER_TYPE(living_target.pulledby, /datum/ai_controller/basic_controller/faithless)) //Dont steal from my fellow faithless. - if(living_pawn.Adjacent(living_target) && isturf(living_target.loc) && living_target.stat == SOFT_CRIT) - living_target.grabbedby(living_pawn) //Drag their bodies around as a menace. - if(prob(paralyze_chance) && iscarbon(target)) - var/mob/living/carbon/carbon_target = target - carbon_target.Paralyze(paralyze_duration) - carbon_target.visible_message(span_danger("\The [living_pawn] knocks down \the [carbon_target]!"), \ - span_userdanger("\The [living_pawn] knocks you down!")) diff --git a/code/modules/mob/living/basic/space_fauna/garden_gnome.dm b/code/modules/mob/living/basic/space_fauna/garden_gnome.dm index 9b57eba8fe2..d9dfc3c5343 100644 --- a/code/modules/mob/living/basic/space_fauna/garden_gnome.dm +++ b/code/modules/mob/living/basic/space_fauna/garden_gnome.dm @@ -17,6 +17,7 @@ attack_verb_continuous = "punches" attack_verb_simple = "punch" attack_sound = 'sound/weapons/punch1.ogg' + melee_attack_cooldown = 1.2 SECONDS damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1) speak_emote = list("announces") @@ -132,12 +133,6 @@ planning_subtrees = list( /datum/ai_planning_subtree/target_retaliate, /datum/ai_planning_subtree/attack_obstacle_in_path, - /datum/ai_planning_subtree/basic_melee_attack_subtree/garden_gnome, + /datum/ai_planning_subtree/basic_melee_attack_subtree, /datum/ai_planning_subtree/random_speech/garden_gnome, ) - -/datum/ai_planning_subtree/basic_melee_attack_subtree/garden_gnome - melee_attack_behavior = /datum/ai_behavior/basic_melee_attack/garden_gnome - -/datum/ai_behavior/basic_melee_attack/garden_gnome - action_cooldown = 1.2 SECONDS diff --git a/code/modules/mob/living/basic/space_fauna/lightgeist.dm b/code/modules/mob/living/basic/space_fauna/lightgeist.dm index 28debb6c0a1..c70588f4502 100644 --- a/code/modules/mob/living/basic/space_fauna/lightgeist.dm +++ b/code/modules/mob/living/basic/space_fauna/lightgeist.dm @@ -21,6 +21,7 @@ health = 2 melee_damage_lower = 5 melee_damage_upper = 5 + melee_attack_cooldown = 5 SECONDS friendly_verb_continuous = "taps" friendly_verb_simple = "tap" density = FALSE @@ -65,10 +66,10 @@ complete_text = "%TARGET%'s wounds mend together.",\ ) -/mob/living/basic/lightgeist/melee_attack(atom/target, list/modifiers) - if (isliving(target)) +/mob/living/basic/lightgeist/melee_attack(atom/target, list/modifiers, ignore_cooldown = FALSE) + . = ..() + if (. && isliving(target)) faction |= REF(target) // Anyone we heal will treat us as a friend - return ..() /mob/living/basic/lightgeist/ghost() . = ..() @@ -86,7 +87,7 @@ planning_subtrees = list( /datum/ai_planning_subtree/simple_find_target, - /datum/ai_planning_subtree/basic_melee_attack_subtree/lightgeist, // We heal things by attacking them + /datum/ai_planning_subtree/basic_melee_attack_subtree, // We heal things by attacking them ) /// Attack only mobs who have damage that we can heal, I think this is specific enough not to be a generic type @@ -111,9 +112,3 @@ continue return TRUE return FALSE - -/datum/ai_planning_subtree/basic_melee_attack_subtree/lightgeist - melee_attack_behavior = /datum/ai_behavior/basic_melee_attack/lightgeist - -/datum/ai_behavior/basic_melee_attack/lightgeist - action_cooldown = 5 SECONDS diff --git a/code/modules/mob/living/basic/space_fauna/mushroom.dm b/code/modules/mob/living/basic/space_fauna/mushroom.dm index 5e52dabae75..e6d47e2db5c 100644 --- a/code/modules/mob/living/basic/space_fauna/mushroom.dm +++ b/code/modules/mob/living/basic/space_fauna/mushroom.dm @@ -64,7 +64,7 @@ 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/mushroom, + /datum/ai_planning_subtree/basic_melee_attack_subtree, /datum/ai_planning_subtree/find_and_hunt_target/mushroom_food, ) @@ -76,13 +76,6 @@ /datum/targetting_datum/basic/mushroom/faction_check(mob/living/living_mob, mob/living/the_target) return !living_mob.faction_check_mob(the_target, exact_match = check_factions_exactly) - -/datum/ai_planning_subtree/basic_melee_attack_subtree/mushroom - melee_attack_behavior = /datum/ai_behavior/basic_melee_attack/mushroom - -/datum/ai_behavior/basic_melee_attack/mushroom - action_cooldown = 2 SECONDS - /datum/ai_planning_subtree/find_and_hunt_target/mushroom_food target_key = BB_LOW_PRIORITY_HUNTING_TARGET hunting_behavior = /datum/ai_behavior/hunt_target/unarmed_attack_target/mushroom_food diff --git a/code/modules/mob/living/basic/space_fauna/netherworld/blankbody.dm b/code/modules/mob/living/basic/space_fauna/netherworld/blankbody.dm index 35d597e53ca..5a7bb075f19 100644 --- a/code/modules/mob/living/basic/space_fauna/netherworld/blankbody.dm +++ b/code/modules/mob/living/basic/space_fauna/netherworld/blankbody.dm @@ -14,6 +14,7 @@ attack_verb_simple = "punch" attack_sound = 'sound/weapons/bladeslice.ogg' attack_vis_effect = ATTACK_EFFECT_SLASH + melee_attack_cooldown = 1 SECONDS faction = list(FACTION_NETHER) speak_emote = list("screams") death_message = "falls apart into a fine dust." @@ -42,5 +43,5 @@ planning_subtrees = list( /datum/ai_planning_subtree/simple_find_target, /datum/ai_planning_subtree/attack_obstacle_in_path, - /datum/ai_planning_subtree/basic_melee_attack_subtree/average_speed, + /datum/ai_planning_subtree/basic_melee_attack_subtree, ) diff --git a/code/modules/mob/living/basic/space_fauna/netherworld/creature.dm b/code/modules/mob/living/basic/space_fauna/netherworld/creature.dm index 5fabbf2afb2..b38ada0f6e1 100644 --- a/code/modules/mob/living/basic/space_fauna/netherworld/creature.dm +++ b/code/modules/mob/living/basic/space_fauna/netherworld/creature.dm @@ -15,6 +15,7 @@ gold_core_spawnable = HOSTILE_SPAWN attack_sound = 'sound/weapons/bite.ogg' attack_vis_effect = ATTACK_EFFECT_BITE + melee_attack_cooldown = 1 SECONDS faction = list(FACTION_NETHER) speak_emote = list("screams") death_message = "gets his head split open." @@ -111,5 +112,5 @@ planning_subtrees = list( /datum/ai_planning_subtree/simple_find_target, /datum/ai_planning_subtree/attack_obstacle_in_path, - /datum/ai_planning_subtree/basic_melee_attack_subtree/average_speed, + /datum/ai_planning_subtree/basic_melee_attack_subtree, ) diff --git a/code/modules/mob/living/basic/space_fauna/netherworld/migo.dm b/code/modules/mob/living/basic/space_fauna/netherworld/migo.dm index 57d90da264a..18dca95013e 100644 --- a/code/modules/mob/living/basic/space_fauna/netherworld/migo.dm +++ b/code/modules/mob/living/basic/space_fauna/netherworld/migo.dm @@ -12,6 +12,7 @@ speed = 1 attack_verb_continuous = "lacerates" attack_verb_simple = "lacerate" + melee_attack_cooldown = 1 SECONDS gold_core_spawnable = HOSTILE_SPAWN attack_sound = 'sound/weapons/bladeslice.ogg' attack_vis_effect = ATTACK_EFFECT_SLASH @@ -81,5 +82,5 @@ planning_subtrees = list( /datum/ai_planning_subtree/simple_find_target, /datum/ai_planning_subtree/attack_obstacle_in_path, - /datum/ai_planning_subtree/basic_melee_attack_subtree/average_speed, + /datum/ai_planning_subtree/basic_melee_attack_subtree, ) diff --git a/code/modules/mob/living/basic/space_fauna/regal_rat/regal_rat_actions.dm b/code/modules/mob/living/basic/space_fauna/regal_rat/regal_rat_actions.dm index 1c36ed151a7..7a30f88b4c2 100644 --- a/code/modules/mob/living/basic/space_fauna/regal_rat/regal_rat_actions.dm +++ b/code/modules/mob/living/basic/space_fauna/regal_rat/regal_rat_actions.dm @@ -161,6 +161,7 @@ nearby_roach.melee_damage_upper += 4 nearby_roach.obj_damage += 5 nearby_roach.ai_controller = new /datum/ai_controller/basic_controller/cockroach/sewer(nearby_roach) + nearby_roach.melee_attack_cooldown = 0.8 SECONDS nearby_roach.icon_state += "_sewer" nearby_roach.maxHealth += 1 diff --git a/code/modules/mob/living/basic/space_fauna/statue/statue.dm b/code/modules/mob/living/basic/space_fauna/statue/statue.dm index 7d13ee9a1ab..bce35146ecf 100644 --- a/code/modules/mob/living/basic/space_fauna/statue/statue.dm +++ b/code/modules/mob/living/basic/space_fauna/statue/statue.dm @@ -27,6 +27,7 @@ attack_verb_simple = "claw" attack_sound = 'sound/hallucinations/growl1.ogg' attack_vis_effect = ATTACK_EFFECT_CLAW + melee_attack_cooldown = 1 SECONDS faction = list(FACTION_STATUE) speak_emote = list("screams") @@ -147,16 +148,10 @@ ai_movement = /datum/ai_movement/basic_avoidance planning_subtrees = list( /datum/ai_planning_subtree/simple_find_target, - /datum/ai_planning_subtree/basic_melee_attack_subtree/statue, + /datum/ai_planning_subtree/basic_melee_attack_subtree, /datum/ai_planning_subtree/find_and_hunt_target/look_for_light_fixtures, ) -/datum/ai_planning_subtree/basic_melee_attack_subtree/statue - melee_attack_behavior = /datum/ai_behavior/basic_melee_attack/statue - -/datum/ai_behavior/basic_melee_attack/statue - action_cooldown = 1 SECONDS - /mob/living/basic/statue/frosty name = "Frosty" desc = "Just a snowman. Just a snowman. Oh god, it's just a snowman." 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 index f632a38dc1b..9d3a09c5348 100644 --- 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 @@ -1,5 +1,3 @@ -#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( @@ -15,23 +13,15 @@ /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, ) -/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 + action_cooldown = 2.5 SECONDS /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 index e13bef35482..bf8be2051d8 100644 --- 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 @@ -29,6 +29,7 @@ melee_damage_upper = 0 attack_sound = 'sound/weapons/punch1.ogg' attack_vis_effect = ATTACK_EFFECT_BITE + melee_attack_cooldown = 2.5 SECONDS attack_verb_continuous = "chomps" attack_verb_simple = "chomp" friendly_verb_continuous = "floats near" diff --git a/code/modules/mob/living/basic/syndicate/syndicate.dm b/code/modules/mob/living/basic/syndicate/syndicate.dm index c11d592cd3b..a4fd0981198 100644 --- a/code/modules/mob/living/basic/syndicate/syndicate.dm +++ b/code/modules/mob/living/basic/syndicate/syndicate.dm @@ -15,6 +15,7 @@ attack_verb_continuous = "punches" attack_verb_simple = "punch" attack_sound = 'sound/weapons/punch1.ogg' + melee_attack_cooldown = 1.2 SECONDS combat_mode = TRUE unsuitable_atmos_damage = 7.5 unsuitable_cold_damage = 7.5 diff --git a/code/modules/mob/living/basic/syndicate/syndicate_ai.dm b/code/modules/mob/living/basic/syndicate/syndicate_ai.dm index be24b37441a..393ef19287e 100644 --- a/code/modules/mob/living/basic/syndicate/syndicate_ai.dm +++ b/code/modules/mob/living/basic/syndicate/syndicate_ai.dm @@ -8,18 +8,12 @@ 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 + /datum/ai_planning_subtree/basic_melee_attack_subtree, ) /datum/targetting_datum/basic/syndicate stat_attack = HARD_CRIT -/datum/ai_planning_subtree/basic_melee_attack_subtree/syndicate - melee_attack_behavior = /datum/ai_behavior/basic_melee_attack/syndicate - -/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 diff --git a/code/modules/mob/living/basic/tree.dm b/code/modules/mob/living/basic/tree.dm index f93ab14a37f..2a0806b105c 100644 --- a/code/modules/mob/living/basic/tree.dm +++ b/code/modules/mob/living/basic/tree.dm @@ -74,7 +74,7 @@ our_turf.air.gases[/datum/gas/carbon_dioxide][MOLES] -= amt our_turf.atmos_spawn_air("[GAS_O2]=[amt]") -/mob/living/basic/tree/melee_attack(atom/target, list/modifiers) +/mob/living/basic/tree/melee_attack(atom/target, list/modifiers, ignore_cooldown = FALSE) . = ..() if(!.) @@ -107,12 +107,6 @@ idle_behavior = /datum/idle_behavior/idle_random_walk/less_walking planning_subtrees = list( /datum/ai_planning_subtree/simple_find_target, - /datum/ai_planning_subtree/basic_melee_attack_subtree/tree, + /datum/ai_planning_subtree/basic_melee_attack_subtree, /datum/ai_planning_subtree/random_speech/tree, ) - -/datum/ai_planning_subtree/basic_melee_attack_subtree/tree - melee_attack_behavior = /datum/ai_behavior/basic_melee_attack/tree - -/datum/ai_behavior/basic_melee_attack/tree - action_cooldown = 2 SECONDS diff --git a/code/modules/mob/living/basic/vermin/cockroach.dm b/code/modules/mob/living/basic/vermin/cockroach.dm index 7aff4a844d3..5c69ad90447 100644 --- a/code/modules/mob/living/basic/vermin/cockroach.dm +++ b/code/modules/mob/living/basic/vermin/cockroach.dm @@ -131,6 +131,7 @@ melee_damage_lower = 2.5 melee_damage_upper = 10 obj_damage = 10 + melee_attack_cooldown = 1 SECONDS gold_core_spawnable = HOSTILE_SPAWN attack_sound = 'sound/weapons/bladeslice.ogg' attack_vis_effect = ATTACK_EFFECT_SLASH @@ -165,31 +166,19 @@ /datum/ai_planning_subtree/pet_planning, /datum/ai_planning_subtree/random_speech/insect, /datum/ai_planning_subtree/simple_find_target, - /datum/ai_planning_subtree/basic_melee_attack_subtree/hauberoach, //If we are attacking someone, this will prevent us from hunting + /datum/ai_planning_subtree/basic_melee_attack_subtree, //If we are attacking someone, this will prevent us from hunting /datum/ai_planning_subtree/find_and_hunt_target/roach, ) -/datum/ai_planning_subtree/basic_melee_attack_subtree/hauberoach - melee_attack_behavior = /datum/ai_behavior/basic_melee_attack/hauberoach - -/datum/ai_behavior/basic_melee_attack/hauberoach //Slightly slower, as this is being made in feature freeze ;) - action_cooldown = 1 SECONDS - /datum/ai_controller/basic_controller/cockroach/sewer planning_subtrees = list( /datum/ai_planning_subtree/pet_planning, /datum/ai_planning_subtree/random_speech/insect, /datum/ai_planning_subtree/simple_find_target, - /datum/ai_planning_subtree/basic_melee_attack_subtree/sewer, + /datum/ai_planning_subtree/basic_melee_attack_subtree, /datum/ai_planning_subtree/find_and_hunt_target/roach, ) -/datum/ai_planning_subtree/basic_melee_attack_subtree/sewer - melee_attack_behavior = /datum/ai_behavior/basic_melee_attack/sewer - -/datum/ai_behavior/basic_melee_attack/sewer - action_cooldown = 0.8 SECONDS - /mob/living/basic/cockroach/glockroach/mobroach name = "mobroach" desc = "WE'RE FUCKED, THAT GLOCKROACH HAS A TOMMYGUN!" diff --git a/code/modules/mob/living/basic/vermin/frog.dm b/code/modules/mob/living/basic/vermin/frog.dm index 282ed17b00c..191ea12b4df 100644 --- a/code/modules/mob/living/basic/vermin/frog.dm +++ b/code/modules/mob/living/basic/vermin/frog.dm @@ -17,6 +17,7 @@ obj_damage = 10 attack_verb_continuous = "bites" attack_verb_simple = "bite" + melee_attack_cooldown = 2.5 SECONDS response_help_continuous = "pets" response_help_simple = "pet" response_disarm_continuous = "pokes" @@ -85,19 +86,13 @@ planning_subtrees = list( /datum/ai_planning_subtree/target_retaliate, /datum/ai_planning_subtree/random_speech/frog, - /datum/ai_planning_subtree/basic_melee_attack_subtree/frog, + /datum/ai_planning_subtree/basic_melee_attack_subtree, ) -/datum/ai_planning_subtree/basic_melee_attack_subtree/frog - melee_attack_behavior = /datum/ai_behavior/basic_melee_attack/frog - -/datum/ai_behavior/basic_melee_attack/frog - action_cooldown = 2.5 SECONDS - /datum/ai_controller/basic_controller/frog/trash planning_subtrees = list( /datum/ai_planning_subtree/pet_planning, /datum/ai_planning_subtree/random_speech/frog, /datum/ai_planning_subtree/simple_find_target, - /datum/ai_planning_subtree/basic_melee_attack_subtree/frog, + /datum/ai_planning_subtree/basic_melee_attack_subtree, ) diff --git a/code/modules/mob/living/carbon/damage_procs.dm b/code/modules/mob/living/carbon/damage_procs.dm index 98827ae3ce3..01551ac0743 100644 --- a/code/modules/mob/living/carbon/damage_procs.dm +++ b/code/modules/mob/living/carbon/damage_procs.dm @@ -1,4 +1,4 @@ -/mob/living/carbon/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, spread_damage = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = NONE, attack_direction = null, attacking_item) +/mob/living/carbon/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked = 0, forced = FALSE, spread_damage = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = NONE, attack_direction = null, attacking_item) SEND_SIGNAL(src, COMSIG_MOB_APPLY_DAMAGE, damage, damagetype, def_zone) var/hit_percent = (100-blocked)/100 if(!damage || (!forced && hit_percent <= 0)) diff --git a/code/modules/mob/living/carbon/human/damage_procs.dm b/code/modules/mob/living/carbon/human/damage_procs.dm index 47cbbe12188..d4fc0b40365 100644 --- a/code/modules/mob/living/carbon/human/damage_procs.dm +++ b/code/modules/mob/living/carbon/human/damage_procs.dm @@ -1,4 +1,4 @@ /// depending on the species, it will run the corresponding apply_damage code there -/mob/living/carbon/human/apply_damage(damage = 0, damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, spread_damage = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = NONE, attack_direction = null, attacking_item) +/mob/living/carbon/human/apply_damage(damage = 0, damagetype = BRUTE, def_zone = null, blocked = 0, forced = FALSE, spread_damage = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = NONE, attack_direction = null, attacking_item) return dna.species.apply_damage(damage, damagetype, def_zone, blocked, src, forced, spread_damage, wound_bonus, bare_wound_bonus, sharpness, attack_direction, attacking_item) diff --git a/code/modules/mob/living/damage_procs.dm b/code/modules/mob/living/damage_procs.dm index f08d45678e9..2cd75c7921a 100644 --- a/code/modules/mob/living/damage_procs.dm +++ b/code/modules/mob/living/damage_procs.dm @@ -14,7 +14,7 @@ * * Returns TRUE if damage applied */ -/mob/living/proc/apply_damage(damage = 0, damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, spread_damage = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = NONE, attack_direction = null, attacking_item) +/mob/living/proc/apply_damage(damage = 0, damagetype = BRUTE, def_zone = null, blocked = 0, forced = FALSE, spread_damage = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = NONE, attack_direction = null, attacking_item) SEND_SIGNAL(src, COMSIG_MOB_APPLY_DAMAGE, damage, damagetype, def_zone) var/hit_percent = (100-blocked)/100 if(!damage || (!forced && hit_percent <= 0)) diff --git a/code/modules/mob/living/silicon/damage_procs.dm b/code/modules/mob/living/silicon/damage_procs.dm index 59db1264a30..8ee146508a4 100644 --- a/code/modules/mob/living/silicon/damage_procs.dm +++ b/code/modules/mob/living/silicon/damage_procs.dm @@ -1,5 +1,5 @@ -/mob/living/silicon/apply_damage(damage = 0, damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, spread_damage = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = NONE, attack_direction = null, attacking_item) +/mob/living/silicon/apply_damage(damage = 0, damagetype = BRUTE, def_zone = null, blocked = 0, forced = FALSE, spread_damage = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = NONE, attack_direction = null, attacking_item) var/hit_percent = (100-blocked)/100 if((!damage || (!forced && hit_percent <= 0))) return 0 diff --git a/tgstation.dme b/tgstation.dme index 6068c4d2138..189bf970029 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -1305,6 +1305,7 @@ #include "code\datums\elements\light_eater.dm" #include "code\datums\elements\loomable.dm" #include "code\datums\elements\mirage_border.dm" +#include "code\datums\elements\mob_grabber.dm" #include "code\datums\elements\mob_killed_tally.dm" #include "code\datums\elements\movement_turf_changer.dm" #include "code\datums\elements\movetype_handler.dm"