[MIRROR] Netherworld Mobs Refractor [MDB IGNORE] (#19181)

* Netherworld Mobs Refractor

* Update statues.dm

* Update tgstation.dme

* w

---------

Co-authored-by: Comxy <tijntensen@gmail.com>
Co-authored-by: Gandalf <9026500+Gandalf2k15@users.noreply.github.com>
This commit is contained in:
SkyratBot
2023-03-10 03:44:53 +01:00
committed by GitHub
parent e07ce00128
commit 88f8ef7adc
26 changed files with 618 additions and 390 deletions
@@ -0,0 +1,78 @@
/mob/living/basic/blankbody
name = "blank body"
desc = "This looks human enough, but its flesh has an ashy texture, and it's face is featureless save an eerie smile."
icon_state = "blank-body"
icon_living = "blank-body"
icon_dead = "blank-dead"
health = 100
maxHealth = 100
obj_damage = 50
melee_damage_lower = 2
melee_damage_upper = 6
speed = 1
attack_verb_continuous = "punches"
attack_verb_simple = "punch"
attack_sound = 'sound/weapons/bladeslice.ogg'
attack_vis_effect = ATTACK_EFFECT_SLASH
faction = list("nether")
speak_emote = list("screams")
death_message = "falls apart into a fine dust."
unsuitable_atmos_damage = 0
unsuitable_cold_damage = 0
unsuitable_heat_damage = 0
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
ai_controller = /datum/ai_controller/basic_controller/blankbody
/// Used for mobs that get spawned in a spawner appearently.
var/datum/component/spawner/nest
/mob/living/basic/blankbody/Initialize(mapload)
. = ..()
var/datum/callback/health_changes_callback = CALLBACK(src, PROC_REF(health_check))
AddElement(/datum/element/swabable, CELL_LINE_TABLE_NETHER, CELL_VIRUS_TABLE_GENERIC_MOB, 1, 0)
AddComponent(/datum/component/damage_buffs, health_changes_callback)
/mob/living/basic/blankbody/proc/health_check(mob/living/attacker)
if(health < maxHealth * 0.25)
health_low_behaviour()
else if (health < maxHealth * 0.5)
health_medium_behaviour()
else if (health < maxHealth * 0.75)
health_high_behaviour()
else
health_full_behaviour()
/mob/living/basic/blankbody/proc/health_full_behaviour()
melee_damage_lower = 2
melee_damage_upper = 6
/mob/living/basic/blankbody/proc/health_high_behaviour()
melee_damage_lower = 4
melee_damage_upper = 8
/mob/living/basic/blankbody/proc/health_medium_behaviour()
melee_damage_lower = 8
melee_damage_upper = 12
/mob/living/basic/blankbody/proc/health_low_behaviour()
melee_damage_lower = 10
melee_damage_upper = 20
/mob/living/basic/blankbody/Destroy()
if(nest)
nest.spawned_mobs -= src
nest = null
return ..()
/datum/ai_controller/basic_controller/blankbody
blackboard = list(
BB_TARGETTING_DATUM = new /datum/targetting_datum/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/attack_obstacle_in_path,
/datum/ai_planning_subtree/basic_melee_attack_subtree/average_speed,
)
@@ -0,0 +1,140 @@
/mob/living/basic/creature
name = "creature"
desc = "A sanity-destroying otherthing from the netherworld."
icon_state = "otherthing"
icon_living = "otherthing"
icon_dead = "otherthing-dead"
health = 50
maxHealth = 50
obj_damage = 50
melee_damage_lower = 20
melee_damage_upper = 30
speed = 2
attack_verb_continuous = "slashes"
attack_verb_simple = "slash"
gold_core_spawnable = HOSTILE_SPAWN
attack_sound = 'sound/weapons/bite.ogg'
attack_vis_effect = ATTACK_EFFECT_BITE
faction = list("nether")
speak_emote = list("screams")
death_message = "gets his head split open."
unsuitable_atmos_damage = 0
unsuitable_cold_damage = 0
unsuitable_heat_damage = 0
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
ai_controller = /datum/ai_controller/basic_controller/creature
/// Used for checking if the mob is phased or not.
var/is_phased = FALSE
/// Used for mobs that get spawned in a spawner appearently.
var/datum/component/spawner/nest
/mob/living/basic/creature/Initialize(mapload)
. = ..()
var/datum/callback/health_changes_callback = CALLBACK(src, PROC_REF(health_check))
AddElement(/datum/element/swabable, CELL_LINE_TABLE_NETHER, CELL_VIRUS_TABLE_GENERIC_MOB, 1, 0)
AddComponent(/datum/component/damage_buffs, health_changes_callback)
var/datum/action/innate/creature/teleport/teleport = new(src)
teleport.Grant(src)
/mob/living/basic/creature/proc/health_check(mob/living/attacker)
if(health < maxHealth * 0.25)
health_low_behaviour()
else if (health < maxHealth * 0.5)
health_medium_behaviour()
else if (health < maxHealth * 0.75)
health_high_behaviour()
else
health_full_behaviour()
/mob/living/basic/creature/proc/health_full_behaviour()
melee_damage_lower = 20
melee_damage_upper = 30
set_varspeed(2)
/mob/living/basic/creature/proc/health_high_behaviour()
melee_damage_lower = 25
melee_damage_upper = 40
set_varspeed(1.5)
/mob/living/basic/creature/proc/health_medium_behaviour()
melee_damage_lower = 30
melee_damage_upper = 50
set_varspeed(1)
/mob/living/basic/creature/proc/health_low_behaviour()
melee_damage_lower = 35
melee_damage_upper = 60
set_varspeed(0.5)
/mob/living/basic/creature/proc/can_be_seen(turf/location)
// Check for darkness
if(location?.lighting_object)
if(location.get_lumcount() < 0.1) // No one can see us in the darkness, right?
return null
// We aren't in darkness, loop for viewers.
var/list/check_list = list(src)
if(location)
check_list += location
// This loop will, at most, loop twice.
for(var/atom/check in check_list)
for(var/mob/living/mob_target in oview(src, 7)) // They probably cannot see us if we cannot see them... can they?
if(mob_target.client && !mob_target.is_blind() && !mob_target.has_unlimited_silicon_privilege)
return mob_target
for(var/obj/vehicle/sealed/mecha/mecha_mob_target in oview(src, 7))
for(var/mob/mechamob_target as anything in mecha_mob_target.occupants)
if(mechamob_target.client && !mechamob_target.is_blind())
return mechamob_target
return null
/datum/action/innate/creature
background_icon_state = "bg_default"
overlay_icon_state = "bg_default_border"
/datum/action/innate/creature/teleport
name = "Teleport"
desc = "Teleport to wherever you want, as long as you aren't seen."
/datum/action/innate/creature/teleport/Activate()
var/mob/living/basic/creature/owner_mob = owner
var/obj/effect/dummy/phased_mob/holder = null
if(owner_mob.stat == DEAD)
return
var/turf/owner_turf = get_turf(owner_mob)
if (owner_mob.can_be_seen(owner_turf) || !do_after(owner_mob, 60, target = owner_turf))
to_chat(owner_mob, span_warning("You can't phase in or out while being observed and you must stay still!"))
return
if (get_dist(owner_mob, owner_turf) != 0 || owner_mob.can_be_seen(owner_turf))
to_chat(owner_mob, span_warning("Action cancelled, as you moved while reappearing or someone is now viewing your location."))
return
if(owner_mob.is_phased)
holder = owner_mob.loc
holder.eject_jaunter()
holder = null
owner_mob.is_phased = FALSE
playsound(get_turf(owner_mob), 'sound/effects/podwoosh.ogg', 50, TRUE, -1)
else
playsound(get_turf(owner_mob), 'sound/effects/podwoosh.ogg', 50, TRUE, -1)
holder = new /obj/effect/dummy/phased_mob(owner_turf, owner_mob)
owner_mob.is_phased = TRUE
/mob/living/basic/creature/Destroy()
if(nest)
nest.spawned_mobs -= src
nest = null
return ..()
/datum/ai_controller/basic_controller/creature
blackboard = list(
BB_TARGETTING_DATUM = new /datum/targetting_datum/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/attack_obstacle_in_path,
/datum/ai_planning_subtree/basic_melee_attack_subtree/average_speed,
)
@@ -0,0 +1,113 @@
/mob/living/basic/migo
name = "mi-go"
desc = "A pinkish, fungoid crustacean-like creature with numerous pairs of clawed appendages and a head covered with waving antennae."
icon_state = "mi-go"
icon_living = "mi-go"
icon_dead = "mi-go-dead"
health = 80
maxHealth = 80
obj_damage = 50
melee_damage_lower = 25
melee_damage_upper = 50
speed = 1
attack_verb_continuous = "lacerates"
attack_verb_simple = "lacerate"
gold_core_spawnable = HOSTILE_SPAWN
attack_sound = 'sound/weapons/bladeslice.ogg'
attack_vis_effect = ATTACK_EFFECT_SLASH
faction = list("nether")
speak_emote = list("screams", "clicks", "chitters", "barks", "moans", "growls", "meows", "reverberates", "roars", "squeaks", "rattles", "exclaims", "yells", "remarks", "mumbles", "jabbers", "stutters", "seethes")
death_message = "wails as its form turns into a pulpy mush."
death_sound = 'sound/voice/hiss6.ogg'
unsuitable_atmos_damage = 0
unsuitable_cold_damage = 0
unsuitable_heat_damage = 0
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
ai_controller = /datum/ai_controller/basic_controller/migo
var/static/list/migo_sounds
/// Odds migo will dodge
var/dodge_prob = 10
/// Used for mobs that get spawned in a spawner appearently.
var/datum/component/spawner/nest
/mob/living/basic/migo/Initialize(mapload)
. = ..()
migo_sounds = list('sound/items/bubblewrap.ogg', 'sound/items/change_jaws.ogg', 'sound/items/crowbar.ogg', 'sound/items/drink.ogg', 'sound/items/deconstruct.ogg', 'sound/items/carhorn.ogg', 'sound/items/change_drill.ogg', 'sound/items/dodgeball.ogg', 'sound/items/eatfood.ogg', 'sound/items/megaphone.ogg', 'sound/items/screwdriver.ogg', 'sound/items/weeoo1.ogg', 'sound/items/wirecutter.ogg', 'sound/items/welder.ogg', 'sound/items/zip.ogg', 'sound/items/rped.ogg', 'sound/items/ratchet.ogg', 'sound/items/polaroid1.ogg', 'sound/items/pshoom.ogg', 'sound/items/airhorn.ogg', 'sound/items/geiger/high1.ogg', 'sound/items/geiger/high2.ogg', 'sound/voice/beepsky/creep.ogg', 'sound/voice/beepsky/iamthelaw.ogg', 'sound/voice/ed209_20sec.ogg', 'sound/voice/hiss3.ogg', 'sound/voice/hiss6.ogg', 'sound/voice/medbot/patchedup.ogg', 'sound/voice/medbot/feelbetter.ogg', 'sound/voice/human/manlaugh1.ogg', 'sound/voice/human/womanlaugh.ogg', 'sound/weapons/sear.ogg', 'sound/ambience/antag/clockcultalr.ogg', 'sound/ambience/antag/ling_alert.ogg', 'sound/ambience/antag/tatoralert.ogg', 'sound/ambience/antag/monkey.ogg', 'sound/mecha/nominal.ogg', 'sound/mecha/weapdestr.ogg', 'sound/mecha/critdestr.ogg', 'sound/mecha/imag_enh.ogg', 'sound/effects/adminhelp.ogg', 'sound/effects/alert.ogg', 'sound/effects/attackblob.ogg', 'sound/effects/bamf.ogg', 'sound/effects/blobattack.ogg', 'sound/effects/break_stone.ogg', 'sound/effects/bubbles.ogg', 'sound/effects/bubbles2.ogg', 'sound/effects/clang.ogg', 'sound/effects/clockcult_gateway_disrupted.ogg', 'sound/effects/clownstep2.ogg', 'sound/effects/curse1.ogg', 'sound/effects/dimensional_rend.ogg', 'sound/effects/doorcreaky.ogg', 'sound/effects/empulse.ogg', 'sound/effects/explosion_distant.ogg', 'sound/effects/explosionfar.ogg', 'sound/effects/explosion1.ogg', 'sound/effects/grillehit.ogg', 'sound/effects/genetics.ogg', 'sound/effects/heart_beat.ogg', 'sound/runtime/hyperspace/hyperspace_begin.ogg', 'sound/runtime/hyperspace/hyperspace_end.ogg', 'sound/effects/his_grace_awaken.ogg', 'sound/effects/pai_boot.ogg', 'sound/effects/phasein.ogg', 'sound/effects/picaxe1.ogg', 'sound/effects/ratvar_reveal.ogg', 'sound/effects/sparks1.ogg', 'sound/effects/smoke.ogg', 'sound/effects/splat.ogg', 'sound/effects/snap.ogg', 'sound/effects/tendril_destroyed.ogg', 'sound/effects/supermatter.ogg', 'sound/misc/desecration-01.ogg', 'sound/misc/desecration-02.ogg', 'sound/misc/desecration-03.ogg', 'sound/misc/bloblarm.ogg', 'sound/misc/airraid.ogg', 'sound/misc/bang.ogg','sound/misc/highlander.ogg', 'sound/misc/interference.ogg', 'sound/misc/notice1.ogg', 'sound/misc/notice2.ogg', 'sound/misc/sadtrombone.ogg', 'sound/misc/slip.ogg', 'sound/misc/splort.ogg', 'sound/weapons/armbomb.ogg', 'sound/weapons/beam_sniper.ogg', 'sound/weapons/chainsawhit.ogg', 'sound/weapons/emitter.ogg', 'sound/weapons/emitter2.ogg', 'sound/weapons/blade1.ogg', 'sound/weapons/bladeslice.ogg', 'sound/weapons/blastcannon.ogg', 'sound/weapons/blaster.ogg', 'sound/weapons/bulletflyby3.ogg', 'sound/weapons/circsawhit.ogg', 'sound/weapons/cqchit2.ogg', 'sound/weapons/drill.ogg', 'sound/weapons/genhit1.ogg', 'sound/weapons/gun/pistol/shot_suppressed.ogg', 'sound/weapons/gun/pistol/shot.ogg', 'sound/weapons/handcuffs.ogg', 'sound/weapons/homerun.ogg', 'sound/weapons/kenetic_accel.ogg', 'sound/machines/clockcult/steam_whoosh.ogg', 'sound/machines/fryer/deep_fryer_emerge.ogg', 'sound/machines/airlock.ogg', 'sound/machines/airlock_alien_prying.ogg', 'sound/machines/airlockclose.ogg', 'sound/machines/airlockforced.ogg', 'sound/machines/airlockopen.ogg', 'sound/machines/alarm.ogg', 'sound/machines/blender.ogg', 'sound/machines/boltsdown.ogg', 'sound/machines/boltsup.ogg', 'sound/machines/buzz-sigh.ogg', 'sound/machines/buzz-two.ogg', 'sound/machines/chime.ogg', 'sound/machines/cryo_warning.ogg', 'sound/machines/defib_charge.ogg', 'sound/machines/defib_failed.ogg', 'sound/machines/defib_ready.ogg', 'sound/machines/defib_zap.ogg', 'sound/machines/deniedbeep.ogg', 'sound/machines/ding.ogg', 'sound/machines/disposalflush.ogg', 'sound/machines/door_close.ogg', 'sound/machines/door_open.ogg', 'sound/machines/engine_alert1.ogg', 'sound/machines/engine_alert2.ogg', 'sound/machines/hiss.ogg', 'sound/machines/honkbot_evil_laugh.ogg', 'sound/machines/juicer.ogg', 'sound/machines/ping.ogg', 'sound/ambience/signal.ogg', 'sound/machines/synth_no.ogg', 'sound/machines/synth_yes.ogg', 'sound/machines/terminal_alert.ogg', 'sound/machines/triple_beep.ogg', 'sound/machines/twobeep.ogg', 'sound/machines/ventcrawl.ogg', 'sound/machines/warning-buzzer.ogg', 'sound/ai/default/outbreak5.ogg', 'sound/ai/default/outbreak7.ogg', 'sound/ai/default/poweroff.ogg', 'sound/ai/default/radiation.ogg', 'sound/ai/default/shuttlecalled.ogg', 'sound/ai/default/shuttledock.ogg', 'sound/ai/default/shuttlerecalled.ogg', 'sound/ai/default/aimalf.ogg') //hahahaha fuck you code divers
var/datum/callback/health_changes_callback = CALLBACK(src, PROC_REF(health_check))
AddElement(/datum/element/swabable, CELL_LINE_TABLE_NETHER, CELL_VIRUS_TABLE_GENERIC_MOB, 1, 0)
AddComponent(/datum/component/damage_buffs, health_changes_callback)
/mob/living/basic/migo/proc/health_check(mob/living/attacker)
if(health < maxHealth * 0.25)
health_low_behaviour()
else if (health < maxHealth * 0.5)
health_medium_behaviour()
else if (health < maxHealth * 0.75)
health_high_behaviour()
else
health_full_behaviour()
/mob/living/basic/migo/proc/health_full_behaviour()
set_varspeed(1)
dodge_prob = 10
/mob/living/basic/migo/proc/health_high_behaviour()
set_varspeed(0.5)
dodge_prob = 20
/mob/living/basic/migo/proc/health_medium_behaviour()
set_varspeed(0)
dodge_prob = 30
/mob/living/basic/migo/proc/health_low_behaviour()
set_varspeed(-0.5)
dodge_prob = 50
/mob/living/basic/migo/say(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null, filterproof = null, message_range = 7, datum/saymode/saymode = null)
..()
if(stat)
return
var/chosen_sound = pick(migo_sounds)
playsound(src, chosen_sound, 50, TRUE)
/mob/living/basic/migo/Life(delta_time = SSMOBS_DT, times_fired)
..()
if(stat)
return
if(DT_PROB(5, delta_time))
var/chosen_sound = pick(migo_sounds)
playsound(src, chosen_sound, 50, TRUE)
/mob/living/basic/migo/Move(atom/newloc, dir, step_x, step_y)
if(!ckey && prob(dodge_prob) && moving_diagonally == 0 && isturf(loc) && isturf(newloc))
return dodge(newloc, dir)
else
return ..()
/mob/living/basic/migo/proc/dodge(moving_to, move_direction)
//Assuming we move towards the target we want to swerve toward them to get closer
var/cdir = turn(move_direction, 45)
var/ccdir = turn(move_direction, -45)
. = Move(get_step(loc,pick(cdir, ccdir)))
if(!.)//Can't dodge there so we just carry on
. = Move(moving_to, move_direction)
/mob/living/basic/migo/Destroy()
if(nest)
nest.spawned_mobs -= src
nest = null
return ..()
/datum/ai_controller/basic_controller/migo
blackboard = list(
BB_TARGETTING_DATUM = new /datum/targetting_datum/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/attack_obstacle_in_path,
/datum/ai_planning_subtree/basic_melee_attack_subtree/average_speed,
)
@@ -0,0 +1,201 @@
// A mob which only moves when it isn't being watched by living beings.
/mob/living/basic/statue
name = "statue" // matches the name of the statue with the flesh-to-stone spell
desc = "An incredibly lifelike marble carving. Its eyes seem to follow you..." // same as an ordinary statue with the added "eye following you" description
icon = 'icons/obj/art/statue.dmi'
icon_state = "human_male"
icon_living = "human_male"
icon_dead = "human_male"
gender = NEUTER
combat_mode = TRUE
mob_biotypes = MOB_HUMANOID
gold_core_spawnable = NO_SPAWN
response_help_continuous = "touches"
response_help_simple = "touch"
response_disarm_continuous = "pushes"
response_disarm_simple = "push"
speed = -1
maxHealth = 50000
health = 50000
obj_damage = 100
melee_damage_lower = 68
melee_damage_upper = 83
attack_verb_continuous = "claws"
attack_verb_simple = "claw"
attack_sound = 'sound/hallucinations/growl1.ogg'
attack_vis_effect = ATTACK_EFFECT_CLAW
faction = list("statue")
speak_emote = list("screams")
death_message = "falls apart into a fine dust."
unsuitable_atmos_damage = 0
unsuitable_cold_damage = 0
unsuitable_heat_damage = 0
animate_movement = NO_STEPS // Do not animate movement, you jump around as you're a scary statue.
hud_possible = list(ANTAG_HUD)
see_in_dark = 13
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE
sight = SEE_SELF|SEE_MOBS|SEE_OBJS|SEE_TURFS
move_force = MOVE_FORCE_EXTREMELY_STRONG
move_resist = MOVE_FORCE_EXTREMELY_STRONG
pull_force = MOVE_FORCE_EXTREMELY_STRONG
ai_controller = /datum/ai_controller/basic_controller/statue
/// Loot this mob drops on death.
var/loot
/// Stores the creator in here if it has one.
var/mob/living/creator = null
// No movement while seen code.
/mob/living/basic/statue/Initialize(mapload, mob/living/creator)
. = ..()
if(LAZYLEN(loot))
AddElement(/datum/element/death_drops, loot)
// Give spells
var/datum/action/cooldown/spell/aoe/flicker_lights/flicker = new(src)
flicker.Grant(src)
var/datum/action/cooldown/spell/aoe/blindness/blind = new(src)
blind.Grant(src)
var/datum/action/cooldown/spell/night_vision/night_vision = new(src)
night_vision.Grant(src)
// Set creator
if(creator)
src.creator = creator
/mob/living/basic/statue/med_hud_set_health()
return //we're a statue we're invincible
/mob/living/basic/statue/med_hud_set_status()
return //we're a statue we're invincible
/mob/living/basic/statue/Move(turf/NewLoc)
if(can_be_seen(NewLoc))
if(client)
to_chat(src, span_warning("You cannot move, there are eyes on you!"))
return
return ..()
/mob/living/basic/statue/face_atom()
if(!can_be_seen(get_turf(loc)))
..()
/mob/living/basic/statue/can_speak(allow_mimes = FALSE)
return FALSE // We're a statue, of course we can't talk.
// Cannot talk
/mob/living/basic/statue/say(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null, filterproof = null, message_range = 7, datum/saymode/saymode = null)
return
// Turn to dust when gibbed
/mob/living/basic/statue/gib()
dust()
/mob/living/basic/statue/proc/can_be_seen(turf/location)
// Check for darkness
if(location?.lighting_object)
if(location.get_lumcount() < 0.1) // No one can see us in the darkness, right?
return null
// We aren't in darkness, loop for viewers.
var/list/check_list = list(src)
if(location)
check_list += location
// This loop will, at most, loop twice.
for(var/atom/check in check_list)
for(var/mob/living/mob_target in oview(src, 7)) // They probably cannot see us if we cannot see them... can they?
if(mob_target.client && !mob_target.is_blind() && !mob_target.has_unlimited_silicon_privilege)
if(!istype(mob_target, /mob/living/basic/statue))
return mob_target
for(var/obj/vehicle/sealed/mecha/mecha_mob_target in oview(src, 7))
for(var/mob/mechamob_target as anything in mecha_mob_target.occupants)
if(mechamob_target.client && !mechamob_target.is_blind())
return mechamob_target
return null
// Statue powers
// Flicker lights
/datum/action/cooldown/spell/aoe/flicker_lights
name = "Flicker Lights"
desc = "You will trigger a large amount of lights around you to flicker."
cooldown_time = 30 SECONDS
spell_requirements = NONE
aoe_radius = 14
/datum/action/cooldown/spell/aoe/flicker_lights/get_things_to_cast_on(atom/center)
var/list/things = list()
for(var/obj/machinery/light/nearby_light in range(aoe_radius, center))
if(!nearby_light.on)
continue
things += nearby_light
return things
/datum/action/cooldown/spell/aoe/flicker_lights/cast_on_thing_in_aoe(obj/machinery/light/victim, atom/caster)
victim.flicker()
//Blind AOE
/datum/action/cooldown/spell/aoe/blindness
name = "Blindness"
desc = "Your prey will be momentarily blind for you to advance on them."
cooldown_time = 1 MINUTES
spell_requirements = NONE
aoe_radius = 14
/datum/action/cooldown/spell/aoe/blindness/cast(atom/cast_on)
cast_on.visible_message(span_danger("[cast_on] glares their eyes."))
return ..()
/datum/action/cooldown/spell/aoe/blindness/get_things_to_cast_on(atom/center)
var/list/things = list()
for(var/mob/living/nearby_mob in range(aoe_radius, center))
if(nearby_mob == owner || nearby_mob == center)
continue
things += nearby_mob
return things
/datum/action/cooldown/spell/aoe/blindness/cast_on_thing_in_aoe(mob/living/victim, atom/caster)
victim.adjust_temp_blindness(8 SECONDS)
/datum/ai_controller/basic_controller/statue
blackboard = list(
BB_TARGETTING_DATUM = new /datum/targetting_datum/basic(),
BB_LOW_PRIORITY_HUNTING_TARGET = null, // lights
)
ai_movement = /datum/ai_movement/basic_avoidance
planning_subtrees = list(
/datum/ai_planning_subtree/simple_find_target,
/datum/ai_planning_subtree/basic_melee_attack_subtree/statue,
/datum/ai_planning_subtree/find_and_hunt_target/look_for_light_fixtures,
)
/datum/ai_planning_subtree/basic_melee_attack_subtree/statue
melee_attack_behavior = /datum/ai_behavior/basic_melee_attack/statue
/datum/ai_behavior/basic_melee_attack/statue
action_cooldown = 1 SECONDS
/datum/ai_behavior/basic_melee_attack/statue/setup(datum/ai_controller/controller, target_key, targetting_datum_key, hiding_location_key)
. = ..()
var/mob/living/basic/statue/statue_mob = controller.pawn
if(statue_mob.can_be_seen(get_turf(statue_mob)))
return FALSE