mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-22 12:41:09 +01:00
Netherworld Mobs Refractor (#73086)
## About The Pull Request This PR refactors netherworld mobs into basic mobs as best as possible. Also makes some of them run faster when they are getting damaged or deal more damage. Now the mobs might be able to keep up a little with the players. ## Why It's Good For The Game Makes the mobs have better movement and more dynamic movement. Makes the quality of these mobs better. ## Changelog 🆑 add: Added new damage buffs for netherworld mobs refactor: Refactors netherworld mobs into basic mobs /🆑
This commit is contained in:
@@ -617,7 +617,7 @@
|
||||
/area/ruin/space/has_grav/derelictoutpost)
|
||||
"cC" = (
|
||||
/obj/structure/alien/weeds/creature,
|
||||
/mob/living/simple_animal/hostile/netherworld{
|
||||
/mob/living/basic/creature{
|
||||
desc = "Awh its so sm-OH GOD WHAT THE FUCK.";
|
||||
health = 25;
|
||||
maxHealth = 25;
|
||||
@@ -633,7 +633,7 @@
|
||||
icon_state = "trails_1";
|
||||
name = "dried blood trail"
|
||||
},
|
||||
/mob/living/simple_animal/hostile/netherworld{
|
||||
/mob/living/basic/creature{
|
||||
desc = "Awh its so sm-OH GOD WHAT THE FUCK.";
|
||||
health = 25;
|
||||
maxHealth = 25;
|
||||
@@ -822,7 +822,7 @@
|
||||
/area/ruin/space/has_grav/derelictoutpost)
|
||||
"dl" = (
|
||||
/obj/structure/alien/weeds/creature,
|
||||
/mob/living/simple_animal/hostile/netherworld{
|
||||
/mob/living/basic/creature{
|
||||
name = "Miss Tiggles"
|
||||
},
|
||||
/turf/open/floor/iron,
|
||||
@@ -1476,7 +1476,7 @@
|
||||
/area/ruin/space/has_grav/derelictoutpost)
|
||||
"RH" = (
|
||||
/obj/structure/alien/weeds/creature,
|
||||
/mob/living/simple_animal/hostile/netherworld{
|
||||
/mob/living/basic/creature{
|
||||
desc = "Awh its so sm-OH GOD WHAT THE FUCK.";
|
||||
health = 25;
|
||||
maxHealth = 25;
|
||||
|
||||
@@ -4575,7 +4575,7 @@
|
||||
desc = "It looks like fancy glitter to me.";
|
||||
name = "icy wind"
|
||||
},
|
||||
/mob/living/simple_animal/hostile/netherworld/statue{
|
||||
/mob/living/basic/statue{
|
||||
desc = "Just a snowman. Just a snowman. Oh god, it's just a snowman.";
|
||||
faction = list("statue","mining");
|
||||
health = 5000;
|
||||
|
||||
@@ -2848,7 +2848,7 @@
|
||||
},
|
||||
/area/awaymission/snowdin/cave/cavern)
|
||||
"in" = (
|
||||
/mob/living/simple_animal/hostile/netherworld/blankbody{
|
||||
/mob/living/basic/blankbody{
|
||||
desc = "It's Caleb Reed, but their flesh has an ashy texture, and their face is featureless save an eerie smile.";
|
||||
name = "Caleb Reed"
|
||||
},
|
||||
@@ -3546,7 +3546,7 @@
|
||||
/turf/open/floor/plating,
|
||||
/area/awaymission/snowdin/post/garage)
|
||||
"jO" = (
|
||||
/mob/living/simple_animal/hostile/netherworld/blankbody{
|
||||
/mob/living/basic/blankbody{
|
||||
desc = "It's Jacob Ullman, but their flesh has an ashy texture, and their face is featureless save an eerie smile.";
|
||||
name = "Jacob Ullman"
|
||||
},
|
||||
@@ -6461,7 +6461,7 @@
|
||||
/turf/open/floor/wood,
|
||||
/area/awaymission/snowdin/igloo)
|
||||
"rZ" = (
|
||||
/mob/living/simple_animal/hostile/netherworld/migo,
|
||||
/mob/living/basic/migo,
|
||||
/turf/open/floor/engine/cult,
|
||||
/area/awaymission/snowdin/post/cavern2)
|
||||
"sa" = (
|
||||
@@ -7491,7 +7491,7 @@
|
||||
/obj/effect/turf_decal/tile/neutral{
|
||||
dir = 8
|
||||
},
|
||||
/mob/living/simple_animal/hostile/netherworld/migo,
|
||||
/mob/living/basic/migo,
|
||||
/turf/open/floor/iron,
|
||||
/area/awaymission/snowdin/post/mining_dock)
|
||||
"xB" = (
|
||||
@@ -8649,7 +8649,7 @@
|
||||
/turf/open/misc/asteroid/snow,
|
||||
/area/awaymission/snowdin/cave)
|
||||
"BJ" = (
|
||||
/mob/living/simple_animal/hostile/netherworld/blankbody{
|
||||
/mob/living/basic/blankbody{
|
||||
desc = "It's Caleb Reed, but their flesh has an ashy texture, and their face is featureless save an eerie smile.";
|
||||
name = "Caleb Reed"
|
||||
},
|
||||
@@ -9757,7 +9757,7 @@
|
||||
/turf/open/floor/iron,
|
||||
/area/awaymission/snowdin/post/mining_dock)
|
||||
"Hb" = (
|
||||
/mob/living/simple_animal/hostile/netherworld/migo,
|
||||
/mob/living/basic/migo,
|
||||
/turf/open/floor/iron,
|
||||
/area/awaymission/snowdin/post/mining_dock)
|
||||
"Hc" = (
|
||||
@@ -9956,7 +9956,7 @@
|
||||
/area/awaymission/snowdin/post/mining_main/mechbay)
|
||||
"HQ" = (
|
||||
/obj/effect/turf_decal/stripes/line,
|
||||
/mob/living/simple_animal/hostile/netherworld/migo,
|
||||
/mob/living/basic/migo,
|
||||
/obj/effect/mapping_helpers/broken_floor,
|
||||
/turf/open/floor/plating,
|
||||
/area/awaymission/snowdin/post/mining_main/mechbay)
|
||||
@@ -12839,7 +12839,7 @@
|
||||
/turf/open/misc/asteroid/snow,
|
||||
/area/awaymission/snowdin/cave)
|
||||
"Vd" = (
|
||||
/mob/living/simple_animal/hostile/netherworld/migo,
|
||||
/mob/living/basic/migo,
|
||||
/turf/open/floor/iron/white,
|
||||
/area/awaymission/snowdin/post/mining_main/robotics)
|
||||
"Ve" = (
|
||||
|
||||
@@ -40,8 +40,8 @@
|
||||
/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden{
|
||||
dir = 4
|
||||
},
|
||||
/mob/living/simple_animal/hostile/netherworld/migo{
|
||||
environment_smash = 0
|
||||
/mob/living/basic/migo{
|
||||
obj_damage = 0
|
||||
},
|
||||
/turf/open/floor/plating,
|
||||
/area/shuttle/abandoned/engine)
|
||||
@@ -381,8 +381,8 @@
|
||||
/obj/structure/chair/office/light{
|
||||
dir = 4
|
||||
},
|
||||
/mob/living/simple_animal/hostile/netherworld/blankbody{
|
||||
environment_smash = 0
|
||||
/mob/living/basic/blankbody{
|
||||
obj_damage = 0
|
||||
},
|
||||
/obj/effect/decal/cleanable/blood,
|
||||
/obj/item/paper/crumpled/bloody{
|
||||
@@ -433,8 +433,8 @@
|
||||
/obj/structure/chair{
|
||||
dir = 4
|
||||
},
|
||||
/mob/living/simple_animal/hostile/netherworld/migo{
|
||||
environment_smash = 0
|
||||
/mob/living/basic/migo{
|
||||
obj_damage = 0
|
||||
},
|
||||
/turf/open/floor/bamboo,
|
||||
/area/shuttle/abandoned/bar)
|
||||
@@ -753,8 +753,8 @@
|
||||
dir = 1
|
||||
},
|
||||
/obj/effect/decal/cleanable/dirt,
|
||||
/mob/living/simple_animal/hostile/netherworld{
|
||||
environment_smash = 0
|
||||
/mob/living/basic/creature{
|
||||
obj_damage = 0
|
||||
},
|
||||
/obj/effect/decal/cleanable/greenglow,
|
||||
/turf/open/floor/plating,
|
||||
@@ -1112,8 +1112,8 @@
|
||||
/area/shuttle/abandoned/engine)
|
||||
"Wj" = (
|
||||
/obj/effect/decal/cleanable/dirt,
|
||||
/mob/living/simple_animal/hostile/netherworld{
|
||||
environment_smash = 0
|
||||
/mob/living/basic/creature{
|
||||
obj_damage = 0
|
||||
},
|
||||
/turf/open/floor/plating,
|
||||
/area/shuttle/abandoned/cargo)
|
||||
|
||||
@@ -188,7 +188,7 @@
|
||||
/area/centcom/wizard_station)
|
||||
"tv" = (
|
||||
/obj/effect/decal/cleanable/blood/splatter,
|
||||
/mob/living/simple_animal/hostile/netherworld{
|
||||
/mob/living/basic/creature{
|
||||
name = "Experiment 35b"
|
||||
},
|
||||
/turf/open/floor/grass,
|
||||
|
||||
@@ -41,6 +41,9 @@
|
||||
if(!succeeded)
|
||||
controller.blackboard -= target_key
|
||||
|
||||
/datum/ai_behavior/basic_melee_attack/average_speed
|
||||
action_cooldown = 1 SECONDS
|
||||
|
||||
/datum/ai_behavior/basic_ranged_attack
|
||||
action_cooldown = 0.6 SECONDS
|
||||
behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT | AI_BEHAVIOR_MOVE_AND_PERFORM
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
controller.queue_behavior(melee_attack_behavior, BB_BASIC_MOB_CURRENT_TARGET, BB_TARGETTING_DATUM, BB_BASIC_MOB_CURRENT_TARGET_HIDING_LOCATION)
|
||||
return SUBTREE_RETURN_FINISH_PLANNING //we are going into battle...no distractions.
|
||||
|
||||
/datum/ai_planning_subtree/basic_melee_attack_subtree/average_speed
|
||||
melee_attack_behavior = /datum/ai_behavior/basic_melee_attack/average_speed
|
||||
|
||||
//If you give this to something without the element you are a dumbass.
|
||||
/datum/ai_planning_subtree/basic_ranged_attack_subtree
|
||||
var/datum/ai_behavior/basic_ranged_attack/ranged_attack_behavior = /datum/ai_behavior/basic_ranged_attack
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* Attached to a mob so it can change or do actions based on the fact it got attacked.
|
||||
*/
|
||||
/datum/component/damage_buffs
|
||||
/// Callback to a mob for health changes
|
||||
var/datum/callback/health_callback
|
||||
|
||||
/datum/component/damage_buffs/Initialize(datum/callback/health_callback)
|
||||
if(!ismob(parent))
|
||||
return ELEMENT_INCOMPATIBLE
|
||||
|
||||
src.health_callback = health_callback
|
||||
parent.AddElement(/datum/element/relay_attackers)
|
||||
|
||||
/datum/component/damage_buffs/RegisterWithParent()
|
||||
RegisterSignal(parent, COMSIG_ATOM_WAS_ATTACKED, PROC_REF(on_attacked))
|
||||
|
||||
/datum/component/damage_buffs/UnregisterFromParent()
|
||||
UnregisterSignal(parent, COMSIG_ATOM_WAS_ATTACKED)
|
||||
|
||||
/// Add an attacking atom to a blackboard list of things which attacked us
|
||||
/datum/component/damage_buffs/proc/on_attacked(mob/victim, atom/attacker)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
health_callback?.InvokeAsync(attacker)
|
||||
@@ -237,6 +237,7 @@
|
||||
/mob/living/basic/pet/dog/breaddog,
|
||||
/mob/living/basic/pet/dog/corgi,
|
||||
/mob/living/basic/pet/dog/pug,
|
||||
/mob/living/basic/statue,
|
||||
/mob/living/basic/stickman,
|
||||
/mob/living/basic/stickman/dog,
|
||||
/mob/living/simple_animal/butterfly,
|
||||
@@ -256,7 +257,6 @@
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/lesser,
|
||||
/mob/living/simple_animal/hostile/morph,
|
||||
/mob/living/simple_animal/hostile/mushroom,
|
||||
/mob/living/simple_animal/hostile/netherworld/statue,
|
||||
/mob/living/simple_animal/hostile/retaliate/bat,
|
||||
/mob/living/simple_animal/hostile/retaliate/goat,
|
||||
/mob/living/simple_animal/parrot,
|
||||
|
||||
@@ -351,7 +351,7 @@
|
||||
for(var/direction in GLOB.alldirs)
|
||||
var/turf/stepped_turf = get_step(get_turf(user), direction)
|
||||
do_sparks(3, FALSE, stepped_turf)
|
||||
new /mob/living/simple_animal/hostile/netherworld(stepped_turf)
|
||||
new /mob/living/basic/creature(stepped_turf)
|
||||
if(4)
|
||||
//Destroy Equipment
|
||||
selected_turf.visible_message(span_userdanger("Everything [user] is holding and wearing disappears!"))
|
||||
|
||||
@@ -43,8 +43,8 @@
|
||||
|
||||
/obj/structure/statue/petrified/Destroy()
|
||||
|
||||
if(istype(src.loc, /mob/living/simple_animal/hostile/netherworld/statue))
|
||||
var/mob/living/simple_animal/hostile/netherworld/statue/S = src.loc
|
||||
if(istype(src.loc, /mob/living/basic/statue))
|
||||
var/mob/living/basic/statue/S = src.loc
|
||||
forceMove(S.loc)
|
||||
if(S.mind)
|
||||
if(petrified_mob)
|
||||
|
||||
@@ -92,3 +92,48 @@
|
||||
name = "wumborian fugu den"
|
||||
desc = "A den housing a nest of wumborian fugus, how do they all even fit in there?"
|
||||
mob_types = list(/mob/living/simple_animal/hostile/asteroid/fugu)
|
||||
|
||||
/obj/structure/spawner/nether
|
||||
name = "netherworld link"
|
||||
desc = null //see examine()
|
||||
icon_state = "nether"
|
||||
max_integrity = 50
|
||||
spawn_time = 60 SECONDS
|
||||
max_mobs = 15
|
||||
icon = 'icons/mob/simple/lavaland/nest.dmi'
|
||||
spawn_text = "crawls through"
|
||||
mob_types = list(/mob/living/basic/migo, /mob/living/basic/creature, /mob/living/basic/blankbody)
|
||||
faction = list("nether")
|
||||
|
||||
/obj/structure/spawner/nether/Initialize(mapload)
|
||||
. = ..()
|
||||
START_PROCESSING(SSprocessing, src)
|
||||
|
||||
/obj/structure/spawner/nether/examine(mob/user)
|
||||
. = ..()
|
||||
if(isskeleton(user) || iszombie(user))
|
||||
. += "A direct link to another dimension full of creatures very happy to see you. [span_nicegreen("You can see your house from here!")]"
|
||||
else
|
||||
. += "A direct link to another dimension full of creatures not very happy to see you. [span_warning("Entering the link would be a very bad idea.")]"
|
||||
|
||||
/obj/structure/spawner/nether/attack_hand(mob/user, list/modifiers)
|
||||
. = ..()
|
||||
if(isskeleton(user) || iszombie(user))
|
||||
to_chat(user, span_notice("You don't feel like going home yet..."))
|
||||
else
|
||||
user.visible_message(span_warning("[user] is violently pulled into the link!"), \
|
||||
span_userdanger("Touching the portal, you are quickly pulled through into a world of unimaginable horror!"))
|
||||
contents.Add(user)
|
||||
|
||||
/obj/structure/spawner/nether/process(delta_time)
|
||||
for(var/mob/living/living_mob in contents)
|
||||
if(living_mob)
|
||||
playsound(src, 'sound/magic/demon_consume.ogg', 50, TRUE)
|
||||
living_mob.adjustBruteLoss(60 * delta_time)
|
||||
new /obj/effect/gibspawner/generic(get_turf(living_mob), living_mob)
|
||||
if(living_mob.stat == DEAD)
|
||||
var/mob/living/basic/blankbody/newmob = new(loc)
|
||||
newmob.name = "[living_mob]"
|
||||
newmob.desc = "It's [living_mob], but [living_mob.p_their()] flesh has an ashy texture, and [living_mob.p_their()] face is featureless save an eerie smile."
|
||||
src.visible_message(span_warning("[living_mob] reemerges from the link!"))
|
||||
qdel(living_mob)
|
||||
|
||||
@@ -298,7 +298,7 @@
|
||||
AddElement(/datum/element/eyestab)
|
||||
AddElement(/datum/element/wall_engraver)
|
||||
//deals 200 damage to statues, meaning you can actually kill one in ~250 hits
|
||||
AddElement(/datum/element/bane, target_type = /mob/living/simple_animal/hostile/netherworld/statue, damage_multiplier = 40)
|
||||
AddElement(/datum/element/bane, target_type = /mob/living/basic/statue, damage_multiplier = 40)
|
||||
|
||||
/obj/item/chisel/Destroy()
|
||||
prepared_block = null
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
+84
-156
@@ -1,120 +1,77 @@
|
||||
/mob/living/simple_animal/hostile/netherworld
|
||||
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 = 5
|
||||
melee_damage_lower = 25
|
||||
melee_damage_upper = 50
|
||||
attack_verb_continuous = "slashes"
|
||||
attack_verb_simple = "slash"
|
||||
attack_sound = 'sound/weapons/bladeslice.ogg'
|
||||
attack_vis_effect = ATTACK_EFFECT_SLASH // I always thought they bit. Guess I was wrong.
|
||||
faction = list("nether")
|
||||
speak_emote = list("screams")
|
||||
gold_core_spawnable = HOSTILE_SPAWN
|
||||
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
minbodytemp = 0
|
||||
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
|
||||
var/phaser = TRUE
|
||||
var/is_phased = FALSE
|
||||
|
||||
/mob/living/simple_animal/hostile/netherworld/Initialize(mapload)
|
||||
. = ..()
|
||||
if(phaser)
|
||||
var/datum/action/innate/creature/teleport/teleport = new(src)
|
||||
teleport.Grant(src)
|
||||
add_cell_sample()
|
||||
|
||||
/mob/living/simple_animal/hostile/netherworld/add_cell_sample()
|
||||
AddElement(/datum/element/swabable, CELL_LINE_TABLE_NETHER, CELL_VIRUS_TABLE_GENERIC_MOB, 1, 0)
|
||||
|
||||
/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/simple_animal/hostile/netherworld/N = owner
|
||||
var/obj/effect/dummy/phased_mob/holder = null
|
||||
if(N.stat == DEAD)
|
||||
return
|
||||
var/turf/T = get_turf(N)
|
||||
if (N.can_be_seen(T) || !do_after(N, 60, target = T))
|
||||
to_chat(N, span_warning("You can't phase in or out while being observed and you must stay still!"))
|
||||
return
|
||||
if (get_dist(N, T) != 0 || N.can_be_seen(T))
|
||||
to_chat(N, span_warning("Action cancelled, as you moved while reappearing or someone is now viewing your location."))
|
||||
return
|
||||
if(N.is_phased)
|
||||
holder = N.loc
|
||||
holder.eject_jaunter()
|
||||
holder = null
|
||||
N.is_phased = FALSE
|
||||
playsound(get_turf(N), 'sound/effects/podwoosh.ogg', 50, TRUE, -1)
|
||||
else
|
||||
playsound(get_turf(N), 'sound/effects/podwoosh.ogg', 50, TRUE, -1)
|
||||
holder = new /obj/effect/dummy/phased_mob(T, N)
|
||||
N.is_phased = TRUE
|
||||
|
||||
/mob/living/simple_animal/hostile/netherworld/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/M in viewers(world.view + 1, check) - src)
|
||||
if(M.client && CanAttack(M) && !M.has_unlimited_silicon_privilege)
|
||||
if(!M.is_blind())
|
||||
return M
|
||||
for(var/obj/vehicle/sealed/mecha/M in view(world.view + 1, check)) //assuming if you can see them they can see you
|
||||
for(var/mob/mechamob as anything in M.occupants)
|
||||
if(mechamob.client && !mechamob.is_blind())
|
||||
return mechamob
|
||||
return null
|
||||
|
||||
/mob/living/simple_animal/hostile/netherworld/migo
|
||||
/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."
|
||||
speak_emote = list("screams", "clicks", "chitters", "barks", "moans", "growls", "meows", "reverberates", "roars", "squeaks", "rattles", "exclaims", "yells", "remarks", "mumbles", "jabbers", "stutters", "seethes")
|
||||
health = 80
|
||||
maxHealth = 80
|
||||
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"
|
||||
speed = -0.5
|
||||
var/static/list/migo_sounds
|
||||
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'
|
||||
phaser = FALSE
|
||||
unsuitable_atmos_damage = 0
|
||||
unsuitable_cold_damage = 0
|
||||
unsuitable_heat_damage = 0
|
||||
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
|
||||
|
||||
/mob/living/simple_animal/hostile/netherworld/migo/Initialize(mapload)
|
||||
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/simple_animal/hostile/netherworld/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)
|
||||
/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/simple_animal/hostile/netherworld/migo/Life(delta_time = SSMOBS_DT, times_fired)
|
||||
/mob/living/basic/migo/Life(delta_time = SSMOBS_DT, times_fired)
|
||||
..()
|
||||
if(stat)
|
||||
return
|
||||
@@ -122,64 +79,35 @@
|
||||
var/chosen_sound = pick(migo_sounds)
|
||||
playsound(src, chosen_sound, 50, TRUE)
|
||||
|
||||
/mob/living/simple_animal/hostile/netherworld/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"
|
||||
gold_core_spawnable = NO_SPAWN
|
||||
health = 100
|
||||
maxHealth = 100
|
||||
melee_damage_lower = 5
|
||||
melee_damage_upper = 10
|
||||
attack_verb_continuous = "punches"
|
||||
attack_verb_simple = "punch"
|
||||
death_message = "falls apart into a fine dust."
|
||||
phaser = FALSE
|
||||
|
||||
/obj/structure/spawner/nether
|
||||
name = "netherworld link"
|
||||
desc = null //see examine()
|
||||
icon_state = "nether"
|
||||
max_integrity = 50
|
||||
spawn_time = 60 SECONDS
|
||||
max_mobs = 15
|
||||
icon = 'icons/mob/simple/lavaland/nest.dmi'
|
||||
spawn_text = "crawls through"
|
||||
mob_types = list(/mob/living/simple_animal/hostile/netherworld/migo, /mob/living/simple_animal/hostile/netherworld, /mob/living/simple_animal/hostile/netherworld/blankbody)
|
||||
faction = list("nether")
|
||||
|
||||
/obj/structure/spawner/nether/Initialize(mapload)
|
||||
.=..()
|
||||
START_PROCESSING(SSprocessing, src)
|
||||
|
||||
/obj/structure/spawner/nether/examine(mob/user)
|
||||
. = ..()
|
||||
if(isskeleton(user) || iszombie(user))
|
||||
. += "A direct link to another dimension full of creatures very happy to see you. [span_nicegreen("You can see your house from here!")]"
|
||||
/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
|
||||
. += "A direct link to another dimension full of creatures not very happy to see you. [span_warning("Entering the link would be a very bad idea.")]"
|
||||
return ..()
|
||||
|
||||
/obj/structure/spawner/nether/attack_hand(mob/user, list/modifiers)
|
||||
. = ..()
|
||||
if(isskeleton(user) || iszombie(user))
|
||||
to_chat(user, span_notice("You don't feel like going home yet..."))
|
||||
else
|
||||
user.visible_message(span_warning("[user] is violently pulled into the link!"), \
|
||||
span_userdanger("Touching the portal, you are quickly pulled through into a world of unimaginable horror!"))
|
||||
contents.Add(user)
|
||||
/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)
|
||||
|
||||
/obj/structure/spawner/nether/process(delta_time)
|
||||
for(var/mob/living/M in contents)
|
||||
if(M)
|
||||
playsound(src, 'sound/magic/demon_consume.ogg', 50, TRUE)
|
||||
M.adjustBruteLoss(60 * delta_time)
|
||||
new /obj/effect/gibspawner/generic(get_turf(M), M)
|
||||
if(M.stat == DEAD)
|
||||
var/mob/living/simple_animal/hostile/netherworld/blankbody/blank
|
||||
blank = new(loc)
|
||||
blank.name = "[M]"
|
||||
blank.desc = "It's [M], but [M.p_their()] flesh has an ashy texture, and [M.p_their()] face is featureless save an eerie smile."
|
||||
src.visible_message(span_warning("[M] reemerges from the link!"))
|
||||
qdel(M)
|
||||
/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,
|
||||
)
|
||||
+66
-63
@@ -1,6 +1,6 @@
|
||||
// A mob which only moves when it isn't being watched by living beings.
|
||||
|
||||
/mob/living/simple_animal/hostile/netherworld/statue
|
||||
/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'
|
||||
@@ -20,8 +20,6 @@
|
||||
speed = -1
|
||||
maxHealth = 50000
|
||||
health = 50000
|
||||
healable = 0
|
||||
harm_intent_damage = 10
|
||||
obj_damage = 100
|
||||
melee_damage_lower = 68
|
||||
melee_damage_upper = 83
|
||||
@@ -30,21 +28,18 @@
|
||||
attack_sound = 'sound/hallucinations/growl1.ogg'
|
||||
attack_vis_effect = ATTACK_EFFECT_CLAW
|
||||
|
||||
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
minbodytemp = 0
|
||||
|
||||
faction = list("statue")
|
||||
move_to_delay = 0 // Very fast
|
||||
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
|
||||
vision_range = 12
|
||||
aggro_vision_range = 12
|
||||
|
||||
search_objects = 1 // So that it can see through walls
|
||||
|
||||
sight = SEE_SELF|SEE_MOBS|SEE_OBJS|SEE_TURFS
|
||||
|
||||
@@ -52,15 +47,20 @@
|
||||
move_resist = MOVE_FORCE_EXTREMELY_STRONG
|
||||
pull_force = MOVE_FORCE_EXTREMELY_STRONG
|
||||
|
||||
var/cannot_be_seen = 1
|
||||
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/simple_animal/hostile/netherworld/statue/Initialize(mapload, mob/living/creator)
|
||||
/mob/living/basic/statue/Initialize(mapload, mob/living/creator)
|
||||
. = ..()
|
||||
// Give spells
|
||||
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)
|
||||
@@ -72,80 +72,58 @@
|
||||
if(creator)
|
||||
src.creator = creator
|
||||
|
||||
/mob/living/simple_animal/hostile/netherworld/statue/add_cell_sample()
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/hostile/netherworld/statue/med_hud_set_health()
|
||||
/mob/living/basic/statue/med_hud_set_health()
|
||||
return //we're a statue we're invincible
|
||||
|
||||
/mob/living/simple_animal/hostile/netherworld/statue/med_hud_set_status()
|
||||
/mob/living/basic/statue/med_hud_set_status()
|
||||
return //we're a statue we're invincible
|
||||
|
||||
/mob/living/simple_animal/hostile/netherworld/statue/Move(turf/NewLoc)
|
||||
/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/simple_animal/hostile/netherworld/statue/Life(delta_time = SSMOBS_DT, times_fired)
|
||||
..()
|
||||
if(!client && target) // If we have a target and we're AI controlled
|
||||
var/mob/watching = can_be_seen()
|
||||
// If they're not our target
|
||||
if(watching && watching != target)
|
||||
// This one is closer.
|
||||
if(get_dist(watching, src) > get_dist(target, src))
|
||||
LoseTarget()
|
||||
GiveTarget(watching)
|
||||
|
||||
/mob/living/simple_animal/hostile/netherworld/statue/AttackingTarget()
|
||||
if(can_be_seen(get_turf(loc)))
|
||||
if(client)
|
||||
to_chat(src, span_warning("You cannot attack, there are eyes on you!"))
|
||||
return FALSE
|
||||
else
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/netherworld/statue/DestroyPathToTarget()
|
||||
/mob/living/basic/statue/face_atom()
|
||||
if(!can_be_seen(get_turf(loc)))
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/netherworld/statue/face_atom()
|
||||
if(!can_be_seen(get_turf(loc)))
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/netherworld/statue/can_speak(allow_mimes = FALSE)
|
||||
/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/simple_animal/hostile/netherworld/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)
|
||||
/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/simple_animal/hostile/netherworld/statue/gib()
|
||||
/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
|
||||
|
||||
// Stop attacking clientless mobs
|
||||
// We aren't in darkness, loop for viewers.
|
||||
var/list/check_list = list(src)
|
||||
if(location)
|
||||
check_list += location
|
||||
|
||||
/mob/living/simple_animal/hostile/netherworld/statue/CanAttack(atom/the_target)
|
||||
if(isliving(the_target))
|
||||
var/mob/living/L = the_target
|
||||
if(!L.client && !L.ckey)
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
// Don't attack your creator if there is one
|
||||
|
||||
/mob/living/simple_animal/hostile/netherworld/statue/ListTargets()
|
||||
. = ..()
|
||||
return . - creator
|
||||
|
||||
/mob/living/simple_animal/hostile/netherworld/statue/sentience_act()
|
||||
faction -= FACTION_NEUTRAL
|
||||
// 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
|
||||
|
||||
@@ -196,3 +174,28 @@
|
||||
|
||||
/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
|
||||
@@ -1345,7 +1345,7 @@
|
||||
/mob/living/basic/carp,
|
||||
/mob/living/simple_animal/hostile/bear,
|
||||
/mob/living/simple_animal/hostile/mushroom,
|
||||
/mob/living/simple_animal/hostile/netherworld/statue,
|
||||
/mob/living/basic/statue,
|
||||
/mob/living/simple_animal/hostile/retaliate/bat,
|
||||
/mob/living/simple_animal/hostile/retaliate/goat,
|
||||
/mob/living/simple_animal/hostile/killertomato,
|
||||
|
||||
@@ -198,7 +198,7 @@
|
||||
var/obj/structure/statue/petrified/P = src
|
||||
if(P.petrified_mob)
|
||||
var/mob/living/L = P.petrified_mob
|
||||
var/mob/living/simple_animal/hostile/netherworld/statue/S = new(P.loc, owner)
|
||||
var/mob/living/basic/statue/S = new(P.loc, owner)
|
||||
S.name = "statue of [L.name]"
|
||||
if(owner)
|
||||
S.faction = list("[REF(owner)]")
|
||||
|
||||
@@ -471,10 +471,10 @@
|
||||
/datum/reagent/consumable/liquidgibs = -2)
|
||||
|
||||
virus_suspectibility = 0
|
||||
resulting_atoms = list(/mob/living/simple_animal/hostile/netherworld = 1)
|
||||
resulting_atoms = list()
|
||||
|
||||
/datum/micro_organism/cell_line/netherworld/succeed_growing(obj/machinery/plumbing/growing_vat/vat)
|
||||
var/random_result = pick(typesof(/mob/living/simple_animal/hostile/netherworld) - /mob/living/simple_animal/hostile/netherworld/statue) //i looked myself, pretty much all of them are reasonably strong and somewhat on the same level. except migo is the jackpot and the blank body is whiff.
|
||||
var/random_result = pick(/mob/living/basic/creature, /mob/living/basic/migo, /mob/living/basic/blankbody) //i looked myself, pretty much all of them are reasonably strong and somewhat on the same level. except migo is the jackpot and the blank body is whiff.
|
||||
resulting_atoms = list()
|
||||
resulting_atoms[random_result] = 1
|
||||
return ..()
|
||||
|
||||
@@ -11,5 +11,5 @@
|
||||
spell_requirements = NONE
|
||||
|
||||
summon_radius = 3
|
||||
summon_type = list(/mob/living/simple_animal/hostile/netherworld)
|
||||
summon_type = list(/mob/living/basic/creature)
|
||||
summon_amount = 10
|
||||
|
||||
@@ -244,10 +244,6 @@
|
||||
/mob/living/simple_animal/hostile/nanotrasen/ranged/assault,
|
||||
/mob/living/simple_animal/hostile/nanotrasen/ranged/smg,
|
||||
/mob/living/simple_animal/hostile/nanotrasen/screaming,
|
||||
/mob/living/simple_animal/hostile/netherworld,
|
||||
/mob/living/simple_animal/hostile/netherworld/blankbody,
|
||||
/mob/living/simple_animal/hostile/netherworld/migo,
|
||||
/mob/living/simple_animal/hostile/netherworld/statue,
|
||||
/mob/living/simple_animal/hostile/ooze,
|
||||
/mob/living/simple_animal/hostile/ooze/gelatinous,
|
||||
/mob/living/simple_animal/hostile/ooze/grapes,
|
||||
|
||||
+5
-2
@@ -858,6 +858,7 @@
|
||||
#include "code\datums\components\cult_ritual_item.dm"
|
||||
#include "code\datums\components\curse_of_hunger.dm"
|
||||
#include "code\datums\components\customizable_reagent_holder.dm"
|
||||
#include "code\datums\components\damage_buffs.dm"
|
||||
#include "code\datums\components\deadchat_control.dm"
|
||||
#include "code\datums\components\dejavu.dm"
|
||||
#include "code\datums\components\deployable.dm"
|
||||
@@ -3763,6 +3764,10 @@
|
||||
#include "code\modules\mob\living\basic\space_fauna\carp\magicarp.dm"
|
||||
#include "code\modules\mob\living\basic\space_fauna\carp\megacarp.dm"
|
||||
#include "code\modules\mob\living\basic\space_fauna\faithless\faithless.dm"
|
||||
#include "code\modules\mob\living\basic\space_fauna\netherworld\blankbody.dm"
|
||||
#include "code\modules\mob\living\basic\space_fauna\netherworld\creature.dm"
|
||||
#include "code\modules\mob\living\basic\space_fauna\netherworld\migo.dm"
|
||||
#include "code\modules\mob\living\basic\space_fauna\statue\statue.dm"
|
||||
#include "code\modules\mob\living\basic\syndicate\syndicate.dm"
|
||||
#include "code\modules\mob\living\basic\syndicate\syndicate_ai.dm"
|
||||
#include "code\modules\mob\living\basic\vermin\axolotl.dm"
|
||||
@@ -3988,7 +3993,6 @@
|
||||
#include "code\modules\mob\living\simple_animal\hostile\morph.dm"
|
||||
#include "code\modules\mob\living\simple_animal\hostile\mushroom.dm"
|
||||
#include "code\modules\mob\living\simple_animal\hostile\nanotrasen.dm"
|
||||
#include "code\modules\mob\living\simple_animal\hostile\netherworld.dm"
|
||||
#include "code\modules\mob\living\simple_animal\hostile\ooze.dm"
|
||||
#include "code\modules\mob\living\simple_animal\hostile\pirate.dm"
|
||||
#include "code\modules\mob\living\simple_animal\hostile\regalrat.dm"
|
||||
@@ -3997,7 +4001,6 @@
|
||||
#include "code\modules\mob\living\simple_animal\hostile\slaughter_demon.dm"
|
||||
#include "code\modules\mob\living\simple_animal\hostile\smspider.dm"
|
||||
#include "code\modules\mob\living\simple_animal\hostile\space_dragon.dm"
|
||||
#include "code\modules\mob\living\simple_animal\hostile\statue.dm"
|
||||
#include "code\modules\mob\living\simple_animal\hostile\tree.dm"
|
||||
#include "code\modules\mob\living\simple_animal\hostile\vatbeast.dm"
|
||||
#include "code\modules\mob\living\simple_animal\hostile\venus_human_trap.dm"
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
/mob/living/simple_animal/hostile/netherworld/blankbody : /mob/living/basic/blankbody{@OLD}
|
||||
/mob/living/simple_animal/hostile/netherworld : /mob/living/basic/creature{@OLD}
|
||||
/mob/living/simple_animal/hostile/netherworld/migo : /mob/living/basic/migo{@OLD}
|
||||
/mob/living/simple_animal/hostile/netherworld/statue : /mob/living/basic/statue{@OLD}
|
||||
Reference in New Issue
Block a user