From 3a03e29187f97de6fb9940d70e365096a4a97318 Mon Sep 17 00:00:00 2001 From: PollardTheDragon <144391971+PollardTheDragon@users.noreply.github.com> Date: Thu, 31 Jul 2025 02:14:05 -0400 Subject: [PATCH] Converts hivebots to basic mob AI (#29849) * Converts hivebots to basic mob AI * Updatepaths * Linters * Hivebot beacon * New linters --------- Signed-off-by: PollardTheDragon <144391971+PollardTheDragon@users.noreply.github.com> Co-authored-by: Burzah <116982774+Burzah@users.noreply.github.com> --- .../RandomRuins/SpaceRuins/oldstation.dmm | 92 ++++++------- .../SpaceRuins/telecomns_returns.dmm | 4 +- code/__DEFINES/ai/blackboard_defines.dm | 9 ++ .../mission_code/ruins/telecomns.dm | 22 +-- code/modules/mob/living/basic/basic_mob.dm | 13 ++ .../mob/living/basic/hostile/hivebot.dm | 96 +++++++++++++ .../mob/living/basic/hostile/hivebot_ai.dm | 128 ++++++++++++++++++ .../living/simple_animal/hostile/hivebot.dm | 102 -------------- paradise.dme | 3 +- tools/UpdatePaths/Scripts/29849_hivebot.txt | 1 + 10 files changed, 309 insertions(+), 161 deletions(-) create mode 100644 code/modules/mob/living/basic/hostile/hivebot.dm create mode 100644 code/modules/mob/living/basic/hostile/hivebot_ai.dm delete mode 100644 code/modules/mob/living/simple_animal/hostile/hivebot.dm create mode 100644 tools/UpdatePaths/Scripts/29849_hivebot.txt diff --git a/_maps/map_files/RandomRuins/SpaceRuins/oldstation.dmm b/_maps/map_files/RandomRuins/SpaceRuins/oldstation.dmm index 3a171529490..eb76ef87707 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/oldstation.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/oldstation.dmm @@ -83,7 +83,7 @@ /turf/simulated/floor/plasteel/dark, /area/ruin/ancientstation/hivebot) "ap" = ( -/mob/living/simple_animal/hostile/hivebot, +/mob/living/basic/hivebot, /turf/simulated/floor/plasteel/dark, /area/ruin/ancientstation/hivebot) "aq" = ( @@ -222,7 +222,7 @@ "aM" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/hostile/hivebot, +/mob/living/basic/hivebot, /obj/machinery/atmospherics/unary/vent_scrubber/on{ dir = 8 }, @@ -522,7 +522,7 @@ /area/ruin/ancientstation) "bI" = ( /obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/hostile/hivebot, +/mob/living/basic/hivebot, /turf/simulated/floor/plasteel{ dir = 4; icon_state = "whitecorner" @@ -716,7 +716,7 @@ /area/ruin/ancientstation/engi) "co" = ( /obj/effect/decal/cleanable/blood/oil, -/mob/living/simple_animal/hostile/hivebot, +/mob/living/basic/hivebot, /turf/simulated/floor/plasteel/dark, /area/ruin/ancientstation/hivebot) "cs" = ( @@ -742,7 +742,7 @@ /obj/effect/decal/remains/robot{ icon_state = "gib2" }, -/mob/living/simple_animal/hostile/hivebot, +/mob/living/basic/hivebot, /turf/simulated/floor/plasteel/dark, /area/ruin/ancientstation/hivebot) "cw" = ( @@ -850,11 +850,11 @@ /obj/effect/decal/remains/robot{ icon_state = "gib5" }, -/mob/living/simple_animal/hostile/hivebot, +/mob/living/basic/hivebot, /turf/simulated/floor/plasteel/dark, /area/ruin/ancientstation/hivebot) "cL" = ( -/mob/living/simple_animal/hostile/hivebot/strong, +/mob/living/basic/hivebot/strong, /turf/simulated/floor/plasteel/dark, /area/ruin/ancientstation/hivebot) "cM" = ( @@ -872,7 +872,7 @@ /area/ruin/ancientstation/atmo) "cP" = ( /obj/effect/decal/cleanable/blood/oil, -/mob/living/simple_animal/hostile/hivebot/strong, +/mob/living/basic/hivebot/strong, /turf/simulated/floor/plasteel/dark, /area/ruin/ancientstation/hivebot) "cQ" = ( @@ -1007,7 +1007,7 @@ "dm" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/hostile/hivebot, +/mob/living/basic/hivebot, /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers, /obj/machinery/atmospherics/pipe/simple/hidden/supply, /obj/structure/cable{ @@ -1054,7 +1054,7 @@ /obj/effect/decal/remains/robot{ icon_state = "gibup" }, -/mob/living/simple_animal/hostile/hivebot, +/mob/living/basic/hivebot, /turf/simulated/floor/plasteel/dark, /area/ruin/ancientstation/hivebot) "dt" = ( @@ -1147,7 +1147,7 @@ /area/ruin/ancientstation/rnd) "dH" = ( /obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/hostile/hivebot, +/mob/living/basic/hivebot, /turf/simulated/floor/plating, /area/ruin/ancientstation/thetacorridor) "dI" = ( @@ -1162,7 +1162,7 @@ dir = 4 }, /obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/hostile/hivebot, +/mob/living/basic/hivebot, /obj/structure/cable{ icon_state = "4-8" }, @@ -1175,7 +1175,7 @@ /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, /obj/item/kirbyplants/large/dead, -/mob/living/simple_animal/hostile/hivebot/strong, +/mob/living/basic/hivebot/strong, /turf/simulated/floor/plasteel, /area/ruin/ancientstation/thetacorridor) "dL" = ( @@ -1411,7 +1411,7 @@ "ew" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/hostile/hivebot, +/mob/living/basic/hivebot, /turf/simulated/floor/plasteel, /area/ruin/ancientstation/thetacorridor) "ex" = ( @@ -1426,7 +1426,7 @@ dir = 4 }, /obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/hostile/hivebot, +/mob/living/basic/hivebot, /turf/simulated/floor/plating, /area/ruin/ancientstation/thetacorridor) "ez" = ( @@ -1534,7 +1534,7 @@ /area/ruin/ancientstation) "eN" = ( /obj/machinery/door/firedoor, -/mob/living/simple_animal/hostile/hivebot, +/mob/living/basic/hivebot, /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plasteel, @@ -1991,7 +1991,7 @@ }, /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/hostile/hivebot/strong, +/mob/living/basic/hivebot/strong, /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ dir = 10 }, @@ -2411,7 +2411,7 @@ /turf/simulated/floor/plating/airless, /area/ruin/ancientstation/betanorth) "hg" = ( -/mob/living/simple_animal/hostile/hivebot, +/mob/living/basic/hivebot, /obj/machinery/firealarm/directional/west, /obj/machinery/atmospherics/unary/vent_scrubber/on{ dir = 4 @@ -2432,7 +2432,7 @@ }, /area/ruin/ancientstation/rnd) "hj" = ( -/mob/living/simple_animal/hostile/hivebot, +/mob/living/basic/hivebot, /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ dir = 5 }, @@ -2474,7 +2474,7 @@ "hn" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/hostile/hivebot/strong, +/mob/living/basic/hivebot/strong, /turf/simulated/floor/plasteel, /area/ruin/ancientstation/thetacorridor) "ho" = ( @@ -2557,7 +2557,7 @@ dir = 4 }, /obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/hostile/hivebot, +/mob/living/basic/hivebot, /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ dir = 4 }, @@ -2618,7 +2618,7 @@ /area/ruin/ancientstation/hydroponics) "hE" = ( /obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/hostile/hivebot, +/mob/living/basic/hivebot, /obj/machinery/atmospherics/unary/vent_scrubber/on{ dir = 8 }, @@ -2717,7 +2717,7 @@ /area/ruin/ancientstation/rnd) "hT" = ( /obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/hostile/hivebot/strong, +/mob/living/basic/hivebot/strong, /turf/simulated/floor/plasteel{ dir = 9; icon_state = "whitepurple" @@ -2847,7 +2847,7 @@ "ih" = ( /obj/machinery/atmospherics/pipe/simple/hidden/supply, /obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/hostile/hivebot, +/mob/living/basic/hivebot, /obj/structure/cable{ icon_state = "1-2" }, @@ -3078,7 +3078,7 @@ }, /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/hostile/hivebot, +/mob/living/basic/hivebot, /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ dir = 4 }, @@ -3626,13 +3626,13 @@ /area/ruin/ancientstation/thetacorridor) "kL" = ( /obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/hostile/hivebot/strong, +/mob/living/basic/hivebot/strong, /turf/simulated/floor/plasteel/white, /area/ruin/ancientstation/rnd) "kM" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/hostile/hivebot, +/mob/living/basic/hivebot, /obj/machinery/door/firedoor, /turf/simulated/floor/plasteel, /area/ruin/ancientstation/thetacorridor) @@ -3650,13 +3650,13 @@ /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, /obj/machinery/door/firedoor, -/mob/living/simple_animal/hostile/hivebot, +/mob/living/basic/hivebot, /turf/simulated/floor/plasteel, /area/ruin/ancientstation/thetacorridor) "kP" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/hostile/hivebot/strong, +/mob/living/basic/hivebot/strong, /turf/simulated/floor/plasteel, /area/ruin/ancientstation/rnd) "kR" = ( @@ -3675,7 +3675,7 @@ /area/ruin/ancientstation/thetacorridor) "kS" = ( /obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/hostile/hivebot, +/mob/living/basic/hivebot, /turf/simulated/floor/plasteel, /area/ruin/ancientstation/thetacorridor) "kT" = ( @@ -3780,7 +3780,7 @@ "lh" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/firealarm/directional/south, -/mob/living/simple_animal/hostile/hivebot, +/mob/living/basic/hivebot, /turf/simulated/floor/plasteel, /area/ruin/ancientstation/thetacorridor) "li" = ( @@ -3849,7 +3849,7 @@ in_use = 1 }, /obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/hostile/hivebot, +/mob/living/basic/hivebot, /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ dir = 4 }, @@ -3879,7 +3879,7 @@ /obj/structure/cable{ icon_state = "2-8" }, -/mob/living/simple_animal/hostile/hivebot, +/mob/living/basic/hivebot, /obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers, /obj/machinery/atmospherics/pipe/manifold/hidden/supply, /obj/effect/decal/cleanable/dirt, @@ -4001,7 +4001,7 @@ /turf/simulated/floor/plating/airless, /area/ruin/ancientstation/atmo) "lK" = ( -/mob/living/simple_animal/hostile/hivebot, +/mob/living/basic/hivebot, /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ dir = 6 }, @@ -4366,7 +4366,7 @@ /area/ruin/ancientstation/atmo) "qj" = ( /obj/machinery/atmospherics/pipe/simple/hidden/supply, -/mob/living/simple_animal/hostile/hivebot, +/mob/living/basic/hivebot, /obj/structure/cable{ icon_state = "1-2" }, @@ -5425,7 +5425,7 @@ /area/ruin/ancientstation/thetacorridor) "CN" = ( /obj/machinery/atmospherics/pipe/manifold4w/hidden/supply, -/mob/living/simple_animal/hostile/hivebot, +/mob/living/basic/hivebot, /obj/structure/cable{ icon_state = "2-8" }, @@ -5445,7 +5445,7 @@ dir = 4 }, /obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/hostile/hivebot, +/mob/living/basic/hivebot, /obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{ dir = 4 }, @@ -5715,7 +5715,7 @@ }, /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/hostile/hivebot, +/mob/living/basic/hivebot, /obj/structure/cable{ icon_state = "4-8" }, @@ -6084,7 +6084,7 @@ /area/space/nearstation) "LB" = ( /obj/machinery/atmospherics/pipe/simple/hidden/supply, -/mob/living/simple_animal/hostile/hivebot, +/mob/living/basic/hivebot, /obj/structure/cable{ icon_state = "1-2" }, @@ -6195,7 +6195,7 @@ /turf/simulated/floor/plasteel/white, /area/ruin/ancientstation/proto) "MP" = ( -/mob/living/simple_animal/hostile/hivebot, +/mob/living/basic/hivebot, /obj/effect/decal/cleanable/dirt, /obj/effect/spawner/random/cobweb/right/frequent, /turf/simulated/floor/plating, @@ -6338,7 +6338,7 @@ }, /area/ruin/ancientstation/engi) "OW" = ( -/mob/living/simple_animal/hostile/hivebot, +/mob/living/basic/hivebot, /obj/effect/decal/cleanable/dirt, /obj/machinery/light{ dir = 8 @@ -6464,7 +6464,7 @@ }, /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/hostile/hivebot, +/mob/living/basic/hivebot, /obj/structure/cable{ icon_state = "2-4" }, @@ -6539,7 +6539,7 @@ }, /area/ruin/ancientstation/comm) "Ru" = ( -/mob/living/simple_animal/hostile/hivebot, +/mob/living/basic/hivebot, /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plasteel, /area/ruin/ancientstation/thetacorridor) @@ -6898,7 +6898,7 @@ /obj/machinery/light, /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/hostile/hivebot, +/mob/living/basic/hivebot, /obj/structure/cable{ icon_state = "4-8" }, @@ -6977,7 +6977,7 @@ /obj/machinery/atmospherics/pipe/simple/hidden/supply, /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt, -/mob/living/simple_animal/hostile/hivebot, +/mob/living/basic/hivebot, /obj/machinery/door/firedoor, /obj/structure/cable{ icon_state = "1-2" @@ -7073,7 +7073,7 @@ /turf/simulated/floor/plating/airless, /area/ruin/ancientstation/betanorth) "Xq" = ( -/mob/living/simple_animal/hostile/hivebot, +/mob/living/basic/hivebot, /obj/effect/decal/cleanable/dirt, /turf/simulated/floor/plating, /area/ruin/ancientstation/thetacorridor) diff --git a/_maps/map_files/RandomRuins/SpaceRuins/telecomns_returns.dmm b/_maps/map_files/RandomRuins/SpaceRuins/telecomns_returns.dmm index d371d1d7322..8fcfc730121 100644 --- a/_maps/map_files/RandomRuins/SpaceRuins/telecomns_returns.dmm +++ b/_maps/map_files/RandomRuins/SpaceRuins/telecomns_returns.dmm @@ -1393,7 +1393,7 @@ icon_state = "4-8" }, /obj/machinery/recharge_station/upgraded, -/mob/living/simple_animal/hostile/hivebot/strong/malfborg, +/mob/living/basic/hivebot/strong/malfborg, /turf/simulated/floor/plasteel{ dir = 4; icon_state = "vault"; @@ -2471,7 +2471,7 @@ icon_state = "2-4" }, /obj/machinery/recharge_station/upgraded, -/mob/living/simple_animal/hostile/hivebot/strong/malfborg, +/mob/living/basic/hivebot/strong/malfborg, /turf/simulated/floor/plasteel{ dir = 4; icon_state = "vault"; diff --git a/code/__DEFINES/ai/blackboard_defines.dm b/code/__DEFINES/ai/blackboard_defines.dm index adb7f72e57a..ac248a6ff2c 100644 --- a/code/__DEFINES/ai/blackboard_defines.dm +++ b/code/__DEFINES/ai/blackboard_defines.dm @@ -85,6 +85,12 @@ /// key holding a range to look for vents (recommended: 10) #define BB_VENT_SEARCH_RANGE "BB_VENT_SEARCH_RANGE" +// Ranged +/// Minimum range to keep target within +#define BB_RANGED_SKIRMISH_MIN_DISTANCE "BB_ranged_skirmish_min_distance" +/// Maximum range to keep target within +#define BB_RANGED_SKIRMISH_MAX_DISTANCE "BB_ranged_skirmish_max_distance" + // Tipped blackboards /// Bool that means a basic mob will start reacting to being tipped in its planning @@ -143,6 +149,9 @@ /// List of strings used to apologize for attacking friends. #define BB_OWNER_FRIENDLY_FIRE_APOLOGIES "BB_FF_APOLOGIES" +// Hivebot keys +/// the hivebot partner we will go communicate with +#define BB_HIVE_PARTNER "BB_HIVE_PARTNER" // Misc diff --git a/code/modules/awaymissions/mission_code/ruins/telecomns.dm b/code/modules/awaymissions/mission_code/ruins/telecomns.dm index 651019383f0..90ab71ac61b 100644 --- a/code/modules/awaymissions/mission_code/ruins/telecomns.dm +++ b/code/modules/awaymissions/mission_code/ruins/telecomns.dm @@ -324,7 +324,7 @@ GLOBAL_LIST_EMPTY(telecomms_trap_tank) aggressive = TRUE aggressive_tilt_chance = 100 //It will tip on you, and it will be funny. -/mob/living/simple_animal/hostile/hivebot/strong/malfborg +/mob/living/basic/hivebot/strong/malfborg name = "Security cyborg" desc = "Oh god they still have access to these!" icon = 'icons/mob/robots.dmi' @@ -332,37 +332,39 @@ GLOBAL_LIST_EMPTY(telecomms_trap_tank) health = 200 maxHealth = 200 faction = list("malf_drone") - rapid = 2 speed = 0.5 - projectiletype = /obj/item/projectile/beam/disabler/weak - projectilesound = 'sound/weapons/taser2.ogg' + projectile_type = /obj/item/projectile/beam/disabler/weak + projectile_sound = 'sound/weapons/taser2.ogg' + ranged_burst_count = 2 gold_core_spawnable = NO_SPAWN // Could you imagine xenobio with this? lmao. a_intent = INTENT_HARM var/obj/item/melee/baton/infinite_cell/baton = null // stunbaton bot uses to melee attack + ai_controller = /datum/ai_controller/basic_controller/simple/simple_skirmisher -/mob/living/simple_animal/hostile/hivebot/strong/malfborg/Initialize(mapload) +/mob/living/basic/hivebot/strong/malfborg/Initialize(mapload) . = ..() baton = new(src) -/mob/living/simple_animal/hostile/hivebot/strong/malfborg/Destroy() +/mob/living/basic/hivebot/strong/malfborg/Destroy() QDEL_NULL(baton) return ..() -/mob/living/simple_animal/hostile/hivebot/strong/malfborg/AttackingTarget() +/mob/living/basic/hivebot/strong/malfborg/melee_attack(atom/target, list/modifiers, ignore_cooldown) + . = ..() if(QDELETED(target)) return face_atom(target) baton.melee_attack_chain(src, target) return TRUE -/mob/living/simple_animal/hostile/hivebot/strong/malfborg/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect) +/mob/living/basic/hivebot/strong/malfborg/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect) if(!used_item && !isturf(A)) used_item = baton ..() -/mob/living/simple_animal/hostile/hivebot/strong/malfborg/emp_act(severity) +/mob/living/basic/hivebot/strong/malfborg/emp_act(severity) . = ..() - target = null + ai_controller.clear_blackboard_key(BB_BASIC_MOB_CURRENT_TARGET) adjustBruteLoss(50) /obj/structure/displaycase/dvoraks_treat diff --git a/code/modules/mob/living/basic/basic_mob.dm b/code/modules/mob/living/basic/basic_mob.dm index 429f276be59..37a0859c706 100644 --- a/code/modules/mob/living/basic/basic_mob.dm +++ b/code/modules/mob/living/basic/basic_mob.dm @@ -154,6 +154,17 @@ RESTRICT_TYPE(/mob/living/basic) /// Footsteps var/step_type + /// Does this type do range attacks? + var/is_ranged = FALSE + /// How many shots in a burst? + var/ranged_burst_count = 1 + /// How fast do we fire between bursts? + var/ranged_burst_interval = 0.2 SECONDS + /// What projectile do we shoot? + var/projectile_type + /// What sound does it make when firing? + var/projectile_sound + /mob/living/basic/Initialize(mapload) . = ..() @@ -164,6 +175,8 @@ RESTRICT_TYPE(/mob/living/basic) apply_temperature_requirements() if(step_type) AddComponent(/datum/component/footstep, step_type) + if(is_ranged) + AddComponent(/datum/component/ranged_attacks, projectile_type = projectile_type, projectile_sound = projectile_sound, burst_shots = ranged_burst_count, burst_intervals = ranged_burst_interval) /mob/living/basic/Destroy() if(nest) diff --git a/code/modules/mob/living/basic/hostile/hivebot.dm b/code/modules/mob/living/basic/hostile/hivebot.dm new file mode 100644 index 00000000000..c01e6821d29 --- /dev/null +++ b/code/modules/mob/living/basic/hostile/hivebot.dm @@ -0,0 +1,96 @@ +/obj/item/projectile/hivebotbullet + +/mob/living/basic/hivebot + name = "Hivebot" + desc = "A small robot." + icon = 'icons/mob/hivebot.dmi' + icon_state = "basic" + icon_living = "basic" + icon_dead = "basic" + mob_biotypes = MOB_ROBOTIC + health = 15 + maxHealth = 15 + melee_damage_lower = 2 + melee_damage_upper = 3 + melee_attack_cooldown_min = 1.5 SECONDS + melee_attack_cooldown_max = 2.5 SECONDS + attack_verb_continuous = "claws" + attack_verb_simple = "claw" + attack_sound = 'sound/weapons/bladeslice.ogg' + faction = list("hivebot") + 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) + minimum_survivable_temperature = 0 + speak_emote = list("states") + gold_core_spawnable = HOSTILE_SPAWN + loot = list(/obj/effect/decal/cleanable/blood/gibs/robot) + death_message = "blows apart!" + bubble_icon = "machine" + basic_mob_flags = DEL_ON_DEATH + step_type = FOOTSTEP_MOB_CLAW + ai_controller = /datum/ai_controller/basic_controller/hivebot + projectile_type = /obj/item/projectile/hivebotbullet + projectile_sound = 'sound/weapons/gunshots/gunshot.ogg' + +/mob/living/basic/hivebot/range + desc = "A smallish robot, this one is armed!" + is_ranged = TRUE + ai_controller = /datum/ai_controller/basic_controller/hivebot/ranged + +/mob/living/basic/hivebot/rapid + is_ranged = TRUE + ranged_burst_count = 3 + ai_controller = /datum/ai_controller/basic_controller/hivebot/ranged/rapid + +/mob/living/basic/hivebot/strong + name = "Strong Hivebot" + desc = "A robot, this one is armed and looks tough!" + health = 80 + maxHealth = 80 + is_ranged = TRUE + ai_controller = /datum/ai_controller/basic_controller/hivebot/ranged + +/mob/living/basic/hivebot/death(gibbed) + // Only execute the below if we successfully died + . = ..(gibbed) + if(!.) + return FALSE + do_sparks(3, 1, src) + +/mob/living/basic/hivebot/tele // Hivebot Telebeacon + name = "Beacon" + desc = "Some odd beacon thing." + icon_state = "def_radar-off" + icon_living = "def_radar-off" + health = 200 + maxHealth = 200 + status_flags = 0 + anchored = TRUE + ai_controller = /datum/ai_controller/basic_controller/beacon + /// The total number of hivebots to spawn + var/bot_amt = 10 + +/mob/living/basic/hivebot/tele/Initialize(mapload) + . = ..() + var/datum/effect_system/smoke_spread/smoke = new + smoke.set_up(5, FALSE, loc) + smoke.start() + visible_message("[src] warps in!") + playsound(src.loc, 'sound/effects/empulse.ogg', 25, 1) + +/mob/living/basic/hivebot/tele/proc/warpbots() + icon_state = "def_radar" + visible_message("[src] turns on!") + while(bot_amt > 0) + bot_amt-- + if(bot_amt > 3) + var/mob/living/basic/hivebot/H = new /mob/living/basic/hivebot(get_turf(src)) + H.faction = faction + else if(bot_amt > 0) + var/mob/living/basic/hivebot/range/R = new /mob/living/basic/hivebot/range(get_turf(src)) + R.faction = faction + else + var/mob/living/basic/hivebot/rapid/F = new /mob/living/basic/hivebot/rapid(get_turf(src)) + F.faction = faction + spawn(100) + qdel(src) + return diff --git a/code/modules/mob/living/basic/hostile/hivebot_ai.dm b/code/modules/mob/living/basic/hostile/hivebot_ai.dm new file mode 100644 index 00000000000..e66e357c1a4 --- /dev/null +++ b/code/modules/mob/living/basic/hostile/hivebot_ai.dm @@ -0,0 +1,128 @@ +/datum/ai_controller/basic_controller/hivebot + blackboard = list( + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, + ) + + ai_movement = /datum/ai_movement/basic_avoidance + idle_behavior = /datum/idle_behavior/idle_random_walk + planning_subtrees = list( + /datum/ai_planning_subtree/simple_find_target, + /datum/ai_planning_subtree/basic_melee_attack_subtree, + /datum/ai_planning_subtree/attack_obstacle_in_path, + /datum/ai_planning_subtree/hive_communicate, + ) + +/datum/ai_controller/basic_controller/hivebot/ranged + planning_subtrees = list( + /datum/ai_planning_subtree/simple_find_target, + /datum/ai_planning_subtree/basic_ranged_attack_subtree/hivebot, + /datum/ai_planning_subtree/attack_obstacle_in_path, + /datum/ai_planning_subtree/hive_communicate, + ) + +/datum/ai_controller/basic_controller/hivebot/ranged/rapid + planning_subtrees = list( + /datum/ai_planning_subtree/simple_find_target, + /datum/ai_planning_subtree/basic_ranged_attack_subtree/hivebot_rapid, + /datum/ai_planning_subtree/attack_obstacle_in_path, + /datum/ai_planning_subtree/hive_communicate, + ) + +/datum/ai_planning_subtree/basic_ranged_attack_subtree/hivebot_rapid + ranged_attack_behavior = /datum/ai_behavior/basic_ranged_attack/hivebot_rapid + +/datum/ai_planning_subtree/basic_ranged_attack_subtree/hivebot + ranged_attack_behavior = /datum/ai_behavior/basic_ranged_attack/hivebot + +/datum/ai_planning_subtree/hive_communicate + /// chance to go and relay message + var/relay_chance = 10 + +/datum/ai_planning_subtree/hive_communicate/select_behaviors(datum/ai_controller/controller, seconds_per_tick) + + if(!SPT_PROB(relay_chance, seconds_per_tick)) + return + + if(controller.blackboard_key_exists(BB_HIVE_PARTNER)) + controller.queue_behavior(/datum/ai_behavior/relay_message, BB_HIVE_PARTNER) + return SUBTREE_RETURN_FINISH_PLANNING + controller.queue_behavior(/datum/ai_behavior/find_and_set/hive_partner, BB_HIVE_PARTNER, /mob/living/basic/hivebot) + +/datum/ai_behavior/find_and_set/hive_partner + +/datum/ai_behavior/find_and_set/hive_partner/search_tactic(datum/ai_controller/controller, locate_path, search_range) + var/mob/living/living_pawn = controller.pawn + var/list/hive_partners = list() + for(var/mob/living/target in oview(10, living_pawn)) + if(!istype(target, locate_path)) + continue + if(target.stat == DEAD) + continue + hive_partners += target + + if(length(hive_partners)) + return pick(hive_partners) + +/// behavior that allow us to go communicate with other hivebots +/datum/ai_behavior/relay_message + /// length of the message we will relay + var/length_of_message = 4 + behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT| AI_BEHAVIOR_REQUIRE_REACH | AI_BEHAVIOR_CAN_PLAN_DURING_EXECUTION + +/datum/ai_behavior/relay_message/setup(datum/ai_controller/controller, target_key) + . = ..() + var/mob/living/target = controller.blackboard[target_key] + // It stopped existing + if(QDELETED(target)) + return FALSE + set_movement_target(controller, target) + +/datum/ai_behavior/relay_message/perform(seconds_per_tick, datum/ai_controller/controller, target_key) + var/mob/living/target = controller.blackboard[target_key] + var/mob/living/living_pawn = controller.pawn + + if(QDELETED(target)) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED + var/message_relayed = "" + for(var/i in 1 to length_of_message) + message_relayed += prob(50) ? "1" : "0" + living_pawn.say(message_relayed) + return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED + +/datum/ai_behavior/relay_message/finish_action(datum/ai_controller/controller, succeeded, target_key) + . = ..() + controller.clear_blackboard_key(target_key) + +/datum/ai_behavior/basic_ranged_attack/hivebot + action_cooldown = 3 SECONDS + avoid_friendly_fire = TRUE + +/datum/ai_behavior/basic_ranged_attack/hivebot_rapid + action_cooldown = 1 SECONDS + avoid_friendly_fire = TRUE + +/datum/ai_controller/basic_controller/beacon + blackboard = list( + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, + ) + ai_movement = /datum/ai_movement/basic_avoidance + idle_behavior = null + planning_subtrees = list( + /datum/ai_planning_subtree/simple_find_target, + /datum/ai_planning_subtree/warpbots, + /datum/ai_planning_subtree/hive_communicate, + ) + +/datum/ai_planning_subtree/warpbots + /// chance to summon hivebots + var/warp_chance = 2 + +/datum/ai_planning_subtree/warpbots/select_behaviors(datum/ai_controller/controller, seconds_per_tick) + + if(!SPT_PROB(warp_chance, seconds_per_tick)) + return + + if(controller.blackboard_key_exists(BB_BASIC_MOB_CURRENT_TARGET)) + var/mob/living/basic/hivebot/tele/beacon = controller.pawn + beacon.warpbots() + return SUBTREE_RETURN_FINISH_PLANNING diff --git a/code/modules/mob/living/simple_animal/hostile/hivebot.dm b/code/modules/mob/living/simple_animal/hostile/hivebot.dm deleted file mode 100644 index def1d8d926d..00000000000 --- a/code/modules/mob/living/simple_animal/hostile/hivebot.dm +++ /dev/null @@ -1,102 +0,0 @@ -/obj/item/projectile/hivebotbullet - -/mob/living/simple_animal/hostile/hivebot - name = "Hivebot" - desc = "A small robot." - icon = 'icons/mob/hivebot.dmi' - icon_state = "basic" - icon_living = "basic" - icon_dead = "basic" - mob_biotypes = MOB_ROBOTIC - health = 15 - maxHealth = 15 - melee_damage_lower = 2 - melee_damage_upper = 3 - attacktext = "claws" - attack_sound = 'sound/weapons/bladeslice.ogg' - projectilesound = 'sound/weapons/gunshots/gunshot.ogg' - projectiletype = /obj/item/projectile/hivebotbullet - faction = list("hivebot") - check_friendly_fire = TRUE - 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) - minbodytemp = 0 - speak_emote = list("states") - gold_core_spawnable = HOSTILE_SPAWN - loot = list(/obj/effect/decal/cleanable/blood/gibs/robot) - deathmessage = "blows apart!" - bubble_icon = "machine" - del_on_death = TRUE - footstep_type = FOOTSTEP_MOB_CLAW - -/mob/living/simple_animal/hostile/hivebot/range - desc = "A smallish robot, this one is armed!" - ranged = TRUE - retreat_distance = 5 - minimum_distance = 5 - -/mob/living/simple_animal/hostile/hivebot/rapid - ranged = TRUE - rapid = 3 - retreat_distance = 5 - minimum_distance = 5 - -/mob/living/simple_animal/hostile/hivebot/strong - name = "Strong Hivebot" - desc = "A robot, this one is armed and looks tough!" - health = 80 - maxHealth = 80 - ranged = TRUE - -/mob/living/simple_animal/hostile/hivebot/death(gibbed) - // Only execute the below if we successfully died - . = ..(gibbed) - if(!.) - return FALSE - do_sparks(3, 1, src) - -/mob/living/simple_animal/hostile/hivebot/tele - name = "Beacon" - desc = "Some odd beacon thing." - icon_state = "def_radar-off" - icon_living = "def_radar-off" - health = 200 - maxHealth = 200 - status_flags = 0 - anchored = TRUE - stop_automated_movement = TRUE - var/bot_type = "norm" - var/bot_amt = 10 - var/spawn_delay = 600 - -/mob/living/simple_animal/hostile/hivebot/tele/Initialize(mapload) - . = ..() - var/datum/effect_system/smoke_spread/smoke = new - smoke.set_up(5, FALSE, loc) - smoke.start() - visible_message("[src] warps in!") - playsound(src.loc, 'sound/effects/empulse.ogg', 25, 1) - -/mob/living/simple_animal/hostile/hivebot/tele/proc/warpbots() - icon_state = "def_radar" - visible_message("[src] turns on!") - while(bot_amt > 0) - bot_amt-- - switch(bot_type) - if("norm") - var/mob/living/simple_animal/hostile/hivebot/H = new /mob/living/simple_animal/hostile/hivebot(get_turf(src)) - H.faction = faction - if("range") - var/mob/living/simple_animal/hostile/hivebot/range/R = new /mob/living/simple_animal/hostile/hivebot/range(get_turf(src)) - R.faction = faction - if("rapid") - var/mob/living/simple_animal/hostile/hivebot/rapid/F = new /mob/living/simple_animal/hostile/hivebot/rapid(get_turf(src)) - F.faction = faction - spawn(100) - qdel(src) - return - -/mob/living/simple_animal/hostile/hivebot/tele/handle_automated_action() - if(!..()) - return - if(prob(2))//Might be a bit low, will mess with it likely - warpbots() diff --git a/paradise.dme b/paradise.dme index c06bc1522e0..85034a94f7e 100644 --- a/paradise.dme +++ b/paradise.dme @@ -2417,6 +2417,8 @@ #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\hivebot.dm" +#include "code\modules\mob\living\basic\hostile\hivebot_ai.dm" #include "code\modules\mob\living\basic\hostile\skeleton_mob.dm" #include "code\modules\mob\living\basic\hostile\giant_spider\giant_spider.dm" #include "code\modules\mob\living\basic\hostile\giant_spider\giant_spider_actions.dm" @@ -2636,7 +2638,6 @@ #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\hivebot.dm" #include "code\modules\mob\living\simple_animal\hostile\hostile.dm" #include "code\modules\mob\living\simple_animal\hostile\illusion.dm" #include "code\modules\mob\living\simple_animal\hostile\jungle_animals.dm" diff --git a/tools/UpdatePaths/Scripts/29849_hivebot.txt b/tools/UpdatePaths/Scripts/29849_hivebot.txt new file mode 100644 index 00000000000..28ee194ffa0 --- /dev/null +++ b/tools/UpdatePaths/Scripts/29849_hivebot.txt @@ -0,0 +1 @@ +/mob/living/simple_animal/hostile/hivebot/@SUBTYPES : /mob/living/basic/hivebot/@SUBTYPES{@OLD}