mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-12 08:36:00 +01:00
[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:
@@ -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
|
||||
Reference in New Issue
Block a user