Adds a new mecha-fauna to lavaland. Ready to TM (#17999)
* pain * more progress * progress continues * more progress™️ * saving progress while I swap brances * leg moving working for real, woo * more saving as power goes out * eeven more * fix transfer * More changes, closer to pr ready * final stuff for night backup * almost done™️ * almost done * Final changes to get ready for posting * Update code/modules/mob/living/simple_animal/hostile/megafauna/ancient_robot.dm Co-authored-by: AffectedArc07 <25063394+AffectedArc07@users.noreply.github.com> * new sprite * Loot added (minus crusher loot) * Apply suggestions from code review Co-authored-by: AffectedArc07 <25063394+AffectedArc07@users.noreply.github.com> * Defines, loot, and requested changes, oh my! * Apply suggestions from code review Co-authored-by: Sirryan2002 <80364400+Sirryan2002@users.noreply.github.com> * sound, bluespace charge improvements, more text * Update code/game/gamemodes/nuclear/pinpointer.dm Co-authored-by: Sirryan2002 <80364400+Sirryan2002@users.noreply.github.com> * WOOO CRUSHER ITEM * don't code when dead tired kids * Update code/modules/mob/living/simple_animal/hostile/megafauna/ancient_robot.dm Co-authored-by: Sirryan2002 <80364400+Sirryan2002@users.noreply.github.com> * Makes crusher loot work, reworks shield for mecha fauna * Names it, lets it spawn, buffs it, should be ready. * Adds better sprites. * pick to rand * Buff, prevent cheese. * Merge conflict hook test * double checking to see if I installed it or not, think I need to manual * fixes the merge issue * makes gibtonite not yeet the mechafauna as much. * fixes hostile/hostile fuckup * fix most beam issues * extra qdel insurance but it should be good * fixes chasm issues, beep on self destruct, extra bluspace charge * Shrinks the kaboom. * spelling + beam fix * Apply suggestions from code review Co-authored-by: Charlie <69320440+hal9000PR@users.noreply.github.com> * late_initialize, var names, and styling, oh my! * attacl Co-authored-by: AffectedArc07 <25063394+AffectedArc07@users.noreply.github.com> Co-authored-by: Sirryan2002 <80364400+Sirryan2002@users.noreply.github.com> Co-authored-by: Charlie <69320440+hal9000PR@users.noreply.github.com>
@@ -12,6 +12,7 @@
|
||||
#define BOSS_MEDAL_LEGION "Legion"
|
||||
#define BOSS_MEDAL_SWARMERS "Swarmer Beacon"
|
||||
#define BOSS_MEDAL_TENDRIL "Tendril"
|
||||
#define BOSS_MEDAL_ROBOT "Ancient Robot"
|
||||
|
||||
// Score names
|
||||
#define HIEROPHANT_SCORE "Hierophants Killed"
|
||||
@@ -22,3 +23,4 @@
|
||||
#define LEGION_SCORE "Legion Killed"
|
||||
#define SWARMER_BEACON_SCORE "Swarmer Beacons Killed"
|
||||
#define TENDRIL_CLEAR_SCORE "Tendrils Killed"
|
||||
#define ROBOT_SCORE "Ancient Robots Killed"
|
||||
|
||||
@@ -71,6 +71,9 @@
|
||||
#define STATUS_EFFECT_TELEPORTSICK /datum/status_effect/teleport_sickness //increasing debuffs as you rapidly teleport.
|
||||
|
||||
#define STATUS_EFFECT_PACIFIED /datum/status_effect/pacifism //forces the pacifism trait
|
||||
|
||||
#define STATUS_EFFECT_BLUESPACESLOWDOWN /datum/status_effect/bluespace_slowdown //Halfs victims next move modifier
|
||||
|
||||
//#define STATUS_EFFECT_NECROPOLIS_CURSE /datum/status_effect/necropolis_curse
|
||||
//#define CURSE_BLINDING 1 //makes the edges of the target's screen obscured
|
||||
//#define CURSE_SPAWNING 2 //spawns creatures that attack the target only
|
||||
@@ -126,3 +129,5 @@
|
||||
#define STATUS_EFFECT_CRUSHERDAMAGETRACKING /datum/status_effect/crusher_damage //tracks total kinetic crusher damage on a target
|
||||
|
||||
#define STATUS_EFFECT_SYPHONMARK /datum/status_effect/syphon_mark //tracks kills for the KA death syphon module
|
||||
|
||||
#define STATUS_EFFECT_ADAPTIVELEARNING /datum/status_effect/adaptive_learning //tracks the total bonus damage needed to be done to target
|
||||
|
||||
@@ -178,6 +178,18 @@
|
||||
/datum/status_effect/pacifism/on_remove()
|
||||
REMOVE_TRAIT(owner, TRAIT_PACIFISM, id)
|
||||
|
||||
/datum/status_effect/bluespace_slowdown
|
||||
id = "bluespace_slowdown"
|
||||
alert_type = null
|
||||
duration = 15 SECONDS
|
||||
|
||||
/datum/status_effect/bluespace_slowdown/on_apply()
|
||||
owner.next_move_modifier *= 2
|
||||
return ..()
|
||||
|
||||
/datum/status_effect/bluespace_slowdown/on_remove()
|
||||
owner.next_move_modifier /= 2
|
||||
|
||||
// start of `living` level status procs.
|
||||
|
||||
/**
|
||||
|
||||
@@ -38,6 +38,13 @@
|
||||
get_kill()
|
||||
. = ..()
|
||||
|
||||
/datum/status_effect/adaptive_learning
|
||||
id = "adaptive_learning"
|
||||
duration = 30 SECONDS
|
||||
status_type = STATUS_EFFECT_REFRESH
|
||||
alert_type = null
|
||||
var/bonus_damage = 0
|
||||
|
||||
/datum/status_effect/high_five
|
||||
id = "high_five"
|
||||
duration = 5 SECONDS
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#define MODE_OPERATIVE 5
|
||||
#define MODE_CREW 6
|
||||
#define MODE_DET 7
|
||||
#define MODE_TENDRIL 8
|
||||
#define SETTING_DISK 0
|
||||
#define SETTING_LOCATION 1
|
||||
#define SETTING_OBJECT 2
|
||||
@@ -87,6 +88,8 @@
|
||||
return "You point the pinpointer to the nearest operative."
|
||||
if(MODE_CREW)
|
||||
return "You turn on the pinpointer."
|
||||
if(MODE_TENDRIL)
|
||||
return "High energy scanner active"
|
||||
|
||||
/obj/item/pinpointer/proc/activate_mode(mode, mob/user) //for crew pinpointer
|
||||
return
|
||||
@@ -459,6 +462,49 @@
|
||||
var/turf/there = get_turf(H)
|
||||
return istype(there) && istype(here) && there.z == here.z
|
||||
|
||||
/obj/item/pinpointer/tendril
|
||||
name = "ancient scanning unit"
|
||||
desc = "Convenient that the scanning unit for the robot survived. Seems to point to the tendrils around here."
|
||||
icon_state = "pinoff_ancient"
|
||||
icon_off = "pinoff_ancient"
|
||||
icon_null = "pinonnull_ancient"
|
||||
icon_direct = "pinondirect_ancient"
|
||||
icon_close = "pinonclose_ancient"
|
||||
icon_medium = "pinonmedium_ancient"
|
||||
icon_far = "pinonfar_ancient"
|
||||
modes = list(MODE_TENDRIL)
|
||||
var/obj/structure/spawner/lavaland/target
|
||||
|
||||
/obj/item/pinpointer/tendril/process()
|
||||
if(mode == MODE_TENDRIL)
|
||||
worktendril()
|
||||
point_at(target, FALSE)
|
||||
else
|
||||
icon_state = icon_off
|
||||
|
||||
/obj/item/pinpointer/tendril/proc/worktendril()
|
||||
if(mode == MODE_TENDRIL)
|
||||
scan_for_tendrils()
|
||||
point_at(target)
|
||||
else
|
||||
return FALSE
|
||||
|
||||
/obj/item/pinpointer/tendril/proc/scan_for_tendrils()
|
||||
if(mode == MODE_TENDRIL)
|
||||
target = null //Resets nearest_op every time it scans
|
||||
var/closest_distance = 1000
|
||||
for(var/obj/structure/spawner/lavaland/T in GLOB.tendrils)
|
||||
var/temp_distance = get_dist(T, get_turf(src))
|
||||
if(temp_distance < closest_distance)
|
||||
target = T
|
||||
closest_distance = temp_distance
|
||||
|
||||
/obj/item/pinpointer/tendril/examine(mob/user)
|
||||
. = ..()
|
||||
if(mode == MODE_TENDRIL)
|
||||
. += "Number of high energy signatures remaining: [length(GLOB.tendrils)]"
|
||||
|
||||
|
||||
#undef MODE_OFF
|
||||
#undef MODE_DISK
|
||||
#undef MODE_NUKE
|
||||
@@ -466,6 +512,7 @@
|
||||
#undef MODE_SHIP
|
||||
#undef MODE_OPERATIVE
|
||||
#undef MODE_CREW
|
||||
#undef MODE_TENDRIL
|
||||
#undef SETTING_DISK
|
||||
#undef SETTING_LOCATION
|
||||
#undef SETTING_OBJECT
|
||||
|
||||
@@ -182,8 +182,13 @@
|
||||
icon = 'icons/obj/projectiles.dmi'
|
||||
icon_state = "bluespace"
|
||||
density = TRUE
|
||||
var/mass_teleporting = TRUE
|
||||
aSignal = /obj/item/assembly/signaler/anomaly/bluespace
|
||||
|
||||
/obj/effect/anomaly/bluespace/Initialize(mapload, new_lifespan, drops_core = TRUE, _mass_teleporting = TRUE)
|
||||
. = ..()
|
||||
mass_teleporting = _mass_teleporting
|
||||
|
||||
/obj/effect/anomaly/bluespace/anomalyEffect()
|
||||
..()
|
||||
for(var/mob/living/M in range(1, src))
|
||||
@@ -194,6 +199,8 @@
|
||||
do_teleport(AM, locate(AM.x, AM.y, AM.z), 8)
|
||||
|
||||
/obj/effect/anomaly/bluespace/detonate()
|
||||
if(!mass_teleporting)
|
||||
return
|
||||
var/turf/T = pick(get_area_turfs(impact_area))
|
||||
if(T)
|
||||
// Calculate new position (searches through beacons in world)
|
||||
@@ -257,8 +264,13 @@
|
||||
name = "pyroclastic anomaly"
|
||||
icon_state = "mustard"
|
||||
var/ticks = 0
|
||||
var/produces_slime = TRUE
|
||||
aSignal = /obj/item/assembly/signaler/anomaly/pyro
|
||||
|
||||
/obj/effect/anomaly/pyro/Initialize(mapload, new_lifespan, drops_core = TRUE, _produces_slime = TRUE)
|
||||
. = ..()
|
||||
produces_slime = _produces_slime
|
||||
|
||||
/obj/effect/anomaly/pyro/anomalyEffect()
|
||||
..()
|
||||
ticks++
|
||||
@@ -271,7 +283,8 @@
|
||||
T.atmos_spawn_air(LINDA_SPAWN_HEAT | LINDA_SPAWN_TOXINS | LINDA_SPAWN_OXYGEN, 5)
|
||||
|
||||
/obj/effect/anomaly/pyro/detonate()
|
||||
INVOKE_ASYNC(src, .proc/makepyroslime)
|
||||
if(produces_slime)
|
||||
INVOKE_ASYNC(src, .proc/makepyroslime)
|
||||
|
||||
/obj/effect/anomaly/pyro/proc/makepyroslime()
|
||||
var/turf/simulated/T = get_turf(src)
|
||||
|
||||
@@ -156,7 +156,7 @@
|
||||
#define SPAWN_MEGAFAUNA "bluh bluh huge boss"
|
||||
#define SPAWN_BUBBLEGUM 6
|
||||
|
||||
GLOBAL_LIST_INIT(megafauna_spawn_list, list(/mob/living/simple_animal/hostile/megafauna/dragon = 4, /mob/living/simple_animal/hostile/megafauna/colossus = 2, /mob/living/simple_animal/hostile/megafauna/bubblegum = SPAWN_BUBBLEGUM))
|
||||
GLOBAL_LIST_INIT(megafauna_spawn_list, list(/mob/living/simple_animal/hostile/megafauna/dragon = 4, /mob/living/simple_animal/hostile/megafauna/colossus = 2, /mob/living/simple_animal/hostile/megafauna/bubblegum = SPAWN_BUBBLEGUM, /mob/living/simple_animal/hostile/megafauna/ancient_robot = 4))
|
||||
|
||||
/turf/simulated/floor/plating/asteroid/airless/cave
|
||||
var/length = 100
|
||||
@@ -302,6 +302,9 @@ GLOBAL_LIST_INIT(megafauna_spawn_list, list(/mob/living/simple_animal/hostile/me
|
||||
if(ispath(randumb, /mob/living/simple_animal/hostile/megafauna/bubblegum)) //there can be only one bubblegum, so don't waste spawns on it
|
||||
megafauna_spawn_list.Remove(randumb)
|
||||
|
||||
if(ispath(randumb, /mob/living/simple_animal/hostile/megafauna/ancient_robot)) //same as above, we do not want multiple of these robots
|
||||
megafauna_spawn_list.Remove(randumb)
|
||||
|
||||
new randumb(T)
|
||||
|
||||
#undef SPAWN_MEGAFAUNA
|
||||
|
||||
@@ -22,7 +22,9 @@
|
||||
/obj/effect/temp_visual,
|
||||
/obj/effect/light_emitter/tendril,
|
||||
/obj/effect/collapse,
|
||||
/obj/effect/particle_effect/ion_trails
|
||||
/obj/effect/particle_effect/ion_trails,
|
||||
/obj/effect/abstract,
|
||||
/obj/effect/ebeam
|
||||
))
|
||||
var/drop_x = 1
|
||||
var/drop_y = 1
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
var/backstab_bonus = 30
|
||||
var/light_on = FALSE
|
||||
var/brightness_on = 5
|
||||
var/adaptive_damage_bonus = 0
|
||||
|
||||
/obj/item/twohanded/kinetic_crusher/Destroy()
|
||||
QDEL_LIST(trophies)
|
||||
@@ -68,7 +69,16 @@
|
||||
if(!C)
|
||||
C = target.apply_status_effect(STATUS_EFFECT_CRUSHERDAMAGETRACKING)
|
||||
var/target_health = target.health
|
||||
var/temp_force_bonus = 0
|
||||
var/datum/status_effect/adaptive_learning/A = target.has_status_effect(STATUS_EFFECT_ADAPTIVELEARNING)
|
||||
if(!A && adaptive_damage_bonus)
|
||||
A = target.apply_status_effect(STATUS_EFFECT_ADAPTIVELEARNING)
|
||||
if(A)
|
||||
temp_force_bonus = A.bonus_damage
|
||||
A.bonus_damage = min((A.bonus_damage + adaptive_damage_bonus), 20)
|
||||
force += temp_force_bonus
|
||||
..()
|
||||
force -= temp_force_bonus
|
||||
for(var/t in trophies)
|
||||
if(!QDELETED(target))
|
||||
var/obj/item/crusher_trophy/T = t
|
||||
@@ -445,3 +455,23 @@
|
||||
|
||||
/obj/effect/temp_visual/hierophant/wall/crusher
|
||||
duration = 75
|
||||
|
||||
/obj/item/crusher_trophy/adaptive_intelligence_core
|
||||
name = "adaptive inteligence core"
|
||||
desc = "Seems to be one of the cores from a massive robot. Suitable as a trophy for a kinetic crusher."
|
||||
icon_state = "adaptive_core"
|
||||
denied_type = /obj/item/crusher_trophy/adaptive_intelligence_core
|
||||
bonus_value = 2
|
||||
|
||||
/obj/item/crusher_trophy/adaptive_intelligence_core/effect_desc()
|
||||
return "melee hits deal <b>[bonus_value]</b> more damage per hit after hitting a target, up to <b>[bonus_value * 10]</b> extra damage to that target"
|
||||
|
||||
/obj/item/crusher_trophy/adaptive_intelligence_core/add_to(obj/item/twohanded/kinetic_crusher/H, mob/living/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
H.adaptive_damage_bonus += bonus_value
|
||||
|
||||
/obj/item/crusher_trophy/adaptive_intelligence_core/remove_from(obj/item/twohanded/kinetic_crusher/H, mob/living/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
H.adaptive_damage_bonus -= bonus_value
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/obj/structure/closet/crate/necropolis/ancient
|
||||
name = "ancient supply cache"
|
||||
|
||||
/obj/structure/closet/crate/necropolis/ancient/populate_contents()
|
||||
new /obj/item/pinpointer/tendril(src) // in pinpointers, with the rest of them
|
||||
var/list/common_ore = list(
|
||||
/obj/item/stack/ore/uranium,
|
||||
/obj/item/stack/ore/silver,
|
||||
/obj/item/stack/ore/gold,
|
||||
/obj/item/stack/ore/plasma,
|
||||
/obj/item/stack/ore/titanium
|
||||
)
|
||||
|
||||
for(var/res in common_ore)
|
||||
var/obj/item/stack/R = new res(src)
|
||||
R.amount = rand(15, 30)
|
||||
|
||||
var/list/rare_ore = list(
|
||||
/obj/item/stack/ore/diamond,
|
||||
/obj/item/stack/ore/bluespace_crystal,
|
||||
/obj/item/stack/sheet/mineral/abductor // few ruins of it often spawn, should be fine.
|
||||
)
|
||||
|
||||
for(var/res in rare_ore)
|
||||
var/obj/item/stack/R = new res(src)
|
||||
R.amount = rand(10, 15) //ash drakes drop 5, this is perfectly fine
|
||||
|
||||
|
||||
/obj/structure/closet/crate/necropolis/ancient/ex_act(severity)
|
||||
return
|
||||
|
||||
/obj/structure/closet/crate/necropolis/ancient/crusher
|
||||
name = "alloyed ancient supply cache"
|
||||
|
||||
/obj/structure/closet/crate/necropolis/ancient/crusher/populate_contents()
|
||||
. = ..()
|
||||
new /obj/item/crusher_trophy/adaptive_intelligence_core(src)
|
||||
|
||||
@@ -0,0 +1,744 @@
|
||||
#define BODY_SHIELD_COOLDOWN_TIME 5 SECONDS
|
||||
#define EXTRA_PLAYER_ANGER_NORMAL_CAP 6
|
||||
#define EXTRA_PLAYER_ANGER_STATION_CAP 3
|
||||
#define BLUESPACE 1
|
||||
#define GRAV 2
|
||||
#define PYRO 3
|
||||
#define FLUX 4
|
||||
#define VORTEX 5
|
||||
#define TOP_RIGHT 1
|
||||
#define TOP_LEFT 2
|
||||
#define BOTTOM_RIGHT 3
|
||||
#define BOTTOM_LEFT 4
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Vetus Speculator
|
||||
|
||||
An old 4 legged self learning robot made from a long gone civilization. Likes to scan and learn from things... Including crewmembers.
|
||||
|
||||
Hybrid ranged / melee combatant, similar to bubblegum.
|
||||
|
||||
It has several attacks at it's disposal. It can melee with it's body and legs, however a person will not be hit by both at once unless poorly positioned. Legs also have a weak turret on each leg, that can be broken via damage.
|
||||
|
||||
Every 5 seconds it creates a shield around itself, that blocks 1 hit, or multiple non damaging hits. Crusher users will need blast tube to break the shield, OR melee the robot with shield up to de-activate it.
|
||||
|
||||
The main feature that makes it unique, is that it has 5 modes, based on each anomaly core, that can augment it's remaning attacks.
|
||||
|
||||
It can charge like bubblegum. If it has a pyro core, it makes a trail of fire and temporary lava. If it is bluespace, it charges with more delay between charges, but instead teleports between charges, to make it less predictable. Grav throws people if they bump into them during charge.
|
||||
|
||||
It can spawn 3 anomalies around it for 15 seconds with a low chance. They do not explode / mass teleport / spawn slimes.
|
||||
|
||||
Finaly, for each mode, it has a special attack.
|
||||
- Bluespace causes it's current target to have half attack speed for 10 seconds.
|
||||
- Grav picks up rocks from the terrain, and throws them at the target.
|
||||
- Pyro turns 3x3 areas around the target (but not too close) into lava.
|
||||
- Flux shoots weakened tesla revolver shots at all humans nearby.
|
||||
- Vortex causes a small earthquake, leading to rocks falling from the sky.
|
||||
|
||||
Upon reaching critical HP (normally death), it preps a 10 second self destruct, before exploding. Large tell, hard to miss.
|
||||
Loot: Anomaly core that matches the mode that was picked of the robot. A pinpointer that can point to tendrils, which should be fine, as by the time this is killed, the round should be an hour or more over. As well as a variety of raw ores.
|
||||
Crusher Loot: Adaptive inteligence core, a trophy that temporarly increases the force of a crusher against a target it has hit within the last 30 seconds by 2 per hit, up to 20 extra force.
|
||||
|
||||
Difficulty: Hard
|
||||
|
||||
*/
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/ancient_robot
|
||||
name = "\improper Vetus Speculator"
|
||||
desc = "An ancient robot from a long forgotten civilization. Adapts to the enviroment, and what it finds, to be the ideal combatant."
|
||||
health = 2500
|
||||
maxHealth = 2500
|
||||
attacktext = "shocks"
|
||||
attack_sound = 'sound/machines/defib_zap.ogg'
|
||||
icon = 'icons/mob/lavaland/64x64megafauna.dmi'
|
||||
icon_state = "ancient_robot"
|
||||
icon_living = "ancient_robot"
|
||||
friendly = "stares down"
|
||||
speak_emote = list("BUZZES")
|
||||
universal_speak = TRUE
|
||||
universal_understand = TRUE
|
||||
armour_penetration = 40
|
||||
melee_damage_lower = 20
|
||||
melee_damage_upper = 20
|
||||
melee_damage_type = BURN //Legs do the stomping, this is just a shock
|
||||
speed = 5
|
||||
move_to_delay = 5
|
||||
ranged = TRUE
|
||||
pixel_x = -16
|
||||
pixel_y = -16
|
||||
del_on_death = TRUE
|
||||
loot = list(/obj/structure/closet/crate/necropolis/ancient)
|
||||
crusher_loot = list(/obj/structure/closet/crate/necropolis/ancient/crusher)
|
||||
internal_type = /obj/item/gps/internal/ancient
|
||||
medal_type = BOSS_MEDAL_ROBOT
|
||||
score_type = ROBOT_SCORE
|
||||
deathmessage = "explodes into a shower of alloys"
|
||||
footstep_type = FOOTSTEP_MOB_HEAVY //make stomp like bubble
|
||||
attack_action_types = list()
|
||||
|
||||
var/charging = FALSE
|
||||
var/revving_charge = FALSE
|
||||
var/player_cooldown = 0
|
||||
var/body_shield_enabled = FALSE
|
||||
var/extra_player_anger = 0
|
||||
var/mode = 0 //This variable controls the special attacks of the robot, one for each anomaly core.
|
||||
var/exploding = FALSE
|
||||
|
||||
/// Legs and the connector for the legs
|
||||
|
||||
var/mob/living/simple_animal/hostile/ancient_robot_leg/TR = null
|
||||
var/mob/living/simple_animal/hostile/ancient_robot_leg/TL = null
|
||||
var/mob/living/simple_animal/hostile/ancient_robot_leg/BR = null
|
||||
var/mob/living/simple_animal/hostile/ancient_robot_leg/BL = null
|
||||
var/obj/effect/abstract/beam = null
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/ancient_robot/Initialize(mapload, mob/living/ancient) //We spawn and move them to clear out area for the legs, rather than risk the legs getting put in a wall
|
||||
. = ..()
|
||||
TR = new /mob/living/simple_animal/hostile/ancient_robot_leg(loc, src, TOP_RIGHT)
|
||||
TL = new /mob/living/simple_animal/hostile/ancient_robot_leg(loc, src, TOP_LEFT)
|
||||
BR = new /mob/living/simple_animal/hostile/ancient_robot_leg(loc, src, BOTTOM_RIGHT)
|
||||
BL = new /mob/living/simple_animal/hostile/ancient_robot_leg(loc, src, BOTTOM_LEFT)
|
||||
beam = new /obj/effect/abstract(loc)
|
||||
mode = pick(BLUESPACE, GRAV, PYRO, FLUX, VORTEX) //picks one of the 5 cores.
|
||||
if(mode == FLUX) // Main attack is shock, so flux makes it stronger
|
||||
melee_damage_lower = 25
|
||||
melee_damage_upper = 25
|
||||
body_shield()
|
||||
add_overlay("[mode]")
|
||||
add_overlay("eyes")
|
||||
return INITIALIZE_HINT_LATELOAD
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/ancient_robot/LateInitialize()
|
||||
fix_specific_leg(TOP_RIGHT)
|
||||
fix_specific_leg(TOP_LEFT)
|
||||
fix_specific_leg(BOTTOM_RIGHT)
|
||||
fix_specific_leg(BOTTOM_LEFT)
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/ancient_robot/Destroy()
|
||||
QDEL_NULL(TR)
|
||||
QDEL_NULL(TL)
|
||||
QDEL_NULL(BR)
|
||||
QDEL_NULL(BL)
|
||||
QDEL_NULL(beam)
|
||||
return ..()
|
||||
|
||||
/obj/item/gps/internal/ancient
|
||||
icon_state = null
|
||||
gpstag = "Malfunctioning Signal"
|
||||
desc = "ERROR_NULL_ENTRY"
|
||||
invisibility = 100
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/ancient_robot/death(gibbed, allowed = FALSE)
|
||||
if(allowed)
|
||||
return ..()
|
||||
else if(exploding) //but it refused
|
||||
return
|
||||
adjustBruteLoss(-1)
|
||||
self_destruct()
|
||||
exploding = TRUE
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/ancient_robot/Life(seconds, times_fired)
|
||||
..()
|
||||
if(!exploding)
|
||||
return
|
||||
playsound(src, 'sound/items/timer.ogg', 70, 0)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/ancient_robot/drop_loot()
|
||||
var/core_type = null
|
||||
switch(mode)
|
||||
if(BLUESPACE)
|
||||
core_type = /obj/item/assembly/signaler/anomaly/bluespace
|
||||
if(GRAV)
|
||||
core_type = /obj/item/assembly/signaler/anomaly/grav
|
||||
if(PYRO)
|
||||
core_type = /obj/item/assembly/signaler/anomaly/pyro
|
||||
if(FLUX)
|
||||
core_type = /obj/item/assembly/signaler/anomaly/flux
|
||||
if(VORTEX)
|
||||
core_type = /obj/item/assembly/signaler/anomaly/vortex
|
||||
|
||||
var/crate_type = pick(loot)
|
||||
var/obj/structure/closet/crate/C = new crate_type(loc)
|
||||
new core_type(C)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/ancient_robot/OpenFire()
|
||||
if(charging)
|
||||
return
|
||||
|
||||
if(exploding)
|
||||
return
|
||||
|
||||
anger_modifier = clamp(((maxHealth - health) / 50), 0, 20)
|
||||
ranged_cooldown = world.time + (ranged_cooldown_time * ((10 - extra_player_anger) / 10))
|
||||
|
||||
if(prob(30 + anger_modifier))
|
||||
triple_charge()
|
||||
|
||||
else if(prob(15 + anger_modifier))
|
||||
spawn_anomalies()
|
||||
|
||||
else if(prob(60 + anger_modifier))
|
||||
do_special_move()
|
||||
|
||||
calculate_extra_player_anger()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/ancient_robot/proc/triple_charge()
|
||||
if(mode == BLUESPACE)
|
||||
charge(delay = 24) //An extra charge, to make up for the longer time between teleports
|
||||
charge(delay = 18)
|
||||
charge(delay = 12)
|
||||
charge(delay = 6)
|
||||
else
|
||||
charge(delay = 9)
|
||||
charge(delay = 6)
|
||||
charge(delay = 3)
|
||||
SetRecoveryTime(15)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/ancient_robot/proc/charge(atom/chargeat = target, delay = 5, chargepast = 2) //add limb charge as well
|
||||
if(!chargeat)
|
||||
return
|
||||
if(mode == BLUESPACE)
|
||||
new /obj/effect/temp_visual/bsg_kaboom(get_turf(src))
|
||||
src.visible_message("<span class='danger'>[src] teleports somewhere nearby!</span>")
|
||||
do_teleport(src, target, 7, asoundin = 'sound/effects/phasein.ogg', safe_turf_pick = TRUE) //Teleport within 7 tiles of the target
|
||||
new /obj/effect/temp_visual/bsg_kaboom(get_turf(src))
|
||||
|
||||
TR.health_and_snap_check(FALSE)// We want the legs to instantly teleport with it, without regening
|
||||
TL.health_and_snap_check(FALSE)
|
||||
BR.health_and_snap_check(FALSE)
|
||||
BL.health_and_snap_check(FALSE)
|
||||
|
||||
var/chargeturf = get_turf(chargeat)
|
||||
if(!chargeturf)
|
||||
return
|
||||
var/dir = get_dir(src, chargeturf)
|
||||
var/turf/T = get_ranged_target_turf(chargeturf, dir, chargepast)
|
||||
if(!T)
|
||||
return
|
||||
new /obj/effect/temp_visual/dragon_swoop/bubblegum/ancient_robot(T, beam)
|
||||
charging = TRUE
|
||||
revving_charge = TRUE
|
||||
DestroySurroundings()
|
||||
walk(src, 0)
|
||||
setDir(dir)
|
||||
SLEEP_CHECK_DEATH(delay)
|
||||
revving_charge = FALSE
|
||||
var/movespeed = 0.8
|
||||
walk_towards(src, T, movespeed)
|
||||
SLEEP_CHECK_DEATH(get_dist(src, T) * movespeed)
|
||||
walk(src, 0) // cancel the movement
|
||||
charging = FALSE
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/ancient_robot/MeleeAction(patience = TRUE)
|
||||
if(charging)
|
||||
return
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/ancient_robot/Bump(atom/A)
|
||||
if(charging)
|
||||
DestroySurroundings()
|
||||
if(isliving(A))
|
||||
var/mob/living/L = A
|
||||
if(!istype(A, /mob/living/simple_animal/hostile/ancient_robot_leg))
|
||||
L.visible_message("<span class='danger'>[src] slams into [L]!</span>", "<span class='userdanger'>[src] tramples you into the ground!</span>")
|
||||
forceMove(get_turf(L))
|
||||
var/limb_to_hit = L.get_organ(pick(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG))
|
||||
L.apply_damage(25, BRUTE, limb_to_hit, L.run_armor_check(limb_to_hit, MELEE, null, null, armour_penetration))
|
||||
playsound(get_turf(L), 'sound/effects/meteorimpact.ogg', 100, TRUE)
|
||||
shake_camera(L, 4, 3)
|
||||
shake_camera(src, 2, 3)
|
||||
if(mode == GRAV)
|
||||
var/atom/throw_target = get_edge_target_turf(L, get_dir(src, get_step_away(L, src)))
|
||||
L.throw_at(throw_target, 3, 2)
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/ancient_robot/proc/body_shield()
|
||||
body_shield_enabled = TRUE
|
||||
visible_message("<span class='danger'>[src] creates some sort of energy shield!</span>")
|
||||
add_overlay("shield")
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/ancient_robot/proc/disable_shield()
|
||||
visible_message("<span class='danger'>[src]'s shield fails!</span>")
|
||||
cut_overlay("shield")
|
||||
body_shield_enabled = FALSE
|
||||
addtimer(CALLBACK(src, .proc/body_shield), BODY_SHIELD_COOLDOWN_TIME)
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/ancient_robot/bullet_act(obj/item/projectile/P)
|
||||
if(!body_shield_enabled)
|
||||
return ..()
|
||||
do_sparks(2, 1, src)
|
||||
visible_message("<span class='danger'>[src]'s shield deflects [P] in a shower of sparks!</span>", "<span class='userdanger'>You deflect the projectile!</span>")
|
||||
if(P.damage)
|
||||
disable_shield()
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/ancient_robot/attacked_by(obj/item/I, mob/living/user)
|
||||
if(!body_shield_enabled)
|
||||
return ..()
|
||||
do_sparks(2, 1, src)
|
||||
visible_message("<span class='danger'>[src]'s shield deflects [I] in a shower of sparks!</span>", "<span class='userdanger'>You deflect the attack!</span>")
|
||||
if(I.force)
|
||||
disable_shield()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/ancient_robot/devour(mob/living/L)
|
||||
say(pick("JKYZXAIZOBK GTGREYKX GIZOBK", "OTZKMXGZOTM YAHPKIZ YZXKTMZNY", "JKIUSVOROTM GTJ RKGXTOTM", "LOTJOTM IXOZOIGR CKGQTKYYKY")) //what can I say, I like the trope of something talking in cypher
|
||||
visible_message("<span class='userdanger'>[src] disintigrates [L]!</span>","<span class='userdanger'>You analyse [L], restoring your health!</span>")
|
||||
if(client || !is_station_level(z))
|
||||
adjustHealth(-maxHealth * 0.1)
|
||||
L.dust()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/ancient_robot/proc/do_special_move()
|
||||
say(pick("JKVRUEOTM LUIAYKJ VUCKX", "JKVRUEOTM KDVKXOSKTZGR GZZGIQ", "LUIAYOTM VUCKX OTZU GTUSGRUAY UHPKIZ", "VUCKX UL ZNK YAT OT ZNK NKGXZ UL SE IUXK"))
|
||||
switch(mode)
|
||||
if(BLUESPACE)
|
||||
if(ishuman(target))
|
||||
var/mob/living/carbon/human/H = target
|
||||
to_chat(H, "<span class='danger'>[src] starts to slow time around you!</span>")
|
||||
H.apply_status_effect(STATUS_EFFECT_BLUESPACESLOWDOWN)
|
||||
if(GRAV)
|
||||
visible_message("<span class='danger'>Debris from the battlefield begin to get compressed into rocks!</span>")
|
||||
var/list/turfs = new/list()
|
||||
var/rocks = 0
|
||||
for(var/turf/T in view(4, target))
|
||||
if(T.density)
|
||||
continue
|
||||
if(T in range (2, target))
|
||||
continue
|
||||
turfs += T
|
||||
while(rocks < 3 && length(turfs))
|
||||
var/turf/spot = pick_n_take(turfs)
|
||||
new /obj/effect/temp_visual/rock(spot)
|
||||
addtimer(CALLBACK(src, .proc/throw_rock, spot, target), 2 SECONDS)
|
||||
rocks++
|
||||
if(PYRO)
|
||||
visible_message("<span class='danger'>The ground begins to heat up around you!</span>")
|
||||
var/list/turfs = new/list()
|
||||
var/volcanos = 0
|
||||
for(var/turf/T in view(4, target))
|
||||
if(T.density)
|
||||
continue
|
||||
if(T in range(1, target))
|
||||
continue
|
||||
turfs += T
|
||||
while(volcanos < 3 && length(turfs))
|
||||
var/turf/spot = pick_n_take(turfs)
|
||||
for(var/turf/around in range(1, spot))
|
||||
new /obj/effect/temp_visual/lava_warning(around)
|
||||
volcanos++
|
||||
if(FLUX)
|
||||
for(var/mob/living/carbon/human/H in view(7, src))
|
||||
var/turf/T = get_turf(H)
|
||||
var/turf/S = get_turf(src)
|
||||
if(!S || !T)
|
||||
return
|
||||
var/obj/item/projectile/energy/shock_revolver/ancient/O = new /obj/item/projectile/energy/shock_revolver/ancient(S)
|
||||
O.current = S
|
||||
O.yo = T.y - S.y
|
||||
O.xo = T.x - S.x
|
||||
O.fire()
|
||||
if(VORTEX)
|
||||
visible_message("<span class='danger'>[src] begins vibrate rapidly. It's causing an earthquake!</span>")
|
||||
for(var/turf/turf in range(9,get_turf(target)))
|
||||
if(prob(11))
|
||||
new /obj/effect/temp_visual/target/ancient(turf)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/ancient_robot/proc/spawn_anomalies()
|
||||
say(pick("JKVRUEOTM XGC VUCKX", "KXXUX OT GTUSGRE IUTZGOTSKTZ", "YZGHOROZE OT OTYZGHOROZE OT YZGHOROZE OT OTYZGH-"))
|
||||
var/list/turfs = list()
|
||||
var/anomalies = 0
|
||||
for(var/turf/T in view(5, src))
|
||||
if(T.density)
|
||||
continue
|
||||
turfs += T
|
||||
while(anomalies < 3 && length(turfs))
|
||||
var/turf/spot = pick(turfs)
|
||||
turfs -= spot
|
||||
switch(mode)
|
||||
if(BLUESPACE)
|
||||
var/obj/effect/anomaly/bluespace/A = new(spot, 150, FALSE)
|
||||
A.mass_teleporting = FALSE
|
||||
if(GRAV)
|
||||
new /obj/effect/anomaly/grav(spot, 150, FALSE)
|
||||
if(PYRO)
|
||||
var/obj/effect/anomaly/pyro/A = new(spot, 150, FALSE)
|
||||
A.produces_slime = FALSE
|
||||
if(FLUX)
|
||||
var/obj/effect/anomaly/flux/A = new(spot, 150, FALSE)
|
||||
A.explosive = FALSE
|
||||
if(VORTEX)
|
||||
new /obj/effect/anomaly/bhole(spot, 150, FALSE)
|
||||
anomalies++
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/ancient_robot/proc/throw_rock(turf/spot, mob/target)
|
||||
var/turf/T = get_turf(target)
|
||||
if(!spot || !T)
|
||||
return
|
||||
var/obj/item/projectile/rock/O = new /obj/item/projectile/rock(spot)
|
||||
O.current = spot
|
||||
O.yo = T.y - spot.y
|
||||
O.xo = T.x - spot.x
|
||||
O.fire()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/ancient_robot/proc/calculate_extra_player_anger()// To make this fight harder, it scales it's attacks based on number of players. Capped lower on station.
|
||||
var/anger = 0
|
||||
var/cap = 0
|
||||
for(var/mob/living/carbon/human/H in range(10, src))
|
||||
if(stat == DEAD)
|
||||
continue
|
||||
anger++
|
||||
cap = (is_station_level(loc.z) ? EXTRA_PLAYER_ANGER_STATION_CAP : EXTRA_PLAYER_ANGER_NORMAL_CAP)
|
||||
extra_player_anger = clamp(anger,1,cap) - 1
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/ancient_robot/proc/self_destruct()
|
||||
say(pick("OTZKMXOZE LGORAXK, YKRL JKYZXAIZ GIZOBK", "RUYY IKXZGOT, KTMGMKOTM XKIUBKXE JKTOGR", "VUCKX IUXKY 8-12 HXKGINKJ, UBKXRUGJOTM XKSGOTOTM IUXKY", "KXXUX KXXUX KXXUX KXXUX KXX-", "-ROQK ZKGXY OT XGOT- - -ZOSK ZU JOK"))
|
||||
visible_message("<span class='biggerdanger'>[src] begins to overload it's core. It is going to explode!</span>")
|
||||
walk(src, 0)
|
||||
playsound(src,'sound/machines/alarm.ogg',100,0,5)
|
||||
addtimer(CALLBACK(src, .proc/kaboom), 10 SECONDS)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/ancient_robot/proc/kaboom()
|
||||
explosion(get_turf(src), -1, 7, 15, 20)
|
||||
health = 0
|
||||
death(allowed = TRUE)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/ancient_robot/proc/disable_legs()
|
||||
TR.ranged = FALSE
|
||||
|
||||
TL.ranged = FALSE
|
||||
|
||||
BR.ranged = FALSE
|
||||
|
||||
BL.ranged = FALSE
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/ancient_robot/face_atom(atom/A) //This is used to make the legs get near the core when a user is meleeing the core
|
||||
. = ..()
|
||||
switch(dir)
|
||||
if(NORTH)
|
||||
leg_control_system(TOP_RIGHT, 1, 2)
|
||||
leg_control_system(TOP_LEFT, -1, 2)
|
||||
if(SOUTH)
|
||||
leg_control_system(BOTTOM_RIGHT, 1, -2)
|
||||
leg_control_system(BOTTOM_LEFT, -1, -2)
|
||||
if(EAST)
|
||||
leg_control_system(TOP_RIGHT, 2, 1)
|
||||
leg_control_system(BOTTOM_RIGHT, 2, -1)
|
||||
if(WEST)
|
||||
leg_control_system(TOP_LEFT, -2, 1)
|
||||
leg_control_system(BOTTOM_LEFT, -2,- 1)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/ancient_robot/proc/fix_specific_leg(input) //Used to reset legs to specific locations
|
||||
switch(input)
|
||||
if(TOP_RIGHT)
|
||||
leg_control_system(input, 2, 2)
|
||||
if(TOP_LEFT)
|
||||
leg_control_system(input, -2, 2)
|
||||
if(BOTTOM_RIGHT)
|
||||
leg_control_system(input, 2, -2)
|
||||
if(BOTTOM_LEFT)
|
||||
leg_control_system(input, -2, -2)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/ancient_robot/proc/leg_walking_controler(dir) //This controls the legs. Here be pain.
|
||||
switch(dir)
|
||||
if(NORTH)
|
||||
leg_walking_orderer(TOP_RIGHT, TOP_LEFT, BOTTOM_RIGHT, BOTTOM_LEFT)
|
||||
if(SOUTH)
|
||||
leg_walking_orderer(BOTTOM_LEFT, BOTTOM_RIGHT, TOP_LEFT, TOP_RIGHT)
|
||||
if(EAST)
|
||||
leg_walking_orderer(TOP_RIGHT, TOP_LEFT, BOTTOM_RIGHT, BOTTOM_LEFT)
|
||||
if(WEST)
|
||||
leg_walking_orderer(BOTTOM_LEFT, BOTTOM_RIGHT, TOP_LEFT, TOP_RIGHT)
|
||||
if(NORTHEAST)
|
||||
leg_walking_orderer(TOP_RIGHT, TOP_LEFT, BOTTOM_RIGHT, BOTTOM_LEFT)
|
||||
if(SOUTHEAST)
|
||||
leg_walking_orderer(BOTTOM_RIGHT, TOP_LEFT, BOTTOM_LEFT, TOP_RIGHT)
|
||||
if(NORTHWEST)
|
||||
leg_walking_orderer(TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT)
|
||||
if(SOUTHEAST)
|
||||
leg_walking_orderer(BOTTOM_LEFT, TOP_LEFT, BOTTOM_RIGHT, TOP_RIGHT)
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/ancient_robot/proc/leg_walking_orderer(A, B, C, D)
|
||||
addtimer(CALLBACK(src, .proc/fix_specific_leg, A), 1)
|
||||
addtimer(CALLBACK(src, .proc/fix_specific_leg, B), 2)
|
||||
addtimer(CALLBACK(src, .proc/fix_specific_leg, C), 3)
|
||||
addtimer(CALLBACK(src, .proc/fix_specific_leg, D), 4)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/ancient_robot/proc/leg_control_system(input, horizontal, vertical)
|
||||
var/turf/target = locate(x + horizontal, y + vertical, z)
|
||||
switch(input)
|
||||
if(TOP_RIGHT)
|
||||
TR.leg_movement(target, 0.6)
|
||||
if(TOP_LEFT)
|
||||
TL.leg_movement(target, 0.6)
|
||||
if(BOTTOM_RIGHT)
|
||||
BR.leg_movement(target, 0.6)
|
||||
if(BOTTOM_LEFT)
|
||||
BL.leg_movement(target, 0.6)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/anicent_robot/ex_act(severity, target)
|
||||
switch(severity)
|
||||
if(1)
|
||||
adjustBruteLoss(25)
|
||||
|
||||
if(2)
|
||||
adjustBruteLoss(10)
|
||||
|
||||
if(3)
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/ancient_robot/Goto()
|
||||
if(!exploding)
|
||||
return ..()
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/ancient_robot/Moved(atom/OldLoc, Dir, Forced = FALSE)
|
||||
if(charging)
|
||||
DestroySurroundings()
|
||||
if(Dir)
|
||||
leg_walking_controler(Dir)
|
||||
if(charging)
|
||||
if(mode == PYRO)
|
||||
var/turf/C = get_turf(src)
|
||||
new /obj/effect/temp_visual/lava_warning(C)
|
||||
for(var/turf/T in range (1,src))
|
||||
new /obj/effect/hotspot(T)
|
||||
T.hotspot_expose(700,50,1)
|
||||
if(mode == VORTEX)
|
||||
var/turf/C = get_turf(src)
|
||||
C.ex_act(3)
|
||||
|
||||
beam.forceMove(get_turf(src))
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/ancient_robot_leg
|
||||
name = "leg"
|
||||
desc = "Legs with a mounted turret, for shooting and crushing small miners like you."
|
||||
icon = 'icons/mob/lavaland/lavaland_monsters.dmi'
|
||||
icon_state = "leg"
|
||||
maxHealth = INFINITY //it's fine trust me
|
||||
health = INFINITY
|
||||
faction = list("mining", "boss") // No attacking your leg
|
||||
weather_immunities = list("lava","ash")
|
||||
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
flying = TRUE
|
||||
check_friendly_fire = 1
|
||||
ranged = TRUE
|
||||
projectilesound = 'sound/weapons/gunshots/gunshot.ogg'
|
||||
projectiletype = /obj/item/projectile/ancient_robot_bullet
|
||||
attacktext = "stomps on"
|
||||
armour_penetration = 40
|
||||
melee_damage_lower = 15
|
||||
melee_damage_upper = 15
|
||||
obj_damage = 400
|
||||
move_force = MOVE_FORCE_OVERPOWERING
|
||||
move_resist = MOVE_FORCE_OVERPOWERING
|
||||
pull_force = MOVE_FORCE_OVERPOWERING
|
||||
sentience_type = SENTIENCE_BOSS
|
||||
environment_smash = ENVIRONMENT_SMASH_RWALLS
|
||||
stop_automated_movement = 1
|
||||
wander = 0
|
||||
robust_searching = TRUE
|
||||
ranged_ignores_vision = TRUE
|
||||
stat_attack = DEAD
|
||||
var/range = 3
|
||||
var/mob/living/simple_animal/hostile/megafauna/ancient_robot/core = null
|
||||
var/fake_max_hp = 400
|
||||
var/fake_hp = 400
|
||||
var/fake_hp_regen = 10
|
||||
var/transfer_rate = 0.75
|
||||
var/who_am_i = null
|
||||
var/datum/beam/leg_part
|
||||
|
||||
/mob/living/simple_animal/hostile/ancient_robot_leg/Initialize(mapload, mob/living/ancient, who)
|
||||
. = ..()
|
||||
if(!ancient)
|
||||
qdel(src) //no
|
||||
core = ancient
|
||||
who_am_i = who
|
||||
ranged_cooldown_time = rand(30, 60) // keeps them not running on the same time
|
||||
addtimer(CALLBACK(src, .proc/beam_setup), 1 SECONDS)
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/ancient_robot_leg/Destroy()
|
||||
QDEL_NULL(leg_part)
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/ancient_robot_leg/Life(seconds, times_fired)
|
||||
..()
|
||||
health_and_snap_check(TRUE)
|
||||
|
||||
/mob/living/simple_animal/hostile/ancient_robot_leg/bullet_act(obj/item/projectile/P)
|
||||
if(core.stat == CONSCIOUS && !core.target && core.AIStatus != AI_OFF && !core.client)
|
||||
if(P.firer && get_dist(core, P.firer) <= core.aggro_vision_range)
|
||||
core.FindTarget(list(P.firer), 1)
|
||||
core.Goto(P.starting, core.move_to_delay, 3)
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/ancient_robot_leg/Goto()
|
||||
return // stops the legs from trying to move on their own
|
||||
|
||||
/mob/living/simple_animal/hostile/ancient_robot_leg/proc/beam_setup()
|
||||
leg_part = Beam(core.beam, "leg_connection", 'icons/effects/effects.dmi', time=INFINITY, maxdistance=INFINITY, beam_type=/obj/effect/ebeam)
|
||||
|
||||
/mob/living/simple_animal/hostile/ancient_robot_leg/onTransitZ(old_z,new_z)
|
||||
..()
|
||||
update_z(new_z)
|
||||
if(leg_part)
|
||||
QDEL_NULL(leg_part)
|
||||
addtimer(CALLBACK(src, .proc/beam_setup), 1 SECONDS)
|
||||
|
||||
/mob/living/simple_animal/hostile/ancient_robot_leg/adjustHealth(amount, updating_health = TRUE)
|
||||
var/damage = amount * transfer_rate
|
||||
core.adjustBruteLoss(damage)
|
||||
fake_hp = clamp(fake_hp - damage, 0, fake_max_hp)
|
||||
if(damage && ranged && fake_hp <= 200)
|
||||
ranged = FALSE
|
||||
visible_message("<span class='danger'>[src]'s turret breaks and pulls back into the leg!</span>")
|
||||
if(damage && transfer_rate <= 0.25) //warn that you are not doing much damage
|
||||
visible_message("<span class='danger'>[src] looks too damaged to hurt it much more!</span>")
|
||||
health_and_snap_check(FALSE)
|
||||
|
||||
/mob/living/simple_animal/hostile/ancient_robot_leg/proc/health_and_snap_check(regen = FALSE)
|
||||
if(regen)
|
||||
fake_hp = min(fake_hp + fake_hp_regen, fake_max_hp)
|
||||
transfer_rate = 0.75 * (fake_hp/fake_max_hp)
|
||||
if(fake_hp >= 300 && !ranged)
|
||||
ranged = TRUE
|
||||
visible_message("<span class='danger'>[src]'s turret pops out of it!</span>")
|
||||
if(get_dist(get_turf(core),get_turf(src)) <= range)
|
||||
return
|
||||
else
|
||||
forceMove(core.loc)
|
||||
core.fix_specific_leg(who_am_i)
|
||||
|
||||
/mob/living/simple_animal/hostile/ancient_robot_leg/proc/leg_movement(turf/T, movespeed) //byond doesn't like calling walk_towards on the legs directly
|
||||
walk_towards(src, T, movespeed)
|
||||
DestroySurroundings()
|
||||
|
||||
/mob/living/simple_animal/hostile/ancient_robot_leg/Bump(atom/A)
|
||||
if(!core.charging)
|
||||
return
|
||||
if(isliving(A))
|
||||
if(!istype(A, /mob/living/simple_animal/hostile/megafauna/ancient_robot))
|
||||
var/mob/living/L = A
|
||||
L.visible_message("<span class='danger'>[src] slams into [L]!</span>", "<span class='userdanger'>[src] tramples you into the ground!</span>")
|
||||
forceMove(get_turf(L))
|
||||
var/limb_to_hit = L.get_organ(pick(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG))
|
||||
L.apply_damage(12.5, BRUTE, limb_to_hit, L.run_armor_check(limb_to_hit, MELEE, null, null, armour_penetration))
|
||||
playsound(get_turf(L), 'sound/effects/meteorimpact.ogg', 100, TRUE)
|
||||
shake_camera(L, 4, 3)
|
||||
shake_camera(src, 2, 3)
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/ancient_robot_leg/ex_act(severity, target)
|
||||
switch(severity)
|
||||
if(1)
|
||||
adjustBruteLoss(25)
|
||||
|
||||
if(2)
|
||||
adjustBruteLoss(10)
|
||||
|
||||
if(3)
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/hostile/ancient_robot_leg/MeleeAction(patience = TRUE)
|
||||
if(core.charging || core.exploding)
|
||||
return
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/ancient_robot_leg/OpenFire() // This is (idealy) to keep the turrets on the legs from shooting people that are close to the robot. The guns will only shoot if they won't hit the robot, or if the user is between a leg and another leg / robot
|
||||
if(core.exploding)
|
||||
return
|
||||
if(get_dist(target, core) < 3)
|
||||
return
|
||||
if(prob(33))
|
||||
return
|
||||
ranged_cooldown_time = (rand(30, 60)) // keeps them not running on the same time
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/ancient_robot_leg/Moved(atom/OldLoc, Dir, Forced = FALSE)
|
||||
playsound(src, 'sound/effects/meteorimpact.ogg', 60, TRUE, 2, TRUE) //turned way down from bubblegum levels due to 4 legs
|
||||
|
||||
/obj/item/projectile/ancient_robot_bullet
|
||||
damage = 8
|
||||
damage_type = BRUTE
|
||||
|
||||
/obj/item/projectile/rock
|
||||
name= "thrown rock"
|
||||
damage = 25
|
||||
damage_type = BRUTE
|
||||
icon = 'icons/obj/meteor.dmi'
|
||||
icon_state = "small1"
|
||||
|
||||
/obj/effect/temp_visual/rock
|
||||
name = "floating rock"
|
||||
desc = "Might want to focus on dodging, rather than looking at it."
|
||||
icon = 'icons/obj/meteor.dmi'
|
||||
icon_state = "small1"
|
||||
duration = 20
|
||||
|
||||
/obj/item/projectile/energy/shock_revolver/ancient
|
||||
damage = 5
|
||||
|
||||
/obj/item/projectile/energy/shock_revolver/ancient/Bump(atom/A, yes) // Don't want the projectile hitting the legs
|
||||
if(!istype(/mob/living/simple_animal/hostile/ancient_robot_leg, A))
|
||||
return ..()
|
||||
var/turf/target_turf = get_turf(A)
|
||||
loc = target_turf
|
||||
|
||||
/obj/effect/temp_visual/dragon_swoop/bubblegum/ancient_robot //this is the worst path I have ever made
|
||||
icon_state = "target"
|
||||
|
||||
/obj/effect/temp_visual/dragon_swoop/bubblegum/ancient_robot/Initialize(mapload, target)
|
||||
. = ..()
|
||||
new /obj/effect/temp_visual/beam_target(get_turf(src), target) // Yup, we have to make *another* effect since beam doesn't work right with 64x64
|
||||
set_light(4, l_color = "#ee2e27")
|
||||
|
||||
/obj/effect/temp_visual/beam_target
|
||||
duration = 1.6 SECONDS
|
||||
var/datum/beam/charge
|
||||
|
||||
/obj/effect/temp_visual/beam_target/Initialize(mapload, target)
|
||||
. = ..()
|
||||
charge = Beam(target, "target_beam", 'icons/effects/effects.dmi', time=1.5 SECONDS, maxdistance=INFINITY, beam_type=/obj/effect/ebeam)
|
||||
|
||||
|
||||
/obj/effect/temp_visual/beam_target/Destroy()
|
||||
QDEL_NULL(charge)
|
||||
return ..()
|
||||
|
||||
/obj/effect/temp_visual/target/ancient
|
||||
|
||||
/obj/effect/temp_visual/target/ancient/fall(list/flame_hit)
|
||||
var/turf/T = get_turf(src)
|
||||
playsound(T,'sound/magic/fleshtostone.ogg', 80, TRUE)
|
||||
new /obj/effect/temp_visual/fireball/rock(T)
|
||||
sleep(duration)
|
||||
if(ismineralturf(T))
|
||||
var/turf/simulated/mineral/M = T
|
||||
M.gets_drilled()
|
||||
playsound(T, 'sound/effects/meteorimpact.ogg', 80, TRUE)
|
||||
for(var/mob/living/L in T.contents)
|
||||
if(istype(L, /mob/living/simple_animal/hostile/megafauna/ancient_robot))
|
||||
continue
|
||||
L.adjustBruteLoss(35)
|
||||
to_chat(L, "<span class='userdanger'>You're hit by the falling rock!</span>")
|
||||
|
||||
/obj/effect/temp_visual/fireball/rock
|
||||
icon = 'icons/obj/meteor.dmi'
|
||||
icon_state = "small1"
|
||||
|
||||
#undef BODY_SHIELD_COOLDOWN_TIME
|
||||
#undef EXTRA_PLAYER_ANGER_NORMAL_CAP
|
||||
#undef EXTRA_PLAYER_ANGER_STATION_CAP
|
||||
#undef BLUESPACE
|
||||
#undef GRAV
|
||||
#undef PYRO
|
||||
#undef FLUX
|
||||
#undef VORTEX
|
||||
|
Before Width: | Height: | Size: 380 KiB After Width: | Height: | Size: 385 KiB |
|
Before Width: | Height: | Size: 373 KiB After Width: | Height: | Size: 381 KiB |
|
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 92 KiB |
|
Before Width: | Height: | Size: 139 KiB After Width: | Height: | Size: 140 KiB |
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 49 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
@@ -1829,6 +1829,7 @@
|
||||
#include "code\modules\mining\laborcamp\laborstacker.dm"
|
||||
#include "code\modules\mining\lavaland\ash_flora.dm"
|
||||
#include "code\modules\mining\lavaland\necropolis_chests.dm"
|
||||
#include "code\modules\mining\lavaland\loot\ancient_loot.dm"
|
||||
#include "code\modules\mining\lavaland\loot\ashdragon_loot.dm"
|
||||
#include "code\modules\mining\lavaland\loot\bubblegum_loot.dm"
|
||||
#include "code\modules\mining\lavaland\loot\colossus_loot.dm"
|
||||
@@ -2102,6 +2103,7 @@
|
||||
#include "code\modules\mob\living\simple_animal\hostile\tree.dm"
|
||||
#include "code\modules\mob\living\simple_animal\hostile\venus_human_trap.dm"
|
||||
#include "code\modules\mob\living\simple_animal\hostile\winter_mobs.dm"
|
||||
#include "code\modules\mob\living\simple_animal\hostile\megafauna\ancient_robot.dm"
|
||||
#include "code\modules\mob\living\simple_animal\hostile\megafauna\blood_drunk_miner.dm"
|
||||
#include "code\modules\mob\living\simple_animal\hostile\megafauna\bubblegum.dm"
|
||||
#include "code\modules\mob\living\simple_animal\hostile\megafauna\colossus.dm"
|
||||
|
||||