From 2aeeed086fda7d7dbc762064d8f3ba2d8bad605a Mon Sep 17 00:00:00 2001 From: Jacquerel Date: Thu, 23 Jan 2025 03:50:07 +0000 Subject: [PATCH] Basic Dark Wizards (#89147) ## About The Pull Request Simple animal Dark Wizard => Basic mob Dark Wizard. This mob is I think used in literally one ruin, and very occasionally spawned in deathmatch. They don't really do anything except shoot you with slowing projectiles and hit you with sticks. I gave them a version of blink with a longer cooldown that they use when attacked in melee range purely to make them very marginally more wizard-like, and they will also now try to back away from you while shooting you instead of running towards you. They will also retaliate against anyone who attacks them including as a response to friendly fire from other Dark Wizards, because I think it is funny if they have very little loyalty to each other and that's a fun thing to trigger when you are playing Doom. Finally, we have a component called "revenge ability" which is mostly a standin for AI responses to getting attacked. I made all existing uses of it turn off if you're controlled by a sapient player who can hit those buttons themselves, because they can choose when they want to use those abilities themselves. ## Why It's Good For The Game The march of progress is almost complete ## Changelog :cl: refactor: refactored some code balance: Dark Wizards now teleport when attacked, but are more likely to turn on their allies /:cl: --- .../LavaRuins/lavaland_surface_wizard.dmm | 2 +- code/_globalvars/phobias.dm | 2 +- .../basic_subtrees/ranged_skirmish.dm | 3 + code/datums/components/revenge_ability.dm | 7 +- .../modules/deathmatch/deathmatch_modifier.dm | 2 +- .../living/basic/ruin_defender/dark_wizard.dm | 77 +++++++++++++++++++ .../simple_animal/hostile/dark_wizard.dm | 46 ----------- .../spells/spell_types/teleport/blink.dm | 5 ++ .../unit_tests/simple_animal_freeze.dm | 1 - tgstation.dme | 2 +- .../Scripts/89147_simple_to_basic_wizards.txt | 1 + 11 files changed, 96 insertions(+), 52 deletions(-) create mode 100644 code/modules/mob/living/basic/ruin_defender/dark_wizard.dm delete mode 100644 code/modules/mob/living/simple_animal/hostile/dark_wizard.dm create mode 100644 tools/UpdatePaths/Scripts/89147_simple_to_basic_wizards.txt diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_wizard.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_wizard.dmm index 20b3a851265..fb0a070b894 100644 --- a/_maps/RandomRuins/LavaRuins/lavaland_surface_wizard.dmm +++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_wizard.dmm @@ -309,7 +309,7 @@ /turf/open/misc/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) "K" = ( -/mob/living/simple_animal/hostile/dark_wizard, +/mob/living/basic/dark_wizard, /turf/open/misc/asteroid/basalt/lava_land_surface, /area/lavaland/surface/outdoors) diff --git a/code/_globalvars/phobias.dm b/code/_globalvars/phobias.dm index 6c93c07bbb8..560d0c1e67f 100644 --- a/code/_globalvars/phobias.dm +++ b/code/_globalvars/phobias.dm @@ -99,6 +99,7 @@ GLOBAL_LIST_INIT(phobia_mobs, list( /mob/dead/observer, /mob/living/basic/bat, /mob/living/basic/construct, + /mob/living/basic/dark_wizard, /mob/living/basic/demon, /mob/living/basic/faithless, /mob/living/basic/ghost, @@ -109,7 +110,6 @@ GLOBAL_LIST_INIT(phobia_mobs, list( /mob/living/basic/wizard, /mob/living/basic/zombie, /mob/living/simple_animal/bot/mulebot/paranormal, - /mob/living/simple_animal/hostile/dark_wizard, )), )) 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 43a3d400bc5..efe5dc911cd 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/ranged_skirmish.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/ranged_skirmish.dm @@ -45,3 +45,6 @@ controller.ai_interact(target = target, combat_mode = TRUE) return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED + +/datum/ai_planning_subtree/ranged_skirmish/no_minimum + min_range = 0 diff --git a/code/datums/components/revenge_ability.dm b/code/datums/components/revenge_ability.dm index 8d9faec52e0..2c52b8cd31a 100644 --- a/code/datums/components/revenge_ability.dm +++ b/code/datums/components/revenge_ability.dm @@ -15,8 +15,10 @@ var/max_range /// Target the ability at ourself instead of at the offender var/target_self + /// Should this behavoid continue if our mob is sapient? + var/activate_with_mind -/datum/component/revenge_ability/Initialize(datum/action/cooldown/ability, datum/targeting_strategy/targeting, min_range = 0, max_range = INFINITY, target_self = FALSE) +/datum/component/revenge_ability/Initialize(datum/action/cooldown/ability, datum/targeting_strategy/targeting, min_range = 0, max_range = INFINITY, target_self = FALSE, activate_with_mind = FALSE) . = ..() if (!isliving(parent)) return COMPONENT_INCOMPATIBLE @@ -25,6 +27,7 @@ src.min_range = min_range src.max_range = max_range src.target_self = target_self + src.activate_with_mind = activate_with_mind RegisterSignal(ability, COMSIG_QDELETING, PROC_REF(ability_destroyed)) @@ -41,6 +44,8 @@ /// If we were attacked, get revenge /datum/component/revenge_ability/proc/on_attacked(mob/living/victim, atom/attacker) SIGNAL_HANDLER + if (victim.mind && !activate_with_mind) + return // This is mostly a component for the use of AI var/atom/ability_user = ability.owner var/distance = get_dist(ability_user, attacker) if (distance < min_range || distance > max_range) diff --git a/code/modules/deathmatch/deathmatch_modifier.dm b/code/modules/deathmatch/deathmatch_modifier.dm index cec65fa3577..77ef9785aba 100644 --- a/code/modules/deathmatch/deathmatch_modifier.dm +++ b/code/modules/deathmatch/deathmatch_modifier.dm @@ -388,6 +388,7 @@ contents = list( /mob/living/basic/ant = 2, /mob/living/basic/construct/proteon = 2, + /mob/living/basic/dark_wizard = 2, /mob/living/basic/flesh_spider = 2, /mob/living/basic/garden_gnome = 2, /mob/living/basic/killer_tomato = 2, @@ -403,7 +404,6 @@ /mob/living/basic/spider/giant/nurse/scrawny = 2, /mob/living/basic/spider/giant/tarantula/scrawny = 2, /mob/living/basic/spider/giant/hunter/scrawny = 2, - /mob/living/simple_animal/hostile/dark_wizard = 2, /mob/living/simple_animal/hostile/retaliate/goose = 2, /mob/living/simple_animal/hostile/ooze = 1, ) diff --git a/code/modules/mob/living/basic/ruin_defender/dark_wizard.dm b/code/modules/mob/living/basic/ruin_defender/dark_wizard.dm new file mode 100644 index 00000000000..6e88219244a --- /dev/null +++ b/code/modules/mob/living/basic/ruin_defender/dark_wizard.dm @@ -0,0 +1,77 @@ +/// Wizard-looking guy who basically just shoots you +/mob/living/basic/dark_wizard + name = "Dark Wizard" + desc = "Killing amateurs since the dawn of times." + icon = 'icons/mob/simple/simple_human.dmi' + icon_state = "dark_wizard" + icon_living = "dark_wizard" + maxHealth = 50 + health = 50 + melee_damage_lower = 5 + melee_damage_upper = 5 + obj_damage = 20 + basic_mob_flags = DEL_ON_DEATH + attack_verb_continuous = "staves" + attack_verb_simple = "stave" + combat_mode = TRUE + speak_emote = list("chants") + attack_sound = 'sound/items/weapons/bladeslice.ogg' + mob_biotypes = MOB_ORGANIC|MOB_HUMANOID + sentience_type = SENTIENCE_HUMANOID + faction = list(ROLE_WIZARD) + unsuitable_atmos_damage = 0 + unsuitable_cold_damage = 0 + unsuitable_heat_damage = 0 + ai_controller = /datum/ai_controller/basic_controller/dark_wizard + +/mob/living/basic/dark_wizard/Initialize(mapload) + . = ..() + + apply_dynamic_human_appearance(src, mob_spawn_path = /obj/effect/mob_spawn/corpse/human/wizard/dark, r_hand = /obj/item/staff) + add_traits(list(TRAIT_LAVA_IMMUNE, TRAIT_ASHSTORM_IMMUNE, TRAIT_SNOWSTORM_IMMUNE), INNATE_TRAIT) + + var/corpse = string_list(list(/obj/effect/decal/remains/human)) + AddElement(/datum/element/death_drops, corpse) + AddElement(/datum/element/footstep, FOOTSTEP_MOB_SHOE) + AddElement(/datum/element/ai_retaliate) + + AddComponent(\ + /datum/component/ranged_attacks,\ + projectile_type = /obj/projectile/temp/earth_bolt,\ + projectile_sound = 'sound/effects/magic/ethereal_enter.ogg',\ + cooldown_time = 2 SECONDS,\ + ) + + var/datum/action/cooldown/spell/teleport/radius_turf/blink/slow/escape_spell = new(src) + escape_spell.Grant(src) + AddComponent(\ + /datum/component/revenge_ability,\ + escape_spell,\ + max_range = 3,\ + target_self = TRUE,\ + ) + + new /obj/item/clothing/head/wizard/hood(src) // Having this hat in our contents allows us to cast wizard spells + +/datum/ai_controller/basic_controller/dark_wizard + 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/target_retaliate, // If you get them to shoot each other it will start a wiz-war + /datum/ai_planning_subtree/simple_find_target, + /datum/ai_planning_subtree/maintain_distance, + /datum/ai_planning_subtree/ranged_skirmish/no_minimum, + ) + +/// I don't know why an earth bolt freezes you but I guess it does +/obj/projectile/temp/earth_bolt + name = "earth bolt" + icon_state = "declone" + damage = 4 + damage_type = BURN + armor_flag = ENERGY + temperature = -100 diff --git a/code/modules/mob/living/simple_animal/hostile/dark_wizard.dm b/code/modules/mob/living/simple_animal/hostile/dark_wizard.dm deleted file mode 100644 index e2c2aca2693..00000000000 --- a/code/modules/mob/living/simple_animal/hostile/dark_wizard.dm +++ /dev/null @@ -1,46 +0,0 @@ -/mob/living/simple_animal/hostile/dark_wizard - name = "Dark Wizard" - desc = "Killing amateurs since the dawn of times." - icon = 'icons/mob/simple/simple_human.dmi' - icon_state = "dark_wizard" - icon_living = "dark_wizard" - move_to_delay = 10 - projectiletype = /obj/projectile/temp/earth_bolt - projectilesound = 'sound/effects/magic/ethereal_enter.ogg' - ranged = TRUE - ranged_message = "earth bolts" - ranged_cooldown_time = 20 - maxHealth = 50 - health = 50 - harm_intent_damage = 5 - obj_damage = 20 - melee_damage_lower = 5 - melee_damage_upper = 5 - attack_verb_continuous = "staves" - combat_mode = TRUE - speak_emote = list("chants") - attack_sound = 'sound/items/weapons/bladeslice.ogg' - aggro_vision_range = 9 - turns_per_move = 5 - mob_biotypes = MOB_ORGANIC|MOB_HUMANOID - sentience_type = SENTIENCE_HUMANOID - faction = list(ROLE_WIZARD) - footstep_type = FOOTSTEP_MOB_SHOE - weather_immunities = list(TRAIT_LAVA_IMMUNE, TRAIT_ASHSTORM_IMMUNE) - minbodytemp = 0 - maxbodytemp = INFINITY - atmos_requirements = null - loot = list(/obj/effect/decal/remains/human) - del_on_death = TRUE - -/mob/living/simple_animal/hostile/dark_wizard/Initialize(mapload) - . = ..() - apply_dynamic_human_appearance(src, mob_spawn_path = /obj/effect/mob_spawn/corpse/human/wizard/dark, r_hand = /obj/item/staff) - -/obj/projectile/temp/earth_bolt - name = "earth bolt" - icon_state = "declone" - damage = 4 - damage_type = BURN - armor_flag = ENERGY - temperature = -100 // closer to the old temp loss diff --git a/code/modules/spells/spell_types/teleport/blink.dm b/code/modules/spells/spell_types/teleport/blink.dm index 18531949a53..7c365b2e723 100644 --- a/code/modules/spells/spell_types/teleport/blink.dm +++ b/code/modules/spells/spell_types/teleport/blink.dm @@ -17,3 +17,8 @@ outer_tele_radius = 6 post_teleport_sound = 'sound/effects/magic/blink.ogg' + +/datum/action/cooldown/spell/teleport/radius_turf/blink/slow + name = "Minor Blink" + desc = "This spell randomly teleports you a short distance, you're still practising doing it quickly." + cooldown_time = 8 SECONDS diff --git a/code/modules/unit_tests/simple_animal_freeze.dm b/code/modules/unit_tests/simple_animal_freeze.dm index 272748c0245..39e239a37ed 100644 --- a/code/modules/unit_tests/simple_animal_freeze.dm +++ b/code/modules/unit_tests/simple_animal_freeze.dm @@ -31,7 +31,6 @@ /mob/living/simple_animal/hostile/asteroid/elite/pandora, /mob/living/simple_animal/hostile/asteroid/polarbear, /mob/living/simple_animal/hostile/asteroid/polarbear/lesser, - /mob/living/simple_animal/hostile/dark_wizard, /mob/living/simple_animal/hostile/illusion, /mob/living/simple_animal/hostile/illusion/escape, /mob/living/simple_animal/hostile/illusion/mirage, diff --git a/tgstation.dme b/tgstation.dme index d533c8ffe52..1fb53dae109 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -5068,6 +5068,7 @@ #include "code\modules\mob\living\basic\pets\pet_cult\pet_cult_abilities.dm" #include "code\modules\mob\living\basic\pets\pet_cult\pet_cult_ai.dm" #include "code\modules\mob\living\basic\ruin_defender\cybersun_aicore.dm" +#include "code\modules\mob\living\basic\ruin_defender\dark_wizard.dm" #include "code\modules\mob\living\basic\ruin_defender\flesh.dm" #include "code\modules\mob\living\basic\ruin_defender\living_floor.dm" #include "code\modules\mob\living\basic\ruin_defender\mad_piano.dm" @@ -5349,7 +5350,6 @@ #include "code\modules\mob\living\simple_animal\bot\mulebot.dm" #include "code\modules\mob\living\simple_animal\bot\secbot.dm" #include "code\modules\mob\living\simple_animal\bot\SuperBeepsky.dm" -#include "code\modules\mob\living\simple_animal\hostile\dark_wizard.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\ooze.dm" diff --git a/tools/UpdatePaths/Scripts/89147_simple_to_basic_wizards.txt b/tools/UpdatePaths/Scripts/89147_simple_to_basic_wizards.txt new file mode 100644 index 00000000000..3d76a8db7c1 --- /dev/null +++ b/tools/UpdatePaths/Scripts/89147_simple_to_basic_wizards.txt @@ -0,0 +1 @@ +/mob/living/simple_animal/hostile/dark_wizard : /mob/living/basic/dark_wizard{@OLD}