From 6701e12613aa195b972ce62b50425ca41a7a5997 Mon Sep 17 00:00:00 2001 From: PollardTheDragon <144391971+PollardTheDragon@users.noreply.github.com> Date: Wed, 6 Aug 2025 02:30:29 -0400 Subject: [PATCH] Converts Pirates, Soviets, and Drakehounds to basic mob AI (#29903) * Converts pirates, soviets, and drakehounds to basic mob AI * Linters and fixes * Pirate fire rate adjustment * Merge fixes * Better ranged attack code * Even better ranged code --------- Signed-off-by: PollardTheDragon <144391971+PollardTheDragon@users.noreply.github.com> Signed-off-by: Burzah <116982774+Burzah@users.noreply.github.com> Co-authored-by: Burzah <116982774+Burzah@users.noreply.github.com> --- _maps/map_files/RandomRuins/SpaceRuins/dj.dmm | 2 +- .../RandomRuins/SpaceRuins/druglab.dmm | 2 +- .../RandomRuins/SpaceRuins/freighter.dmm | 6 +- .../RandomRuins/SpaceRuins/meatpackers.dmm | 8 +- .../RandomRuins/SpaceRuins/mechtransport.dmm | 8 +- .../RandomRuins/SpaceRuins/spacebar.dmm | 8 +- .../RandomRuins/SpaceRuins/unathi_skiff.dmm | 12 +- .../map_files/RandomRuins/SpaceRuins/ussp.dmm | 16 +-- .../SpaceRuins/wreckedcargoship.dmm | 8 +- .../basic_subtrees/attack_adjacent_target.dm | 27 ++++ .../basic_subtrees/maintain_distance.dm | 115 +++++++++++++++++ .../basic_subtrees/ranged_skirmish.dm | 40 ++++++ .../components/basic_mob_aggro_emote.dm | 14 ++- .../effects/spawners/random/misc_spawners.dm | 4 +- .../spawners/random/pool/misc_pools.dm | 2 +- .../awaymissions/mission_code/ruins/casino.dm | 4 +- code/modules/mob/living/basic/basic_mob.dm | 5 +- .../mob/living/basic/hostile/drakehound.dm | 78 ++++++++++++ .../mob/living/basic/hostile/pirate.dm | 119 ++++++++++++++++++ .../mob/living/basic/hostile/soviet.dm | 103 +++++++++++++++ .../mob/living/simple_animal/corpse.dm | 11 ++ .../simple_animal/hostile/drakehound.dm | 56 --------- .../living/simple_animal/hostile/pirate.dm | 90 ------------- .../living/simple_animal/hostile/soviet.dm | 78 ------------ paradise.dme | 8 +- 25 files changed, 554 insertions(+), 270 deletions(-) create mode 100644 code/datums/ai/basic_mobs/basic_subtrees/attack_adjacent_target.dm create mode 100644 code/datums/ai/basic_mobs/basic_subtrees/maintain_distance.dm create mode 100644 code/modules/mob/living/basic/hostile/drakehound.dm create mode 100644 code/modules/mob/living/basic/hostile/pirate.dm create mode 100644 code/modules/mob/living/basic/hostile/soviet.dm delete mode 100644 code/modules/mob/living/simple_animal/hostile/drakehound.dm delete mode 100644 code/modules/mob/living/simple_animal/hostile/pirate.dm delete mode 100644 code/modules/mob/living/simple_animal/hostile/soviet.dm diff --git a/_maps/map_files/RandomRuins/SpaceRuins/dj.dmm b/_maps/map_files/RandomRuins/SpaceRuins/dj.dmm index dca8ca79f35..7b011526f6b 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/dj.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/dj.dmm @@ -480,7 +480,7 @@ /area/ruin/space/djstation) "bp" = ( /obj/structure/chair/office, -/mob/living/simple_animal/hostile/soviet/ranged/mosin, +/mob/living/basic/soviet/ranged/mosin, /turf/simulated/floor/plasteel/dark, /area/ruin/space/djstation) "bq" = ( diff --git a/_maps/map_files/RandomRuins/SpaceRuins/druglab.dmm b/_maps/map_files/RandomRuins/SpaceRuins/druglab.dmm index 278fd1222a1..42af01889b8 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/druglab.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/druglab.dmm @@ -109,7 +109,7 @@ /area/ruin/space/methlab) "v" = ( /obj/structure/chair, -/mob/living/simple_animal/hostile/pirate, +/mob/living/basic/pirate, /turf/simulated/floor/plating, /area/ruin/space/methlab) "w" = ( diff --git a/_maps/map_files/RandomRuins/SpaceRuins/freighter.dmm b/_maps/map_files/RandomRuins/SpaceRuins/freighter.dmm index 9d6c4486ee0..c4d5942b9aa 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/freighter.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/freighter.dmm @@ -547,7 +547,7 @@ /area/ruin/space/powered) "Mu" = ( /obj/machinery/light, -/mob/living/simple_animal/hostile/soviet_nian, +/mob/living/basic/soviet/nian, /turf/simulated/floor/plasteel, /area/ruin/space/powered) "MX" = ( @@ -655,7 +655,7 @@ /area/ruin/space/powered) "SL" = ( /obj/structure/railing, -/mob/living/simple_animal/hostile/soviet_nian, +/mob/living/basic/soviet/nian, /turf/simulated/floor/plasteel, /area/ruin/space/powered) "Tf" = ( @@ -669,7 +669,7 @@ /turf/simulated/floor/mineral/plastitanium, /area/ruin/space/powered) "UZ" = ( -/mob/living/simple_animal/hostile/soviet_nian, +/mob/living/basic/soviet/nian, /turf/simulated/floor/mineral/plastitanium, /area/ruin/space/powered) "WF" = ( diff --git a/_maps/map_files/RandomRuins/SpaceRuins/meatpackers.dmm b/_maps/map_files/RandomRuins/SpaceRuins/meatpackers.dmm index 6a77239121f..c24ace9580a 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/meatpackers.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/meatpackers.dmm @@ -1329,7 +1329,7 @@ /obj/structure/cable{ icon_state = "2-4" }, -/mob/living/simple_animal/hostile/pirate/ranged, +/mob/living/basic/pirate/ranged, /turf/simulated/floor/plasteel{ icon_state = "bar" }, @@ -2153,7 +2153,7 @@ /area/ruin/unpowered/bmp_ship/aft) "hE" = ( /obj/effect/mapping_helpers/turfs/damage, -/mob/living/simple_animal/hostile/pirate, +/mob/living/basic/pirate, /turf/simulated/floor/plating, /area/ruin/unpowered/bmp_ship/midship) "qM" = ( @@ -2165,7 +2165,7 @@ /turf/simulated/floor/plating, /area/ruin/unpowered/bmp_ship/midship) "uK" = ( -/mob/living/simple_animal/hostile/pirate, +/mob/living/basic/pirate, /turf/simulated/floor/plasteel{ icon_state = "bar" }, @@ -2177,7 +2177,7 @@ /obj/structure/cable{ icon_state = "4-8" }, -/mob/living/simple_animal/hostile/pirate, +/mob/living/basic/pirate, /turf/simulated/floor/plasteel{ icon_state = "bar" }, diff --git a/_maps/map_files/RandomRuins/SpaceRuins/mechtransport.dmm b/_maps/map_files/RandomRuins/SpaceRuins/mechtransport.dmm index ff18f57dd56..7dfdeda5eb9 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/mechtransport.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/mechtransport.dmm @@ -316,7 +316,7 @@ /obj/effect/decal/cleanable/shreds{ pixel_y = -10 }, -/mob/living/simple_animal/hostile/pirate/ranged, +/mob/living/basic/pirate/ranged, /turf/simulated/floor/plating/airless, /area/ruin/space/mech_transport) "xE" = ( @@ -360,7 +360,7 @@ /turf/simulated/floor/mineral/plastitanium/red/airless, /area/ruin/space/mech_transport) "zM" = ( -/mob/living/simple_animal/hostile/pirate, +/mob/living/basic/pirate, /turf/simulated/floor/mineral/plastitanium/red/airless, /area/ruin/space/mech_transport) "zP" = ( @@ -543,7 +543,7 @@ pixel_y = -32; name = "secure supplies blast door control" }, -/mob/living/simple_animal/hostile/pirate/ranged, +/mob/living/basic/pirate/ranged, /turf/simulated/floor/mineral/plastitanium, /area/ruin/space/mech_transport) "Nq" = ( @@ -702,7 +702,7 @@ /turf/simulated/floor/plating/airless, /area/ruin/space/mech_transport) "Yq" = ( -/mob/living/simple_animal/hostile/pirate, +/mob/living/basic/pirate, /turf/simulated/floor/plasteel/dark, /area/ruin/space/mech_transport) "Zn" = ( diff --git a/_maps/map_files/RandomRuins/SpaceRuins/spacebar.dmm b/_maps/map_files/RandomRuins/SpaceRuins/spacebar.dmm index b38055bcc17..0ca32881bef 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/spacebar.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/spacebar.dmm @@ -494,7 +494,7 @@ }, /area/ruin/space/powered/bar) "rC" = ( -/mob/living/simple_animal/hostile/pirate, +/mob/living/basic/pirate, /turf/simulated/floor/plasteel{ icon_state = "dark" }, @@ -509,7 +509,7 @@ /obj/structure/chair/stool{ dir = 4 }, -/mob/living/simple_animal/hostile/pirate, +/mob/living/basic/pirate, /turf/simulated/floor/plasteel, /area/ruin/space/powered/bar) "sq" = ( @@ -563,7 +563,7 @@ /turf/simulated/floor/plating/asteroid/ancient, /area/ruin/space/powered) "wo" = ( -/mob/living/simple_animal/hostile/pirate/ranged, +/mob/living/basic/pirate/ranged, /turf/simulated/floor/wood, /area/ruin/space/powered/bar) "wy" = ( @@ -653,7 +653,7 @@ /obj/structure/chair/stool{ dir = 8 }, -/mob/living/simple_animal/hostile/pirate, +/mob/living/basic/pirate, /turf/simulated/floor/plasteel, /area/ruin/space/powered/bar) "Cx" = ( diff --git a/_maps/map_files/RandomRuins/SpaceRuins/unathi_skiff.dmm b/_maps/map_files/RandomRuins/SpaceRuins/unathi_skiff.dmm index 656a7f78516..202c3d6a01e 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/unathi_skiff.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/unathi_skiff.dmm @@ -47,7 +47,7 @@ /turf/simulated/floor/plasteel/dark, /area/ruin/space/unathi_breacher/bar) "ec" = ( -/mob/living/simple_animal/hostile/drakehound_breacher, +/mob/living/basic/drakehound_breacher, /obj/effect/mapping_helpers/turfs/damage, /turf/simulated/floor/plating/airless, /area/ruin/space/unathi_breacher/engineering) @@ -168,7 +168,7 @@ /obj/machinery/light/small{ dir = 8 }, -/mob/living/simple_animal/hostile/drakehound_breacher, +/mob/living/basic/drakehound_breacher, /obj/effect/turf_decal/siding, /turf/simulated/floor/mineral/plastitanium, /area/ruin/space/unathi_breacher/bridge) @@ -237,7 +237,7 @@ /area/template_noop) "rv" = ( /obj/structure/chair/stool/bar, -/mob/living/simple_animal/hostile/drakehound_breacher, +/mob/living/basic/drakehound_breacher, /turf/simulated/floor/plasteel/dark, /area/ruin/space/unathi_breacher/bar) "rx" = ( @@ -367,7 +367,7 @@ /obj/structure/cable{ icon_state = "1-2" }, -/mob/living/simple_animal/hostile/drakehound_breacher, +/mob/living/basic/drakehound_breacher, /obj/effect/turf_decal/siding{ dir = 1 }, @@ -554,13 +554,13 @@ /turf/simulated/floor/pod/dark, /area/ruin/space/unathi_breacher/hold) "QS" = ( -/mob/living/simple_animal/hostile/drakehound_breacher, +/mob/living/basic/drakehound_breacher, /turf/simulated/floor/plasteel/dark, /area/ruin/space/unathi_breacher/dorms) "RI" = ( /obj/item/stack/rods, /obj/structure/table_frame, -/mob/living/simple_animal/hostile/drakehound_breacher, +/mob/living/basic/drakehound_breacher, /turf/template_noop, /area/template_noop) "Sg" = ( diff --git a/_maps/map_files/RandomRuins/SpaceRuins/ussp.dmm b/_maps/map_files/RandomRuins/SpaceRuins/ussp.dmm index bb99edfcd92..c0a825d3ad1 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/ussp.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/ussp.dmm @@ -272,7 +272,7 @@ /obj/structure/chair/comfy/red{ dir = 1 }, -/mob/living/simple_animal/hostile/soviet/ranged/mosin, +/mob/living/basic/soviet/ranged/mosin, /turf/simulated/floor/plasteel/dark, /area/ruin/space/derelict/bridge) "aN" = ( @@ -2150,7 +2150,7 @@ desc = "This guy seemed to have died in terrible way! Half his remains are dust."; name = "Human remains" }, -/mob/living/simple_animal/hostile/soviet/ranged/mosin, +/mob/living/basic/soviet/ranged/mosin, /turf/simulated/floor/plasteel/dark, /area/ruin/space/derelict/arrival) "fF" = ( @@ -2855,7 +2855,7 @@ /area/ruin/space/derelict/hallway/primary) "hC" = ( /obj/structure/chair/stool, -/mob/living/simple_animal/hostile/soviet, +/mob/living/basic/soviet, /turf/simulated/floor/plasteel, /area/ruin/space/derelict/hallway/primary) "hD" = ( @@ -3982,7 +3982,7 @@ icon_state = "4-8" }, /obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/hostile/soviet, +/mob/living/basic/soviet, /turf/simulated/floor/wood, /area/ruin/space/derelict/crew_quarters) "kF" = ( @@ -6881,7 +6881,7 @@ /turf/simulated/floor/wood, /area/ruin/space/derelict/crew_quarters) "Ci" = ( -/mob/living/simple_animal/hostile/pirate/ranged, +/mob/living/basic/pirate/ranged, /turf/simulated/floor/plasteel/airless{ icon_state = "white" }, @@ -6910,7 +6910,7 @@ /turf/simulated/wall/indestructible/titanium/soviet/nodiagonal, /area/ruin/space/derelict/crew_quarters) "PR" = ( -/mob/living/simple_animal/hostile/pirate, +/mob/living/basic/pirate, /turf/simulated/floor/plasteel/airless{ icon_state = "white" }, @@ -6931,7 +6931,7 @@ /obj/structure/chair/wood{ dir = 4 }, -/mob/living/simple_animal/hostile/soviet, +/mob/living/basic/soviet, /turf/simulated/floor/plasteel/dark, /area/ruin/space/derelict/crew_quarters) "Ye" = ( @@ -6942,7 +6942,7 @@ /obj/structure/cable{ icon_state = "1-2" }, -/mob/living/simple_animal/hostile/pirate/ranged, +/mob/living/basic/pirate/ranged, /turf/simulated/floor/plasteel/airless{ icon_state = "white" }, diff --git a/_maps/map_files/RandomRuins/SpaceRuins/wreckedcargoship.dmm b/_maps/map_files/RandomRuins/SpaceRuins/wreckedcargoship.dmm index c581443c2a9..fd752afab45 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/wreckedcargoship.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/wreckedcargoship.dmm @@ -143,7 +143,7 @@ /obj/structure/chair/comfy/shuttle{ dir = 4 }, -/mob/living/simple_animal/hostile/pirate/ranged, +/mob/living/basic/pirate/ranged, /turf/simulated/floor/plasteel{ icon_state = "dark" }, @@ -180,7 +180,7 @@ /obj/structure/chair/comfy/corp{ dir = 8 }, -/mob/living/simple_animal/hostile/pirate, +/mob/living/basic/pirate, /turf/simulated/floor/plasteel, /area/ruin/space/wreck_cargoship) "hO" = ( @@ -1051,7 +1051,7 @@ /area/ruin/space/wreck_cargoship) "RM" = ( /obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/hostile/pirate, +/mob/living/basic/pirate, /turf/simulated/floor/plasteel{ icon_state = "titanium"; dir = 4 @@ -1190,7 +1190,7 @@ }, /area/ruin/space/wreck_cargoship) "Vo" = ( -/mob/living/simple_animal/hostile/pirate/ranged, +/mob/living/basic/pirate/ranged, /turf/simulated/floor/plating, /area/ruin/space/wreck_cargoship) "Vs" = ( diff --git a/code/datums/ai/basic_mobs/basic_subtrees/attack_adjacent_target.dm b/code/datums/ai/basic_mobs/basic_subtrees/attack_adjacent_target.dm new file mode 100644 index 00000000000..53e37950048 --- /dev/null +++ b/code/datums/ai/basic_mobs/basic_subtrees/attack_adjacent_target.dm @@ -0,0 +1,27 @@ +/// Attack something which is already adjacent to us, without ending planning +/datum/ai_planning_subtree/basic_melee_attack_subtree/opportunistic + melee_attack_behavior = /datum/ai_behavior/basic_melee_attack/opportunistic + end_planning = FALSE + +/datum/ai_planning_subtree/basic_melee_attack_subtree/opportunistic/select_behaviors(datum/ai_controller/controller, seconds_per_tick) + . = ..() + var/atom/target = controller.blackboard[BB_BASIC_MOB_CURRENT_TARGET] + if(QDELETED(target) || !controller.pawn.Adjacent(target)) + return + controller.queue_behavior(melee_attack_behavior, BB_BASIC_MOB_CURRENT_TARGET, BB_TARGETING_STRATEGY, BB_BASIC_MOB_CURRENT_TARGET_HIDING_LOCATION) + +/// Attack something which is already adjacent to us without moving +/datum/ai_behavior/basic_melee_attack/opportunistic + behavior_flags = AI_BEHAVIOR_CAN_PLAN_DURING_EXECUTION + +/datum/ai_behavior/basic_melee_attack/opportunistic/setup(datum/ai_controller/controller, target_key, targeting_strategy_key, hiding_location_key) + if(!controller.blackboard_key_exists(targeting_strategy_key)) + CRASH("No target datum was supplied in the blackboard for [controller.pawn]") + return controller.blackboard_key_exists(target_key) + +/datum/ai_behavior/basic_melee_attack/opportunistic/perform(seconds_per_tick, datum/ai_controller/controller, target_key, targeting_strategy_key, hiding_location_key) + var/atom/movable/atom_pawn = controller.pawn + if(!atom_pawn.can_reach(controller.blackboard[target_key])) + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_SUCCEEDED + . = ..() + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED diff --git a/code/datums/ai/basic_mobs/basic_subtrees/maintain_distance.dm b/code/datums/ai/basic_mobs/basic_subtrees/maintain_distance.dm new file mode 100644 index 00000000000..c44ab8508bd --- /dev/null +++ b/code/datums/ai/basic_mobs/basic_subtrees/maintain_distance.dm @@ -0,0 +1,115 @@ +/// Step away if too close, or towards if too far +/datum/ai_planning_subtree/maintain_distance + /// Blackboard key holding atom we want to stay away from + var/target_key = BB_BASIC_MOB_CURRENT_TARGET + /// How far do we look for our target? + var/view_distance = 11 + /// the run away behavior we will use + var/run_away_behavior = /datum/ai_behavior/step_away + +/datum/ai_planning_subtree/maintain_distance/select_behaviors(datum/ai_controller/controller, seconds_per_tick) + . = ..() + + var/atom/target = controller.blackboard[target_key] + if(!isliving(target) || !can_see(controller.pawn, target, view_distance)) + return // Don't run away from cucumbers, they're not snakes + var/range = get_dist(controller.pawn, target) + + var/minimum_distance = controller.blackboard[BB_RANGED_SKIRMISH_MIN_DISTANCE] || 4 + var/maximum_distance = controller.blackboard[BB_RANGED_SKIRMISH_MAX_DISTANCE] || 6 + + if(range < minimum_distance) + controller.queue_behavior(run_away_behavior, target_key, minimum_distance) + return + if(range > maximum_distance) + controller.queue_behavior(/datum/ai_behavior/pursue_to_range, target_key, maximum_distance) + return + +/datum/ai_planning_subtree/maintain_distance/cover_minimum_distance + run_away_behavior = /datum/ai_behavior/cover_minimum_distance + +/// Take one step away +/datum/ai_behavior/step_away + behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT | AI_BEHAVIOR_CAN_PLAN_DURING_EXECUTION + required_distance = 0 + action_cooldown = 0.2 SECONDS + +/datum/ai_behavior/step_away/setup(datum/ai_controller/controller, target_key) + . = ..() + var/atom/current_target = controller.blackboard[target_key] + if(QDELETED(current_target)) + return FALSE + + var/mob/living/our_pawn = controller.pawn + our_pawn.face_atom(current_target) + + var/turf/next_step = get_step_away(controller.pawn, current_target) + if(!isnull(next_step) && !next_step.is_blocked_turf(exclude_mobs = TRUE)) + set_movement_target(controller, target = next_step, new_movement = /datum/ai_movement/basic_avoidance/backstep) + return TRUE + + var/list/all_dirs = GLOB.alldirs.Copy() + all_dirs -= get_dir(controller.pawn, next_step) + all_dirs -= get_dir(controller.pawn, current_target) + shuffle_inplace(all_dirs) + + for(var/dir in all_dirs) + next_step = get_step(controller.pawn, dir) + if(!isnull(next_step) && !next_step.is_blocked_turf(exclude_mobs = TRUE)) + set_movement_target(controller, target = next_step, new_movement = /datum/ai_movement/basic_avoidance/backstep) + return TRUE + return FALSE + +/datum/ai_behavior/step_away/perform(seconds_per_tick, datum/ai_controller/controller) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED + +/datum/ai_behavior/step_away/finish_action(datum/ai_controller/controller, succeeded) + . = ..() + controller.change_ai_movement_type(initial(controller.ai_movement)) + +/// Pursue a target until we are within a provided range +/datum/ai_behavior/pursue_to_range + behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT | AI_BEHAVIOR_CAN_PLAN_DURING_EXECUTION | AI_BEHAVIOR_MOVE_AND_PERFORM + +/datum/ai_behavior/pursue_to_range/setup(datum/ai_controller/controller, target_key, range) + . = ..() + var/atom/current_target = controller.blackboard[target_key] + if(QDELETED(current_target)) + return FALSE + if(get_dist(controller.pawn, current_target) <= range) + return FALSE + set_movement_target(controller, current_target) + +/datum/ai_behavior/pursue_to_range/perform(seconds_per_tick, datum/ai_controller/controller, target_key, range) + var/atom/current_target = controller.blackboard[target_key] + if(!QDELETED(current_target) && get_dist(controller.pawn, current_target) > range) + return AI_BEHAVIOR_INSTANT + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_SUCCEEDED + +/// instead of taking a single step, we cover the entire distance +/datum/ai_behavior/cover_minimum_distance + behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT | AI_BEHAVIOR_CAN_PLAN_DURING_EXECUTION + required_distance = 0 + action_cooldown = 0.2 SECONDS + +/datum/ai_behavior/cover_minimum_distance/setup(datum/ai_controller/controller, target_key, minimum_distance) + . = ..() + var/atom/target = controller.blackboard[target_key] + if(QDELETED(target)) + return FALSE + var/required_distance = minimum_distance - get_dist(controller.pawn, target) // the distance we need to move + var/distance = 0 + var/turf/chosen_turf + for(var/turf/open/potential_turf in oview(required_distance, controller.pawn)) + var/new_distance_from_target = get_dist(potential_turf, target) + if(potential_turf.is_blocked_turf()) + continue + if(new_distance_from_target > distance) + chosen_turf = potential_turf + distance = new_distance_from_target + if(isnull(chosen_turf)) + return FALSE + set_movement_target(controller, target = chosen_turf) + +/datum/ai_behavior/cover_minimum_distance/perform(seconds_per_tick, datum/ai_controller/controller, target_key) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED diff --git a/code/datums/ai/basic_mobs/basic_subtrees/ranged_skirmish.dm b/code/datums/ai/basic_mobs/basic_subtrees/ranged_skirmish.dm index 220336592a4..a99be14545f 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/ranged_skirmish.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/ranged_skirmish.dm @@ -19,6 +19,8 @@ /// How often will we try to perform our ranged attack? /datum/ai_behavior/ranged_skirmish action_cooldown = 0.5 SECONDS + ///do we care about avoiding friendly fire? + var/avoid_friendly_fire = FALSE /datum/ai_behavior/ranged_skirmish/setup(datum/ai_controller/controller, target_key, targeting_strategy_key, hiding_location_key, max_range, min_range) . = ..() @@ -43,8 +45,46 @@ if(distance > max_range || distance < min_range) return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED + if(avoid_friendly_fire && check_friendly_in_path(controller.pawn, target, targeting_strategy)) + return AI_BEHAVIOR_DELAY + controller.ai_interact(target = target, intent = INTENT_HARM) return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED +/datum/ai_behavior/ranged_skirmish/proc/check_friendly_in_path(mob/living/source, atom/target, datum/targeting_strategy/targeting_strategy) + var/list/turfs_list = calculate_trajectory(source, target) + for(var/turf/possible_turf as anything in turfs_list) + + for(var/mob/living/potential_friend in possible_turf) + if(!targeting_strategy.can_attack(source, potential_friend)) + return TRUE + + return FALSE + +/datum/ai_behavior/ranged_skirmish/proc/calculate_trajectory(mob/living/source, atom/target) + var/list/turf_list = get_line(source, target) + var/list_length = length(turf_list) - 1 + for(var/i in 1 to list_length) + var/turf/current_turf = turf_list[i] + var/turf/next_turf = turf_list[i + 1] + var/direction_to_turf = get_dir(current_turf, next_turf) + if(!IS_DIR_DIAGONAL(direction_to_turf)) + continue + + for(var/cardinal_direction in GLOB.cardinal) + if(cardinal_direction & direction_to_turf) + turf_list += get_step(current_turf, cardinal_direction) + + turf_list -= get_turf(source) + turf_list -= get_turf(target) + + return turf_list + /datum/ai_planning_subtree/ranged_skirmish/no_minimum min_range = 0 + +/datum/ai_planning_subtree/ranged_skirmish/avoid_friendly + attack_behavior = /datum/ai_behavior/ranged_skirmish/avoid_friendly + +/datum/ai_behavior/ranged_skirmish/avoid_friendly + avoid_friendly_fire = TRUE diff --git a/code/datums/components/basic_mob_aggro_emote.dm b/code/datums/components/basic_mob_aggro_emote.dm index 2a8d6f8b929..18849790378 100644 --- a/code/datums/components/basic_mob_aggro_emote.dm +++ b/code/datums/components/basic_mob_aggro_emote.dm @@ -12,11 +12,17 @@ var/subtract_chance /// Minimum chance to play an emote var/minimum_chance + /// Aggro sound + var/aggro_sound + /// Volume for the sound + var/aggro_volume /datum/component/aggro_emote/Initialize( target_key = BB_BASIC_MOB_CURRENT_TARGET, living_only = FALSE, list/emote_list, + aggro_sound = null, + aggro_volume = 70, emote_chance = 30, minimum_chance = 2, subtract_chance = 7, @@ -27,7 +33,8 @@ var/atom/atom_parent = parent if(!atom_parent.ai_controller) return COMPONENT_INCOMPATIBLE - + src.aggro_sound = aggro_sound + src.aggro_volume = aggro_volume src.target_key = target_key src.emote_list = emote_list src.emote_chance = emote_chance @@ -54,4 +61,7 @@ var/mob/living/mob_parent = source if(!istype(mob_parent)) return - mob_parent.emote("me", EMOTE_VISIBLE, "[pick(emote_list)] at [new_target].") + if(emote_list) + mob_parent.emote("me", EMOTE_VISIBLE, "[pick(emote_list)] at [new_target].") + if(aggro_sound) + playsound(mob_parent.loc, aggro_sound, aggro_volume, TRUE) diff --git a/code/game/objects/effects/spawners/random/misc_spawners.dm b/code/game/objects/effects/spawners/random/misc_spawners.dm index a045610af26..fbed0b38a8c 100644 --- a/code/game/objects/effects/spawners/random/misc_spawners.dm +++ b/code/game/objects/effects/spawners/random/misc_spawners.dm @@ -190,8 +190,8 @@ name = "random space pirate spawner" icon_state = "pirate" loot = list( - /mob/living/simple_animal/hostile/pirate, - /mob/living/simple_animal/hostile/pirate/ranged, + /mob/living/basic/pirate, + /mob/living/basic/pirate/ranged, ) /obj/effect/spawner/random/fancy_table diff --git a/code/game/objects/effects/spawners/random/pool/misc_pools.dm b/code/game/objects/effects/spawners/random/pool/misc_pools.dm index 9ec1b59a588..e2464120f92 100644 --- a/code/game/objects/effects/spawners/random/pool/misc_pools.dm +++ b/code/game/objects/effects/spawners/random/pool/misc_pools.dm @@ -7,6 +7,6 @@ guaranteed = TRUE point_value = 0 loot = list( - /mob/living/simple_animal/hostile/pirate, + /mob/living/basic/pirate, /obj/effect/spawner/random/space_pirate, ) diff --git a/code/modules/awaymissions/mission_code/ruins/casino.dm b/code/modules/awaymissions/mission_code/ruins/casino.dm index 552ba603a18..1f6ca04cd0a 100644 --- a/code/modules/awaymissions/mission_code/ruins/casino.dm +++ b/code/modules/awaymissions/mission_code/ruins/casino.dm @@ -9,6 +9,6 @@ spawn_pool = /datum/spawn_pool/casino_mobs point_value = 1 loot = list( - /mob/living/simple_animal/hostile/pirate, - /mob/living/simple_animal/hostile/pirate/ranged, + /mob/living/basic/pirate, + /mob/living/basic/pirate/ranged, ) diff --git a/code/modules/mob/living/basic/basic_mob.dm b/code/modules/mob/living/basic/basic_mob.dm index a6995681900..9964b5abcb9 100644 --- a/code/modules/mob/living/basic/basic_mob.dm +++ b/code/modules/mob/living/basic/basic_mob.dm @@ -162,6 +162,9 @@ RESTRICT_TYPE(/mob/living/basic) var/ranged_burst_interval = 0.2 SECONDS /// Time between bursts var/ranged_cooldown = 2 SECONDS + + /// What casing type is the projectile? + var/casing_type /// What projectile do we shoot? var/projectile_type /// What sound does it make when firing? @@ -181,7 +184,7 @@ RESTRICT_TYPE(/mob/living/basic) var/datum/action/innate/hide/hide = new() hide.Grant(src) if(is_ranged) - AddComponent(/datum/component/ranged_attacks, cooldown_time = ranged_cooldown, projectile_type = projectile_type, projectile_sound = projectile_sound, burst_shots = ranged_burst_count, burst_intervals = ranged_burst_interval) + AddComponent(/datum/component/ranged_attacks, casing_type = casing_type, projectile_type = projectile_type, projectile_sound = projectile_sound, burst_shots = ranged_burst_count, burst_intervals = ranged_burst_interval, cooldown_time = ranged_cooldown) /mob/living/basic/Destroy() if(nest) diff --git a/code/modules/mob/living/basic/hostile/drakehound.dm b/code/modules/mob/living/basic/hostile/drakehound.dm new file mode 100644 index 00000000000..6a4dda6b9fe --- /dev/null +++ b/code/modules/mob/living/basic/hostile/drakehound.dm @@ -0,0 +1,78 @@ +/mob/living/basic/drakehound_breacher + name = "Drakehound Breacher" + desc = "A unathi raider with a viscious streak." + icon = 'icons/mob/simple_human.dmi' + icon_state = "drakehound" + icon_living = "drakehound" + icon_dead = "drakehound_dead" // Does not actually exist. del_on_death. + mob_biotypes = MOB_ORGANIC | MOB_HUMANOID + response_help_continuous = "pushes the" + response_help_continuous = "push the" + response_harm_continuous = "slashes" + response_harm_simple = "slash" + speed = 0 + harm_intent_damage = 5 + obj_damage = 60 + melee_damage_lower = 30 + melee_damage_upper = 30 + melee_attack_cooldown_min = 1.5 SECONDS + melee_attack_cooldown_max = 2.5 SECONDS + attack_verb_continuous = "slashes" + attack_verb_simple = "slash" + attack_sound = 'sound/weapons/bladeslice.ogg' + minimum_survivable_temperature = 0 + atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) + speak_emote = list("hisses") + ai_controller = /datum/ai_controller/basic_controller/simple/drakehound + loot = list( + /obj/effect/mob_spawn/human/corpse/drakehound, + /obj/effect/decal/cleanable/blood/innards, + /obj/effect/decal/cleanable/blood, + /obj/effect/gibspawner/generic, + /obj/effect/gibspawner/generic) + basic_mob_flags = DEL_ON_DEATH + faction = list("pirate") + sentience_type = SENTIENCE_OTHER + step_type = FOOTSTEP_MOB_SHOE + +/mob/living/basic/drakehound_breacher/Initialize(mapload) + . = ..() + add_language("Sinta'unathi") + set_default_language(GLOB.all_languages["Sinta'unathi"]) + AddComponent(/datum/component/aggro_emote, aggro_sound = 'sound/effects/unathihiss.ogg', emote_chance = 100) + if(prob(50)) + loot = list( + /obj/item/salvage/loot/pirate, + /obj/effect/mob_spawn/human/corpse/drakehound, + /obj/effect/decal/cleanable/blood/innards, + /obj/effect/decal/cleanable/blood, + /obj/effect/gibspawner/generic, + /obj/effect/gibspawner/generic) + +/mob/living/basic/drakehound_breacher/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) + return TRUE + +/datum/ai_controller/basic_controller/simple/drakehound + blackboard = list( + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, + BB_TARGET_MINIMUM_STAT = UNCONSCIOUS, + ) + planning_subtrees = list( + /datum/ai_planning_subtree/random_speech/drakehound, + /datum/ai_planning_subtree/simple_find_target, + /datum/ai_planning_subtree/attack_obstacle_in_path, + /datum/ai_planning_subtree/basic_melee_attack_subtree, + ) + +/datum/ai_planning_subtree/random_speech/drakehound + speech_chance = 10 + speak = list( + "I'll send you back to the pits!", + "Finally, some action!", + "You're gonna be quick work!", + "Oh, now you fucked up!", + "Maybe don't board the clearly dangerous looking ship?", + "Heart Smash is better, you don't know good music.", + "We wouldn't be stuck here if we just zigged when we zagged.", + "Well, atleast I'm away from my brother!", + "Got any smokes?") diff --git a/code/modules/mob/living/basic/hostile/pirate.dm b/code/modules/mob/living/basic/hostile/pirate.dm new file mode 100644 index 00000000000..f00080b1da9 --- /dev/null +++ b/code/modules/mob/living/basic/hostile/pirate.dm @@ -0,0 +1,119 @@ +/mob/living/basic/pirate + name = "Pirate" + desc = "Does what he wants cause a pirate is free." + icon = 'icons/mob/simple_human.dmi' + icon_state = "piratespace" + icon_living = "piratespace" + icon_dead = "piratemelee_dead" // Does not actually exist. del_on_death. + mob_biotypes = MOB_ORGANIC | MOB_HUMANOID + death_sound = 'sound/creatures/piratedeath.ogg' + response_help_continuous = "pushes the" + response_help_continuous = "push the" + response_harm_continuous = "slashes" + response_harm_simple = "slash" + speed = 0 + harm_intent_damage = 5 + obj_damage = 60 + melee_damage_lower = 30 + melee_damage_upper = 30 + melee_attack_cooldown_min = 1.5 SECONDS + melee_attack_cooldown_max = 2.5 SECONDS + attack_verb_continuous = "slashes" + attack_verb_simple = "slash" + attack_sound = 'sound/weapons/blade1.ogg' + minimum_survivable_temperature = 0 + ai_controller = /datum/ai_controller/basic_controller/simple/pirate + atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) + speak_emote = list("yarrs") + loot = list(/obj/item/melee/energy/sword/pirate, + /obj/item/clothing/head/helmet/space/pirate, + /obj/effect/mob_spawn/human/corpse/pirate, + /obj/effect/decal/cleanable/blood/innards, + /obj/effect/decal/cleanable/blood, + /obj/effect/gibspawner/generic, + /obj/effect/gibspawner/generic) + basic_mob_flags = DEL_ON_DEATH + faction = list("pirate") + sentience_type = SENTIENCE_OTHER + step_type = FOOTSTEP_MOB_SHOE + +/mob/living/basic/pirate/Initialize(mapload) + . = ..() + AddComponent(/datum/component/aggro_emote, aggro_sound = 'sound/creatures/pirateengage.ogg', emote_chance = 100) + add_language("Galactic Common") + set_default_language(GLOB.all_languages["Galactic Common"]) + if(prob(50)) + loot = list(/obj/item/clothing/head/helmet/space/pirate, + /obj/item/salvage/loot/pirate, + /obj/effect/mob_spawn/human/corpse/pirate, + /obj/effect/decal/cleanable/blood/innards, + /obj/effect/decal/cleanable/blood, + /obj/effect/gibspawner/generic, + /obj/effect/gibspawner/generic) + +/mob/living/basic/pirate/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) + return TRUE + +/mob/living/basic/pirate/ranged + name = "Pirate Gunner" + icon_state = "piratespaceranged" + icon_living = "piratespaceranged" + is_ranged = TRUE + projectile_type = /obj/item/projectile/beam + projectile_sound = 'sound/weapons/laser.ogg' + ranged_burst_count = 2 + ranged_burst_interval = 0.5 SECONDS // Same fire rate as people! + ai_controller = /datum/ai_controller/basic_controller/simple/pirate/ranged + loot = list(/obj/effect/mob_spawn/human/corpse/pirate, + /obj/item/gun/energy/laser, + /obj/item/clothing/head/helmet/space/pirate, + /obj/effect/decal/cleanable/blood/innards, + /obj/effect/decal/cleanable/blood, + /obj/effect/gibspawner/generic, + /obj/effect/gibspawner/generic) + +/mob/living/basic/pirate/ranged/Initialize(mapload) + . = ..() + if(prob(50)) + loot = list(/obj/item/clothing/head/helmet/space/pirate, + /obj/item/salvage/loot/pirate, + /obj/effect/mob_spawn/human/corpse/pirate, + /obj/effect/decal/cleanable/blood/innards, + /obj/effect/decal/cleanable/blood, + /obj/effect/gibspawner/generic, + /obj/effect/gibspawner/generic) + +/datum/ai_controller/basic_controller/simple/pirate + blackboard = list( + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, + BB_TARGET_MINIMUM_STAT = UNCONSCIOUS, + ) + planning_subtrees = list( + /datum/ai_planning_subtree/random_speech/pirate, + /datum/ai_planning_subtree/simple_find_target, + /datum/ai_planning_subtree/attack_obstacle_in_path, + /datum/ai_planning_subtree/basic_melee_attack_subtree, + ) + +/datum/ai_planning_subtree/random_speech/pirate + speech_chance = 10 + speak = list( + "Arrrg!", + "Avast!", + "Shiver me timbers!", + "Yo ho ho!", + "Where's the rum gone?", + "Dead men tell no tales!", + "Scurvy dog!", + "Weigh anchor!", + "Raise the Jolly Rodger!", + "No quarter!") + +/datum/ai_controller/basic_controller/simple/pirate/ranged + planning_subtrees = list( + /datum/ai_planning_subtree/random_speech/pirate, + /datum/ai_planning_subtree/simple_find_target, + /datum/ai_planning_subtree/basic_melee_attack_subtree/opportunistic, + /datum/ai_planning_subtree/maintain_distance, + /datum/ai_planning_subtree/ranged_skirmish/avoid_friendly, + ) diff --git a/code/modules/mob/living/basic/hostile/soviet.dm b/code/modules/mob/living/basic/hostile/soviet.dm new file mode 100644 index 00000000000..e8bcfb000ad --- /dev/null +++ b/code/modules/mob/living/basic/hostile/soviet.dm @@ -0,0 +1,103 @@ +/mob/living/basic/soviet + name = "Soviet" + desc = "For the Union!" + icon = 'icons/mob/simple_human.dmi' + icon_state = "sovietmelee" + icon_living = "sovietmelee" + icon_dead = "sovietmelee_dead" // Does not actually exist. del_on_death. + icon_gib = "sovietmelee_gib" // Does not actually exist. del_on_death. + mob_biotypes = MOB_ORGANIC | MOB_HUMANOID + speed = 0 + harm_intent_damage = 5 + melee_damage_lower = 15 + melee_damage_upper = 15 + melee_attack_cooldown_min = 1.5 SECONDS + melee_attack_cooldown_max = 2.5 SECONDS + attack_verb_continuous = "punches" + attack_verb_simple = "punch" + attack_sound = 'sound/weapons/bladeslice.ogg' + a_intent = INTENT_HARM + unsuitable_atmos_damage = 15 + ai_controller = /datum/ai_controller/basic_controller/simple/soviet + faction = list("soviet") + loot = list(/obj/effect/mob_spawn/human/corpse/soviet, + /obj/item/kitchen/knife, + /obj/item/salvage/loot/soviet) + basic_mob_flags = DEL_ON_DEATH + sentience_type = SENTIENCE_OTHER + step_type = FOOTSTEP_MOB_SHOE + +/mob/living/basic/soviet/Initialize(mapload) + . = ..() + add_language("Zvezhan") + set_default_language(GLOB.all_languages["Zvezhan"]) + +/mob/living/basic/soviet/ranged + icon_state = "sovietranged" + icon_living = "sovietranged" + is_ranged = TRUE + casing_type = /obj/item/ammo_casing/a357 + ranged_cooldown = 4 SECONDS + projectile_sound = 'sound/weapons/gunshots/gunshot.ogg' + loot = list(/obj/effect/mob_spawn/human/corpse/soviet/ranged, /obj/item/gun/projectile/revolver/mateba) + ai_controller = /datum/ai_controller/basic_controller/simple/soviet/ranged + +/mob/living/basic/soviet/ranged/mosin + loot = list(/obj/effect/mob_spawn/human/corpse/soviet/ranged, + /obj/item/gun/projectile/shotgun/boltaction, + /obj/item/salvage/loot/soviet) + casing_type = /obj/item/ammo_casing/a762 + projectile_sound = 'sound/weapons/gunshots/gunshot_rifle.ogg' + +/mob/living/basic/soviet/nian + name = "Soviet Nian" + desc = "Buzz!" + icon_state = "sovietnian" + icon_living = "sovietnian" + obj_damage = 60 + melee_damage_lower = 30 + melee_damage_upper = 30 + attack_verb_continuous = "slashes" + attack_verb_simple = "slash" + attack_sound = 'sound/weapons/blade1.ogg' + minimum_survivable_temperature = 0 + loot = list( + /obj/effect/mob_spawn/human/corpse/soviet_nian, + /obj/item/melee/energy/sword/pirate, + /obj/item/salvage/loot/soviet + ) + +/datum/ai_controller/basic_controller/simple/soviet + blackboard = list( + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, + BB_TARGET_MINIMUM_STAT = UNCONSCIOUS, + ) + planning_subtrees = list( + /datum/ai_planning_subtree/random_speech/soviet, + /datum/ai_planning_subtree/simple_find_target, + /datum/ai_planning_subtree/attack_obstacle_in_path, + /datum/ai_planning_subtree/basic_melee_attack_subtree, + ) + +/datum/ai_controller/basic_controller/simple/soviet/ranged + planning_subtrees = list( + /datum/ai_planning_subtree/random_speech/soviet, + /datum/ai_planning_subtree/simple_find_target, + /datum/ai_planning_subtree/basic_melee_attack_subtree/opportunistic, + /datum/ai_planning_subtree/maintain_distance, + /datum/ai_planning_subtree/ranged_skirmish/avoid_friendly, + ) + +/datum/ai_planning_subtree/random_speech/soviet + speech_chance = 10 + speak = list( + "We work for the future.", + "The party leads us forward.", + "Long live socialism!", + "One people, one purpse!", + "For the state!", + "Forward to communism!", + "Glory to the worker!", + "With sweat we strengthen the state!", + "From each, according to ability!", + "We forge tomorrow with our hands!") diff --git a/code/modules/mob/living/simple_animal/corpse.dm b/code/modules/mob/living/simple_animal/corpse.dm index e7834347492..5e5298d73d1 100644 --- a/code/modules/mob/living/simple_animal/corpse.dm +++ b/code/modules/mob/living/simple_animal/corpse.dm @@ -141,6 +141,17 @@ /datum/outfit/piratecorpse/ranged name = "Corpse of a Pirate Gunner" +/obj/effect/mob_spawn/human/corpse/drakehound + name = "Drakehound" + mob_name = "Drakehound" + mob_species = /datum/species/unathi + outfit = /datum/outfit/drakehound + +/datum/outfit/drakehound + name = "Drakehound" + uniform = /obj/item/clothing/under/syndicate/tacticool + gloves = /obj/item/clothing/gloves/color/black + shoes = /obj/item/clothing/shoes/jackboots /obj/effect/mob_spawn/human/corpse/soviet name = "Soviet" diff --git a/code/modules/mob/living/simple_animal/hostile/drakehound.dm b/code/modules/mob/living/simple_animal/hostile/drakehound.dm deleted file mode 100644 index 5d9cf46d5ac..00000000000 --- a/code/modules/mob/living/simple_animal/hostile/drakehound.dm +++ /dev/null @@ -1,56 +0,0 @@ -/mob/living/simple_animal/hostile/drakehound_breacher - name = "Drakehound Breacher" - desc = "A unathi raider with a viscious streak." - icon = 'icons/mob/simple_human.dmi' - icon_state = "drakehound" - icon_living = "drakehound" - icon_dead = "drakehound_dead" // Does not actually exist. del_on_death. - mob_biotypes = MOB_ORGANIC | MOB_HUMANOID - speak_chance = 1 - turns_per_move = 3 - response_help = "pushes the" - response_harm = "slashes" - speed = 0 - maxHealth = 100 - health = 100 - - harm_intent_damage = 5 - obj_damage = 60 - melee_damage_lower = 30 - melee_damage_upper = 30 - attacktext = "slashes" - attack_sound = 'sound/weapons/bladeslice.ogg' - minbodytemp = 0 - - atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) - speak_emote = list("hisses") - loot = list( - /obj/effect/decal/cleanable/blood/innards, - /obj/effect/decal/cleanable/blood, - /obj/effect/gibspawner/generic, - /obj/effect/gibspawner/generic) - del_on_death = TRUE - faction = list("pirate") - sentience_type = SENTIENCE_OTHER - footstep_type = FOOTSTEP_MOB_SHOE - -/mob/living/simple_animal/hostile/drakehound_breacher/Initialize(mapload) - . = ..() - if(prob(50)) - loot = list( - /obj/item/salvage/loot/pirate, - /obj/effect/decal/cleanable/blood/innards, - /obj/effect/decal/cleanable/blood, - /obj/effect/gibspawner/generic, - /obj/effect/gibspawner/generic) - -/mob/living/simple_animal/hostile/drakehound_breacher/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) - return TRUE - -/mob/living/simple_animal/hostile/drakehound_breacher/ListTargetsLazy() - return ListTargets() - -/mob/living/simple_animal/hostile/drakehound_breacher/Aggro() - . = ..() - if(target) - playsound(loc, 'sound/effects/unathihiss.ogg', 70, TRUE) diff --git a/code/modules/mob/living/simple_animal/hostile/pirate.dm b/code/modules/mob/living/simple_animal/hostile/pirate.dm deleted file mode 100644 index 01a8a1eb8ee..00000000000 --- a/code/modules/mob/living/simple_animal/hostile/pirate.dm +++ /dev/null @@ -1,90 +0,0 @@ -/mob/living/simple_animal/hostile/pirate - name = "Pirate" - desc = "Does what he wants cause a pirate is free." - icon = 'icons/mob/simple_human.dmi' - icon_state = "piratespace" - icon_living = "piratespace" - icon_dead = "piratemelee_dead" // Does not actually exist. del_on_death. - mob_biotypes = MOB_ORGANIC | MOB_HUMANOID - speak_chance = 1 - turns_per_move = 3 - death_sound = 'sound/creatures/piratedeath.ogg' - response_help = "pushes the" - response_harm = "slashes" - speed = 0 - maxHealth = 100 - health = 100 - - harm_intent_damage = 5 - obj_damage = 60 - melee_damage_lower = 30 - melee_damage_upper = 30 - attacktext = "slashes" - attack_sound = 'sound/weapons/blade1.ogg' - minbodytemp = 0 - - atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) - speak_emote = list("yarrs") - loot = list(/obj/item/melee/energy/sword/pirate, - /obj/item/clothing/head/helmet/space/pirate, - /obj/effect/mob_spawn/human/corpse/pirate, - /obj/effect/decal/cleanable/blood/innards, - /obj/effect/decal/cleanable/blood, - /obj/effect/gibspawner/generic, - /obj/effect/gibspawner/generic) - del_on_death = TRUE - faction = list("pirate") - sentience_type = SENTIENCE_OTHER - footstep_type = FOOTSTEP_MOB_SHOE - -/mob/living/simple_animal/hostile/pirate/Initialize(mapload) - . = ..() - if(prob(50)) - loot = list(/obj/item/clothing/head/helmet/space/pirate, - /obj/item/salvage/loot/pirate, - /obj/effect/mob_spawn/human/corpse/pirate, - /obj/effect/decal/cleanable/blood/innards, - /obj/effect/decal/cleanable/blood, - /obj/effect/gibspawner/generic, - /obj/effect/gibspawner/generic) - -/mob/living/simple_animal/hostile/pirate/Process_Spacemove(movement_dir = 0, continuous_move = FALSE) - return TRUE - -/mob/living/simple_animal/hostile/pirate/ListTargetsLazy() - return ListTargets() - -/mob/living/simple_animal/hostile/pirate/Aggro() - . = ..() - if(target) - playsound(loc, 'sound/creatures/pirateengage.ogg', 70, TRUE) - -/mob/living/simple_animal/hostile/pirate/ranged - name = "Pirate Gunner" - icon_state = "piratespaceranged" - icon_living = "piratespaceranged" - projectilesound = 'sound/weapons/laser.ogg' - ranged = TRUE - rapid = 2 - turns_per_move = 5 - retreat_distance = 5 - minimum_distance = 5 - projectiletype = /obj/item/projectile/beam - loot = list(/obj/effect/mob_spawn/human/corpse/pirate, - /obj/item/gun/energy/laser, - /obj/item/clothing/head/helmet/space/pirate, - /obj/effect/decal/cleanable/blood/innards, - /obj/effect/decal/cleanable/blood, - /obj/effect/gibspawner/generic, - /obj/effect/gibspawner/generic) - -/mob/living/simple_animal/hostile/pirate/ranged/Initialize(mapload) - . = ..() - if(prob(50)) - loot = list(/obj/item/clothing/head/helmet/space/pirate, - /obj/item/salvage/loot/pirate, - /obj/effect/mob_spawn/human/corpse/pirate, - /obj/effect/decal/cleanable/blood/innards, - /obj/effect/decal/cleanable/blood, - /obj/effect/gibspawner/generic, - /obj/effect/gibspawner/generic) diff --git a/code/modules/mob/living/simple_animal/hostile/soviet.dm b/code/modules/mob/living/simple_animal/hostile/soviet.dm deleted file mode 100644 index 1d946f856ad..00000000000 --- a/code/modules/mob/living/simple_animal/hostile/soviet.dm +++ /dev/null @@ -1,78 +0,0 @@ -/mob/living/simple_animal/hostile/soviet - name = "Soviet" - desc = "For the Union!" - icon = 'icons/mob/simple_human.dmi' - icon_state = "sovietmelee" - icon_living = "sovietmelee" - icon_dead = "sovietmelee_dead" // Does not actually exist. del_on_death. - icon_gib = "sovietmelee_gib" // Does not actually exist. del_on_death. - mob_biotypes = MOB_ORGANIC | MOB_HUMANOID - turns_per_move = 5 - response_help = "pokes the" - response_disarm = "shoves the" - response_harm = "hits the" - speed = 0 - maxHealth = 100 - health = 100 - harm_intent_damage = 5 - melee_damage_lower = 15 - melee_damage_upper = 15 - attacktext = "punches" - attack_sound = 'sound/weapons/punch1.ogg' - a_intent = INTENT_HARM - unsuitable_atmos_damage = 15 - faction = list("soviet") - loot = list(/obj/effect/mob_spawn/human/corpse/soviet, - /obj/item/kitchen/knife, - /obj/item/salvage/loot/soviet) - del_on_death = TRUE - sentience_type = SENTIENCE_OTHER - footstep_type = FOOTSTEP_MOB_SHOE - -/mob/living/simple_animal/hostile/soviet/ranged - icon_state = "sovietranged" - icon_living = "sovietranged" - ranged = TRUE - retreat_distance = 5 - minimum_distance = 5 - projectilesound = 'sound/weapons/gunshots/gunshot.ogg' - casingtype = /obj/item/ammo_casing/a357 - loot = list(/obj/effect/mob_spawn/human/corpse/soviet/ranged, /obj/item/gun/projectile/revolver/mateba) - -/mob/living/simple_animal/hostile/soviet/ranged/mosin - loot = list(/obj/effect/mob_spawn/human/corpse/soviet/ranged, - /obj/item/gun/projectile/shotgun/boltaction, - /obj/item/salvage/loot/soviet) - casingtype = /obj/item/ammo_casing/a762 - -/mob/living/simple_animal/hostile/soviet_nian - name = "Soviet Nian" - desc = "Buzz!" - icon = 'icons/mob/simple_human.dmi' - icon_state = "sovietnian" - icon_living = "sovietnian" - turns_per_move = 5 - response_help = "pokes the" - response_disarm = "shoves the" - response_harm = "hits the" - speed = 0 - maxHealth = 100 - health = 100 - harm_intent_damage = 5 - obj_damage = 60 - melee_damage_lower = 30 - melee_damage_upper = 30 - attacktext = "slashes" - attack_sound = 'sound/weapons/blade1.ogg' - minbodytemp = 0 - a_intent = INTENT_HARM - unsuitable_atmos_damage = 15 - faction = list("soviet") - loot = list( - /obj/effect/mob_spawn/human/corpse/soviet_nian, - /obj/item/melee/energy/sword/pirate, - /obj/item/salvage/loot/soviet - ) - del_on_death = TRUE - sentience_type = SENTIENCE_OTHER - footstep_type = FOOTSTEP_MOB_SHOE diff --git a/paradise.dme b/paradise.dme index f1a0f48eb3f..546276467e5 100644 --- a/paradise.dme +++ b/paradise.dme @@ -466,9 +466,11 @@ #include "code\datums\ai\basic_mobs\basic_ai_behaviors\targeting.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_subtrees\attack_adjacent_target.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" +#include "code\datums\ai\basic_mobs\basic_subtrees\maintain_distance.dm" #include "code\datums\ai\basic_mobs\basic_subtrees\mine_walls.dm" #include "code\datums\ai\basic_mobs\basic_subtrees\prowl.dm" #include "code\datums\ai\basic_mobs\basic_subtrees\random_speech.dm" @@ -2428,6 +2430,9 @@ #include "code\modules\mob\living\basic\hostile\bats.dm" #include "code\modules\mob\living\basic\hostile\bear.dm" #include "code\modules\mob\living\basic\hostile\carp.dm" +#include "code\modules\mob\living\basic\hostile\drakehound.dm" +#include "code\modules\mob\living\basic\hostile\pirate.dm" +#include "code\modules\mob\living\basic\hostile\soviet.dm" #include "code\modules\mob\living\basic\hostile\creature.dm" #include "code\modules\mob\living\basic\hostile\feral_cat.dm" #include "code\modules\mob\living\basic\hostile\hellhound.dm" @@ -2646,7 +2651,6 @@ #include "code\modules\mob\living\simple_animal\hostile\angel_statue.dm" #include "code\modules\mob\living\simple_animal\hostile\bees.dm" #include "code\modules\mob\living\simple_animal\hostile\deathsquid.dm" -#include "code\modules\mob\living\simple_animal\hostile\drakehound.dm" #include "code\modules\mob\living\simple_animal\hostile\floorcluwne.dm" #include "code\modules\mob\living\simple_animal\hostile\headslug.dm" #include "code\modules\mob\living\simple_animal\hostile\hostile.dm" @@ -2655,8 +2659,6 @@ #include "code\modules\mob\living\simple_animal\hostile\mimic_mobs.dm" #include "code\modules\mob\living\simple_animal\hostile\mushroom.dm" #include "code\modules\mob\living\simple_animal\hostile\netherworld.dm" -#include "code\modules\mob\living\simple_animal\hostile\pirate.dm" -#include "code\modules\mob\living\simple_animal\hostile\soviet.dm" #include "code\modules\mob\living\simple_animal\hostile\syndicate_mobs.dm" #include "code\modules\mob\living\simple_animal\hostile\tree.dm" #include "code\modules\mob\living\simple_animal\hostile\venus_human_trap.dm"