From 9c1a8e8c81e661e8f59e56426a6843efaa63142f Mon Sep 17 00:00:00 2001 From: SkyratBot <59378654+SkyratBot@users.noreply.github.com> Date: Fri, 20 Oct 2023 08:54:31 +0200 Subject: [PATCH] [MIRROR] Basic Constructs: Artificer [MDB IGNORE] (#24456) * Basic Constructs: Artificer (#79015) Really getting into the meat of the constructs now. Artificers have become basic mobs. On the whole, this was a pretty rote conversion, with no significant gameplay changes other than the switch to using healing hands rather than a unique heal ability. The player experience as an artificer is more or less identical. The _interesting_ part comes with the AI for the seldom-used "hostile" variant. Hostile artificers, being squishy and laughably weak, are now a dedicated "medic" role for constructs. They will perform triage, always seeking the most wounded construct (or shade!) to give healing to. They will not attack at all, but they _will_ flee with great speed if attacked and not busy healing. If they are healing another construct, they will remain even if they are beaten to death. I've added some more AI functionality that may come in handy in the future, and done some refactoring to keep things from getting out of hand: - A planning subtree for finding targets that will always select the most heavily wounded living target that the mob can see (or rather, the one with the least health). Useful again for medical triage, or for making a particularly cruel mob that always attacks whoever is easiest to kill. I plan to use this for NPC wraith constructs when I convert them. - Targeting datums can now check a blackboard key to see if they should only target wounded mobs. This is particularly useful for "medic" type mobs such as this one. - I've refactored the "minimum stat" behavior of targeting datums to be stored in a blackboard key. This removes the need to have unique subtypes for each different minimum stat we might want. Which... for the most part, weren't even used, leading to proliferation of several completely identical targeting datums in a bunch of different files. Hopefully this change will make things cleaner. In addition, this PR fixes a pair of bugs from #78807 that I didn't catch: - Healing constructs can now actually heal shades. Turns out I forgot to add the correct biotype. - Healing hands, when set to print the target's remaining health, no longer does so as a visible message. The one thing I didn't do that I kind of wanted to is make NPC artificers heal themselves when wounded and not busy doing something else, but it ended up being kind of annoying to make a mob willingly target itself. NPC artificers never had this behavior before, so I consider it okay, but maybe I'll circle back to it later. Another basic conversion, another 5 items off the checklist. Very little should change in-game, though I think the new NPC AI could make for interesting challenges in ruins or bitrunning or something. :cl: refactor: Artificer constructs have been converted to the basic mob framework. This should change very little about them, but please report any bugs. NPC artificers are now smarter, and will focus on healing nearby wounded constructs - if you see them, take them out first! /:cl: * Basic Constructs: Artificer * Modular * Modular paths * Modular paths --------- Co-authored-by: lizardqueenlexi <105025397+lizardqueenlexi@users.noreply.github.com> Co-authored-by: Giz <13398309+vinylspiders@users.noreply.github.com> --- _maps/RandomRuins/SpaceRuins/medieval1.dmm | 10 +-- .../SpaceRuins/skyrat/port_tarkon/defcon2.dmm | 14 ++-- _maps/shuttles/emergency_narnar.dmm | 2 +- code/__DEFINES/ai/ai_blackboard.dm | 4 ++ code/__DEFINES/traits.dm | 3 + code/__HELPERS/cmp.dm | 4 ++ .../basic_ai_behaviors/wounded_targetting.dm | 11 +++ .../simple_find_wounded_target.dm | 6 ++ .../basic_targetting_datum.dm | 20 +++--- code/datums/components/healing_touch.dm | 2 +- .../pet_commands/pet_commands_basic.dm | 3 +- code/modules/antagonists/cult/runes.dm | 2 +- .../antagonists/wizard/equipment/soulstone.dm | 8 +-- code/modules/events/portal_storm.dm | 2 +- .../mob/living/basic/blob_minions/blob_ai.dm | 9 ++- .../mob/living/basic/clown/clown_ai.dm | 3 +- .../mob/living/basic/constructs/_construct.dm | 1 + .../hostile => basic}/constructs/artificer.dm | 70 +++++-------------- .../living/basic/constructs/construct_ai.dm | 25 +++++++ .../basic/farm_animals/gorilla/gorilla_ai.dm | 6 +- .../mob/living/basic/heretic/star_gazer.dm | 9 ++- .../basic/icemoon/ice_whelp/ice_whelp_ai.dm | 3 +- .../basic/lavaland/brimdemon/brimdemon_ai.dm | 6 +- .../basic/lavaland/goliath/goliath_ai.dm | 6 +- .../living/basic/lavaland/legion/legion_ai.dm | 10 +-- .../lavaland/lobstrosity/lobstrosity_ai.dm | 6 +- .../mob/living/basic/space_fauna/faithless.dm | 6 +- .../mob/living/basic/space_fauna/mushroom.dm | 2 +- .../living/basic/syndicate/syndicate_ai.dm | 3 +- code/modules/mob/living/living_defense.dm | 2 +- .../hostile/constructs/juggernaut.dm | 4 ++ .../hostile/constructs/wraith.dm | 4 ++ .../unit_tests/simple_animal_freeze.dm | 5 -- .../mothership_astrum/abductor_ai.dm | 7 +- .../code/mobs/clockwork_marauder.dm | 15 ++-- tgstation.dme | 5 +- ...15_simple_to_basic_construct_artificer.txt | 1 + 37 files changed, 163 insertions(+), 136 deletions(-) create mode 100644 code/datums/ai/basic_mobs/basic_ai_behaviors/wounded_targetting.dm create mode 100644 code/datums/ai/basic_mobs/basic_subtrees/simple_find_wounded_target.dm rename code/modules/mob/living/{simple_animal/hostile => basic}/constructs/artificer.dm (50%) create mode 100644 code/modules/mob/living/basic/constructs/construct_ai.dm create mode 100644 tools/UpdatePaths/Scripts/79015_simple_to_basic_construct_artificer.txt diff --git a/_maps/RandomRuins/SpaceRuins/medieval1.dmm b/_maps/RandomRuins/SpaceRuins/medieval1.dmm index 7216e62eb4f..e4df5166993 100644 --- a/_maps/RandomRuins/SpaceRuins/medieval1.dmm +++ b/_maps/RandomRuins/SpaceRuins/medieval1.dmm @@ -11,13 +11,13 @@ /turf/open/floor/wood/parquet, /area/ruin/space) "eo" = ( -/mob/living/simple_animal/hostile/construct/artificer/hostile{ +/mob/living/basic/construct/artificer/hostile{ dir = 1 }, /turf/open/floor/stone, /area/ruin/space) "gv" = ( -/mob/living/simple_animal/hostile/construct/artificer/hostile, +/mob/living/basic/construct/artificer/hostile, /turf/open/space/basic, /area/ruin/space) "hi" = ( @@ -37,7 +37,7 @@ /turf/open/space/basic, /area/ruin/space) "jy" = ( -/mob/living/simple_animal/hostile/construct/artificer/hostile{ +/mob/living/basic/construct/artificer/hostile{ dir = 4 }, /turf/open/misc/asteroid/basalt/wasteland, @@ -92,7 +92,7 @@ /turf/open/floor/stone, /area/ruin/space) "tj" = ( -/mob/living/simple_animal/hostile/construct/artificer/hostile{ +/mob/living/basic/construct/artificer/hostile{ dir = 4 }, /turf/open/space/basic, @@ -276,7 +276,7 @@ /turf/open/floor/wood/parquet, /area/ruin/space) "XM" = ( -/mob/living/simple_animal/hostile/construct/artificer/hostile{ +/mob/living/basic/construct/artificer/hostile{ dir = 8 }, /turf/open/space/basic, diff --git a/_maps/RandomRuins/SpaceRuins/skyrat/port_tarkon/defcon2.dmm b/_maps/RandomRuins/SpaceRuins/skyrat/port_tarkon/defcon2.dmm index 877faaad71f..95d181b18d6 100644 --- a/_maps/RandomRuins/SpaceRuins/skyrat/port_tarkon/defcon2.dmm +++ b/_maps/RandomRuins/SpaceRuins/skyrat/port_tarkon/defcon2.dmm @@ -1084,7 +1084,7 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/light/dim/directional/east, /obj/effect/turf_decal/delivery/blue, -/mob/living/simple_animal/hostile/construct/artificer/hostile{ +/mob/living/basic/construct/artificer/hostile{ health = 150; maxHealth = 150 }, @@ -1263,7 +1263,7 @@ /turf/open/misc/asteroid/airless, /area/solars/tarkon) "he" = ( -/mob/living/simple_animal/hostile/construct/artificer/hostile, +/mob/living/basic/construct/artificer/hostile, /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron, /area/ruin/space/has_grav/port_tarkon/porthall) @@ -3940,7 +3940,7 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/effect/decal/cleanable/glass, /obj/effect/decal/cleanable/blood, -/mob/living/simple_animal/hostile/construct/artificer/hostile{ +/mob/living/basic/construct/artificer/hostile{ health = 200; maxHealth = 200; name = "Third eye of the veil" @@ -4125,7 +4125,7 @@ /turf/open/floor/engine/co2, /area/ruin/space/has_grav/port_tarkon/atmos) "xo" = ( -/mob/living/simple_animal/hostile/construct/artificer/hostile{ +/mob/living/basic/construct/artificer/hostile{ health = 150; maxHealth = 150 }, @@ -4698,7 +4698,7 @@ /area/ruin/space/has_grav/port_tarkon/starboardhall) "AI" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/mob/living/simple_animal/hostile/construct/artificer/hostile{ +/mob/living/basic/construct/artificer/hostile{ health = 150; maxHealth = 150 }, @@ -8632,7 +8632,7 @@ "Wq" = ( /obj/structure/cable, /obj/effect/decal/cleanable/blood, -/mob/living/simple_animal/hostile/construct/artificer/hostile, +/mob/living/basic/construct/artificer/hostile, /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron, /area/ruin/space/has_grav/port_tarkon/cargo) @@ -8772,7 +8772,7 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/structure/cable, -/mob/living/simple_animal/hostile/construct/artificer/hostile{ +/mob/living/basic/construct/artificer/hostile{ health = 150; maxHealth = 150 }, diff --git a/_maps/shuttles/emergency_narnar.dmm b/_maps/shuttles/emergency_narnar.dmm index 835a6054a87..9f8cbbcc00d 100644 --- a/_maps/shuttles/emergency_narnar.dmm +++ b/_maps/shuttles/emergency_narnar.dmm @@ -111,7 +111,7 @@ /turf/open/floor/cult, /area/shuttle/escape) "w" = ( -/mob/living/simple_animal/hostile/construct/artificer, +/mob/living/basic/construct/artificer, /turf/open/floor/cult, /area/shuttle/escape) "x" = ( diff --git a/code/__DEFINES/ai/ai_blackboard.dm b/code/__DEFINES/ai/ai_blackboard.dm index 079b052853f..9bd23d8cbf9 100644 --- a/code/__DEFINES/ai/ai_blackboard.dm +++ b/code/__DEFINES/ai/ai_blackboard.dm @@ -43,6 +43,10 @@ #define BB_BASIC_MOB_EXECUTION_TARGET "BB_basic_execution_target" ///Blackboard key for a whitelist typecache of "things we can target while trying to move" #define BB_OBSTACLE_TARGETTING_WHITELIST "BB_targetting_whitelist" +/// Key for the minimum status at which we want to target mobs (does not need to be specified if CONSCIOUS) +#define BB_TARGET_MINIMUM_STAT "BB_target_minimum_stat" +/// Flag for whether to target only wounded mobs +#define BB_TARGET_WOUNDED_ONLY "BB_target_wounded_only" /// Blackboard key storing how long your targetting datum has held a particular target #define BB_BASIC_MOB_HAS_TARGET_TIME "BB_basic_mob_has_target_time" diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index 0c55033e60a..be1376f2966 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -924,6 +924,9 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_FISH_FED_LUBE "fish_fed_lube" #define TRAIT_FISH_NO_HUNGER "fish_no_hunger" +/// Trait given to angelic constructs to let them purge cult runes +#define TRAIT_ANGELIC "angelic" + // common trait sources #define TRAIT_GENERIC "generic" #define UNCONSCIOUS_TRAIT "unconscious" diff --git a/code/__HELPERS/cmp.dm b/code/__HELPERS/cmp.dm index 5627e737c2b..e1303882b1a 100644 --- a/code/__HELPERS/cmp.dm +++ b/code/__HELPERS/cmp.dm @@ -194,3 +194,7 @@ var/datum/award/award_a = SSachievements.awards[type_a] var/datum/award/award_b = SSachievements.awards[type_b] return award_b?.load_priority - award_a?.load_priority + +/// Orders mobs by health +/proc/cmp_mob_health(mob/living/mob_a, mob/living/mob_b) + return mob_b.health - mob_a.health diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/wounded_targetting.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/wounded_targetting.dm new file mode 100644 index 00000000000..8535554e54b --- /dev/null +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/wounded_targetting.dm @@ -0,0 +1,11 @@ +/// Picks targets based on which one has the lowest health +/datum/ai_behavior/find_potential_targets/most_wounded + +/datum/ai_behavior/find_potential_targets/most_wounded/pick_final_target(datum/ai_controller/controller, list/filtered_targets) + var/list/living_targets = list() + for(var/mob/living/living_target in filtered_targets) + living_targets += filtered_targets + if(living_targets.len) + sortTim(living_targets, GLOBAL_PROC_REF(cmp_mob_health)) + return living_targets[1] + return ..() diff --git a/code/datums/ai/basic_mobs/basic_subtrees/simple_find_wounded_target.dm b/code/datums/ai/basic_mobs/basic_subtrees/simple_find_wounded_target.dm new file mode 100644 index 00000000000..8840c1ea3a7 --- /dev/null +++ b/code/datums/ai/basic_mobs/basic_subtrees/simple_find_wounded_target.dm @@ -0,0 +1,6 @@ +/// Selects the most wounded potential target that we can see +/datum/ai_planning_subtree/simple_find_wounded_target + +/datum/ai_planning_subtree/simple_find_wounded_target/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) + . = ..() + controller.queue_behavior(/datum/ai_behavior/find_potential_targets/most_wounded, BB_BASIC_MOB_CURRENT_TARGET, BB_TARGETTING_DATUM, BB_BASIC_MOB_CURRENT_TARGET_HIDING_LOCATION) diff --git a/code/datums/ai/basic_mobs/targetting_datums/basic_targetting_datum.dm b/code/datums/ai/basic_mobs/targetting_datums/basic_targetting_datum.dm index 1d6fde335cb..d8b7e49c23c 100644 --- a/code/datums/ai/basic_mobs/targetting_datums/basic_targetting_datum.dm +++ b/code/datums/ai/basic_mobs/targetting_datums/basic_targetting_datum.dm @@ -15,10 +15,12 @@ /datum/targetting_datum/basic /// When we do our basic faction check, do we look for exact faction matches? var/check_factions_exactly = FALSE - /// Minimum status to attack living beings - var/stat_attack = CONSCIOUS - ///Whether we care for seeing the target or not + /// Whether we care for seeing the target or not var/ignore_sight = FALSE + /// Blackboard key containing the minimum stat of a living mob to target + var/minimum_stat_key = BB_TARGET_MINIMUM_STAT + /// If this blackboard key is TRUE, makes us only target wounded mobs + var/target_wounded_key /datum/targetting_datum/basic/can_attack(mob/living/living_mob, atom/the_target, vision_range) var/datum/ai_controller/basic_controller/our_controller = living_mob.ai_controller @@ -54,7 +56,9 @@ var/mob/living/living_target = the_target if(faction_check(our_controller, living_mob, living_target)) return FALSE - if(living_target.stat > stat_attack) + if(living_target.stat > our_controller.blackboard[minimum_stat_key]) + return FALSE + if(target_wounded_key && our_controller.blackboard[target_wounded_key] && living_target.health == living_target.maxHealth) return FALSE return TRUE @@ -121,8 +125,8 @@ find_smaller = FALSE inclusive = FALSE -/datum/targetting_datum/basic/attack_until_dead - stat_attack = HARD_CRIT +/// Makes the mob only attack their own faction. Useful mostly if their attacks do something helpful (e.g. healing touch). +/datum/targetting_datum/basic/same_faction -/datum/targetting_datum/basic/attack_even_if_dead - stat_attack = DEAD +/datum/targetting_datum/basic/same_faction/faction_check(mob/living/living_mob, mob/living/the_target) + return !..() // inverts logic to ONLY target mobs that share a faction diff --git a/code/datums/components/healing_touch.dm b/code/datums/components/healing_touch.dm index 029b0f660ef..a81de7ab04a 100644 --- a/code/datums/components/healing_touch.dm +++ b/code/datums/components/healing_touch.dm @@ -159,7 +159,7 @@ if(show_health && !iscarbon(target)) var/formatted_string = format_string("%TARGET% now has [target.health]/[target.maxHealth] health.", healer, target) - healer.visible_message(span_danger(formatted_string)) + to_chat(healer, span_danger(formatted_string)) /// Reformats the passed string with the replacetext keys /datum/component/healing_touch/proc/format_string(string, atom/source, 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 ff29b8f37d2..672e3183feb 100644 --- a/code/datums/components/pet_commands/pet_commands_basic.dm +++ b/code/datums/components/pet_commands/pet_commands_basic.dm @@ -183,11 +183,10 @@ UnregisterSignal(unfriended, COMSIG_ATOM_WAS_ATTACKED) /datum/pet_command/protect_owner/execute_action(datum/ai_controller/controller) - var/datum/targetting_datum/basic/targetting = controller.blackboard[BB_TARGETTING_DATUM] var/mob/living/victim = controller.blackboard[BB_CURRENT_PET_TARGET] if(QDELETED(victim)) return - if(victim.stat > targetting.stat_attack) + if(victim.stat > controller.blackboard[BB_TARGET_MINIMUM_STAT]) controller.clear_blackboard_key(BB_ACTIVE_PET_COMMAND) return controller.queue_behavior(protect_behavior, BB_CURRENT_PET_TARGET, BB_PET_TARGETTING_DATUM) diff --git a/code/modules/antagonists/cult/runes.dm b/code/modules/antagonists/cult/runes.dm index c24962524e7..63b2c6613c3 100644 --- a/code/modules/antagonists/cult/runes.dm +++ b/code/modules/antagonists/cult/runes.dm @@ -112,7 +112,7 @@ Runes can either be invoked by one's self or with many different cultists. Each /obj/effect/rune/attack_animal(mob/living/simple_animal/user, list/modifiers) if(isshade(user) || isconstruct(user)) - if(istype(user, /mob/living/simple_animal/hostile/construct/wraith/angelic) || istype(user, /mob/living/simple_animal/hostile/construct/juggernaut/angelic) || istype(user, /mob/living/simple_animal/hostile/construct/artificer/angelic)) + if(HAS_TRAIT(user, TRAIT_ANGELIC)) to_chat(user, span_warning("You purge the rune!")) qdel(src) else if(construct_invoke || !IS_CULTIST(user)) //if you're not a cult construct we want the normal fail message diff --git a/code/modules/antagonists/wizard/equipment/soulstone.dm b/code/modules/antagonists/wizard/equipment/soulstone.dm index 610c8425d97..f7be579ad1a 100644 --- a/code/modules/antagonists/wizard/equipment/soulstone.dm +++ b/code/modules/antagonists/wizard/equipment/soulstone.dm @@ -490,15 +490,15 @@ makeNewConstruct(/mob/living/simple_animal/hostile/construct/wraith/noncult, target, creator, cultoverride, loc_override) if(CONSTRUCT_ARTIFICER) if(IS_CULTIST(creator)) - makeNewConstruct(/mob/living/simple_animal/hostile/construct/artificer, target, creator, cultoverride, loc_override) // ignore themes, the actual giving of cult info is in the makeNewConstruct proc + makeNewConstruct(/mob/living/basic/construct/artificer, target, creator, cultoverride, loc_override) // ignore themes, the actual giving of cult info is in the makeNewConstruct proc return switch(theme) if(THEME_WIZARD) - makeNewConstruct(/mob/living/simple_animal/hostile/construct/artificer/mystic, target, creator, cultoverride, loc_override) + makeNewConstruct(/mob/living/basic/construct/artificer/mystic, target, creator, cultoverride, loc_override) if(THEME_HOLY) - makeNewConstruct(/mob/living/simple_animal/hostile/construct/artificer/angelic, target, creator, cultoverride, loc_override) + makeNewConstruct(/mob/living/basic/construct/artificer/angelic, target, creator, cultoverride, loc_override) if(THEME_CULT) - makeNewConstruct(/mob/living/simple_animal/hostile/construct/artificer/noncult, target, creator, cultoverride, loc_override) + makeNewConstruct(/mob/living/basic/construct/artificer/noncult, target, creator, cultoverride, loc_override) /proc/makeNewConstruct(mob/living/simple_animal/hostile/construct/ctype, mob/target, mob/stoner = null, cultoverride = FALSE, loc_override = null) if(QDELETED(target)) diff --git a/code/modules/events/portal_storm.dm b/code/modules/events/portal_storm.dm index 9ba8ca4992e..662b2f404c3 100644 --- a/code/modules/events/portal_storm.dm +++ b/code/modules/events/portal_storm.dm @@ -23,7 +23,7 @@ max_wizard_trigger_potency = 7 /datum/round_event/portal_storm/portal_storm_narsie - boss_types = list(/mob/living/simple_animal/hostile/construct/artificer/hostile = 6) + boss_types = list(/mob/living/basic/construct/artificer/hostile = 6) hostile_types = list(/mob/living/simple_animal/hostile/construct/juggernaut/hostile = 8,\ /mob/living/simple_animal/hostile/construct/wraith/hostile = 6) diff --git a/code/modules/mob/living/basic/blob_minions/blob_ai.dm b/code/modules/mob/living/basic/blob_minions/blob_ai.dm index 6168b7ca83b..fc21d030d07 100644 --- a/code/modules/mob/living/basic/blob_minions/blob_ai.dm +++ b/code/modules/mob/living/basic/blob_minions/blob_ai.dm @@ -4,7 +4,8 @@ */ /datum/ai_controller/basic_controller/blobbernaut blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/attack_until_dead, + BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGET_MINIMUM_STAT = HARD_CRIT, ) ai_movement = /datum/ai_movement/jps @@ -20,7 +21,8 @@ */ /datum/ai_controller/basic_controller/blob_zombie blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/attack_until_dead, + BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGET_MINIMUM_STAT = HARD_CRIT, ) ai_movement = /datum/ai_movement/jps @@ -37,7 +39,8 @@ */ /datum/ai_controller/basic_controller/blob_spore blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/attack_until_dead, + BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGET_MINIMUM_STAT = HARD_CRIT, ) ai_movement = /datum/ai_movement/jps diff --git a/code/modules/mob/living/basic/clown/clown_ai.dm b/code/modules/mob/living/basic/clown/clown_ai.dm index b2e6418dde7..f54c432140e 100644 --- a/code/modules/mob/living/basic/clown/clown_ai.dm +++ b/code/modules/mob/living/basic/clown/clown_ai.dm @@ -14,6 +14,7 @@ /datum/ai_controller/basic_controller/clown/murder blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/attack_until_dead, + BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, BB_BASIC_MOB_SPEAK_LINES = null, + BB_TARGET_MINIMUM_STAT = HARD_CRIT, ) diff --git a/code/modules/mob/living/basic/constructs/_construct.dm b/code/modules/mob/living/basic/constructs/_construct.dm index f2e55cceb86..fcafab62259 100644 --- a/code/modules/mob/living/basic/constructs/_construct.dm +++ b/code/modules/mob/living/basic/constructs/_construct.dm @@ -61,6 +61,7 @@ heal_burn = 0,\ heal_time = 0,\ valid_targets_typecache = typecacheof(list(/mob/living/basic/construct, /mob/living/simple_animal/hostile/construct, /mob/living/simple_animal/shade)),\ + valid_biotypes = MOB_MINERAL | MOB_SPIRIT,\ self_targetting = can_repair_self ? HEALING_TOUCH_ANYONE : HEALING_TOUCH_NOT_SELF,\ action_text = "%SOURCE% begins repairing %TARGET%'s dents.",\ complete_text = "%TARGET%'s dents are repaired.",\ diff --git a/code/modules/mob/living/simple_animal/hostile/constructs/artificer.dm b/code/modules/mob/living/basic/constructs/artificer.dm similarity index 50% rename from code/modules/mob/living/simple_animal/hostile/constructs/artificer.dm rename to code/modules/mob/living/basic/constructs/artificer.dm index 743931c508d..d3be414791b 100644 --- a/code/modules/mob/living/simple_animal/hostile/constructs/artificer.dm +++ b/code/modules/mob/living/basic/constructs/artificer.dm @@ -1,4 +1,4 @@ -/mob/living/simple_animal/hostile/construct/artificer +/mob/living/basic/construct/artificer name = "Artificer" real_name = "Artificer" desc = "A bulbous construct dedicated to building and maintaining the Cult of Nar'Sie's armies." @@ -8,15 +8,11 @@ health = 50 response_harm_continuous = "viciously beats" response_harm_simple = "viciously beat" - harm_intent_damage = 5 obj_damage = 60 melee_damage_lower = 5 melee_damage_upper = 5 - retreat_distance = 10 - minimum_distance = 10 //AI artificers will flee like fuck attack_verb_continuous = "rams" attack_verb_simple = "ram" - environment_smash = ENVIRONMENT_SMASH_WALLS attack_sound = 'sound/weapons/punch2.ogg' construct_spells = list( /datum/action/cooldown/spell/conjure/cult_floor, @@ -33,70 +29,38 @@ can_repair = TRUE can_repair_self = TRUE + smashes_walls = TRUE ///The health HUD applied to this mob. var/health_hud = DATA_HUD_MEDICAL_ADVANCED -/mob/living/simple_animal/hostile/construct/artificer/Initialize(mapload) +/mob/living/basic/construct/artificer/Initialize(mapload) . = ..() + AddElement(/datum/element/ai_retaliate) var/datum/atom_hud/datahud = GLOB.huds[health_hud] datahud.show_to(src) -/mob/living/simple_animal/hostile/construct/artificer/Found(atom/thing) //what have we found here? - if(!isconstruct(thing)) //is it a construct? - return FALSE - var/mob/living/simple_animal/hostile/construct/cultie = thing - if(cultie.health < cultie.maxHealth) //is it hurt? let's go heal it if it is - return TRUE +/// Hostile NPC version. Heals nearby constructs and cult structures, avoids targets that aren't extremely hurt. +/mob/living/basic/construct/artificer/hostile + ai_controller = /datum/ai_controller/basic_controller/artificer + smashes_walls = FALSE -/mob/living/simple_animal/hostile/construct/artificer/CanAttack(atom/the_target) - if(see_invisible < the_target.invisibility)//Target's invisible to us, forget it - return FALSE - if(Found(the_target) || ..()) //If we Found it or Can_Attack it normally, we Can_Attack it as long as it wasn't invisible - return TRUE //as a note this shouldn't be added to base hostile mobs because it'll mess up retaliate hostile mobs - return FALSE - -/mob/living/simple_animal/hostile/construct/artificer/MoveToTarget(list/possible_targets) - ..() - if(!isliving(target)) - return - - var/mob/living/victim = target - if(isconstruct(victim) && victim.health >= victim.maxHealth) //is this target an unhurt construct? stop trying to heal it - LoseTarget() - return - if(victim.health <= melee_damage_lower+melee_damage_upper) //ey bucko you're hurt as fuck let's go hit you - retreat_distance = null - minimum_distance = 1 - -/mob/living/simple_animal/hostile/construct/artificer/Aggro() - ..() - if(isconstruct(target)) //oh the target is a construct no need to flee - retreat_distance = null - minimum_distance = 1 - -/mob/living/simple_animal/hostile/construct/artificer/LoseAggro() - ..() - retreat_distance = initial(retreat_distance) - minimum_distance = initial(minimum_distance) - -/mob/living/simple_animal/hostile/construct/artificer/hostile //actually hostile, will move around, hit things, heal other constructs - AIStatus = AI_ON - environment_smash = ENVIRONMENT_SMASH_STRUCTURES //only token destruction, don't smash the cult wall NO STOP - -/////////////////////////////Artificer-alts///////////////////////// -/mob/living/simple_animal/hostile/construct/artificer/angelic +// Alternate artificer themes +/mob/living/basic/construct/artificer/angelic desc = "A bulbous construct dedicated to building and maintaining holy armies." theme = THEME_HOLY - loot = list(/obj/item/ectoplasm/angelic) construct_spells = list( /datum/action/cooldown/spell/conjure/soulstone/purified, /datum/action/cooldown/spell/conjure/construct/lesser, /datum/action/cooldown/spell/aoe/magic_missile/lesser, /datum/action/innate/cult/create_rune/revive, ) -/mob/living/simple_animal/hostile/construct/artificer/mystic + +/mob/living/basic/construct/artificer/angelic/Initialize(mapload) + . = ..() + ADD_TRAIT(src, TRAIT_ANGELIC, INNATE_TRAIT) + +/mob/living/basic/construct/artificer/mystic theme = THEME_WIZARD - loot = list(/obj/item/ectoplasm/mystic) construct_spells = list( /datum/action/cooldown/spell/conjure/cult_floor, /datum/action/cooldown/spell/conjure/cult_wall, @@ -106,7 +70,7 @@ /datum/action/innate/cult/create_rune/revive, ) -/mob/living/simple_animal/hostile/construct/artificer/noncult +/mob/living/basic/construct/artificer/noncult construct_spells = list( /datum/action/cooldown/spell/conjure/cult_floor, /datum/action/cooldown/spell/conjure/cult_wall, diff --git a/code/modules/mob/living/basic/constructs/construct_ai.dm b/code/modules/mob/living/basic/constructs/construct_ai.dm new file mode 100644 index 00000000000..fde0876955b --- /dev/null +++ b/code/modules/mob/living/basic/constructs/construct_ai.dm @@ -0,0 +1,25 @@ +/// Artificers +/datum/ai_controller/basic_controller/artificer + blackboard = list( + BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/same_faction/construct, + BB_FLEE_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGET_WOUNDED_ONLY = TRUE, + ) + + ai_movement = /datum/ai_movement/basic_avoidance + idle_behavior = /datum/idle_behavior/idle_random_walk + planning_subtrees = list( + /datum/ai_planning_subtree/simple_find_wounded_target, + /datum/ai_planning_subtree/basic_melee_attack_subtree, + /datum/ai_planning_subtree/target_retaliate/to_flee, + /datum/ai_planning_subtree/flee_target/from_flee_key, + ) + +/// Targetting datum that will only allow mobs that constructs can heal. +/datum/targetting_datum/basic/same_faction/construct + target_wounded_key = BB_TARGET_WOUNDED_ONLY + +/datum/targetting_datum/basic/same_faction/construct/can_attack(mob/living/living_mob, atom/the_target, vision_range, check_faction = TRUE) + if(isconstruct(the_target) || istype(the_target, /mob/living/simple_animal/shade)) + return ..() + return FALSE diff --git a/code/modules/mob/living/basic/farm_animals/gorilla/gorilla_ai.dm b/code/modules/mob/living/basic/farm_animals/gorilla/gorilla_ai.dm index c6230754277..daf5b7af083 100644 --- a/code/modules/mob/living/basic/farm_animals/gorilla/gorilla_ai.dm +++ b/code/modules/mob/living/basic/farm_animals/gorilla/gorilla_ai.dm @@ -1,7 +1,8 @@ /// Pretty basic, just click people to death. Also hunt and eat bananas. /datum/ai_controller/basic_controller/gorilla blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/allow_items/gorilla, + BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/allow_items, + BB_TARGET_MINIMUM_STAT = UNCONSCIOUS, BB_EMOTE_KEY = "ooga", BB_EMOTE_CHANCE = 40, ) @@ -18,9 +19,6 @@ /datum/ai_planning_subtree/basic_melee_attack_subtree, ) -/datum/targetting_datum/basic/allow_items/gorilla - stat_attack = UNCONSCIOUS - /datum/ai_planning_subtree/attack_obstacle_in_path/gorilla attack_behaviour = /datum/ai_behavior/attack_obstructions/gorilla diff --git a/code/modules/mob/living/basic/heretic/star_gazer.dm b/code/modules/mob/living/basic/heretic/star_gazer.dm index bef9924efe0..37d35a4037f 100644 --- a/code/modules/mob/living/basic/heretic/star_gazer.dm +++ b/code/modules/mob/living/basic/heretic/star_gazer.dm @@ -78,8 +78,14 @@ /datum/ai_controller/basic_controller/star_gazer blackboard = list( +<<<<<<< HEAD BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/star_gazer(), BB_PET_TARGETTING_DATUM = new /datum/targetting_datum/not_friends/attack_closed_turfs(), +======= + BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGET_MINIMUM_STAT = HARD_CRIT, + BB_PET_TARGETTING_DATUM = new /datum/targetting_datum/basic/not_friends/attack_closed_turfs, +>>>>>>> 6e2fcee00 ([MIRROR] Basic Constructs: Artificer [MDB IGNORE] (#24456)) ) ai_movement = /datum/ai_movement/basic_avoidance @@ -92,9 +98,6 @@ /datum/ai_planning_subtree/basic_melee_attack_subtree, ) -/datum/targetting_datum/basic/star_gazer - stat_attack = HARD_CRIT - /datum/ai_planning_subtree/attack_obstacle_in_path/star_gazer attack_behaviour = /datum/ai_behavior/attack_obstructions/star_gazer 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 47280af4281..2d9715caf37 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 @@ -1,7 +1,8 @@ #define ENRAGE_ADDITION 25 /datum/ai_controller/basic_controller/ice_whelp blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/allow_items/goliath, + BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/allow_items, + BB_TARGET_MINIMUM_STAT = HARD_CRIT, BB_WHELP_ENRAGED = 0, ) diff --git a/code/modules/mob/living/basic/lavaland/brimdemon/brimdemon_ai.dm b/code/modules/mob/living/basic/lavaland/brimdemon/brimdemon_ai.dm index e5d793fa150..18f614359c0 100644 --- a/code/modules/mob/living/basic/lavaland/brimdemon/brimdemon_ai.dm +++ b/code/modules/mob/living/basic/lavaland/brimdemon/brimdemon_ai.dm @@ -3,7 +3,8 @@ */ /datum/ai_controller/basic_controller/brimdemon blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/brimdemon, + BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGET_MINIMUM_STAT = HARD_CRIT, ) ai_traits = PAUSE_DURING_DO_AFTER @@ -16,9 +17,6 @@ /datum/ai_planning_subtree/targeted_mob_ability/brimbeam, ) -/datum/targetting_datum/basic/brimdemon - stat_attack = HARD_CRIT - /datum/ai_planning_subtree/move_to_cardinal/brimdemon move_behaviour = /datum/ai_behavior/move_to_cardinal/brimdemon diff --git a/code/modules/mob/living/basic/lavaland/goliath/goliath_ai.dm b/code/modules/mob/living/basic/lavaland/goliath/goliath_ai.dm index 7e723f5d93a..48f0e213e73 100644 --- a/code/modules/mob/living/basic/lavaland/goliath/goliath_ai.dm +++ b/code/modules/mob/living/basic/lavaland/goliath/goliath_ai.dm @@ -3,7 +3,8 @@ /datum/ai_controller/basic_controller/goliath blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/allow_items/goliath, + BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/allow_items, + BB_TARGET_MINIMUM_STAT = HARD_CRIT, ) ai_movement = /datum/ai_movement/basic_avoidance @@ -19,9 +20,6 @@ /datum/ai_planning_subtree/goliath_dig, ) -/datum/targetting_datum/basic/allow_items/goliath - stat_attack = HARD_CRIT - /datum/ai_planning_subtree/basic_melee_attack_subtree/goliath operational_datums = list(/datum/component/ai_target_timer) melee_attack_behavior = /datum/ai_behavior/basic_melee_attack/goliath diff --git a/code/modules/mob/living/basic/lavaland/legion/legion_ai.dm b/code/modules/mob/living/basic/lavaland/legion/legion_ai.dm index ff29ea3c240..9167846b685 100644 --- a/code/modules/mob/living/basic/lavaland/legion/legion_ai.dm +++ b/code/modules/mob/living/basic/lavaland/legion/legion_ai.dm @@ -1,7 +1,8 @@ /// Keep away and launch skulls at every opportunity, prioritising injured allies /datum/ai_controller/basic_controller/legion blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/attack_until_dead/legion, + BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/legion, + BB_TARGET_MINIMUM_STAT = HARD_CRIT, BB_AGGRO_RANGE = 5, // Unobservant BB_BASIC_MOB_FLEE_DISTANCE = 6, ) @@ -18,7 +19,8 @@ /// Chase and attack whatever we are targetting, if it's friendly we will heal them /datum/ai_controller/basic_controller/legion_brood blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/attack_until_dead/legion, + BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/legion, + BB_TARGET_MINIMUM_STAT = HARD_CRIT, ) ai_movement = /datum/ai_movement/basic_avoidance @@ -29,9 +31,9 @@ ) /// Target nearby friendlies if they are hurt (and are not themselves Legions) -/datum/targetting_datum/basic/attack_until_dead/legion +/datum/targetting_datum/basic/legion -/datum/targetting_datum/basic/attack_until_dead/legion/faction_check(datum/ai_controller/controller, mob/living/living_mob, mob/living/the_target) +/datum/targetting_datum/basic/legion/faction_check(datum/ai_controller/controller, mob/living/living_mob, mob/living/the_target) if (!living_mob.faction_check_atom(the_target, exact_match = check_factions_exactly)) return FALSE if (istype(the_target, living_mob.type)) 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 7b6926fca04..c89cc3b9c07 100644 --- a/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity_ai.dm +++ b/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity_ai.dm @@ -1,6 +1,7 @@ /datum/ai_controller/basic_controller/lobstrosity blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/lobster, + BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGET_MINIMUM_STAT = HARD_CRIT, BB_LOBSTROSITY_EXPLOIT_TRAITS = list(TRAIT_INCAPACITATED, TRAIT_FLOORED, TRAIT_IMMOBILIZED, TRAIT_KNOCKEDOUT), BB_LOBSTROSITY_FINGER_LUST = 0 ) @@ -18,9 +19,6 @@ /datum/ai_planning_subtree/find_fingers, ) -/datum/targetting_datum/basic/lobster - stat_attack = HARD_CRIT - /datum/ai_planning_subtree/basic_melee_attack_subtree/lobster melee_attack_behavior = /datum/ai_behavior/basic_melee_attack/lobster diff --git a/code/modules/mob/living/basic/space_fauna/faithless.dm b/code/modules/mob/living/basic/space_fauna/faithless.dm index 88696b3a3c7..5cfdd4b47b6 100644 --- a/code/modules/mob/living/basic/space_fauna/faithless.dm +++ b/code/modules/mob/living/basic/space_fauna/faithless.dm @@ -55,7 +55,8 @@ /datum/ai_controller/basic_controller/faithless blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/faithless(), + BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGET_MINIMUM_STAT = UNCONSCIOUS, BB_LOW_PRIORITY_HUNTING_TARGET = null, // lights ) @@ -69,6 +70,3 @@ /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 diff --git a/code/modules/mob/living/basic/space_fauna/mushroom.dm b/code/modules/mob/living/basic/space_fauna/mushroom.dm index 6f900b08abf..056a4558081 100644 --- a/code/modules/mob/living/basic/space_fauna/mushroom.dm +++ b/code/modules/mob/living/basic/space_fauna/mushroom.dm @@ -58,6 +58,7 @@ /datum/ai_controller/basic_controller/mushroom blackboard = list( BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/mushroom, + BB_TARGET_MINIMUM_STAT = DEAD, ) ai_movement = /datum/ai_movement/basic_avoidance @@ -70,7 +71,6 @@ /datum/targetting_datum/basic/mushroom - stat_attack = DEAD ///we only attacked another mushrooms /datum/targetting_datum/basic/mushroom/faction_check(datum/ai_controller/controller, mob/living/living_mob, mob/living/the_target) diff --git a/code/modules/mob/living/basic/syndicate/syndicate_ai.dm b/code/modules/mob/living/basic/syndicate/syndicate_ai.dm index be84c1a5685..b256226f161 100644 --- a/code/modules/mob/living/basic/syndicate/syndicate_ai.dm +++ b/code/modules/mob/living/basic/syndicate/syndicate_ai.dm @@ -1,6 +1,7 @@ /datum/ai_controller/basic_controller/syndicate blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/attack_until_dead + BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGET_MINIMUM_STAT = HARD_CRIT, ) ai_movement = /datum/ai_movement/basic_avoidance diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index 4f56c1403bc..af43cc3237c 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -470,7 +470,7 @@ if(2) new /mob/living/simple_animal/hostile/construct/wraith/hostile(get_turf(src)) if(3) - new /mob/living/simple_animal/hostile/construct/artificer/hostile(get_turf(src)) + new /mob/living/basic/construct/artificer/hostile(get_turf(src)) if(4) new /mob/living/simple_animal/hostile/construct/proteon/hostile(get_turf(src)) spawn_dust() diff --git a/code/modules/mob/living/simple_animal/hostile/constructs/juggernaut.dm b/code/modules/mob/living/simple_animal/hostile/constructs/juggernaut.dm index 3eb80cf7a88..893700abe8a 100644 --- a/code/modules/mob/living/simple_animal/hostile/constructs/juggernaut.dm +++ b/code/modules/mob/living/simple_animal/hostile/constructs/juggernaut.dm @@ -68,6 +68,10 @@ theme = THEME_HOLY loot = list(/obj/item/ectoplasm/angelic) +/mob/living/simple_animal/hostile/construct/juggernaut/angelic/Initialize(mapload) + . = ..() + ADD_TRAIT(src, TRAIT_ANGELIC, INNATE_TRAIT) + /mob/living/simple_animal/hostile/construct/juggernaut/mystic theme = THEME_WIZARD loot = list(/obj/item/ectoplasm/mystic) diff --git a/code/modules/mob/living/simple_animal/hostile/constructs/wraith.dm b/code/modules/mob/living/simple_animal/hostile/constructs/wraith.dm index d0727aacfa9..83bc262e8bc 100644 --- a/code/modules/mob/living/simple_animal/hostile/constructs/wraith.dm +++ b/code/modules/mob/living/simple_animal/hostile/constructs/wraith.dm @@ -67,6 +67,10 @@ ) loot = list(/obj/item/ectoplasm/angelic) +/mob/living/simple_animal/hostile/construct/wraith/angelic/Initialize(mapload) + . = ..() + ADD_TRAIT(src, TRAIT_ANGELIC, INNATE_TRAIT) + /mob/living/simple_animal/hostile/construct/wraith/mystic theme = THEME_WIZARD construct_spells = list( diff --git a/code/modules/unit_tests/simple_animal_freeze.dm b/code/modules/unit_tests/simple_animal_freeze.dm index 9771862ad6b..437fe2c3ae8 100644 --- a/code/modules/unit_tests/simple_animal_freeze.dm +++ b/code/modules/unit_tests/simple_animal_freeze.dm @@ -68,11 +68,6 @@ /mob/living/simple_animal/hostile/asteroid/polarbear/lesser, /mob/living/simple_animal/hostile/asteroid/wolf, /mob/living/simple_animal/hostile/construct, - /mob/living/simple_animal/hostile/construct/artificer, - /mob/living/simple_animal/hostile/construct/artificer/angelic, - /mob/living/simple_animal/hostile/construct/artificer/hostile, - /mob/living/simple_animal/hostile/construct/artificer/mystic, - /mob/living/simple_animal/hostile/construct/artificer/noncult, /mob/living/simple_animal/hostile/construct/juggernaut, /mob/living/simple_animal/hostile/construct/juggernaut/angelic, /mob/living/simple_animal/hostile/construct/juggernaut/hostile, diff --git a/modular_skyrat/modules/awaymissions_skyrat/mothership_astrum/abductor_ai.dm b/modular_skyrat/modules/awaymissions_skyrat/mothership_astrum/abductor_ai.dm index 83db9694a7d..8d33efb03d5 100644 --- a/modular_skyrat/modules/awaymissions_skyrat/mothership_astrum/abductor_ai.dm +++ b/modular_skyrat/modules/awaymissions_skyrat/mothership_astrum/abductor_ai.dm @@ -3,7 +3,8 @@ */ /datum/ai_controller/basic_controller/abductor blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/abductor() + BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGET_MINIMUM_STAT = HARD_CRIT, ) ai_movement = /datum/ai_movement/basic_avoidance @@ -13,16 +14,12 @@ /datum/ai_planning_subtree/basic_melee_attack_subtree/abductor ) -/datum/targetting_datum/basic/abductor - stat_attack = HARD_CRIT - /datum/ai_planning_subtree/basic_melee_attack_subtree/abductor melee_attack_behavior = /datum/ai_behavior/basic_melee_attack/abductor /datum/ai_behavior/basic_melee_attack/abductor action_cooldown = 1 SECONDS - /** * Ranged */ diff --git a/modular_skyrat/modules/clock_cult/code/mobs/clockwork_marauder.dm b/modular_skyrat/modules/clock_cult/code/mobs/clockwork_marauder.dm index 77d35257bab..26e29f12f5a 100644 --- a/modular_skyrat/modules/clock_cult/code/mobs/clockwork_marauder.dm +++ b/modular_skyrat/modules/clock_cult/code/mobs/clockwork_marauder.dm @@ -43,7 +43,6 @@ GLOBAL_LIST_EMPTY(clockwork_marauders) /// How many hits the shield can take before it breaks. var/shield_health = MARAUDER_SHIELD_MAX - /mob/living/basic/clockwork_marauder/Initialize(mapload) . = ..() if(length(loot)) @@ -79,9 +78,15 @@ GLOBAL_LIST_EMPTY(clockwork_marauders) return ..() +<<<<<<< HEAD /mob/living/basic/clockwork_marauder/bullet_act(obj/projectile/proj) //Block Ranged Attacks +======= +/mob/living/basic/clockwork_marauder/proc/block_bullets(datum/source, obj/projectile/hitting_projectile) + SIGNAL_HANDLER + +>>>>>>> 6e2fcee00 ([MIRROR] Basic Constructs: Artificer [MDB IGNORE] (#24456)) if(shield_health) damage_shield() to_chat(src, span_warning("Your shield blocks the attack.")) @@ -119,7 +124,8 @@ GLOBAL_LIST_EMPTY(clockwork_marauders) /datum/ai_controller/basic_controller/clockwork_marauder blackboard = list( - BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/clockwork_marauder() + BB_TARGETTING_DATUM = new /datum/targetting_datum/basic, + BB_TARGET_MINIMUM_STAT = HARD_CRIT, ) ai_movement = /datum/ai_movement/basic_avoidance @@ -136,11 +142,6 @@ GLOBAL_LIST_EMPTY(clockwork_marauders) /datum/ai_behavior/basic_melee_attack/clockwork_marauder action_cooldown = 1.2 SECONDS - -/datum/targetting_datum/basic/clockwork_marauder - stat_attack = HARD_CRIT - - /obj/item/nullrod/Initialize(mapload) . = ..() AddElement(/datum/element/bane, /mob/living/basic/clockwork_marauder, 1, 15, FALSE) diff --git a/tgstation.dme b/tgstation.dme index bdb23a0f0d3..e3fd15e5a64 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -922,6 +922,7 @@ #include "code\datums\ai\basic_mobs\basic_ai_behaviors\tipped_reaction.dm" #include "code\datums\ai\basic_mobs\basic_ai_behaviors\travel_towards.dm" #include "code\datums\ai\basic_mobs\basic_ai_behaviors\ventcrawling.dm" +#include "code\datums\ai\basic_mobs\basic_ai_behaviors\wounded_targetting.dm" #include "code\datums\ai\basic_mobs\basic_ai_behaviors\write_on_paper.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" @@ -941,6 +942,7 @@ #include "code\datums\ai\basic_mobs\basic_subtrees\simple_attack_target.dm" #include "code\datums\ai\basic_mobs\basic_subtrees\simple_find_nearest_target_to_flee.dm" #include "code\datums\ai\basic_mobs\basic_subtrees\simple_find_target.dm" +#include "code\datums\ai\basic_mobs\basic_subtrees\simple_find_wounded_target.dm" #include "code\datums\ai\basic_mobs\basic_subtrees\sleep_with_no_target.dm" #include "code\datums\ai\basic_mobs\basic_subtrees\speech_subtree.dm" #include "code\datums\ai\basic_mobs\basic_subtrees\stare_at_thing.dm" @@ -4468,6 +4470,8 @@ #include "code\modules\mob\living\basic\clown\clown.dm" #include "code\modules\mob\living\basic\clown\clown_ai.dm" #include "code\modules\mob\living\basic\constructs\_construct.dm" +#include "code\modules\mob\living\basic\constructs\artificer.dm" +#include "code\modules\mob\living\basic\constructs\construct_ai.dm" #include "code\modules\mob\living\basic\constructs\harvester.dm" #include "code\modules\mob\living\basic\farm_animals\deer.dm" #include "code\modules\mob\living\basic\farm_animals\pig.dm" @@ -4854,7 +4858,6 @@ #include "code\modules\mob\living\simple_animal\hostile\vatbeast.dm" #include "code\modules\mob\living\simple_animal\hostile\wizard.dm" #include "code\modules\mob\living\simple_animal\hostile\zombie.dm" -#include "code\modules\mob\living\simple_animal\hostile\constructs\artificer.dm" #include "code\modules\mob\living\simple_animal\hostile\constructs\constructs.dm" #include "code\modules\mob\living\simple_animal\hostile\constructs\juggernaut.dm" #include "code\modules\mob\living\simple_animal\hostile\constructs\wraith.dm" diff --git a/tools/UpdatePaths/Scripts/79015_simple_to_basic_construct_artificer.txt b/tools/UpdatePaths/Scripts/79015_simple_to_basic_construct_artificer.txt new file mode 100644 index 00000000000..554ed3fe1c2 --- /dev/null +++ b/tools/UpdatePaths/Scripts/79015_simple_to_basic_construct_artificer.txt @@ -0,0 +1 @@ +/mob/living/simple_animal/hostile/construct/artificer/@SUBTYPES : /mob/living/basic/construct/artificer/@SUBTYPES{@OLD}