Forgot to track the new files

This commit is contained in:
Useroth
2019-12-08 14:05:05 +01:00
parent a37f2de71d
commit 5e836c51e4
14 changed files with 1498 additions and 0 deletions

View File

@@ -0,0 +1,111 @@
//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
"a" = (
/turf/template_noop,
/area/lavaland/surface/outdoors)
"b" = (
/obj/structure/elite_tumor,
/turf/open/floor/plating/asteroid/basalt/lava_land_surface,
/area/lavaland/surface/outdoors)
"c" = (
/turf/open/floor/plating/asteroid/basalt/lava_land_surface,
/area/lavaland/surface/outdoors)
(1,1,1) = {"
a
a
a
a
a
a
a
a
a
"}
(2,1,1) = {"
a
a
a
a
a
a
a
a
a
"}
(3,1,1) = {"
a
a
a
a
a
a
a
a
a
"}
(4,1,1) = {"
a
a
a
c
c
c
a
a
a
"}
(5,1,1) = {"
a
a
a
c
b
c
a
a
a
"}
(6,1,1) = {"
a
a
a
c
c
c
a
a
a
"}
(7,1,1) = {"
a
a
a
a
a
a
a
a
a
"}
(8,1,1) = {"
a
a
a
a
a
a
a
a
a
"}
(9,1,1) = {"
a
a
a
a
a
a
a
a
a
"}

View File

@@ -0,0 +1,16 @@
/datum/hud/lavaland_elite
ui_style = 'icons/mob/screen_elite.dmi'
/datum/hud/lavaland_elite/New(mob/living/simple_animal/hostile/asteroid/elite)
..()
pull_icon = new /obj/screen/pull()
pull_icon.icon = ui_style
pull_icon.update_icon()
pull_icon.screen_loc = ui_living_pull
pull_icon.hud = src
static_inventory += pull_icon
healths = new /obj/screen/healths/lavaland_elite()
healths.hud = src
infodisplay += healths

View File

@@ -0,0 +1,360 @@
#define TUMOR_INACTIVE 0
#define TUMOR_ACTIVE 1
#define TUMOR_PASSIVE 2
//Elite mining mobs
/mob/living/simple_animal/hostile/asteroid/elite
name = "elite"
desc = "An elite monster, found in one of the strange tumors on lavaland."
icon = 'icons/mob/lavaland/lavaland_elites.dmi'
faction = list("boss")
robust_searching = TRUE
ranged_ignores_vision = TRUE
ranged = TRUE
obj_damage = 5
vision_range = 6
aggro_vision_range = 18
environment_smash = ENVIRONMENT_SMASH_NONE //This is to prevent elites smashing up the mining station, we'll make sure they can smash minerals fine below.
harm_intent_damage = 0 //Punching elites gets you nowhere
stat_attack = UNCONSCIOUS
layer = LARGE_MOB_LAYER
sentience_type = SENTIENCE_BOSS
hud_type = /datum/hud/lavaland_elite
var/chosen_attack = 1
var/list/attack_action_types = list()
var/can_talk = FALSE
var/obj/loot_drop = null
//Gives player-controlled variants the ability to swap attacks
/mob/living/simple_animal/hostile/asteroid/elite/Initialize(mapload)
. = ..()
for(var/action_type in attack_action_types)
var/datum/action/innate/elite_attack/attack_action = new action_type()
attack_action.Grant(src)
//Prevents elites from attacking members of their faction (can't hurt themselves either) and lets them mine rock with an attack despite not being able to smash walls.
/mob/living/simple_animal/hostile/asteroid/elite/AttackingTarget()
if(istype(target, /mob/living/simple_animal/hostile))
var/mob/living/simple_animal/hostile/M = target
if(faction_check_mob(M))
return FALSE
if(istype(target, /obj/structure/elite_tumor))
var/obj/structure/elite_tumor/T = target
if(T.mychild == src && T.activity == TUMOR_PASSIVE)
var/elite_remove = alert("Re-enter the tumor?", "Despawn yourself?", "Yes", "No")
if(elite_remove == "No" || !src || QDELETED(src))
return
T.mychild = null
T.activity = TUMOR_INACTIVE
T.icon_state = "advanced_tumor"
qdel(src)
return FALSE
. = ..()
if(ismineralturf(target))
var/turf/closed/mineral/M = target
M.gets_drilled()
//Elites can't talk (normally)!
/mob/living/simple_animal/hostile/asteroid/elite/say(message, bubble_type, var/list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null)
if(can_talk)
. = ..()
return TRUE
return FALSE
/*Basic setup for elite attacks, based on Whoneedspace's megafauna attack setup.
While using this makes the system rely on OnFire, it still gives options for timers not tied to OnFire, and it makes using attacks consistent accross the board for player-controlled elites.*/
/datum/action/innate/elite_attack
name = "Elite Attack"
icon_icon = 'icons/mob/actions/actions_elites.dmi'
button_icon_state = ""
background_icon_state = "bg_default"
var/mob/living/simple_animal/hostile/asteroid/elite/M
var/chosen_message
var/chosen_attack_num = 0
/datum/action/innate/elite_attack/Grant(mob/living/L)
if(istype(L, /mob/living/simple_animal/hostile/asteroid/elite))
M = L
return ..()
return FALSE
/datum/action/innate/elite_attack/Activate()
M.chosen_attack = chosen_attack_num
to_chat(M, chosen_message)
/mob/living/simple_animal/hostile/asteroid/elite/updatehealth()
. = ..()
update_health_hud()
/mob/living/simple_animal/hostile/asteroid/elite/update_health_hud()
if(hud_used)
var/severity = 0
var/healthpercent = (health/maxHealth) * 100
switch(healthpercent)
if(100 to INFINITY)
hud_used.healths.icon_state = "elite_health0"
if(80 to 100)
severity = 1
if(60 to 80)
severity = 2
if(40 to 60)
severity = 3
if(20 to 40)
severity = 4
if(10 to 20)
severity = 5
if(1 to 20)
severity = 6
else
severity = 7
hud_used.healths.icon_state = "elite_health[severity]"
if(severity > 0)
overlay_fullscreen("brute", /obj/screen/fullscreen/brute, severity)
else
clear_fullscreen("brute")
//The Pulsing Tumor, the actual "spawn-point" of elites, handles the spawning, arena, and procs for dealing with basic scenarios.
/obj/structure/elite_tumor
name = "pulsing tumor"
desc = "An odd, pulsing tumor sticking out of the ground. You feel compelled to reach out and touch it..."
armor = list("melee" = 100, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100)
resistance_flags = INDESTRUCTIBLE
var/activity = TUMOR_INACTIVE
var/boosted = FALSE
var/times_won = 0
var/mob/living/carbon/human/activator = null
var/mob/living/simple_animal/hostile/asteroid/elite/mychild = null
var/potentialspawns = list(/mob/living/simple_animal/hostile/asteroid/elite/broodmother,
/mob/living/simple_animal/hostile/asteroid/elite/pandora,
/mob/living/simple_animal/hostile/asteroid/elite/legionnaire,
/mob/living/simple_animal/hostile/asteroid/elite/herald)
icon = 'icons/obj/lavaland/tumor.dmi'
icon_state = "tumor"
pixel_x = -16
light_color = LIGHT_COLOR_RED
light_range = 3
anchored = TRUE
density = FALSE
/obj/structure/elite_tumor/attack_hand(mob/user)
. = ..()
if(ishuman(user))
switch(activity)
if(TUMOR_PASSIVE)
activity = TUMOR_ACTIVE
visible_message("<span class='boldwarning'>[src] convulses as your arm enters its radius. Your instincts tell you to step back.</span>")
activator = user
if(boosted)
mychild.playsound_local(get_turf(mychild), 'sound/effects/magic.ogg', 40, 0)
to_chat(mychild, "<b>Someone has activated your tumor. You will be returned to fight shortly, get ready!</b>")
addtimer(CALLBACK(src, .proc/return_elite), 30)
INVOKE_ASYNC(src, .proc/arena_checks)
if(TUMOR_INACTIVE)
activity = TUMOR_ACTIVE
var/mob/dead/observer/elitemind = null
visible_message("<span class='boldwarning'>[src] begins to convulse. Your instincts tell you to step back.</span>")
activator = user
if(!boosted)
addtimer(CALLBACK(src, .proc/spawn_elite), 30)
return
visible_message("<span class='boldwarning'>Something within [src] stirs...</span>")
var/list/candidates = pollCandidatesForMob("Do you want to play as a lavaland elite?", ROLE_SENTIENCE, null, ROLE_SENTIENCE, 50, src, POLL_IGNORE_SENTIENCE_POTION)
if(candidates.len)
audible_message("<span class='boldwarning'>The stirring sounds increase in volume!</span>")
elitemind = pick(candidates)
elitemind.playsound_local(get_turf(elitemind), 'sound/effects/magic.ogg', 40, 0)
to_chat(elitemind, "<b>You have been chosen to play as a Lavaland Elite.\nIn a few seconds, you will be summoned on Lavaland as a monster to fight your activator, in a fight to the death.\nYour attacks can be switched using the buttons on the top left of the HUD, and used by clicking on targets or tiles similar to a gun.\nWhile the opponent might have an upper hand with powerful mining equipment and tools, you have great power normally limited by AI mobs.\nIf you want to win, you'll have to use your powers in creative ways to ensure the kill. It's suggested you try using them all as soon as possible.\nShould you win, you'll receive extra information regarding what to do after. Good luck!</b>")
addtimer(CALLBACK(src, .proc/spawn_elite, elitemind), 100)
else
visible_message("<span class='boldwarning'>The stirring stops, and nothing emerges. Perhaps try again later.</span>")
activity = TUMOR_INACTIVE
activator = null
obj/structure/elite_tumor/proc/spawn_elite(var/mob/dead/observer/elitemind)
var/selectedspawn = pick(potentialspawns)
mychild = new selectedspawn(loc)
visible_message("<span class='boldwarning'>[mychild] emerges from [src]!</span>")
playsound(loc,'sound/effects/phasein.ogg', 200, 0, 50, TRUE, TRUE)
if(boosted)
mychild.key = elitemind.key
mychild.sentience_act()
icon_state = "tumor_popped"
INVOKE_ASYNC(src, .proc/arena_checks)
obj/structure/elite_tumor/proc/return_elite()
mychild.forceMove(loc)
visible_message("<span class='boldwarning'>[mychild] emerges from [src]!</span>")
playsound(loc,'sound/effects/phasein.ogg', 200, 0, 50, TRUE, TRUE)
mychild.revive(full_heal = TRUE, admin_revive = TRUE)
if(boosted)
mychild.maxHealth = mychild.maxHealth * 2
mychild.health = mychild.maxHealth
/obj/structure/elite_tumor/Initialize(mapload)
. = ..()
AddComponent(/datum/component/gps, "Menacing Signal")
START_PROCESSING(SSobj, src)
/obj/structure/elite_tumor/Destroy()
STOP_PROCESSING(SSobj, src)
mychild = null
activator = null
return ..()
/obj/structure/elite_tumor/process()
if(isturf(loc))
for(var/mob/living/simple_animal/hostile/asteroid/elite/elitehere in loc)
if(elitehere == mychild && activity == TUMOR_PASSIVE)
mychild.adjustHealth(-mychild.maxHealth*0.05)
var/obj/effect/temp_visual/heal/H = new /obj/effect/temp_visual/heal(get_turf(mychild))
H.color = "#FF0000"
/obj/structure/elite_tumor/attackby(obj/item/I, mob/user, params)
. = ..()
if(istype(I, /obj/item/organ/regenerative_core) && activity == TUMOR_INACTIVE && !boosted)
var/obj/item/organ/regenerative_core/core = I
if(!core.preserved)
return
visible_message("<span class='boldwarning'>As [user] drops the core into [src], [src] appears to swell.</span>")
icon_state = "advanced_tumor"
boosted = TRUE
light_range = 6
desc = "[desc] This one seems to glow with a strong intensity."
qdel(core)
return TRUE
/obj/structure/elite_tumor/proc/arena_checks()
if(activity != TUMOR_ACTIVE || QDELETED(src))
return
INVOKE_ASYNC(src, .proc/fighters_check) //Checks to see if our fighters died.
INVOKE_ASYNC(src, .proc/arena_trap) //Gets another arena trap queued up for when this one runs out.
INVOKE_ASYNC(src, .proc/border_check) //Checks to see if our fighters got out of the arena somehow.
addtimer(CALLBACK(src, .proc/arena_checks), 50)
/obj/structure/elite_tumor/proc/fighters_check()
if(activator != null && activator.stat == DEAD || activity == TUMOR_ACTIVE && QDELETED(activator))
onEliteWon()
if(mychild != null && mychild.stat == DEAD || activity == TUMOR_ACTIVE && QDELETED(mychild))
onEliteLoss()
/obj/structure/elite_tumor/proc/arena_trap()
var/turf/T = get_turf(src)
if(loc == null)
return
for(var/t in RANGE_TURFS(12, T))
if(get_dist(t, T) == 12)
var/obj/effect/temp_visual/elite_tumor_wall/newwall
newwall = new /obj/effect/temp_visual/elite_tumor_wall(t, src)
newwall.activator = src.activator
newwall.ourelite = src.mychild
/obj/structure/elite_tumor/proc/border_check()
if(activator != null && get_dist(src, activator) >= 12)
activator.forceMove(loc)
visible_message("<span class='boldwarning'>[activator] suddenly reappears above [src]!</span>")
playsound(loc,'sound/effects/phasein.ogg', 200, 0, 50, TRUE, TRUE)
if(mychild != null && get_dist(src, mychild) >= 12)
mychild.forceMove(loc)
visible_message("<span class='boldwarning'>[mychild] suddenly reappears above [src]!</span>")
playsound(loc,'sound/effects/phasein.ogg', 200, 0, 50, TRUE, TRUE)
obj/structure/elite_tumor/proc/onEliteLoss()
playsound(loc,'sound/effects/tendril_destroyed.ogg', 200, 0, 50, TRUE, TRUE)
visible_message("<span class='boldwarning'>[src] begins to convulse violently before beginning to dissipate.</span>")
visible_message("<span class='boldwarning'>As [src] closes, something is forced up from down below.</span>")
var/obj/structure/closet/crate/necropolis/tendril/lootbox = new /obj/structure/closet/crate/necropolis/tendril(loc)
if(!boosted)
mychild = null
activator = null
qdel(src)
return
var/lootpick = rand(1, 2)
if(lootpick == 1 && mychild.loot_drop != null)
new mychild.loot_drop(lootbox)
else
new /obj/item/tumor_shard(lootbox)
mychild = null
activator = null
qdel(src)
obj/structure/elite_tumor/proc/onEliteWon()
activity = TUMOR_PASSIVE
activator = null
mychild.revive(full_heal = TRUE, admin_revive = TRUE)
if(boosted)
times_won++
mychild.maxHealth = mychild.maxHealth * 0.5
mychild.health = mychild.maxHealth
if(times_won == 1)
mychild.playsound_local(get_turf(mychild), 'sound/effects/magic.ogg', 40, 0)
to_chat(mychild, "<span class='boldwarning'>As the life in the activator's eyes fade, the forcefield around you dies out and you feel your power subside.\nDespite this inferno being your home, you feel as if you aren't welcome here anymore.\nWithout any guidance, your purpose is now for you to decide.</span>")
to_chat(mychild, "<b>Your max health has been halved, but can now heal by standing on your tumor. Note, it's your only way to heal.\nBear in mind, if anyone interacts with your tumor, you'll be resummoned here to carry out another fight. In such a case, you will regain your full max health.\nAlso, be weary of your fellow inhabitants, they likely won't be happy to see you!</b>")
to_chat(mychild, "<span class='big bold'>Note that you are a lavaland monster, and thus not allied to the station. You should not cooperate or act friendly with any station crew unless under extreme circumstances!</span>")
/obj/item/tumor_shard
name = "tumor shard"
desc = "A strange, sharp, crystal shard from an odd tumor on Lavaland. Stabbing the corpse of a lavaland elite with this will revive them, assuming their soul still lingers. Revived lavaland elites only have half their max health, but are completely loyal to their reviver."
icon = 'icons/obj/lavaland/artefacts.dmi'
icon_state = "crevice_shard"
lefthand_file = 'icons/mob/inhands/equipment/tools_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/tools_righthand.dmi'
item_state = "screwdriver_head"
throwforce = 5
w_class = WEIGHT_CLASS_SMALL
throw_speed = 3
throw_range = 5
/obj/item/tumor_shard/afterattack(atom/target, mob/user, proximity_flag)
. = ..()
if(istype(target, /mob/living/simple_animal/hostile/asteroid/elite) && proximity_flag)
var/mob/living/simple_animal/hostile/asteroid/elite/E = target
if(E.stat != DEAD || E.sentience_type != SENTIENCE_BOSS || !E.key)
user.visible_message("<span class='notice'>It appears [E] is unable to be revived right now. Perhaps try again later.</span>")
return
E.faction = list("neutral")
E.revive(full_heal = TRUE, admin_revive = TRUE)
user.visible_message("<span class='notice'>[user] stabs [E] with [src], reviving it.</span>")
E.playsound_local(get_turf(E), 'sound/effects/magic.ogg', 40, 0)
to_chat(E, "<span class='userdanger'>You have been revived by [user]. While you can't speak to them, you owe [user] a great debt. Assist [user.p_them()] in achieving [user.p_their()] goals, regardless of risk.</span")
to_chat(E, "<span class='big bold'>Note that you now share the loyalties of [user]. You are expected not to intentionally sabotage their faction unless commanded to!</span>")
E.maxHealth = E.maxHealth * 0.5
E.health = E.maxHealth
E.desc = "[E.desc] However, this one appears appears less wild in nature, and calmer around people."
E.sentience_type = SENTIENCE_ORGANIC
qdel(src)
else
to_chat(user, "<span class='info'>[src] only works on the corpse of a sentient lavaland elite.</span>")
/obj/effect/temp_visual/elite_tumor_wall
name = "magic wall"
icon = 'icons/turf/walls/hierophant_wall_temp.dmi'
icon_state = "wall"
duration = 50
smooth = SMOOTH_TRUE
layer = BELOW_MOB_LAYER
var/mob/living/carbon/human/activator = null
var/mob/living/simple_animal/hostile/asteroid/elite/ourelite = null
color = rgb(255,0,0)
light_range = MINIMUM_USEFUL_LIGHT_RANGE
light_color = LIGHT_COLOR_RED
/obj/effect/temp_visual/elite_tumor_wall/Initialize(mapload, new_caster)
. = ..()
queue_smooth_neighbors(src)
queue_smooth(src)
/obj/effect/temp_visual/elite_tumor_wall/Destroy()
queue_smooth_neighbors(src)
activator = null
ourelite = null
return ..()
/obj/effect/temp_visual/elite_tumor_wall/CanPass(atom/movable/mover, turf/target)
if(mover == ourelite || mover == activator)
return FALSE
else
return TRUE

View File

@@ -0,0 +1,245 @@
#define TENTACLE_PATCH 1
#define SPAWN_CHILDREN 2
#define RAGE 3
#define CALL_CHILDREN 4
/**
* # Goliath Broodmother
*
* A stronger, faster variation of the goliath. Has the ability to spawn baby goliaths, which it can later detonate at will.
* When it's health is below half, tendrils will spawn randomly around it. When it is below a quarter of health, this effect is doubled.
* It's attacks are as follows:
* - Spawns a 3x3/plus shape of tentacles on the target location
* - Spawns 2 baby goliaths on its tile, up to a max of 8. Children blow up when they die.
* - The broodmother lets out a noise, and is able to move faster for 6.5 seconds.
* - Summons your children around you.
* The broodmother is a fight revolving around stage control, as the activator has to manage the baby goliaths and the broodmother herself, along with all the tendrils.
*/
/mob/living/simple_animal/hostile/asteroid/elite/broodmother
name = "goliath broodmother"
desc = "An example of sexual dimorphism, this female goliath looks much different than the males of her species. She is, however, just as dangerous, if not more."
gender = FEMALE
icon_state = "broodmother"
icon_living = "broodmother"
icon_aggro = "broodmother"
icon_dead = "egg_sac"
icon_gib = "syndicate_gib"
maxHealth = 800
health = 800
melee_damage_lower = 30
melee_damage_upper = 30
armour_penetration = 30
attack_verb_continuous = "beats down on"
attack_verb_simple = "beat down on"
attack_sound = 'sound/weapons/punch1.ogg'
throw_message = "does nothing to the rocky hide of the"
speed = 2
move_to_delay = 5
mob_biotypes = MOB_ORGANIC|MOB_BEAST
mouse_opacity = MOUSE_OPACITY_ICON
deathmessage = "explodes into gore!"
loot_drop = /obj/item/crusher_trophy/broodmother_tongue
attack_action_types = list(/datum/action/innate/elite_attack/tentacle_patch,
/datum/action/innate/elite_attack/spawn_children,
/datum/action/innate/elite_attack/rage,
/datum/action/innate/elite_attack/call_children)
var/rand_tent = 0
var/list/mob/living/simple_animal/hostile/asteroid/elite/broodmother_child/children_list = list()
/datum/action/innate/elite_attack/tentacle_patch
name = "Tentacle Patch"
button_icon_state = "tentacle_patch"
chosen_message = "<span class='boldwarning'>You are now attacking with a patch of tentacles.</span>"
chosen_attack_num = TENTACLE_PATCH
/datum/action/innate/elite_attack/spawn_children
name = "Spawn Children"
button_icon_state = "spawn_children"
chosen_message = "<span class='boldwarning'>You will spawn two children at your location to assist you in combat. You can have up to 8.</span>"
chosen_attack_num = SPAWN_CHILDREN
/datum/action/innate/elite_attack/rage
name = "Rage"
button_icon_state = "rage"
chosen_message = "<span class='boldwarning'>You will temporarily increase your movement speed.</span>"
chosen_attack_num = RAGE
/datum/action/innate/elite_attack/call_children
name = "Call Children"
button_icon_state = "call_children"
chosen_message = "<span class='boldwarning'>You will summon your children to your location.</span>"
chosen_attack_num = CALL_CHILDREN
/mob/living/simple_animal/hostile/asteroid/elite/broodmother/OpenFire()
if(client)
switch(chosen_attack)
if(TENTACLE_PATCH)
tentacle_patch(target)
if(SPAWN_CHILDREN)
spawn_children()
if(RAGE)
rage()
if(CALL_CHILDREN)
call_children()
return
var/aiattack = rand(1,4)
switch(aiattack)
if(TENTACLE_PATCH)
tentacle_patch(target)
if(SPAWN_CHILDREN)
spawn_children()
if(RAGE)
rage()
if(CALL_CHILDREN)
call_children()
/mob/living/simple_animal/hostile/asteroid/elite/broodmother/Life()
. = ..()
if(!.) //Checks if they are dead as a rock.
return
if(health < maxHealth * 0.5 && rand_tent < world.time)
rand_tent = world.time + 30
var/tentacle_amount = 5
if(health < maxHealth * 0.25)
tentacle_amount = 10
var/tentacle_loc = spiral_range_turfs(5, get_turf(src))
for(var/i in 1 to tentacle_amount)
var/turf/t = pick_n_take(tentacle_loc)
new /obj/effect/temp_visual/goliath_tentacle/broodmother(t, src)
/mob/living/simple_animal/hostile/asteroid/elite/broodmother/proc/tentacle_patch(var/target)
ranged_cooldown = world.time + 15
var/tturf = get_turf(target)
if(!isturf(tturf))
return
visible_message("<span class='warning'>[src] digs its tentacles under [target]!</span>")
new /obj/effect/temp_visual/goliath_tentacle/broodmother/patch(tturf, src)
/mob/living/simple_animal/hostile/asteroid/elite/broodmother/proc/spawn_children(var/target)
ranged_cooldown = world.time + 40
visible_message("<span class='boldwarning'>The ground churns behind [src]!</span>")
for(var/i in 1 to 2)
if(children_list.len >= 8)
return
var/mob/living/simple_animal/hostile/asteroid/elite/broodmother_child/newchild = new /mob/living/simple_animal/hostile/asteroid/elite/broodmother_child(loc)
newchild.GiveTarget(target)
newchild.faction = faction.Copy()
visible_message("<span class='boldwarning'>[newchild] appears below [src]!</span>")
newchild.mother = src
children_list += newchild
/mob/living/simple_animal/hostile/asteroid/elite/broodmother/proc/rage()
ranged_cooldown = world.time + 70
playsound(src,'sound/spookoween/insane_low_laugh.ogg', 200, 1)
visible_message("<span class='warning'>[src] starts picking up speed!</span>")
color = "#FF0000"
set_varspeed(0)
move_to_delay = 3
addtimer(CALLBACK(src, .proc/reset_rage), 65)
/mob/living/simple_animal/hostile/asteroid/elite/broodmother/proc/reset_rage()
color = "#FFFFFF"
set_varspeed(2)
move_to_delay = 5
/mob/living/simple_animal/hostile/asteroid/elite/broodmother/proc/call_children()
ranged_cooldown = world.time + 60
visible_message("<span class='warning'>The ground shakes near [src]!</span>")
var/list/directions = GLOB.cardinals.Copy() + GLOB.diagonals.Copy()
for(var/mob/child in children_list)
var/spawndir = pick_n_take(directions)
var/turf/T = get_step(src, spawndir)
if(T)
child.forceMove(T)
playsound(src, 'sound/effects/bamf.ogg', 100, 1)
//The goliath's children. Pretty weak, simple mobs which are able to put a single tentacle under their target when at range.
/mob/living/simple_animal/hostile/asteroid/elite/broodmother_child
name = "baby goliath"
desc = "A young goliath recently born from it's mother. While they hatch from eggs, said eggs are incubated in the mother until they are ready to be born."
icon = 'icons/mob/lavaland/lavaland_monsters.dmi'
icon_state = "goliath_baby"
icon_living = "goliath_baby"
icon_aggro = "goliath_baby"
icon_dead = "goliath_baby_dead"
icon_gib = "syndicate_gib"
maxHealth = 30
health = 30
melee_damage_lower = 5
melee_damage_upper = 5
attack_verb_continuous = "bashes against"
attack_verb_simple = "bash against"
attack_sound = 'sound/weapons/punch1.ogg'
throw_message = "does nothing to the rocky hide of the"
speed = 2
move_to_delay = 5
mob_biotypes = MOB_ORGANIC|MOB_BEAST
mouse_opacity = MOUSE_OPACITY_ICON
butcher_results = list()
guaranteed_butcher_results = list(/obj/item/stack/sheet/animalhide/goliath_hide = 1)
deathmessage = "falls to the ground."
status_flags = CANPUSH
var/mob/living/simple_animal/hostile/asteroid/elite/broodmother/mother = null
/mob/living/simple_animal/hostile/asteroid/elite/broodmother_child/OpenFire(target)
ranged_cooldown = world.time + 40
var/tturf = get_turf(target)
if(!isturf(tturf))
return
if(get_dist(src, target) <= 7)//Screen range check, so it can't attack people off-screen
visible_message("<span class='warning'>[src] digs one of its tentacles under [target]!</span>")
new /obj/effect/temp_visual/goliath_tentacle/broodmother(tturf, src)
/mob/living/simple_animal/hostile/asteroid/elite/broodmother_child/death()
. = ..()
if(mother != null)
mother.children_list -= src
visible_message("<span class='warning'>[src] explodes!</span>")
explosion(get_turf(loc),0,0,0,flame_range = 3, adminlog = FALSE)
gib()
//Tentacles have less stun time compared to regular variant, to balance being able to use them much more often. Also, 10 more damage.
/obj/effect/temp_visual/goliath_tentacle/broodmother/trip()
var/latched = FALSE
for(var/mob/living/L in loc)
if((!QDELETED(spawner) && spawner.faction_check_mob(L)) || L.stat == DEAD)
continue
visible_message("<span class='danger'>[src] grabs hold of [L]!</span>")
L.Stun(10)
L.adjustBruteLoss(rand(30,35))
latched = TRUE
if(!latched)
retract()
else
deltimer(timerid)
timerid = addtimer(CALLBACK(src, .proc/retract), 10, TIMER_STOPPABLE)
/obj/effect/temp_visual/goliath_tentacle/broodmother/patch/Initialize(mapload, new_spawner)
. = ..()
var/tentacle_locs = spiral_range_turfs(1, get_turf(src))
for(var/T in tentacle_locs)
new /obj/effect/temp_visual/goliath_tentacle/broodmother(T, spawner)
var/list/directions = GLOB.cardinals.Copy()
for(var/i in directions)
var/turf/T = get_step(get_turf(src), i)
T = get_step(T, i)
new /obj/effect/temp_visual/goliath_tentacle/broodmother(T, spawner)
// Broodmother's loot: Broodmother Tongue
/obj/item/crusher_trophy/broodmother_tongue
name = "broodmother tongue"
desc = "The tongue of a broodmother. If attached a certain way, makes for a suitable crusher trophy."
icon = 'icons/obj/lavaland/elite_trophies.dmi'
icon_state = "broodmother_tongue"
denied_type = /obj/item/crusher_trophy/broodmother_tongue
bonus_value = 10
/obj/item/crusher_trophy/broodmother_tongue/effect_desc()
return "mark detonation to have a <b>[bonus_value]%</b> chance to summon a patch of goliath tentacles at the target's location"
/obj/item/crusher_trophy/broodmother_tongue/on_mark_detonation(mob/living/target, mob/living/user)
if(rand(1, 100) <= bonus_value && target.stat != DEAD)
new /obj/effect/temp_visual/goliath_tentacle/broodmother/patch(get_turf(target), user)

View File

@@ -0,0 +1,274 @@
#define HERALD_TRISHOT 1
#define HERALD_DIRECTIONALSHOT 2
#define HERALD_TELESHOT 3
#define HERALD_MIRROR 4
/**
* # Herald
*
* A slow-moving projectile user with a few tricks up it's sleeve. Less unga-bunga than Colossus, with more cleverness in it's fighting style.
* As it's health gets lower, the amount of projectiles fired per-attack increases.
* It's attacks are as follows:
* - Fires three projectiles in a a given direction.
* - Fires a spread in every cardinal and diagonal direction at once, then does it again after a bit.
* - Shoots a single, golden bolt. Wherever it lands, the herald will be teleported to the location.
* - Spawns a mirror which reflects projectiles directly at the target.
* Herald is a more concentrated variation of the Colossus fight, having less projectiles overall, but more focused attacks.
*/
/mob/living/simple_animal/hostile/asteroid/elite/herald
name = "herald"
desc = "A monstrous beast which fires deadly projectiles at threats and prey."
icon_state = "herald"
icon_living = "herald"
icon_aggro = "herald"
icon_dead = "herald_dying"
icon_gib = "syndicate_gib"
maxHealth = 800
health = 800
melee_damage_lower = 20
melee_damage_upper = 20
attack_verb_continuous = "preaches to"
attack_verb_simple = "preach to"
attack_sound = 'sound/magic/clockwork/ratvar_attack.ogg'
throw_message = "doesn't affect the purity of"
speed = 4
move_to_delay = 10
mouse_opacity = MOUSE_OPACITY_ICON
deathsound = 'sound/magic/demon_dies.ogg'
deathmessage = "begins to shudder as it becomes transparent..."
loot_drop = /obj/item/clothing/neck/cloak/herald_cloak
can_talk = 1
attack_action_types = list(/datum/action/innate/elite_attack/herald_trishot,
/datum/action/innate/elite_attack/herald_directionalshot,
/datum/action/innate/elite_attack/herald_teleshot,
/datum/action/innate/elite_attack/herald_mirror)
var/mob/living/simple_animal/hostile/asteroid/elite/herald/mirror/my_mirror = null
var/is_mirror = FALSE
/mob/living/simple_animal/hostile/asteroid/elite/herald/death()
. = ..()
if(!is_mirror)
addtimer(CALLBACK(src, .proc/become_ghost), 8)
if(my_mirror != null)
qdel(my_mirror)
/mob/living/simple_animal/hostile/asteroid/elite/herald/proc/become_ghost()
icon_state = "herald_ghost"
/mob/living/simple_animal/hostile/asteroid/elite/herald/say(message, bubble_type, var/list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null)
. = ..()
playsound(get_turf(src), 'sound/magic/clockwork/invoke_general.ogg', 20, TRUE)
/datum/action/innate/elite_attack/herald_trishot
name = "Triple Shot"
button_icon_state = "herald_trishot"
chosen_message = "<span class='boldwarning'>You are now firing three shots in your chosen direction.</span>"
chosen_attack_num = HERALD_TRISHOT
/datum/action/innate/elite_attack/herald_directionalshot
name = "Circular Shot"
button_icon_state = "herald_directionalshot"
chosen_message = "<span class='boldwarning'>You are firing projectiles in all directions.</span>"
chosen_attack_num = HERALD_DIRECTIONALSHOT
/datum/action/innate/elite_attack/herald_teleshot
name = "Teleport Shot"
button_icon_state = "herald_teleshot"
chosen_message = "<span class='boldwarning'>You will now fire a shot which teleports you where it lands.</span>"
chosen_attack_num = HERALD_TELESHOT
/datum/action/innate/elite_attack/herald_mirror
name = "Summon Mirror"
button_icon_state = "herald_mirror"
chosen_message = "<span class='boldwarning'>You will spawn a mirror which duplicates your attacks.</span>"
chosen_attack_num = HERALD_MIRROR
/mob/living/simple_animal/hostile/asteroid/elite/herald/OpenFire()
if(client)
switch(chosen_attack)
if(HERALD_TRISHOT)
herald_trishot(target)
if(my_mirror != null)
my_mirror.herald_trishot(target)
if(HERALD_DIRECTIONALSHOT)
herald_directionalshot()
if(my_mirror != null)
my_mirror.herald_directionalshot()
if(HERALD_TELESHOT)
herald_teleshot(target)
if(my_mirror != null)
my_mirror.herald_teleshot(target)
if(HERALD_MIRROR)
herald_mirror()
return
var/aiattack = rand(1,4)
switch(aiattack)
if(HERALD_TRISHOT)
herald_trishot(target)
if(my_mirror != null)
my_mirror.herald_trishot(target)
if(HERALD_DIRECTIONALSHOT)
herald_directionalshot()
if(my_mirror != null)
my_mirror.herald_directionalshot()
if(HERALD_TELESHOT)
herald_teleshot(target)
if(my_mirror != null)
my_mirror.herald_teleshot(target)
if(HERALD_MIRROR)
herald_mirror()
/mob/living/simple_animal/hostile/asteroid/elite/herald/proc/shoot_projectile(turf/marker, set_angle, var/is_teleshot)
var/turf/startloc = get_turf(src)
var/obj/projectile/herald/H = null
if(!is_teleshot)
H = new /obj/projectile/herald(startloc)
else
H = new /obj/projectile/herald/teleshot(startloc)
H.preparePixelProjectile(marker, startloc)
H.firer = src
if(target)
H.original = target
H.fire(set_angle)
/mob/living/simple_animal/hostile/asteroid/elite/herald/proc/herald_trishot(target)
ranged_cooldown = world.time + 30
playsound(get_turf(src), 'sound/magic/clockwork/invoke_general.ogg', 20, TRUE)
var/target_turf = get_turf(target)
var/angle_to_target = Get_Angle(src, target_turf)
shoot_projectile(target_turf, angle_to_target, FALSE)
addtimer(CALLBACK(src, .proc/shoot_projectile, target_turf, angle_to_target, FALSE), 2)
addtimer(CALLBACK(src, .proc/shoot_projectile, target_turf, angle_to_target, FALSE), 4)
if(health < maxHealth * 0.5)
playsound(get_turf(src), 'sound/magic/clockwork/invoke_general.ogg', 20, TRUE)
addtimer(CALLBACK(src, .proc/shoot_projectile, target_turf, angle_to_target, FALSE), 10)
addtimer(CALLBACK(src, .proc/shoot_projectile, target_turf, angle_to_target, FALSE), 12)
addtimer(CALLBACK(src, .proc/shoot_projectile, target_turf, angle_to_target, FALSE), 14)
/mob/living/simple_animal/hostile/asteroid/elite/herald/proc/herald_circleshot()
var/static/list/directional_shot_angles = list(0, 45, 90, 135, 180, 225, 270, 315)
for(var/i in directional_shot_angles)
shoot_projectile(get_turf(src), i, FALSE)
/mob/living/simple_animal/hostile/asteroid/elite/herald/proc/unenrage()
if(stat == DEAD || is_mirror)
return
icon_state = "herald"
/mob/living/simple_animal/hostile/asteroid/elite/herald/proc/herald_directionalshot()
ranged_cooldown = world.time + 50
if(!is_mirror)
icon_state = "herald_enraged"
playsound(get_turf(src), 'sound/magic/clockwork/invoke_general.ogg', 20, TRUE)
addtimer(CALLBACK(src, .proc/herald_circleshot), 5)
if(health < maxHealth * 0.5)
playsound(get_turf(src), 'sound/magic/clockwork/invoke_general.ogg', 20, TRUE)
addtimer(CALLBACK(src, .proc/herald_circleshot), 15)
addtimer(CALLBACK(src, .proc/unenrage), 20)
/mob/living/simple_animal/hostile/asteroid/elite/herald/proc/herald_teleshot(target)
ranged_cooldown = world.time + 30
playsound(get_turf(src), 'sound/magic/clockwork/invoke_general.ogg', 20, TRUE)
var/target_turf = get_turf(target)
var/angle_to_target = Get_Angle(src, target_turf)
shoot_projectile(target_turf, angle_to_target, TRUE)
/mob/living/simple_animal/hostile/asteroid/elite/herald/proc/herald_mirror()
ranged_cooldown = world.time + 40
playsound(get_turf(src), 'sound/magic/clockwork/invoke_general.ogg', 20, TRUE)
if(my_mirror != null)
qdel(my_mirror)
my_mirror = null
var/mob/living/simple_animal/hostile/asteroid/elite/herald/mirror/new_mirror = new /mob/living/simple_animal/hostile/asteroid/elite/herald/mirror(loc)
my_mirror = new_mirror
my_mirror.my_master = src
my_mirror.faction = faction.Copy()
/mob/living/simple_animal/hostile/asteroid/elite/herald/mirror
name = "herald's mirror"
desc = "This fiendish work of magic copies the herald's attacks. Seems logical to smash it."
health = 60
maxHealth = 60
icon_state = "herald_mirror"
deathmessage = "shatters violently!"
deathsound = 'sound/effects/glassbr1.ogg'
movement_type = FLYING
del_on_death = TRUE
is_mirror = TRUE
var/mob/living/simple_animal/hostile/asteroid/elite/herald/my_master = null
/mob/living/simple_animal/hostile/asteroid/elite/herald/mirror/Initialize()
..()
toggle_ai(AI_OFF)
/mob/living/simple_animal/hostile/asteroid/elite/herald/mirror/Destroy()
if(my_master != null)
my_master.my_mirror = null
. = ..()
/obj/projectile/herald
name ="death bolt"
icon_state= "chronobolt"
damage = 15
armour_penetration = 60
speed = 2
eyeblur = 0
damage_type = BRUTE
pass_flags = PASSTABLE
/obj/projectile/herald/teleshot
name ="golden bolt"
damage = 0
color = rgb(255,255,102)
/obj/projectile/herald/on_hit(atom/target, blocked = FALSE)
. = ..()
if(ismineralturf(target))
var/turf/closed/mineral/M = target
M.gets_drilled()
return
else if(isliving(target))
var/mob/living/L = target
var/mob/living/F = firer
if(F != null && istype(F, /mob/living/simple_animal/hostile/asteroid/elite) && F.faction_check_mob(L))
L.heal_overall_damage(damage)
/obj/projectile/herald/teleshot/on_hit(atom/target, blocked = FALSE)
. = ..()
firer.forceMove(get_turf(src))
//Herald's loot: Cloak of the Prophet
/obj/item/clothing/neck/cloak/herald_cloak
name = "cloak of the prophet"
desc = "A cloak which protects you from the heresy of the world."
icon = 'icons/obj/lavaland/elite_trophies.dmi'
icon_state = "herald_cloak"
body_parts_covered = CHEST|GROIN|ARMS
hit_reaction_chance = 10
/obj/item/clothing/neck/cloak/herald_cloak/proc/reactionshot(mob/living/carbon/owner)
var/static/list/directional_shot_angles = list(0, 45, 90, 135, 180, 225, 270, 315)
for(var/i in directional_shot_angles)
shoot_projectile(get_turf(owner), i, owner)
/obj/item/clothing/neck/cloak/herald_cloak/proc/shoot_projectile(turf/marker, set_angle, mob/living/carbon/owner)
var/turf/startloc = get_turf(owner)
var/obj/projectile/herald/H = null
H = new /obj/projectile/herald(startloc)
H.preparePixelProjectile(marker, startloc)
H.firer = owner
H.fire(set_angle)
/obj/item/clothing/neck/cloak/herald_cloak/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
. = ..()
if(rand(1,100) > hit_reaction_chance)
return
owner.visible_message("<span class='danger'>[owner]'s [src] emits a loud noise as [owner] is struck!</span>")
var/static/list/directional_shot_angles = list(0, 45, 90, 135, 180, 225, 270, 315)
playsound(get_turf(owner), 'sound/magic/clockwork/invoke_general.ogg', 20, TRUE)
addtimer(CALLBACK(src, .proc/reactionshot, owner), 10)

View File

@@ -0,0 +1,300 @@
#define LEGIONNAIRE_CHARGE 1
#define HEAD_DETACH 2
#define BONFIRE_TELEPORT 3
#define SPEW_SMOKE 4
/**
* # Legionnaire
*
* A towering skeleton, embodying the power of Legion.
* As it's health gets lower, the head does more damage.
* It's attacks are as follows:
* - Charges at the target after a telegraph, throwing them across the arena should it connect.
* - Legionnaire's head detaches, attacking as it's own entity. Has abilities of it's own later into the fight. Once dead, regenerates after a brief period. If the skill is used while the head is off, it will be killed.
* - Leaves a pile of bones at your location. Upon using this skill again, you'll swap locations with the bone pile.
* - Spews a cloud of smoke from it's maw, wherever said maw is.
* A unique fight incorporating the head mechanic of legion into a whole new beast. Combatants will need to make sure the tag-team of head and body don't lure them into a deadly trap.
*/
/mob/living/simple_animal/hostile/asteroid/elite/legionnaire
name = "legionnaire"
desc = "A towering skeleton, embodying the terrifying power of Legion."
icon_state = "legionnaire"
icon_living = "legionnaire"
icon_aggro = "legionnaire"
icon_dead = "legionnaire_dead"
icon_gib = "syndicate_gib"
maxHealth = 800
health = 800
melee_damage_lower = 30
melee_damage_upper = 30
attack_verb_continuous = "slashes its arms at"
attack_verb_simple = "slash your arms at"
attack_sound = 'sound/weapons/bladeslice.ogg'
throw_message = "doesn't affect the sturdiness of"
speed = 1
move_to_delay = 3
mouse_opacity = MOUSE_OPACITY_ICON
deathsound = 'sound/magic/curse.ogg'
deathmessage = "'s arms reach out before it falls apart onto the floor, lifeless."
loot_drop = /obj/item/crusher_trophy/legionnaire_spine
attack_action_types = list(/datum/action/innate/elite_attack/legionnaire_charge,
/datum/action/innate/elite_attack/head_detach,
/datum/action/innate/elite_attack/bonfire_teleport,
/datum/action/innate/elite_attack/spew_smoke)
var/mob/living/simple_animal/hostile/asteroid/elite/legionnairehead/myhead = null
var/obj/structure/legionnaire_bonfire/mypile = null
var/has_head = TRUE
/datum/action/innate/elite_attack/legionnaire_charge
name = "Legionnaire Charge"
button_icon_state = "legionnaire_charge"
chosen_message = "<span class='boldwarning'>You will attempt to grab your opponent and throw them.</span>"
chosen_attack_num = LEGIONNAIRE_CHARGE
/datum/action/innate/elite_attack/head_detach
name = "Release Head"
button_icon_state = "head_detach"
chosen_message = "<span class='boldwarning'>You will now detach your head or kill it if it is already released.</span>"
chosen_attack_num = HEAD_DETACH
/datum/action/innate/elite_attack/bonfire_teleport
name = "Bonfire Teleport"
button_icon_state = "bonfire_teleport"
chosen_message = "<span class='boldwarning'>You will leave a bonfire. Second use will let you swap positions with it indefintiely. Using this move on the same tile as your active bonfire removes it.</span>"
chosen_attack_num = BONFIRE_TELEPORT
/datum/action/innate/elite_attack/spew_smoke
name = "Spew Smoke"
button_icon_state = "spew_smoke"
chosen_message = "<span class='boldwarning'>Your head will spew smoke in an area, wherever it may be.</span>"
chosen_attack_num = SPEW_SMOKE
/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/OpenFire()
if(client)
switch(chosen_attack)
if(LEGIONNAIRE_CHARGE)
legionnaire_charge(target)
if(HEAD_DETACH)
head_detach(target)
if(BONFIRE_TELEPORT)
bonfire_teleport()
if(SPEW_SMOKE)
spew_smoke()
return
var/aiattack = rand(1,4)
switch(aiattack)
if(LEGIONNAIRE_CHARGE)
legionnaire_charge(target)
if(HEAD_DETACH)
head_detach(target)
if(BONFIRE_TELEPORT)
bonfire_teleport()
if(SPEW_SMOKE)
spew_smoke()
/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/proc/legionnaire_charge(target)
ranged_cooldown = world.time + 50
var/dir_to_target = get_dir(get_turf(src), get_turf(target))
var/turf/T = get_step(get_turf(src), dir_to_target)
for(var/i in 1 to 4)
new /obj/effect/temp_visual/dragon_swoop/legionnaire(T)
T = get_step(T, dir_to_target)
playsound(src,'sound/magic/demon_attack1.ogg', 200, 1)
visible_message("<span class='boldwarning'>[src] prepares to charge!</span>")
addtimer(CALLBACK(src, .proc/legionnaire_charge_2, dir_to_target, 0), 5)
/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/proc/legionnaire_charge_2(var/move_dir, var/times_ran)
if(times_ran >= 4)
return
var/turf/T = get_step(get_turf(src), move_dir)
if(ismineralturf(T))
var/turf/closed/mineral/M = T
M.gets_drilled()
if(T.density)
return
for(var/obj/structure/window/W in T.contents)
return
for(var/obj/machinery/door/D in T.contents)
return
forceMove(T)
playsound(src,'sound/effects/bang.ogg', 200, 1)
var/list/hit_things = list()
var/throwtarget = get_edge_target_turf(src, move_dir)
for(var/mob/living/L in T.contents - hit_things - src)
if(faction_check_mob(L))
return
hit_things += L
visible_message("<span class='boldwarning'>[src] attacks [L] with much force!</span>")
to_chat(L, "<span class='userdanger'>[src] grabs you and throws you with much force!</span>")
L.safe_throw_at(throwtarget, 10, 1, src)
L.Paralyze(20)
L.adjustBruteLoss(50)
addtimer(CALLBACK(src, .proc/legionnaire_charge_2, move_dir, (times_ran + 1)), 2)
/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/proc/head_detach(target)
ranged_cooldown = world.time + 10
if(myhead != null)
myhead.adjustBruteLoss(600)
return
if(has_head)
has_head = FALSE
icon_state = "legionnaire_headless"
icon_living = "legionnaire_headless"
icon_aggro = "legionnaire_headless"
visible_message("<span class='boldwarning'>[src]'s head flies off!</span>")
var/mob/living/simple_animal/hostile/asteroid/elite/legionnairehead/newhead = new /mob/living/simple_animal/hostile/asteroid/elite/legionnairehead(loc)
newhead.flags_1 |= (flags_1 & ADMIN_SPAWNED_1)
newhead.GiveTarget(target)
newhead.faction = faction.Copy()
myhead = newhead
myhead.body = src
if(health < maxHealth * 0.25)
myhead.melee_damage_lower = 30
myhead.melee_damage_upper = 30
else if(health < maxHealth * 0.5)
myhead.melee_damage_lower = 20
myhead.melee_damage_upper = 20
/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/proc/onHeadDeath()
myhead = null
addtimer(CALLBACK(src, .proc/regain_head), 50)
/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/proc/regain_head()
has_head = TRUE
if(stat == DEAD)
return
icon_state = "legionnaire"
icon_living = "legionnaire"
icon_aggro = "legionnaire"
visible_message("<span class='boldwarning'>The top of [src]'s spine leaks a black liquid, forming into a skull!</span>")
/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/proc/bonfire_teleport()
ranged_cooldown = world.time + 5
if(mypile == null)
var/obj/structure/legionnaire_bonfire/newpile = new /obj/structure/legionnaire_bonfire(loc)
mypile = newpile
mypile.myowner = src
playsound(get_turf(src),'sound/items/fulext_deploy.wav', 200, 1)
visible_message("<span class='boldwarning'>[src] summons a bonfire on [get_turf(src)]!</span>")
return
else
var/turf/legionturf = get_turf(src)
var/turf/pileturf = get_turf(mypile)
if(legionturf == pileturf)
mypile.take_damage(100)
mypile = null
return
playsound(pileturf,'sound/items/fulext_deploy.wav', 200, 1)
playsound(legionturf,'sound/items/fulext_deploy.wav', 200, 1)
visible_message("<span class='boldwarning'>[src] melts down into a burning pile of bones!</span>")
forceMove(pileturf)
visible_message("<span class='boldwarning'>[src] forms from the bonfire!</span>")
mypile.forceMove(legionturf)
/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/proc/spew_smoke()
ranged_cooldown = world.time + 60
var/turf/T = null
if(myhead != null)
T = get_turf(myhead)
else
T = get_turf(src)
if(myhead != null)
myhead.visible_message("<span class='boldwarning'>[myhead] spews smoke from its maw!</span>")
else if(!has_head)
visible_message("<span class='boldwarning'>[src] spews smoke from the tip of their spine!</span>")
else
visible_message("<span class='boldwarning'>[src] spews smoke from its maw!</span>")
var/datum/effect_system/smoke_spread/smoke = new
smoke.set_up(2, T)
smoke.start()
//The legionnaire's head. Basically the same as any legion head, but we have to tell our creator when we die so they can generate another head.
/mob/living/simple_animal/hostile/asteroid/elite/legionnairehead
name = "legionnaire head"
desc = "The legionnaire's head floating by itself. One shouldn't get too close, though once it sees you, you really don't have a choice."
icon_state = "legionnaire_head"
icon_living = "legionnaire_head"
icon_aggro = "legionnaire_head"
icon_dead = "legionnaire_dead"
icon_gib = "syndicate_gib"
maxHealth = 80
health = 80
melee_damage_lower = 10
melee_damage_upper = 10
attack_verb_continuous = "bites at"
attack_verb_simple = "bite at"
attack_sound = 'sound/effects/curse1.ogg'
throw_message = "simply misses"
speed = 0
move_to_delay = 2
del_on_death = 1
deathmessage = "crumbles away!"
faction = list()
ranged = FALSE
var/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/body = null
/mob/living/simple_animal/hostile/asteroid/elite/legionnairehead/death()
. = ..()
if(body)
body.onHeadDeath()
//The legionnaire's bonfire, which can be swapped positions with. Also sets flammable living beings on fire when they walk over it.
/obj/structure/legionnaire_bonfire
name = "bone pile"
desc = "A pile of bones which seems to occasionally move a little. It's probably a good idea to smash them."
icon = 'icons/obj/lavaland/legionnaire_bonfire.dmi'
icon_state = "bonfire"
max_integrity = 100
move_resist = MOVE_FORCE_EXTREMELY_STRONG
anchored = TRUE
density = FALSE
light_range = 4
light_color = LIGHT_COLOR_RED
var/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/myowner = null
/obj/structure/legionnaire_bonfire/Entered(atom/movable/mover, turf/target)
if(isliving(mover))
var/mob/living/L = mover
L.adjust_fire_stacks(3)
L.IgniteMob()
. = ..()
/obj/structure/legionnaire_bonfire/Destroy()
if(myowner != null)
myowner.mypile = null
. = ..()
//The visual effect which appears in front of legionnaire when he goes to charge.
/obj/effect/temp_visual/dragon_swoop/legionnaire
duration = 10
color = rgb(0,0,0)
/obj/effect/temp_visual/dragon_swoop/legionnaire/Initialize()
. = ..()
transform *= 0.33
// Legionnaire's loot: Legionnaire Spine
/obj/item/crusher_trophy/legionnaire_spine
name = "legionnaire spine"
desc = "The spine of a legionnaire. It almost feels like it's moving..."
icon = 'icons/obj/lavaland/elite_trophies.dmi'
icon_state = "legionnaire_spine"
denied_type = /obj/item/crusher_trophy/legionnaire_spine
bonus_value = 20
/obj/item/crusher_trophy/legionnaire_spine/effect_desc()
return "mark detonation to have a <b>[bonus_value]%</b> chance to summon a loyal legion skull"
/obj/item/crusher_trophy/legionnaire_spine/on_mark_detonation(mob/living/target, mob/living/user)
if(!rand(1, 100) <= bonus_value || target.stat == DEAD)
return
var/mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion/A = new /mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion(user.loc)
A.flags_1 |= (flags_1 & ADMIN_SPAWNED_1)
A.GiveTarget(target)
A.friends = user
A.faction = user.faction.Copy()

View File

@@ -0,0 +1,192 @@
#define SINGULAR_SHOT 1
#define MAGIC_BOX 2
#define PANDORA_TELEPORT 3
#define AOE_SQUARES 4
/**
* # Pandora
*
* A box with a similar design to the Hierophant which trades large, single attacks for more frequent smaller ones.
* As it's health gets lower, the time between it's attacks decrease.
* It's attacks are as follows:
* - Fires hierophant blasts in a straight line. Can only fire in a straight line in 8 directions, being the diagonals and cardinals.
* - Creates a box of hierophant blasts around the target. If they try to run away to avoid it, they'll very likely get hit.
* - Teleports the pandora from one location to another, almost identical to Hierophant.
* - Spawns a 5x5 AOE at the location of choice, spreading out from the center.
* Pandora's fight mirrors Hierophant's closely, but has stark differences in attack effects. Instead of long-winded dodge times and long cooldowns, Pandora constantly attacks the opponent, but leaves itself open for attack.
*/
/mob/living/simple_animal/hostile/asteroid/elite/pandora
name = "pandora"
desc = "A large magic box with similar power and design to the Hierophant. Once it opens, it's not easy to close it."
icon_state = "pandora"
icon_living = "pandora"
icon_aggro = "pandora"
icon_dead = "pandora_dead"
icon_gib = "syndicate_gib"
maxHealth = 800
health = 800
melee_damage_lower = 15
melee_damage_upper = 15
attack_verb_continuous = "smashes into the side of"
attack_verb_simple = "smash into the side of"
attack_sound = 'sound/weapons/sonic_jackhammer.ogg'
throw_message = "merely dinks off of the"
speed = 4
move_to_delay = 10
mouse_opacity = MOUSE_OPACITY_ICON
deathsound = 'sound/magic/repulse.ogg'
deathmessage = "'s lights flicker, before its top part falls down."
loot_drop = /obj/item/clothing/accessory/pandora_hope
attack_action_types = list(/datum/action/innate/elite_attack/singular_shot,
/datum/action/innate/elite_attack/magic_box,
/datum/action/innate/elite_attack/pandora_teleport,
/datum/action/innate/elite_attack/aoe_squares)
var/sing_shot_length = 8
var/cooldown_time = 20
/datum/action/innate/elite_attack/singular_shot
name = "Singular Shot"
button_icon_state = "singular_shot"
chosen_message = "<span class='boldwarning'>You are now creating a single linear magic square.</span>"
chosen_attack_num = SINGULAR_SHOT
/datum/action/innate/elite_attack/magic_box
name = "Magic Box"
button_icon_state = "magic_box"
chosen_message = "<span class='boldwarning'>You are now attacking with a box of magic squares.</span>"
chosen_attack_num = MAGIC_BOX
/datum/action/innate/elite_attack/pandora_teleport
name = "Line Teleport"
button_icon_state = "pandora_teleport"
chosen_message = "<span class='boldwarning'>You will now teleport to your target.</span>"
chosen_attack_num = PANDORA_TELEPORT
/datum/action/innate/elite_attack/aoe_squares
name = "AOE Blast"
button_icon_state = "aoe_squares"
chosen_message = "<span class='boldwarning'>Your attacks will spawn an AOE blast at your target location.</span>"
chosen_attack_num = AOE_SQUARES
/mob/living/simple_animal/hostile/asteroid/elite/pandora/OpenFire()
if(client)
switch(chosen_attack)
if(SINGULAR_SHOT)
singular_shot(target)
if(MAGIC_BOX)
magic_box(target)
if(PANDORA_TELEPORT)
pandora_teleport(target)
if(AOE_SQUARES)
aoe_squares(target)
return
var/aiattack = rand(1,4)
switch(aiattack)
if(SINGULAR_SHOT)
singular_shot(target)
if(MAGIC_BOX)
magic_box(target)
if(PANDORA_TELEPORT)
pandora_teleport(target)
if(AOE_SQUARES)
aoe_squares(target)
/mob/living/simple_animal/hostile/asteroid/elite/pandora/Life()
. = ..()
if(health >= maxHealth * 0.5)
cooldown_time = 20
return
if(health < maxHealth * 0.5 && health > maxHealth * 0.25)
cooldown_time = 15
return
else
cooldown_time = 10
/mob/living/simple_animal/hostile/asteroid/elite/pandora/proc/singular_shot(target)
ranged_cooldown = world.time + (cooldown_time * 0.5)
var/dir_to_target = get_dir(get_turf(src), get_turf(target))
var/turf/T = get_step(get_turf(src), dir_to_target)
singular_shot_line(sing_shot_length, dir_to_target, T)
/mob/living/simple_animal/hostile/asteroid/elite/pandora/proc/singular_shot_line(var/procsleft, var/angleused, var/turf/T)
if(procsleft <= 0)
return
new /obj/effect/temp_visual/hierophant/blast/pandora(T, src)
T = get_step(T, angleused)
procsleft = procsleft - 1
addtimer(CALLBACK(src, .proc/singular_shot_line, procsleft, angleused, T), 2)
/mob/living/simple_animal/hostile/asteroid/elite/pandora/proc/magic_box(target)
ranged_cooldown = world.time + cooldown_time
var/turf/T = get_turf(target)
for(var/t in spiral_range_turfs(3, T))
if(get_dist(t, T) > 1)
new /obj/effect/temp_visual/hierophant/blast/pandora(t, src)
/mob/living/simple_animal/hostile/asteroid/elite/pandora/proc/pandora_teleport(target)
ranged_cooldown = world.time + cooldown_time
var/turf/T = get_turf(target)
var/turf/source = get_turf(src)
new /obj/effect/temp_visual/hierophant/telegraph(T, src)
new /obj/effect/temp_visual/hierophant/telegraph(source, src)
playsound(source,'sound/machines/airlockopen.ogg', 200, 1)
addtimer(CALLBACK(src, .proc/pandora_teleport_2, T, source), 2)
/mob/living/simple_animal/hostile/asteroid/elite/pandora/proc/pandora_teleport_2(var/turf/T, var/turf/source)
new /obj/effect/temp_visual/hierophant/telegraph/teleport(T, src)
new /obj/effect/temp_visual/hierophant/telegraph/teleport(source, src)
for(var/t in RANGE_TURFS(1, T))
new /obj/effect/temp_visual/hierophant/blast/pandora(t, src)
for(var/t in RANGE_TURFS(1, source))
new /obj/effect/temp_visual/hierophant/blast/pandora(t, src)
animate(src, alpha = 0, time = 2, easing = EASE_OUT) //fade out
visible_message("<span class='hierophant_warning'>[src] fades out!</span>")
density = FALSE
addtimer(CALLBACK(src, .proc/pandora_teleport_3, T), 2)
/mob/living/simple_animal/hostile/asteroid/elite/pandora/proc/pandora_teleport_3(var/turf/T)
forceMove(T)
animate(src, alpha = 255, time = 2, easing = EASE_IN) //fade IN
density = TRUE
visible_message("<span class='hierophant_warning'>[src] fades in!</span>")
/mob/living/simple_animal/hostile/asteroid/elite/pandora/proc/aoe_squares(target)
ranged_cooldown = world.time + cooldown_time
var/turf/T = get_turf(target)
new /obj/effect/temp_visual/hierophant/blast/pandora(T, src)
var/max_size = 2
addtimer(CALLBACK(src, .proc/aoe_squares_2, T, 0, max_size), 2)
/mob/living/simple_animal/hostile/asteroid/elite/pandora/proc/aoe_squares_2(var/turf/T, var/ring, var/max_size)
if(ring > max_size)
return
for(var/t in spiral_range_turfs(ring, T))
if(get_dist(t, T) == ring)
new /obj/effect/temp_visual/hierophant/blast/pandora(t, src)
addtimer(CALLBACK(src, .proc/aoe_squares_2, T, (ring + 1), max_size), 2)
//The specific version of hiero's squares pandora uses
/obj/effect/temp_visual/hierophant/blast/pandora
damage = 20
monster_damage_boost = FALSE
//Pandora's loot: Hope
/obj/item/clothing/accessory/pandora_hope
name = "Hope"
desc = "Found at the bottom of Pandora. After all the evil was released, this was the only thing left inside."
icon = 'icons/obj/lavaland/elite_trophies.dmi'
icon_state = "hope"
resistance_flags = FIRE_PROOF
/obj/item/clothing/accessory/pandora_hope/on_uniform_equip(obj/item/clothing/under/U, user)
var/mob/living/L = user
if(L && L.mind)
SEND_SIGNAL(L, COMSIG_ADD_MOOD_EVENT, "hope_lavaland", /datum/mood_event/hope_lavaland)
/obj/item/clothing/accessory/pandora_hope/on_uniform_dropped(obj/item/clothing/under/U, user)
var/mob/living/L = user
if(L && L.mind)
SEND_SIGNAL(L, COMSIG_CLEAR_MOOD_EVENT, "hope_lavaland")

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
icons/mob/screen_elite.dmi Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 988 B

BIN
sound/magic/curse.ogg Normal file

Binary file not shown.