mirror of
https://github.com/Sandstorm-Station/Sandstorm-Station-13.git
synced 2026-08-21 12:18:11 +01:00
Mining update (#30)
* smol mining update
* Revert "smol mining update"
This reverts commit 9a0bd466ff.
* the .wav files i will use
* the rest that is being added for now
* fixes your stuff
* makes the crusher purchasable
* fixes legion's trophy
* so many icons and oggs
* SIF and more icons
* even more icons, sorry
* new modkits, yay
* oh come on, it didn't update
* some bosses seen to be ready
* Glory Kill system, should work just fine
* even more icons, jeez, also, elite mods
* oh hey, i got the icon
* almost done
* icons and meme dragon
* it's icon was hidden and i didn't notice
* why do i hear boss music ?
* one day...
* while Nano was...
* not continuing that
* stole some compatibility stuff
* the end is near
* some stuff to make stuff work
* probably one of the last commits
* king goat itself
* THE ERRORS, THEY'RE EVERYWHERE
* so close...
* the new ruins should spawn now
* should be the last commit, let's test it
* Now The Gladiator actually exists
* make them mad, and toggle their music
* oh, wait, need to give you the new files
* i think i saved someone's ears
* missing areas, i'm sorry
* good luck fighting KG without a ladder
* just leave a comment, nothing else
* fixes double spawn at least for hiero, aka why the fuck make two of the same proc and not remove 1st
* invisible hat, not anymore
* takes some stuff before bob even merges it on theirs
* how did these icons disappear ?
* fixes some oopsies
* sand plz help
* *fixes your thing*
* and i think i fixed the other
* fixes
* no async needed
* im done, just merge this useless thing
Co-authored-by: crazyraio2 <44246096+crazyraio2@users.noreply.github.com>
This commit is contained in:
co-authored by
crazyraio2
parent
fd16319e61
commit
d312fbc4db
@@ -0,0 +1,12 @@
|
||||
/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner
|
||||
crusher_loot = list(/obj/item/melee/transforming/cleaving_saw, /obj/item/gun/energy/kinetic_accelerator/premiumka/bdminer, /obj/item/borg/upgrade/modkit/lifesteal/miner, /obj/item/crusher_trophy/miner_eye)
|
||||
loot = list(/obj/item/melee/transforming/cleaving_saw, /obj/item/gun/energy/kinetic_accelerator/premiumka/bdminer, /obj/item/borg/upgrade/modkit/lifesteal/miner)
|
||||
songs = list("2360" = sound(file = 'sandcode/sound/ambience/igneon-system-and-death-machine-sins.ogg', repeat = 0, wait = 0, volume = 60, channel = CHANNEL_BOSSMUSIC), "2440" = sound(file = 'sandcode/sound/ambience/machinegirl_excruciatingdeath.ogg', repeat = 0, wait = 0, volume = 60, channel = CHANNEL_BOSSMUSIC)) // I don't actually know if any of this is copyright free or CC. Fuck.
|
||||
glorymessageshand = list("grabs the blood-drunk's arm, flips their cleaving saw with the other hand, and forcefully makes them chop off their own head with it!", "grabs blood-drunk by their PKA, aims it at their head and then shoots, splattering his brains out!", "rips out both of the blood-drunk's arms, then kicks their limp torso on the groundd and curbstomps their head in so hard it explodes!")
|
||||
glorymessagescrusher = list("chops off the blood-drunk's cleaving saw arm in one swift move, then grabs the saw and swings it against their head, chopping their skull vertically in half!", "bashes the miner to the ground with the hilt of their crusher, then elbow drops their skull so hard it explodes in gore!", "chops the blood-drunk diagonally with their crusher, not quite cutting through but getting their crusher halfway stuck and killing the moaning fiend!")
|
||||
glorymessagespka = list("grabs the blood-drunk by the neck and flips them, shooting through their guts with a PKA blast!", "shoots at the blood-drunk's shoulder, exploding their arm! To finish the fiend off, they grab their PKA and bonk the blood-drunk's head inside their torso!", "doesn't bother with being fancy, and simply shoots at the blood-drunk's head with their PKA, exploding it in one violent blast!")
|
||||
glorymessagespkabayonet = list("rams into the blood-drunk's stomach with their PKA's bayonet, knocking them and themselves down! To finish the fiend off, they simply stab into their torso like a madman with their bayonet!", "kicks the blood-drunk's knee hard, breaking it! While the fiend is stunned and barely standing, their chop their head off with the PKA's bayonet!")
|
||||
glorythreshold = 50
|
||||
|
||||
/obj/item/projectile/kinetic/miner
|
||||
color = "#FF0000"
|
||||
@@ -0,0 +1,141 @@
|
||||
#define MEDAL_PREFIX "Bubblegum"
|
||||
|
||||
/*
|
||||
|
||||
BUBBLEGUM
|
||||
|
||||
Removes slaughterlings (because they are bullshit), instead replacing them with the blood rending thing from tg
|
||||
|
||||
*/
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum
|
||||
death_sound = 'sandcode/sound/misc/gorenest.ogg' //fuck it
|
||||
var/movesound = 'sound/effects/meteorimpact.ogg'
|
||||
songs = list("1860" = sound(file = 'sandcode/sound/ambience/bfgdivision.ogg', repeat = 0, wait = 0, volume = 60, channel = CHANNEL_BOSSMUSIC), "2070" = sound(file = 'sandcode/sound/ambience/theonlythingtheyfearisyou.ogg', repeat = 0, wait = 0, volume = 60, channel = CHANNEL_BOSSMUSIC)) //Thanks Mr. Infringio!
|
||||
glorymessageshand = list("grabs bubblegum by the leg, and pulls them down! While downed, they climb on their torso and punch through it, smashing their demonic heart!", "goes around bubblegum and climbs them by their back, once on top of their head they punch right through the demon's skull, ripping out brain matter and killing it as it limply falls on the ground!")
|
||||
glorymessagescrusher = list("jumps and chops off both of bubblegum's legs in one swift move with their crusher! To finish off the now wheelchair-bound demon, they chop at the torso vertically, getting the crusher stuck in the process but killing the demonic fiend!", "goes around bubblegum and climbs them by their back, once on the top they chop their head off with the crusher!")
|
||||
glorymessagespka = list("shoots the weakened demon in the chest, opening a hole and exposing their inner core! With another blast, the demon's heart explodes, and they fall dead and limp on the ground!", "shoots the weakened demon's head, stunning them and revealing their brain! Another PKA blast finishes off what little brainmatter they had!")
|
||||
glorymessagespkabayonet = list("shoots the weakened demon in the chest, opening a hole and exposing their inner core! They run onto the now exposed heart and stab it repeatedly with their bayonet, killing the demon off!")
|
||||
footstep_type = FOOTSTEP_MOB_HEAVY
|
||||
var/dont_move = TRUE //impedes bubbles from moving while using the blood jaunt
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/Move()
|
||||
. = ..()
|
||||
if(dont_move)
|
||||
return FALSE
|
||||
playsound(src, movesound, 200, TRUE, 2, TRUE)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/OpenFire()
|
||||
anger_modifier = clamp(((maxHealth - health)/50),0,20)
|
||||
if(charging)
|
||||
return
|
||||
ranged_cooldown = world.time + ranged_cooldown_time
|
||||
blood_warp()
|
||||
bloodsmacks()
|
||||
if(prob(25))
|
||||
INVOKE_ASYNC(src, .proc/blood_spray)
|
||||
INVOKE_ASYNC(src, .proc/bloodsmacks)
|
||||
else
|
||||
if(health > maxHealth/2 && !client)
|
||||
INVOKE_ASYNC(src, .proc/charge)
|
||||
else
|
||||
INVOKE_ASYNC(src, .proc/triple_charge)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/charge()
|
||||
bloodsmacks()
|
||||
var/turf/T = get_turf(target)
|
||||
if(!T || T == loc)
|
||||
return
|
||||
new /obj/effect/temp_visual/dragon_swoop(T)
|
||||
charging = 1
|
||||
DestroySurroundings()
|
||||
walk(src, 0)
|
||||
setDir(get_dir(src, T))
|
||||
var/obj/effect/temp_visual/decoy/D = new /obj/effect/temp_visual/decoy(loc,src)
|
||||
animate(D, alpha = 0, color = "#FF0000", transform = matrix()*2, time = 5)
|
||||
sleep(5)
|
||||
throw_at(T, get_dist(src, T), 1, src, 0)
|
||||
charging = 0
|
||||
Goto(target, move_to_delay, minimum_distance)
|
||||
bloodsmacks()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/bloodsmacks()
|
||||
for(var/obj/effect/decal/cleanable/blood/B in view(7, src))
|
||||
var/turf/T = get_turf(B)
|
||||
var/mobcount = 0
|
||||
for(var/mob/living/L in T.contents)
|
||||
if(L != src)
|
||||
mobcount++
|
||||
if(mobcount)
|
||||
var/hand = rand(0,1)
|
||||
INVOKE_ASYNC(src, .proc/bloodsmack, T, hand)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/proc/bloodsmack(turf/T, handedness)
|
||||
if(handedness)
|
||||
new /obj/effect/temp_visual/bubblegum_hands/rightsmack(T)
|
||||
else
|
||||
new /obj/effect/temp_visual/bubblegum_hands/leftsmack(T)
|
||||
sleep(5)
|
||||
for(var/mob/living/L in T)
|
||||
if(!faction_check_mob(L))
|
||||
to_chat(L, "<span class='userdanger'>[src] rends you!</span>")
|
||||
playsound(T, attack_sound, 100, TRUE, -1)
|
||||
var/limb_to_hit = L.get_bodypart(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(30, BRUTE, limb_to_hit, L.run_armor_check(limb_to_hit, "melee", null, null)) // You really, really, really better not stand in blood!
|
||||
sleep(3)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/blood_warp()
|
||||
var/obj/effect/decal/cleanable/blood/found_bloodpool
|
||||
var/list/pools = list()
|
||||
var/can_jaunt = FALSE
|
||||
for(var/obj/effect/decal/cleanable/blood/nearby in view(src,2))
|
||||
if(nearby.bloodiness >= 20)
|
||||
can_jaunt = TRUE
|
||||
break
|
||||
if(!can_jaunt)
|
||||
return
|
||||
for(var/obj/effect/decal/cleanable/blood/nearby in view(get_turf(target),2))
|
||||
if(nearby.bloodiness >= 20)
|
||||
pools += nearby
|
||||
if(pools.len)
|
||||
shuffle_inplace(pools)
|
||||
found_bloodpool = pick(pools)
|
||||
if(found_bloodpool)
|
||||
visible_message("<span class='danger'>[src] sinks into the blood...</span>")
|
||||
playsound(get_turf(src), 'sound/magic/enter_blood.ogg', 100, 1, -1)
|
||||
alpha = 0
|
||||
dont_move = TRUE
|
||||
sleep(rand(2, 4))
|
||||
forceMove(get_turf(found_bloodpool))
|
||||
playsound(get_turf(src), 'sound/magic/exit_blood.ogg', 100, 1, -1)
|
||||
alpha = 100
|
||||
dont_move = FALSE
|
||||
visible_message("<span class='danger'>And springs back out!</span>")
|
||||
|
||||
|
||||
/obj/effect/temp_visual/bubblegum_hands
|
||||
icon = 'icons/effects/bubblegum.dmi'
|
||||
duration = 9
|
||||
|
||||
/obj/effect/temp_visual/bubblegum_hands/rightthumb
|
||||
icon_state = "rightthumbgrab"
|
||||
|
||||
/obj/effect/temp_visual/bubblegum_hands/leftthumb
|
||||
icon_state = "leftthumbgrab"
|
||||
|
||||
/obj/effect/temp_visual/bubblegum_hands/rightpaw
|
||||
icon_state = "rightpawgrab"
|
||||
layer = BELOW_MOB_LAYER
|
||||
|
||||
/obj/effect/temp_visual/bubblegum_hands/leftpaw
|
||||
icon_state = "leftpawgrab"
|
||||
layer = BELOW_MOB_LAYER
|
||||
|
||||
/obj/effect/temp_visual/bubblegum_hands/rightsmack
|
||||
icon_state = "rightsmack"
|
||||
|
||||
/obj/effect/temp_visual/bubblegum_hands/leftsmack
|
||||
icon_state = "leftsmack"
|
||||
|
||||
#undef MEDAL_PREFIX
|
||||
@@ -0,0 +1,479 @@
|
||||
#define BUBBLEGUM_SMASH (health <= maxHealth*0.5) // angery
|
||||
#define BUBBLEGUM_CAN_ENRAGE (enrage_till + (enrage_time * 2) <= world.time)
|
||||
#define BUBBLEGUM_IS_ENRAGED (enrage_till > world.time)
|
||||
|
||||
/*
|
||||
BUBBLEGUM (HARD)
|
||||
Bubblegum spawns randomly wherever a lavaland creature is able to spawn. It is the most powerful slaughter demon in existence.
|
||||
Bubblegum's footsteps are heralded by shaking booms, proving its tremendous size.
|
||||
It acts as a melee creature, chasing down and attacking its target while also using different attacks to augment its power
|
||||
It leaves blood trails behind wherever it goes, its clones do as well.
|
||||
It tries to strike at its target through any bloodpools under them; if it fails to do that.
|
||||
If it does warp it will enter an enraged state, becoming immune to all projectiles, becoming much faster, and dealing damage and knockback to anything that gets in the cloud around it.
|
||||
It may summon clones charging from all sides, one of these charges being bubblegum himself.
|
||||
It can charge at its target, and also heavily damaging anything directly hit in the charge.
|
||||
If at half health it will start to charge from all sides with clones.
|
||||
When Bubblegum dies, it leaves behind a H.E.C.K. mining suit as well as a chest that can contain three things:
|
||||
1. A bottle that, when activated, drives everyone nearby into a frenzy
|
||||
2. A contract that marks for death the chosen target
|
||||
3. A spellblade that can slice off limbs at range
|
||||
Difficulty: Hard
|
||||
*/
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/hard
|
||||
name = "enraged bubblegum"
|
||||
desc = "In what passes for a hierarchy among slaughter demons, this one is god."
|
||||
attack_verb_continuous = "brutally rends"
|
||||
attack_verb_simple = "brutally rend"
|
||||
speed = 5
|
||||
move_to_delay = 5
|
||||
retreat_distance = 5
|
||||
minimum_distance = 5
|
||||
rapid_melee = 8 // every 1/4 second
|
||||
melee_queue_distance = 20 // as far as possible really, need this because of blood warp
|
||||
ranged = TRUE
|
||||
del_on_death = TRUE
|
||||
crusher_loot = list(/obj/structure/closet/crate/necropolis/bubblegum/hard/crusher)
|
||||
loot = list(/obj/structure/closet/crate/necropolis/bubblegum/hard)
|
||||
charging = FALSE
|
||||
var/enrage_till = 0
|
||||
var/enrage_time = 70
|
||||
var/revving_charge = FALSE
|
||||
nest_range = 10
|
||||
true_spawn = TRUE
|
||||
|
||||
deathmessage = "sinks into a pool of blood, fleeing the battle. You've won, for now, slayer... "
|
||||
deathsound = 'sound/magic/enter_blood.ogg'
|
||||
|
||||
obj/item/gps/internal/bubblegum/hard
|
||||
icon_state = null
|
||||
gpstag = "Enraged Bloody Signal"
|
||||
desc = "You're not quite sure how a signal can be enraged, neither how it can be bloody."
|
||||
invisibility = 100
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/hard/Initialize()
|
||||
..()
|
||||
internal = new/obj/item/gps/internal/bubblegum/hard(src)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/hard/OpenFire()
|
||||
if(charging)
|
||||
return
|
||||
|
||||
anger_modifier = clamp(((maxHealth - health)/60),0,20)
|
||||
enrage_time = initial(enrage_time) * clamp(anger_modifier / 20, 0.5, 1)
|
||||
ranged_cooldown = world.time + 50
|
||||
|
||||
if(!try_bloodattack() || prob(25 + anger_modifier))
|
||||
blood_warp()
|
||||
|
||||
if(!BUBBLEGUM_SMASH)
|
||||
triple_charge()
|
||||
else
|
||||
if(prob(50 + anger_modifier))
|
||||
hallucination_charge()
|
||||
else
|
||||
surround_with_hallucinations()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/hard/triple_charge()
|
||||
charge(delay = 8)
|
||||
charge(delay = 6)
|
||||
charge(delay = 4)
|
||||
SetRecoveryTime(15)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/hard/proc/hallucination_charge()
|
||||
if(!BUBBLEGUM_SMASH || prob(33))
|
||||
hallucination_charge_around(times = 6, delay = 12)
|
||||
SetRecoveryTime(10)
|
||||
else
|
||||
hallucination_charge_around(times = 4, delay = 14)
|
||||
hallucination_charge_around(times = 4, delay = 10)
|
||||
hallucination_charge_around(times = 4, delay = 10)
|
||||
triple_charge()
|
||||
SetRecoveryTime(20)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/hard/proc/surround_with_hallucinations()
|
||||
for(var/i = 1 to 5)
|
||||
INVOKE_ASYNC(src, .proc/hallucination_charge_around, 2, 8, 2, 0, 4)
|
||||
if(ismob(target))
|
||||
charge(delay = 8)
|
||||
else
|
||||
sleep(10)
|
||||
SetRecoveryTime(20)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/hard/charge(atom/chargeat = target, delay = 8, chargepast = 2)
|
||||
if(!chargeat)
|
||||
return
|
||||
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(T)
|
||||
charging = TRUE
|
||||
revving_charge = TRUE
|
||||
DestroySurroundings()
|
||||
walk(src, 0)
|
||||
setDir(dir)
|
||||
var/obj/effect/temp_visual/decoy/D = new /obj/effect/temp_visual/decoy(loc,src)
|
||||
animate(D, alpha = 0, color = "#FF0000", transform = matrix()*2, time = 3)
|
||||
sleep(delay)
|
||||
revving_charge = FALSE
|
||||
var/movespeed = 0.7
|
||||
walk_towards(src, T, movespeed)
|
||||
sleep(get_dist(src, T) * movespeed)
|
||||
walk(src, 0) // cancel the movement
|
||||
try_bloodattack()
|
||||
charging = FALSE
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/hard/proc/get_mobs_on_blood()
|
||||
var/list/targets = ListTargets()
|
||||
. = list()
|
||||
for(var/mob/living/L in targets)
|
||||
var/list/bloodpool = get_pools(get_turf(L), 0)
|
||||
if(bloodpool.len && (!faction_check_mob(L) || L.stat == DEAD))
|
||||
. += L
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/hard/proc/try_bloodattack()
|
||||
var/list/targets = get_mobs_on_blood()
|
||||
if(targets.len)
|
||||
INVOKE_ASYNC(src, .proc/bloodattack, targets, prob(50))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/hard/proc/bloodattack(list/targets, handedness)
|
||||
var/mob/living/target_one = pick_n_take(targets)
|
||||
var/turf/target_one_turf = get_turf(target_one)
|
||||
var/mob/living/target_two
|
||||
if(targets.len)
|
||||
target_two = pick_n_take(targets)
|
||||
var/turf/target_two_turf = get_turf(target_two)
|
||||
if(target_two.stat != CONSCIOUS || prob(10))
|
||||
bloodgrab(target_two_turf, handedness)
|
||||
else
|
||||
bloodsmack(target_two_turf, handedness)
|
||||
|
||||
if(target_one)
|
||||
var/list/pools = get_pools(get_turf(target_one), 0)
|
||||
if(pools.len)
|
||||
target_one_turf = get_turf(target_one)
|
||||
if(target_one_turf)
|
||||
if(target_one.stat != CONSCIOUS || prob(10))
|
||||
bloodgrab(target_one_turf, !handedness)
|
||||
else
|
||||
bloodsmack(target_one_turf, !handedness)
|
||||
|
||||
if(!target_two && target_one)
|
||||
var/list/poolstwo = get_pools(get_turf(target_one), 0)
|
||||
if(poolstwo.len)
|
||||
target_one_turf = get_turf(target_one)
|
||||
if(target_one_turf)
|
||||
if(target_one.stat != CONSCIOUS || prob(10))
|
||||
bloodgrab(target_one_turf, handedness)
|
||||
else
|
||||
bloodsmack(target_one_turf, handedness)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/hard/bloodsmack(turf/T, handedness)
|
||||
if(handedness)
|
||||
new /obj/effect/temp_visual/bubblegum_handshard/rightsmack(T)
|
||||
else
|
||||
new /obj/effect/temp_visual/bubblegum_handshard/leftsmack(T)
|
||||
sleep(4)
|
||||
for(var/mob/living/L in T)
|
||||
if(!faction_check_mob(L))
|
||||
to_chat(L, "<span class='userdanger'>[src] rends you!</span>")
|
||||
playsound(T, attack_sound, 100, TRUE, -1)
|
||||
var/limb_to_hit = L.get_bodypart(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(10, BRUTE, limb_to_hit, L.run_armor_check(limb_to_hit, "melee", null, null, armour_penetration))
|
||||
sleep(3)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/hard/proc/bloodgrab(turf/T, handedness)
|
||||
if(handedness)
|
||||
new /obj/effect/temp_visual/bubblegum_handshard/rightpaw(T)
|
||||
new /obj/effect/temp_visual/bubblegum_handshard/rightthumb(T)
|
||||
else
|
||||
new /obj/effect/temp_visual/bubblegum_handshard/leftpaw(T)
|
||||
new /obj/effect/temp_visual/bubblegum_handshard/leftthumb(T)
|
||||
sleep(6)
|
||||
for(var/mob/living/L in T)
|
||||
if(!faction_check_mob(L))
|
||||
if(L.stat != CONSCIOUS)
|
||||
to_chat(L, "<span class='userdanger'>[src] drags you through the blood!</span>")
|
||||
playsound(T, 'sound/magic/enter_blood.ogg', 100, TRUE, -1)
|
||||
var/turf/targetturf = get_step(src, dir)
|
||||
L.forceMove(targetturf)
|
||||
playsound(targetturf, 'sound/magic/exit_blood.ogg', 100, TRUE, -1)
|
||||
addtimer(CALLBACK(src, .proc/devour, L), 2)
|
||||
sleep(1)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/hard/blood_warp()
|
||||
if(Adjacent(target))
|
||||
return FALSE
|
||||
var/list/can_jaunt = get_pools(get_turf(src), 1)
|
||||
if(!can_jaunt.len)
|
||||
return FALSE
|
||||
|
||||
var/list/pools = get_pools(get_turf(target), 5)
|
||||
var/list/pools_to_remove = get_pools(get_turf(target), 4)
|
||||
pools -= pools_to_remove
|
||||
if(!pools.len)
|
||||
return FALSE
|
||||
|
||||
var/obj/effect/temp_visual/decoy/DA = new /obj/effect/temp_visual/decoy(loc,src)
|
||||
DA.color = "#FF0000"
|
||||
var/oldtransform = DA.transform
|
||||
DA.transform = matrix()*2
|
||||
animate(DA, alpha = 255, color = initial(DA.color), transform = oldtransform, time = 3)
|
||||
sleep(3)
|
||||
qdel(DA)
|
||||
|
||||
var/obj/effect/decal/cleanable/blood/found_bloodpool
|
||||
pools = get_pools(get_turf(target), 5)
|
||||
pools_to_remove = get_pools(get_turf(target), 4)
|
||||
pools -= pools_to_remove
|
||||
if(pools.len)
|
||||
shuffle_inplace(pools)
|
||||
found_bloodpool = pick(pools)
|
||||
if(found_bloodpool)
|
||||
visible_message("<span class='danger'>[src] sinks into the blood...</span>")
|
||||
playsound(get_turf(src), 'sound/magic/enter_blood.ogg', 100, TRUE, -1)
|
||||
forceMove(get_turf(found_bloodpool))
|
||||
playsound(get_turf(src), 'sound/magic/exit_blood.ogg', 100, TRUE, -1)
|
||||
visible_message("<span class='danger'>And springs back out!</span>")
|
||||
blood_enrage()
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/hard/proc/be_aggressive()
|
||||
if(BUBBLEGUM_IS_ENRAGED)
|
||||
return TRUE
|
||||
if(isliving(target))
|
||||
var/mob/living/livingtarget = target
|
||||
return (livingtarget.stat != CONSCIOUS)
|
||||
return FALSE
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/hard/proc/get_retreat_distance()
|
||||
return (be_aggressive() ? null : initial(retreat_distance))
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/hard/proc/get_minimum_distance()
|
||||
return (be_aggressive() ? 1 : initial(minimum_distance))
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/hard/proc/update_approach()
|
||||
retreat_distance = get_retreat_distance()
|
||||
minimum_distance = get_minimum_distance()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/hard/proc/blood_enrage()
|
||||
if(!BUBBLEGUM_CAN_ENRAGE)
|
||||
return FALSE
|
||||
enrage_till = world.time + enrage_time
|
||||
update_approach()
|
||||
change_move_delay(3.75)
|
||||
var/newcolor = rgb(149, 10, 10)
|
||||
add_atom_colour(newcolor, TEMPORARY_COLOUR_PRIORITY)
|
||||
var/datum/callback/cb = CALLBACK(src, .proc/blood_enrage_end)
|
||||
addtimer(cb, enrage_time)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/hard/proc/blood_enrage_end(var/newcolor = rgb(149, 10, 10))
|
||||
update_approach()
|
||||
change_move_delay()
|
||||
remove_atom_colour(TEMPORARY_COLOUR_PRIORITY, newcolor)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/hard/proc/change_move_delay(var/newmove = initial(move_to_delay))
|
||||
move_to_delay = newmove
|
||||
set_varspeed(move_to_delay)
|
||||
handle_automated_action() // need to recheck movement otherwise move_to_delay won't update until the next checking aka will be wrong speed for a bit
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/hard/proc/get_pools(turf/T, range)
|
||||
. = list()
|
||||
for(var/obj/effect/decal/cleanable/nearby in view(T, range))
|
||||
if(nearby.can_bloodcrawl_in())
|
||||
. += nearby
|
||||
|
||||
/obj/effect/decal/cleanable/blood/bubblegumhard
|
||||
bloodiness = 0
|
||||
|
||||
/obj/effect/decal/cleanable/blood/bubblegumhard/can_bloodcrawl_in()
|
||||
return TRUE
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/hard/proc/hallucination_charge_around(times = 4, delay = 10, chargepast = 0, useoriginal = 1, radius)
|
||||
var/startingangle = rand(1, 360)
|
||||
if(!target)
|
||||
return
|
||||
var/turf/chargeat = get_turf(target)
|
||||
var/srcplaced = FALSE
|
||||
if(!radius)
|
||||
radius = times
|
||||
for(var/i = 1 to times)
|
||||
var/ang = (startingangle + 360/times * i)
|
||||
if(!chargeat)
|
||||
return
|
||||
var/turf/place = locate(chargeat.x + cos(ang) * radius, chargeat.y + sin(ang) * radius, chargeat.z)
|
||||
if(!place)
|
||||
continue
|
||||
if(!nest || nest && nest.parent && get_dist(nest.parent, place) <= nest_range)
|
||||
if(!srcplaced && useoriginal)
|
||||
forceMove(place)
|
||||
srcplaced = TRUE
|
||||
continue
|
||||
var/mob/living/simple_animal/hostile/megafauna/bubblegum/hard/hallucination/B = new /mob/living/simple_animal/hostile/megafauna/bubblegum/hard/hallucination(src.loc)
|
||||
B.forceMove(place)
|
||||
INVOKE_ASYNC(B, .proc/charge, chargeat, delay, chargepast)
|
||||
if(useoriginal)
|
||||
charge(chargeat, delay, chargepast)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/hard/adjustBruteLoss(amount, updating_health = TRUE, forced = FALSE)
|
||||
. = ..()
|
||||
if(. > 0 && prob(25))
|
||||
var/obj/effect/decal/cleanable/blood/gibs/bubblegumhard/B = new /obj/effect/decal/cleanable/blood/gibs/bubblegumhard(loc)
|
||||
if(prob(40))
|
||||
step(B, pick(GLOB.cardinals))
|
||||
else
|
||||
B.setDir(pick(GLOB.cardinals))
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/bubblegumhard
|
||||
name = "thick blood"
|
||||
desc = "Thick, splattered blood."
|
||||
random_icon_states = list("gib3", "gib5", "gib6")
|
||||
bloodiness = 20
|
||||
|
||||
/obj/effect/decal/cleanable/blood/gibs/bubblegumhard/can_bloodcrawl_in()
|
||||
return TRUE
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/hard/do_attack_animation(atom/A, visual_effect_icon, obj/item/used_item, no_effect)
|
||||
if(!charging)
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/hard/AttackingTarget()
|
||||
if(!charging)
|
||||
. = ..()
|
||||
if(.)
|
||||
recovery_time = world.time + 30 //can only attack melee once every 3 seconds but rapid_melee gives higher priority
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/hard/bullet_act(obj/item/projectile/P)
|
||||
if(BUBBLEGUM_IS_ENRAGED)
|
||||
visible_message("<span class='danger'>[src] deflects the projectile; [p_they()] can't be hit with ranged weapons while enraged!</span>", "<span class='userdanger'>You deflect the projectile!</span>")
|
||||
playsound(src, pick('sound/weapons/bulletflyby.ogg', 'sound/weapons/bulletflyby2.ogg', 'sound/weapons/bulletflyby3.ogg'), 300, TRUE)
|
||||
return BULLET_ACT_BLOCK
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/hard/ex_act(severity, target)
|
||||
if(severity >= EXPLODE_LIGHT)
|
||||
return
|
||||
severity = EXPLODE_LIGHT // puny mortals
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/hard/proc/CanAllowThrough(atom/movable/mover, turf/target)
|
||||
if(istype(mover, /mob/living/simple_animal/hostile/megafauna/bubblegum/hard/hallucination))
|
||||
return TRUE
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/hard/Goto(target, delay, minimum_distance)
|
||||
if(!charging)
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/hard/MoveToTarget(list/possible_targets)
|
||||
if(!charging)
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/hard/Move()
|
||||
update_approach()
|
||||
if(revving_charge)
|
||||
return FALSE
|
||||
if(charging)
|
||||
new /obj/effect/temp_visual/decoy/fading(loc,src)
|
||||
DestroySurroundings()
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/hard/Moved(atom/OldLoc, Dir, Forced = FALSE)
|
||||
if(Dir)
|
||||
new /obj/effect/decal/cleanable/blood/bubblegumhard(src.loc)
|
||||
if(charging)
|
||||
DestroySurroundings()
|
||||
playsound(src, 'sound/effects/meteorimpact.ogg', 200, TRUE, 2, TRUE)
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/hard/Bump(atom/A)
|
||||
if(charging)
|
||||
if(isturf(A) || isobj(A) && A.density)
|
||||
A.ex_act(EXPLODE_HEAVY)
|
||||
DestroySurroundings()
|
||||
if(isliving(A))
|
||||
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>")
|
||||
src.forceMove(get_turf(L))
|
||||
L.apply_damage(istype(src, /mob/living/simple_animal/hostile/megafauna/bubblegum/hard/hallucination) ? 15 : 30, BRUTE)
|
||||
playsound(get_turf(L), 'sound/effects/meteorimpact.ogg', 100, TRUE)
|
||||
shake_camera(L, 4, 3)
|
||||
shake_camera(src, 2, 3)
|
||||
..()
|
||||
|
||||
/obj/effect/temp_visual/dragon_swoop/bubblegum
|
||||
duration = 10
|
||||
|
||||
/obj/effect/temp_visual/bubblegum_handshard
|
||||
icon = 'icons/effects/bubblegum.dmi'
|
||||
duration = 9
|
||||
|
||||
/obj/effect/temp_visual/bubblegum_handshard/rightthumb
|
||||
icon_state = "rightthumbgrab"
|
||||
|
||||
/obj/effect/temp_visual/bubblegum_handshard/leftthumb
|
||||
icon_state = "leftthumbgrab"
|
||||
|
||||
/obj/effect/temp_visual/bubblegum_handshard/rightpaw
|
||||
icon_state = "rightpawgrab"
|
||||
layer = BELOW_MOB_LAYER
|
||||
|
||||
/obj/effect/temp_visual/bubblegum_handshard/leftpaw
|
||||
icon_state = "leftpawgrab"
|
||||
layer = BELOW_MOB_LAYER
|
||||
|
||||
/obj/effect/temp_visual/bubblegum_handshard/rightsmack
|
||||
icon_state = "rightsmack"
|
||||
|
||||
/obj/effect/temp_visual/bubblegum_handshard/leftsmack
|
||||
icon_state = "leftsmack"
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/hard/hallucination
|
||||
name = "bubblegum's hallucination"
|
||||
desc = "Is that really just a hallucination?"
|
||||
health = 1
|
||||
maxHealth = 1
|
||||
alpha = 127.5
|
||||
crusher_loot = null
|
||||
loot = null
|
||||
deathmessage = "Explodes into a pool of blood!"
|
||||
deathsound = 'sound/effects/splat.ogg'
|
||||
true_spawn = FALSE
|
||||
mouse_opacity = 0 //This is so clients wont hover and store them, causing them to fail GC
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/hard/hallucination/Initialize()
|
||||
..()
|
||||
toggle_ai(AI_OFF)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/hard/hallucination/charge(atom/chargeat = target, delay = 3, chargepast = 2)
|
||||
..()
|
||||
qdel(src)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/hard/hallucination/Destroy()
|
||||
new /obj/effect/decal/cleanable/blood(get_turf(src))
|
||||
. = ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/hard/hallucination/CanAllowThrough(atom/movable/mover, turf/target)
|
||||
if(istype(mover, /mob/living/simple_animal/hostile/megafauna/bubblegum)) // hallucinations should not be stopping bubblegum or eachother
|
||||
return TRUE
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/hard/hallucination/Life()
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/hard/hallucination/adjustBruteLoss(amount, updating_health = TRUE, forced = FALSE)
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/hard/hallucination/OpenFire()
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/hard/hallucination/AttackingTarget()
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/bubblegum/hard/hallucination/try_bloodattack()
|
||||
return
|
||||
@@ -0,0 +1,15 @@
|
||||
/mob/living/simple_animal/hostile/megafauna/colossus
|
||||
songs = list("1170" = sound(file = 'sandcode/sound/ambience/theopenedway.ogg', repeat = 0, wait = 0, volume = 60, channel = CHANNEL_BOSSMUSIC)) //Shadow of the colossus OST
|
||||
glorymessageshand = list("grabs the colossus by the leg, and pulls them down! While downed, they climb on his neck and violently rip off their vocal cords!", "goes around the colossus and climbs them by their back, once on top of their shoulder they grab it's arm and aim the blaster at the creature's head, which finishes itself off with a penetrating death bolt that blasts off their head!")
|
||||
glorymessagescrusher = list("throws their crusher at the colossus' head, which surprisingly works! Humiliated, the angelic creature dies with a big fucking axe stuck on their skull!", "chops off one of the colossus' legs with the crusher, as it falls down they grab the leg and use it as a makeshift club on the creature's head, which explodes in differently-sized giblets on impact!")
|
||||
glorymessagespka = list("somehow parries a death bolt with a PKA blast, which goes right back to it's owner's torso, opening a hole on them and killing them!")
|
||||
glorymessagespkabayonet = list("goes around the colossus and climbs on their back, ramming their bayonet on it's spine and falling down holding it, pretty much gruesomely opening the colossus' back!")
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/colossus/enrage(mob/living/L)
|
||||
if(ishuman(L))
|
||||
var/mob/living/carbon/human/H = L
|
||||
if(H.mind)
|
||||
if(istype(H.mind.martial_art, /datum/martial_art/the_sleeping_carp) || istype(H.mind.martial_art, /datum/martial_art/the_rising_bass))
|
||||
. = TRUE
|
||||
if(is_species(H, /datum/species/golem/sand))
|
||||
. = TRUE
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
/mob/living/simple_animal/hostile/megafauna/demonic_frost_miner
|
||||
deathsound = "bodyfall"
|
||||
@@ -1,3 +1,24 @@
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon
|
||||
songs = list("1860" = sound(file = 'sandcode/sound/ambience/duskcreations.ogg', repeat = 0, wait = 0, volume = 60, channel = CHANNEL_BOSSMUSIC), "2350" = sound(file = 'sandcode/sound/ambience/dragonborn.ogg', repeat = 0, wait = 0, volume = 60, channel = CHANNEL_BOSSMUSIC)) // Andrew is a nice guy, he'll let it slide. Taken from the DUSK OST. Not sure about the skyrim theme though...
|
||||
glorymessageshand = list("climbs atop the drake's head as it dangles weakly near the ground, ripping its left horn off and jumping down before swinging it at the drake's face full force, cracking its maw!", "goes around the dragon and rips off their tail, using it's spiked end to beat the dragon's bloodied face until it cracks open and it dies!")
|
||||
glorymessagescrusher = list("chops off the dragon's head by the neck, and it falls down with a strong thud!", "rams into the dragon's skull with the hilt of their crusher repeatedly and cracking holes into their skull each time, turning it's brain into mush!")
|
||||
glorymessagespka = list("shoots at the dragon's wings with their PKA, exploding them into bizarre giblets! They then finish the poor creature off with a point-blank blast to the head, exploding it!")
|
||||
glorymessagespkabayonet = list("goes around the drake and chops off their tail's spike with their bayonet, then climbs onto their head and makes them eat it!")
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/lesser/akatosh
|
||||
name = "Holy Dragon"
|
||||
desc = "Destroyer of the gates."
|
||||
icon = 'sandcode/icons/mob/lavaland/drake_greyscale.dmi'
|
||||
icon_state = "dragon"
|
||||
maxHealth = 350
|
||||
health = 350
|
||||
color = "#FFFF00"
|
||||
light_range = 3
|
||||
light_color = "#FFFF00"
|
||||
light_power = 2
|
||||
faction = list("neutral")
|
||||
smallsprite = /datum/action/small_sprite/drake/akatosh
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/sand
|
||||
name = "Sand"
|
||||
desc = "The ultimate form of lord Sand, if he is in this form, he is either saving someone from something, or killing some honkers"
|
||||
|
||||
@@ -0,0 +1,509 @@
|
||||
/*
|
||||
ASH DRAKE
|
||||
Ash drakes spawn randomly wherever a lavaland creature is able to spawn. They are the draconic guardians of the Necropolis.
|
||||
It acts as a melee creature, chasing down and attacking its target while also using different attacks to augment its power that increase as it takes damage.
|
||||
Whenever possible, the drake will breathe fire directly at it's target, igniting and heavily damaging anything caught in the blast.
|
||||
It also often causes lava to pool from the ground around you - many nearby turfs will temporarily turn into lava, dealing damage to anything on the turfs.
|
||||
The drake also utilizes its wings to fly into the sky, flying after its target and attempting to slam down on them. Anything near when it slams down takes huge damage.
|
||||
- Sometimes it will chain these swooping attacks over and over, making swiftness a necessity.
|
||||
- Sometimes, it will encase its target in an arena of lava
|
||||
When an ash drake dies, it leaves behind a chest that can contain four things:
|
||||
1. A spectral blade that allows its wielder to call ghosts to it, enhancing its power
|
||||
2. A lava staff that allows its wielder to create lava
|
||||
3. A spellbook and wand of fireballs
|
||||
4. A bottle of dragon's blood with several effects, including turning its imbiber into a drake themselves.
|
||||
When butchered, they leave behind diamonds, sinew, bone, and ash drake hide. Ash drake hide can be used to create a hooded cloak that protects its wearer from ash storms.
|
||||
Difficulty: Medium
|
||||
*/
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/hard
|
||||
name = "enraged ash drake"
|
||||
desc = "Ultra-guardian of the necropolis."
|
||||
health = 2500
|
||||
maxHealth = 2500
|
||||
armour_penetration = 40
|
||||
melee_damage_lower = 40
|
||||
melee_damage_upper = 40
|
||||
speed = 5
|
||||
move_to_delay = 4
|
||||
ranged = TRUE
|
||||
pixel_x = -16
|
||||
crusher_loot = list(/obj/structure/closet/crate/necropolis/dragon/hard/crusher)
|
||||
loot = list(/obj/structure/closet/crate/necropolis/dragon/hard)
|
||||
butcher_results = list(/obj/item/stack/ore/diamond = 5, /obj/item/stack/sheet/sinew = 5, /obj/item/stack/sheet/bone = 30)
|
||||
guaranteed_butcher_results = list(/obj/item/stack/sheet/animalhide/ashdrake = 10)
|
||||
swooping = NONE
|
||||
var/player_cooldown = 0
|
||||
deathmessage = "collapses into a pile of bones, its flesh sloughing away."
|
||||
deathsound = 'sound/magic/demon_dies.ogg'
|
||||
|
||||
/obj/item/gps/internal/dragon/hard
|
||||
icon_state = null
|
||||
gpstag = "Enraged Fiery Signal"
|
||||
desc = "Here there be 'bad' dragons."
|
||||
invisibility = 100
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/hard/Initialize()
|
||||
..()
|
||||
internal = new/obj/item/gps/internal/dragon/hard(src)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/hard/OpenFire()
|
||||
if(swooping)
|
||||
return
|
||||
|
||||
anger_modifier = clamp(((maxHealth - health)/50),0,20)
|
||||
ranged_cooldown = world.time + ranged_cooldown_time
|
||||
|
||||
if(prob(25 + anger_modifier))
|
||||
lava_swoop()
|
||||
else if(prob(15 + anger_modifier))
|
||||
if(prob(75))
|
||||
swooop_attack()
|
||||
else
|
||||
triple_swooop()
|
||||
else if(prob(5 + anger_modifier))
|
||||
triple_lava_swoop()
|
||||
else if(prob(10+anger_modifier))
|
||||
shoot_fire_attack()
|
||||
else
|
||||
if(prob(50))
|
||||
fire_cone()
|
||||
else
|
||||
if(prob(75))
|
||||
fire_rain()
|
||||
else
|
||||
fire_cone()
|
||||
fire_rain()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/hard/proc/shoot_fire_attack()
|
||||
if(health < maxHealth*0.5)
|
||||
mass_fire()
|
||||
else
|
||||
fire_cone()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/hard/fire_rain()
|
||||
if(!target)
|
||||
return
|
||||
target.visible_message("<span class='boldwarning'>Fire rains from the sky!</span>")
|
||||
for(var/turf/turf in range(9,get_turf(target)))
|
||||
if(prob(11))
|
||||
new /obj/effect/temp_visual/target/hard(turf)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/hard/proc/lava_pools(amount, delay = 0.8)
|
||||
if(!target)
|
||||
return
|
||||
target.visible_message("<span class='boldwarning'>Lava starts to pool up around you!</span>")
|
||||
|
||||
while(amount > 0)
|
||||
if(QDELETED(target))
|
||||
break
|
||||
var/turf/TT = get_turf(target)
|
||||
var/turf/T = pick(RANGE_TURFS(1,TT))
|
||||
new /obj/effect/temp_visual/lava_warning/hard(T, 60) // longer reset time for the lava
|
||||
amount--
|
||||
sleep(delay)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/hard/proc/lava_swoop(amount = 30)
|
||||
if(health < maxHealth * 0.5)
|
||||
return swooop_attack(lava_arena = TRUE, swoop_cooldown = 60)
|
||||
INVOKE_ASYNC(src, .proc/lava_pools, amount)
|
||||
swooop_attack(FALSE, target, 1000) // longer cooldown until it gets reset below
|
||||
sleep(0)
|
||||
fire_cone()
|
||||
if(health < maxHealth*0.66)
|
||||
sleep(10)
|
||||
fire_cone()
|
||||
sleep(10)
|
||||
fire_cone()
|
||||
SetRecoveryTime(20)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/hard/proc/triple_lava_swoop(amount = 45)
|
||||
lava_swoop()
|
||||
sleep(2)
|
||||
lava_swoop()
|
||||
sleep(2)
|
||||
lava_swoop()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/hard/proc/mass_fire(spiral_count = 12, range = 15, times = 3)
|
||||
sleep(0)
|
||||
for(var/i = 1 to times)
|
||||
SetRecoveryTime(50)
|
||||
playsound(get_turf(src),'sound/magic/fireball.ogg', 200, TRUE)
|
||||
var/increment = 360 / spiral_count
|
||||
for(var/j = 1 to spiral_count)
|
||||
var/list/turfs = line_target(j * increment + i * increment / 2, range, src)
|
||||
INVOKE_ASYNC(src, .proc/fire_line, turfs)
|
||||
sleep(25)
|
||||
SetRecoveryTime(30)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/hard/proc/lava_arena()
|
||||
if(!target)
|
||||
return
|
||||
target.visible_message("<span class='boldwarning'>[src] encases you in an arena of fire!</span>")
|
||||
var/amount = 3
|
||||
var/turf/center = get_turf(target)
|
||||
var/list/walled = RANGE_TURFS(3, center) - RANGE_TURFS(2, center)
|
||||
var/list/drakewalls = list()
|
||||
for(var/turf/T in walled)
|
||||
drakewalls += new /obj/effect/temp_visual/drakewall(T) // no people with lava immunity can just run away from the attack for free
|
||||
var/list/indestructible_turfs = list()
|
||||
for(var/turf/T in RANGE_TURFS(2, center))
|
||||
if(istype(T, /turf/open/indestructible))
|
||||
continue
|
||||
if(!istype(T, /turf/closed/indestructible))
|
||||
T.ChangeTurf(/turf/open/floor/plating/asteroid/basalt/lava_land_surface, flags = CHANGETURF_INHERIT_AIR)
|
||||
else
|
||||
indestructible_turfs += T
|
||||
sleep(10) // give them a bit of time to realize what attack is actually happening
|
||||
|
||||
var/list/turfs = RANGE_TURFS(2, center)
|
||||
while(amount > 0)
|
||||
var/list/empty = indestructible_turfs.Copy() // can't place safe turfs on turfs that weren't changed to be open
|
||||
var/any_attack = 0
|
||||
for(var/turf/T in turfs)
|
||||
for(var/mob/living/L in T.contents)
|
||||
if(L.client)
|
||||
empty += pick(((RANGE_TURFS(2, L) - RANGE_TURFS(1, L)) & turfs) - empty) // picks a turf within 2 of the creature not outside or in the shield
|
||||
any_attack = 1
|
||||
for(var/obj/mecha/M in T.contents)
|
||||
empty += pick(((RANGE_TURFS(2, M) - RANGE_TURFS(1, M)) & turfs) - empty)
|
||||
any_attack = 1
|
||||
if(!any_attack)
|
||||
for(var/obj/effect/temp_visual/drakewall/D in drakewalls)
|
||||
qdel(D)
|
||||
return 0 // nothing to attack in the arena time for enraged attack if we still have a target
|
||||
for(var/turf/T in turfs)
|
||||
if(!(T in empty))
|
||||
new /obj/effect/temp_visual/lava_warning/hard(T)
|
||||
else if(!istype(T, /turf/closed/indestructible))
|
||||
new /obj/effect/temp_visual/lava_safe(T)
|
||||
amount--
|
||||
sleep(24)
|
||||
return 1 // attack finished completely
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/hard/proc/arena_escape_enrage() // you ran somehow / teleported away from my arena attack now i'm mad fucker
|
||||
sleep(0)
|
||||
SetRecoveryTime(80)
|
||||
visible_message("<span class='boldwarning'>[src] starts to glow vibrantly as its wounds close up!</span>")
|
||||
adjustBruteLoss(-250) // yeah you're gonna pay for that, don't run nerd
|
||||
add_atom_colour(rgb(255, 255, 0), TEMPORARY_COLOUR_PRIORITY)
|
||||
move_to_delay = move_to_delay / 2
|
||||
light_range = 10
|
||||
sleep(10) // run.
|
||||
mass_fire(20, 15, 3)
|
||||
move_to_delay = initial(move_to_delay)
|
||||
remove_atom_colour(TEMPORARY_COLOUR_PRIORITY)
|
||||
light_range = initial(light_range)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/hard/proc/fire_cone(atom/at = target, meteors = TRUE)
|
||||
playsound(get_turf(src),'sound/magic/fireball.ogg', 200, TRUE)
|
||||
sleep(0)
|
||||
if(prob(50) && meteors)
|
||||
INVOKE_ASYNC(src, .proc/fire_rain)
|
||||
var/range = 15
|
||||
var/list/turfs = list()
|
||||
turfs = line_target(-40, range, at)
|
||||
INVOKE_ASYNC(src, .proc/fire_line, turfs)
|
||||
turfs = line_target(0, range, at)
|
||||
INVOKE_ASYNC(src, .proc/fire_line, turfs)
|
||||
turfs = line_target(40, range, at)
|
||||
INVOKE_ASYNC(src, .proc/fire_line, turfs)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/hard/proc/line_target(offset, range, atom/at = target)
|
||||
if(!at)
|
||||
return
|
||||
var/angle = ATAN2(at.x - src.x, at.y - src.y) + offset
|
||||
var/turf/T = get_turf(src)
|
||||
for(var/i in 1 to range)
|
||||
var/turf/check = locate(src.x + cos(angle) * i, src.y + sin(angle) * i, src.z)
|
||||
if(!check)
|
||||
break
|
||||
T = check
|
||||
return (getline(src, T) - get_turf(src))
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/hard/proc/fire_line(var/list/turfs)
|
||||
sleep(0)
|
||||
dragon_fire_line(src, turfs)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/hard/proc/swooop_attack(lava_arena = FALSE, atom/movable/manual_target, swoop_cooldown = 30)
|
||||
if(stat || swooping)
|
||||
return
|
||||
if(manual_target)
|
||||
target = manual_target
|
||||
if(!target)
|
||||
return
|
||||
stop_automated_movement = TRUE
|
||||
swooping |= SWOOP_DAMAGEABLE
|
||||
density = FALSE
|
||||
icon_state = "shadow"
|
||||
visible_message("<span class='boldwarning'>[src] swoops up high!</span>")
|
||||
|
||||
var/negative
|
||||
var/initial_x = x
|
||||
if(target.x < initial_x) //if the target's x is lower than ours, swoop to the left
|
||||
negative = TRUE
|
||||
else if(target.x > initial_x)
|
||||
negative = FALSE
|
||||
else if(target.x == initial_x) //if their x is the same, pick a direction
|
||||
negative = prob(50)
|
||||
var/obj/effect/temp_visual/dragon_flight/hard/F = new /obj/effect/temp_visual/dragon_flight/hard(loc, negative)
|
||||
|
||||
negative = !negative //invert it for the swoop down later
|
||||
|
||||
var/oldtransform = transform
|
||||
alpha = 255
|
||||
animate(src, alpha = 204, transform = matrix()*0.9, time = 3, easing = BOUNCE_EASING)
|
||||
for(var/i in 1 to 3)
|
||||
sleep(1)
|
||||
if(QDELETED(src) || stat == DEAD) //we got hit and died, rip us
|
||||
qdel(F)
|
||||
if(stat == DEAD)
|
||||
swooping &= ~SWOOP_DAMAGEABLE
|
||||
animate(src, alpha = 255, transform = oldtransform, time = 0, flags = ANIMATION_END_NOW) //reset immediately
|
||||
return
|
||||
animate(src, alpha = 100, transform = matrix()*0.7, time = 7)
|
||||
swooping |= SWOOP_INVULNERABLE
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
sleep(7)
|
||||
|
||||
while(target && loc != get_turf(target))
|
||||
forceMove(get_step(src, get_dir(src, target)))
|
||||
sleep(0.5)
|
||||
|
||||
// Ash drake flies onto its target and rains fire down upon them
|
||||
var/descentTime = 10
|
||||
var/lava_success = TRUE
|
||||
if(lava_arena)
|
||||
lava_success = lava_arena()
|
||||
|
||||
|
||||
//ensure swoop direction continuity.
|
||||
if(negative)
|
||||
if(ISINRANGE(x, initial_x + 1, initial_x + DRAKE_SWOOP_DIRECTION_CHANGE_RANGE))
|
||||
negative = FALSE
|
||||
else
|
||||
if(ISINRANGE(x, initial_x - DRAKE_SWOOP_DIRECTION_CHANGE_RANGE, initial_x - 1))
|
||||
negative = TRUE
|
||||
new /obj/effect/temp_visual/dragon_flight/hard/end(loc, negative)
|
||||
new /obj/effect/temp_visual/dragon_swoop/hard(loc)
|
||||
animate(src, alpha = 255, transform = oldtransform, descentTime)
|
||||
sleep(descentTime)
|
||||
swooping &= ~SWOOP_INVULNERABLE
|
||||
mouse_opacity = initial(mouse_opacity)
|
||||
icon_state = "dragon"
|
||||
playsound(loc, 'sound/effects/meteorimpact.ogg', 200, TRUE)
|
||||
for(var/mob/living/L in orange(1, src))
|
||||
if(L.stat)
|
||||
visible_message("<span class='warning'>[src] slams down on [L], crushing [L.p_them()]!</span>")
|
||||
L.gib()
|
||||
else
|
||||
L.adjustBruteLoss(75)
|
||||
if(L && !QDELETED(L)) // Some mobs are deleted on death
|
||||
var/throw_dir = get_dir(src, L)
|
||||
if(L.loc == loc)
|
||||
throw_dir = pick(GLOB.alldirs)
|
||||
var/throwtarget = get_edge_target_turf(src, throw_dir)
|
||||
L.throw_at(throwtarget, 3)
|
||||
visible_message("<span class='warning'>[L] is thrown clear of [src]!</span>")
|
||||
for(var/obj/mecha/M in orange(1, src))
|
||||
M.take_damage(75, BRUTE, "melee", 1)
|
||||
|
||||
for(var/mob/M in range(7, src))
|
||||
shake_camera(M, 15, 1)
|
||||
|
||||
density = TRUE
|
||||
sleep(1)
|
||||
swooping &= ~SWOOP_DAMAGEABLE
|
||||
SetRecoveryTime(swoop_cooldown)
|
||||
if(!lava_success)
|
||||
arena_escape_enrage()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/hard/proc/triple_swooop(lava_arena = FALSE, atom/movable/manual_target, swoop_cooldown = 4)
|
||||
swooop_attack(lava_arena, manual_target, swoop_cooldown)
|
||||
sleep(15)
|
||||
swooop_attack(lava_arena, manual_target, swoop_cooldown)
|
||||
sleep(15)
|
||||
swooop_attack(lava_arena, manual_target, swoop_cooldown)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/hard/ex_act(severity, target)
|
||||
if(severity == EXPLODE_LIGHT)
|
||||
return
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/hard/adjustHealth(amount, updating_health = TRUE, forced = FALSE)
|
||||
if(!forced && (swooping & SWOOP_INVULNERABLE))
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/hard/visible_message(message, self_message, blind_message, vision_distance = DEFAULT_MESSAGE_RANGE, list/ignored_mobs, mob/target, target_message, user_msg, runechat_popup) //SKYRAT EDIT
|
||||
if(swooping & SWOOP_INVULNERABLE) //to suppress attack messages without overriding every single proc that could send a message saying we got hit
|
||||
return
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/hard/AttackingTarget()
|
||||
if(!swooping)
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/hard/DestroySurroundings()
|
||||
if(!swooping)
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/hard/Move()
|
||||
if(!swooping)
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/hard/Goto(target, delay, minimum_distance)
|
||||
if(!swooping)
|
||||
..()
|
||||
|
||||
/obj/effect/temp_visual/lava_warning/hard
|
||||
icon_state = "lavastaff_warn"
|
||||
layer = BELOW_MOB_LAYER
|
||||
light_range = 2
|
||||
duration = 13
|
||||
|
||||
/obj/effect/temp_visual/lava_warning/hard/ex_act()
|
||||
return
|
||||
|
||||
/obj/effect/temp_visual/lava_warning/hard/Initialize(mapload, reset_time = 10)
|
||||
. = ..()
|
||||
INVOKE_ASYNC(src, .proc/fall, reset_time)
|
||||
src.alpha = 63.75
|
||||
animate(src, alpha = 255, time = duration)
|
||||
|
||||
/obj/effect/temp_visual/lava_warning/hard/fall(var/reset_time)
|
||||
var/turf/T = get_turf(src)
|
||||
playsound(T,'sound/magic/fleshtostone.ogg', 80, TRUE)
|
||||
sleep(duration)
|
||||
playsound(T,'sound/magic/fireball.ogg', 200, TRUE)
|
||||
|
||||
for(var/mob/living/L in T.contents)
|
||||
if(istype(L, /mob/living/simple_animal/hostile/megafauna/dragon))
|
||||
continue
|
||||
L.adjustFireLoss(10)
|
||||
to_chat(L, "<span class='userdanger'>You fall directly into the pool of lava!</span>")
|
||||
|
||||
// deals damage to mechs
|
||||
for(var/obj/mecha/M in T.contents)
|
||||
M.take_damage(45, BRUTE, "melee", 1)
|
||||
|
||||
// changes turf to lava temporarily
|
||||
if(!istype(T, /turf/closed) && !istype(T, /turf/open/lava))
|
||||
var/lava_turf = /turf/open/lava/smooth
|
||||
var/reset_turf = T.type
|
||||
T.ChangeTurf(lava_turf, flags = CHANGETURF_INHERIT_AIR)
|
||||
addtimer(CALLBACK(T, /turf.proc/ChangeTurf, reset_turf, null, CHANGETURF_INHERIT_AIR), reset_time, TIMER_OVERRIDE|TIMER_UNIQUE)
|
||||
|
||||
/obj/effect/temp_visual/drakewall
|
||||
desc = "An ash drakes true flame."
|
||||
name = "Fire Barrier"
|
||||
icon = 'icons/effects/fire.dmi'
|
||||
icon_state = "1"
|
||||
anchored = TRUE
|
||||
opacity = 0
|
||||
density = TRUE
|
||||
CanAtmosPass = ATMOS_PASS_DENSITY
|
||||
duration = 82
|
||||
color = COLOR_DARK_ORANGE
|
||||
|
||||
/obj/effect/temp_visual/lava_safe
|
||||
icon = 'icons/obj/hand_of_god_structures.dmi'
|
||||
icon_state = "trap-earth"
|
||||
layer = BELOW_MOB_LAYER
|
||||
light_range = 2
|
||||
duration = 13
|
||||
|
||||
/obj/effect/temp_visual/dragon_swoop/hard
|
||||
name = "certain death"
|
||||
desc = "Don't just stand there, move!"
|
||||
icon = 'icons/effects/96x96.dmi'
|
||||
icon_state = "landing"
|
||||
layer = BELOW_MOB_LAYER
|
||||
pixel_x = -32
|
||||
pixel_y = -32
|
||||
color = "#FF0000"
|
||||
duration = 10
|
||||
|
||||
/obj/effect/temp_visual/dragon_flight/hard
|
||||
icon = 'icons/mob/lavaland/64x64megafauna.dmi'
|
||||
icon_state = "dragon"
|
||||
layer = ABOVE_ALL_MOB_LAYER
|
||||
pixel_x = -16
|
||||
duration = 10
|
||||
randomdir = FALSE
|
||||
|
||||
/obj/effect/temp_visual/dragon_flight/hard/Initialize(mapload, negative)
|
||||
. = ..()
|
||||
INVOKE_ASYNC(src, .proc/flight, negative)
|
||||
|
||||
/obj/effect/temp_visual/dragon_flight/hard/flight(negative)
|
||||
if(negative)
|
||||
animate(src, pixel_x = -DRAKE_SWOOP_HEIGHT*0.1, pixel_z = DRAKE_SWOOP_HEIGHT*0.15, time = 3, easing = BOUNCE_EASING)
|
||||
else
|
||||
animate(src, pixel_x = DRAKE_SWOOP_HEIGHT*0.1, pixel_z = DRAKE_SWOOP_HEIGHT*0.15, time = 3, easing = BOUNCE_EASING)
|
||||
sleep(3)
|
||||
icon_state = "swoop"
|
||||
if(negative)
|
||||
animate(src, pixel_x = -DRAKE_SWOOP_HEIGHT, pixel_z = DRAKE_SWOOP_HEIGHT, time = 7)
|
||||
else
|
||||
animate(src, pixel_x = DRAKE_SWOOP_HEIGHT, pixel_z = DRAKE_SWOOP_HEIGHT, time = 7)
|
||||
|
||||
/obj/effect/temp_visual/dragon_flight/end
|
||||
pixel_x = DRAKE_SWOOP_HEIGHT
|
||||
pixel_z = DRAKE_SWOOP_HEIGHT
|
||||
duration = 10
|
||||
|
||||
/obj/effect/temp_visual/dragon_flight/hard/end/flight(negative)
|
||||
if(negative)
|
||||
pixel_x = -DRAKE_SWOOP_HEIGHT
|
||||
animate(src, pixel_x = -16, pixel_z = 0, time = 5)
|
||||
else
|
||||
animate(src, pixel_x = -16, pixel_z = 0, time = 5)
|
||||
|
||||
obj/effect/temp_visual/fireball/hard
|
||||
icon = 'icons/obj/wizard.dmi'
|
||||
icon_state = "fireball"
|
||||
name = "fireball"
|
||||
desc = "Get out of the way!"
|
||||
layer = FLY_LAYER
|
||||
randomdir = FALSE
|
||||
duration = 9
|
||||
pixel_z = 270
|
||||
|
||||
/obj/effect/temp_visual/fireball/hard/Initialize()
|
||||
. = ..()
|
||||
animate(src, pixel_z = 0, time = duration)
|
||||
|
||||
/obj/effect/temp_visual/target/hard
|
||||
icon = 'icons/mob/actions/actions_items.dmi'
|
||||
icon_state = "sniper_zoom"
|
||||
layer = BELOW_MOB_LAYER
|
||||
light_range = 2
|
||||
duration = 9
|
||||
|
||||
/obj/effect/temp_visual/target/hard/ex_act()
|
||||
return
|
||||
|
||||
/obj/effect/temp_visual/target/hard/Initialize(mapload, list/flame_hit)
|
||||
. = ..()
|
||||
INVOKE_ASYNC(src, .proc/fall, flame_hit)
|
||||
|
||||
/obj/effect/temp_visual/target/hard/fall(list/flame_hit)
|
||||
var/turf/T = get_turf(src)
|
||||
playsound(T,'sound/magic/fleshtostone.ogg', 80, TRUE)
|
||||
new /obj/effect/temp_visual/fireball/hard(T)
|
||||
sleep(duration)
|
||||
if(ismineralturf(T))
|
||||
var/turf/closed/mineral/M = T
|
||||
M.gets_drilled()
|
||||
playsound(T, "explosion", 80, TRUE)
|
||||
new /obj/effect/hotspot(T)
|
||||
T.hotspot_expose(700, 50, 1)
|
||||
for(var/mob/living/L in T.contents)
|
||||
if(istype(L, /mob/living/simple_animal/hostile/megafauna/dragon))
|
||||
continue
|
||||
if(islist(flame_hit) && !flame_hit[L])
|
||||
L.adjustFireLoss(40)
|
||||
to_chat(L, "<span class='userdanger'>You're hit by the drake's fire breath!</span>")
|
||||
flame_hit[L] = TRUE
|
||||
else
|
||||
L.adjustFireLoss(10) //if we've already hit them, do way less damage
|
||||
@@ -0,0 +1,390 @@
|
||||
/* THE GLADIATOR
|
||||
* Has 4 special attacks, which are used depending on the phase (the gladiator has 3 phases).
|
||||
* AoE Zweihander swing: In a square of 4×4, he swings his sword in a 360 degree arc, damaging anything within it.
|
||||
* Shield bash: The gladiator charges and chases you with increased speed for 21 tiles, if he makes contact, he bashes you and knocks you down.
|
||||
He will stun himself for up to 2.25 seconds, no matter the result of the charge attack; This leaves him vulnerable for attacks for a few precious moments.
|
||||
* Bone daggers: At random times if the player is running, he can throw bone daggers that will go considerably fast in the players direction.
|
||||
They deal 35 brute (armor is considered).
|
||||
* Additionally, he gets more speedy and aggressive as he raises in phase, at the cost of some special attacks.
|
||||
* On phase 1, the gladiator has a 50% block chance for any attack.
|
||||
* Loot:
|
||||
* Gladiator tower shield - A powerful and indestructible shield, that can also be used as a surfboard.
|
||||
* Shielding modkit - A modkit that grants your PKA a 15% chance to block any incoming attack while held.
|
||||
* Tomahawk - Basically a one handed crusher to complement the shield.
|
||||
*/
|
||||
/mob/living/simple_animal/hostile/megafauna/gladiator
|
||||
name = "\proper The Gladiator"
|
||||
desc = "An immortal ash walker, whose powers have been granted by the necropolis itself."
|
||||
icon = 'sandcode/icons/mob/lavaland/lavaland_monsters.dmi'
|
||||
icon_state = "gladiator1"
|
||||
icon_dead = "gladiator_dying"
|
||||
attack_verb_simple = "slashes"
|
||||
attack_verb_continuous = "slash"
|
||||
attack_sound = 'sandcode/sound/weapons/zweihanderslice.ogg'
|
||||
death_sound = 'sandcode/sound/effects/gladiatordeathsound.ogg'
|
||||
deathmessage = "gets discombobulated and dies."
|
||||
rapid_melee = 1
|
||||
melee_queue_distance = 2
|
||||
melee_damage_lower = 35
|
||||
melee_damage_upper = 35
|
||||
speed = 1
|
||||
move_to_delay = 2.25
|
||||
wander = FALSE
|
||||
var/block_chance = 50
|
||||
ranged = 1
|
||||
ranged_cooldown_time = 30
|
||||
minimum_distance = 1
|
||||
health = 1500
|
||||
maxHealth = 1500
|
||||
movement_type = GROUND
|
||||
weather_immunities = list("lava","ash")
|
||||
var/phase = 1
|
||||
var/list/introduced = list() //Basically all the mobs which the gladiator has already introduced himself to.
|
||||
var/speen = FALSE
|
||||
var/speenrange = 4
|
||||
var/obj/savedloot = null
|
||||
var/charging = FALSE
|
||||
var/chargetiles = 0
|
||||
var/chargerange = 21
|
||||
var/stunned = FALSE
|
||||
var/stunduration = 15
|
||||
var/move_to_charge = 1.5
|
||||
loot = list(/obj/structure/closet/crate/necropolis/gladiator)
|
||||
crusher_loot = list(/obj/structure/closet/crate/necropolis/gladiator/crusher)
|
||||
glorymessageshand = list("grabs the gladiator's arm, flips their zweihander with the other hand, and forcefully makes them chop off their own head with it!", "grabs the gladiator by their zweihander, and mark detonate them into a shower of gibs!", "rips out both of the gladiator's arms, then kicks their limp torso on the groundd and curbstomps their head in so hard it explodes!")
|
||||
glorymessagescrusher = list("chops off gladiator's zweihandder arm in one swift move, then grabs the zweihander and swings it against their head, chopping their skull vertically in half!", "bashes the gladiator to the ground with the hilt of their crusher, then elbow drops their skull so hard it explodes in gore!", "chops the gladiator diagonally with their crusher, not quite cutting through but getting their crusher halfway stuck and killing the screaming fiend!")
|
||||
glorymessagespka = list("grabs the gladiator by the neck and flips them, shooting through their guts with a PKA blast!", "shoots at the gladiator's shoulder, exploding their arm! To finish the fiend off, they grab their PKA and bonk the gladiator's head inside their torso!", "doesn't bother with being fancy, and simply shoots at the gladiator's head with their PKA, exploding it in one violent blast!")
|
||||
glorymessagespkabayonet = list("rams into the gladiator's stomach with their PKA's bayonet, knocking them and themselves down! To finish the fiend off, they simply stab into their torso like a madman with their bayonet!", "kicks the gladiator's knee hard, breaking it! While the fiend is stunned and barely standing, their chop their head off with the PKA's bayonet!")
|
||||
glorythreshold = 50
|
||||
weather_immunities = list("lava","ash")
|
||||
|
||||
/obj/item/gps/internal/gladiator
|
||||
icon_state = null
|
||||
gpstag = "Dreadful Signal"
|
||||
desc = "Let me help you to see, miner."
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/gladiator/Initialize(mapload)
|
||||
. = ..()
|
||||
internal = new /obj/item/gps/internal/gladiator(src)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/gladiator/Life()
|
||||
. = ..()
|
||||
if(!wander)
|
||||
for(var/mob/living/M in view(4, src))
|
||||
if(!(M in introduced) && (stat != DEAD))
|
||||
introduction(M)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/gladiator/apply_damage(damage, damagetype, def_zone, blocked, forced, bare_wound_bonus = FALSE, sharpness = FALSE, wound_bonus=CANT_WOUND)
|
||||
if(speen)
|
||||
visible_message("<span class='danger'>[src] brushes off all incoming attacks!")
|
||||
return FALSE
|
||||
else if(prob(50) && (phase == 1) && !stunned)
|
||||
visible_message("<span class='danger'>[src] blocks all incoming damage with his shield!")
|
||||
return FALSE
|
||||
..()
|
||||
update_phase()
|
||||
var/adjustment_amount = min(damage * 0.15, 15)
|
||||
if(world.time + adjustment_amount > next_move)
|
||||
changeNext_move(adjustment_amount)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/gladiator/Retaliate()
|
||||
. = ..()
|
||||
if(!wander)
|
||||
wander = TRUE
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/gladiator/proc/introduction(mob/living/target)
|
||||
if(src == target)
|
||||
introduced += src
|
||||
return
|
||||
if(ishuman(target))
|
||||
var/mob/living/carbon/human/H = target
|
||||
var/datum/species/Hspecies = H.dna.species
|
||||
if(Hspecies.id == "ashlizard")
|
||||
var/list/messages = list("I am sorry, tribesssmate. I cannot let you through.",\
|
||||
"Pleassse leave, walker.",\
|
||||
"The necropolisss must be protected even from it'ss servants. Pleassse retreat.")
|
||||
say(message = pick(messages), language = /datum/language/draconic)
|
||||
introduced |= H
|
||||
else if(Hspecies.id == "lizard")
|
||||
var/list/messages = list("Thisss isss not the time nor place to be. Leave.",\
|
||||
"Go back where you came from. I am sssafeguarding thisss sssacred place.",\
|
||||
"You ssshould not be here. Turn.",\
|
||||
"I can sssee an outlander from a mile away. You're not one of us."\
|
||||
)
|
||||
say(message = pick(messages), language = /datum/language/draconic)
|
||||
introduced |= H
|
||||
else if(Hspecies.id == "dunmer")
|
||||
var/list/messages = list("I will finisssh what little of your race remainsss, starting with you!",\
|
||||
"Lavaland belongsss to the lizzzards!",\
|
||||
"Thisss sacred land wasn't your property before, it won't be now!")
|
||||
say(message = pick(messages))
|
||||
introduced |= H
|
||||
GiveTarget(H)
|
||||
Retaliate()
|
||||
else
|
||||
var/list/messages = list("Get out of my sssight, outlander.",\
|
||||
"You will not run your dirty handsss through what little sssacred land we have left. Out.",\
|
||||
"My urge to end your life isss immeasssurable, but I am willing to ssspare you. Leave.",\
|
||||
"You're not invited. Get out.")
|
||||
say(message = pick(messages))
|
||||
introduced |= H
|
||||
|
||||
else
|
||||
say("You are not welcome into the necropolisss.")
|
||||
introduced |= target
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/gladiator/Move(atom/newloc, dir, step_x, step_y)
|
||||
if(speen || stunned)
|
||||
return FALSE
|
||||
else
|
||||
if(ischasm(newloc))
|
||||
var/list/possiblelocs = list()
|
||||
switch(dir)
|
||||
if(NORTH)
|
||||
possiblelocs += locate(x +1, y + 1, z)
|
||||
possiblelocs += locate(x -1, y + 1, z)
|
||||
if(EAST)
|
||||
possiblelocs += locate(x + 1, y + 1, z)
|
||||
possiblelocs += locate(x + 1, y - 1, z)
|
||||
if(WEST)
|
||||
possiblelocs += locate(x - 1, y + 1, z)
|
||||
possiblelocs += locate(x - 1, y - 1, z)
|
||||
if(SOUTH)
|
||||
possiblelocs += locate(x - 1, y - 1, z)
|
||||
possiblelocs += locate(x + 1, y - 1, z)
|
||||
if(SOUTHEAST)
|
||||
possiblelocs += locate(x + 1, y, z)
|
||||
possiblelocs += locate(x + 1, y + 1, z)
|
||||
if(SOUTHWEST)
|
||||
possiblelocs += locate(x - 1, y, z)
|
||||
possiblelocs += locate(x - 1, y + 1, z)
|
||||
if(NORTHWEST)
|
||||
possiblelocs += locate(x - 1, y, z)
|
||||
possiblelocs += locate(x - 1, y - 1, z)
|
||||
if(NORTHEAST)
|
||||
possiblelocs += locate(x + 1, y - 1, z)
|
||||
possiblelocs += locate(x + 1, y, z)
|
||||
for(var/turf/T in possiblelocs)
|
||||
if(ischasm(T))
|
||||
possiblelocs -= T
|
||||
if(possiblelocs.len)
|
||||
var/turf/validloc = pick(possiblelocs)
|
||||
if(charging)
|
||||
chargetiles++
|
||||
if(chargetiles >= chargerange)
|
||||
discharge()
|
||||
return ..(validloc)
|
||||
return FALSE
|
||||
else
|
||||
if(charging)
|
||||
chargetiles++
|
||||
if(chargetiles >= chargerange)
|
||||
discharge()
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/gladiator/Bump(atom/A)
|
||||
. = ..()
|
||||
if(charging)
|
||||
if(isliving(A))
|
||||
var/mob/living/LM = A
|
||||
forceMove(LM.loc)
|
||||
visible_message("<span class='userdanger'>[src] knocks [LM] down!</span>")
|
||||
LM.DefaultCombatKnockdown(60)
|
||||
discharge()
|
||||
else if(istype(A, /turf/closed))
|
||||
visible_message("<span class='userdanger'>[src] crashes headfirst into [A]!</span>")
|
||||
discharge(1.33)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/gladiator/proc/update_phase()
|
||||
var/healthpercentage = 100 * (health/maxHealth)
|
||||
if(src.stat == DEAD)
|
||||
return
|
||||
switch(healthpercentage)
|
||||
if(75 to 100)
|
||||
phase = 1
|
||||
rapid_melee = initial(rapid_melee)
|
||||
move_to_delay = initial(move_to_delay)
|
||||
melee_damage_upper = initial(melee_damage_upper)
|
||||
melee_damage_lower = initial(melee_damage_lower)
|
||||
if(30 to 75)
|
||||
phase = 2
|
||||
icon_state = "gladiator2"
|
||||
rapid_melee = 2
|
||||
move_to_delay = 2
|
||||
melee_damage_upper = 30
|
||||
melee_damage_lower = 30
|
||||
if(0 to 30)
|
||||
phase = 3
|
||||
icon_state = "gladiator3"
|
||||
rapid_melee = 4
|
||||
melee_damage_upper = 25
|
||||
melee_damage_lower = 25
|
||||
move_to_delay = 1.7
|
||||
if(charging)
|
||||
move_to_delay = move_to_charge
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/gladiator/proc/zweispin()
|
||||
visible_message("<span class='boldwarning'>[src] lifts his zweihander, and prepares to spin!</span>")
|
||||
speen = TRUE
|
||||
animate(src, color = "#ff6666", 10)
|
||||
sleep(5)
|
||||
var/list/speenturfs = list()
|
||||
var/list/temp = (view(speenrange, src) - view(speenrange-1, src))
|
||||
speenturfs.len = temp.len
|
||||
var/woop = FALSE
|
||||
var/start = 0
|
||||
for(var/i in 0 to speenrange)
|
||||
speenturfs[1+i] = locate(x - i, y - speenrange, z)
|
||||
start = i
|
||||
for(var/i in 1 to (speenrange*2))
|
||||
var/turf/T = speenturfs[start]
|
||||
speenturfs[start+i] = locate(T.x, T.y + i, T.z)
|
||||
if(i == (speenrange*2))
|
||||
start = (start+i)
|
||||
for(var/i in 1 to (speenrange*2))
|
||||
var/turf/T = speenturfs[start]
|
||||
speenturfs[start+i] = locate(T.x + i, T.y, T.z)
|
||||
if(i == (speenrange*2))
|
||||
start = (start+i)
|
||||
for(var/i in 1 to (speenrange*2))
|
||||
var/turf/T = speenturfs[start]
|
||||
speenturfs[start+i] = locate(T.x, T.y - i, T.z)
|
||||
if(i == (speenrange*2))
|
||||
start = (start+i)
|
||||
for(var/i in 1 to speenrange)
|
||||
var/turf/T = speenturfs[start]
|
||||
speenturfs[start+i] = locate(T.x - i, T.y, T.z)
|
||||
var/list/hit_things = list()
|
||||
for(var/turf/T in speenturfs)
|
||||
src.dir = get_dir(src, T)
|
||||
for(var/turf/U in (getline(src, T) - get_turf(src)))
|
||||
var/obj/effect/temp_visual/small_smoke/smonk = new /obj/effect/temp_visual/small_smoke(U)
|
||||
QDEL_IN(smonk, 1.25)
|
||||
for(var/mob/living/M in U)
|
||||
if(!faction_check(faction, M.faction) && !(M in hit_things))
|
||||
playsound(src, 'sound/weapons/slash.ogg', 75, 0)
|
||||
if(M.apply_damage(40, BRUTE, BODY_ZONE_CHEST))
|
||||
visible_message("<span class = 'userdanger'>[src] slashes [M] with his spinning zweihander!</span>")
|
||||
else
|
||||
visible_message("<span class = 'userdanger'>[src]'s spinning zweihander is stopped by [M]!</span>")
|
||||
woop = TRUE
|
||||
hit_things += M
|
||||
if(woop)
|
||||
break
|
||||
sleep(1.25)
|
||||
animate(src, color = initial(color), 3)
|
||||
sleep(3)
|
||||
speen = FALSE
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/gladiator/proc/chargeattack(atom/target, var/range)
|
||||
face_atom(target)
|
||||
visible_message("<span class='boldwarning'>[src] lifts his shield, and prepares to charge!</span>")
|
||||
animate(src, color = "#ff6666", 3)
|
||||
sleep(4)
|
||||
face_atom(target)
|
||||
move_to_delay = move_to_charge
|
||||
minimum_distance = 0
|
||||
charging = TRUE
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/gladiator/proc/discharge(var/modifier = 1)
|
||||
stunned = TRUE
|
||||
charging = FALSE
|
||||
minimum_distance = 1
|
||||
chargetiles = 0
|
||||
animate(src, color = initial(color), 7)
|
||||
update_phase()
|
||||
sleep(stunduration * modifier)
|
||||
stunned = FALSE
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/gladiator/proc/teleport(atom/target)
|
||||
var/turf/T = get_step(target, -target.dir)
|
||||
new /obj/effect/temp_visual/small_smoke/halfsecond(get_turf(src))
|
||||
sleep(4)
|
||||
if(!ischasm(T) && !(/mob/living in T))
|
||||
new /obj/effect/temp_visual/small_smoke/halfsecond(T)
|
||||
forceMove(T)
|
||||
else
|
||||
var/list/possiblelocs = (view(3, target) - view(1, target))
|
||||
for(var/atom/A in possiblelocs)
|
||||
if(!isturf(A))
|
||||
possiblelocs -= A
|
||||
else
|
||||
if(ischasm(A) || istype(A, /turf/closed) || (/mob/living in A))
|
||||
possiblelocs -= A
|
||||
if(possiblelocs.len)
|
||||
T = pick(possiblelocs)
|
||||
new /obj/effect/temp_visual/small_smoke/halfsecond(T)
|
||||
forceMove(T)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/gladiator/AttackingTarget()
|
||||
. = ..()
|
||||
if(speen || stunned)
|
||||
return FALSE
|
||||
if(charging)
|
||||
Bump(target)
|
||||
if(. && prob(5 * phase))
|
||||
teleport(target)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/gladiator/proc/boneappletea(atom/target)
|
||||
var/obj/item/kitchen/knife/combat/bone/boned = new /obj/item/kitchen/knife/combat/bone(get_turf(src))
|
||||
boned.throwforce = 35
|
||||
playsound(src, 'sound/weapons/fwoosh.wav', 60, 0)
|
||||
boned.throw_at(target, 7, 3, src)
|
||||
QDEL_IN(boned, 30)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/gladiator/OpenFire()
|
||||
if(world.time < ranged_cooldown)
|
||||
return FALSE
|
||||
if(speen || stunned || charging)
|
||||
return FALSE
|
||||
ranged_cooldown = world.time
|
||||
switch(phase)
|
||||
if(1)
|
||||
if(prob(25) && (get_dist(src, target) <= 4))
|
||||
zweispin()
|
||||
ranged_cooldown += 70
|
||||
else
|
||||
if(prob(66))
|
||||
chargeattack(target, 21)
|
||||
ranged_cooldown += 40
|
||||
else
|
||||
teleport(target)
|
||||
ranged_cooldown += 35
|
||||
if(2)
|
||||
if(prob(40) && (get_dist(src, target) <= 4))
|
||||
zweispin()
|
||||
ranged_cooldown += 55
|
||||
else
|
||||
if(prob(40))
|
||||
boneappletea(target)
|
||||
ranged_cooldown += 35
|
||||
else
|
||||
teleport(target)
|
||||
ranged_cooldown += 30
|
||||
if(3)
|
||||
if(prob(35))
|
||||
boneappletea(target)
|
||||
ranged_cooldown += 30
|
||||
else
|
||||
teleport(target)
|
||||
ranged_cooldown += 20
|
||||
|
||||
//Aggression helpers
|
||||
/obj/effect/step_trigger/gladiator
|
||||
var/mob/living/simple_animal/hostile/megafauna/gladiator/glady
|
||||
|
||||
/obj/effect/step_trigger/gladiator/Initialize()
|
||||
. = ..()
|
||||
for(var/mob/living/simple_animal/hostile/megafauna/gladiator/G in view(7, src))
|
||||
if(!glady)
|
||||
glady = G
|
||||
|
||||
/obj/effect/step_trigger/gladiator/Trigger(atom/movable/A)
|
||||
if(isliving(A))
|
||||
var/mob/living/bruh = A
|
||||
glady.enemies |= bruh
|
||||
glady.GiveTarget(bruh)
|
||||
for(var/obj/effect/step_trigger/gladiator/glad in view(7, src))
|
||||
qdel(glad)
|
||||
return TRUE
|
||||
return FALSE
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
|
||||
GLAURUNG
|
||||
|
||||
Glaurung is a special Ash Drake for admemery roleplay. It's distinguishing features are the name, description, and the glowing blue eyes.
|
||||
|
||||
When not controlled by a player, it acts as a normal ashdrake, but with various changes.
|
||||
|
||||
Whenever possible, the drake will breathe fire in the direction it faces, igniting and heavily damaging anything caught in the blast.
|
||||
It also often causes fire to rain from the sky - many nearby turfs will flash red as a fireball crashes into them, dealing damage to anything on the turfs.
|
||||
Glaurung is unable to fly due to excess years of damage to its wings, but it is much faster on its legs.
|
||||
|
||||
When an ash drake dies, it leaves behind a chest that can contain four things:
|
||||
1. A spectral blade that allows its wielder to call ghosts to it, enhancing its power
|
||||
2. A lava staff that allows its wielder to create lava
|
||||
3. A spellbook and wand of fireballs
|
||||
4. A bottle of dragon's blood with several effects, including turning its imbiber into a drake themselves.
|
||||
|
||||
When butchered, they leave behind diamonds, sinew, bone, and ash drake hide. Ash drake hide can be used to create a hooded cloak that protects its wearer from ash storms.
|
||||
|
||||
Difficulty: Medium
|
||||
|
||||
*/
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/glaurung
|
||||
name = "Glaurung"
|
||||
desc = "An ancient Ash Drake untouched except for age. It's eyes glow a soft blue color as opposed to a regular yellow. It carries itself with more strength than the standard drake, eyeing those who come near with caution. Perhaps it is smarter and capable of speech?"
|
||||
threat = 5
|
||||
health = 2000
|
||||
maxHealth = 2000
|
||||
spacewalk = TRUE
|
||||
initial_language_holder = /datum/language_holder/dragon
|
||||
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
|
||||
sight = SEE_TURFS|SEE_MOBS|SEE_OBJS
|
||||
attack_verb_continuous = "chomps"
|
||||
attack_verb_simple = "chomp"
|
||||
attack_sound = 'sound/magic/demon_attack1.ogg'
|
||||
icon = 'sandcode/icons/mob/lavaland/glaurung.dmi'
|
||||
icon_state = "glaurung"
|
||||
icon_living = "glaurung"
|
||||
icon_dead = "glaurung_dead"
|
||||
friendly_verb_continuous = "stares down"
|
||||
friendly_verb_simple = "stare down"
|
||||
speak_emote = list("roars")
|
||||
armour_penetration = 45
|
||||
melee_damage_lower = 20
|
||||
melee_damage_upper = 40
|
||||
speed = 1
|
||||
move_to_delay = 4
|
||||
ranged = 1
|
||||
pixel_x = -16
|
||||
crusher_loot = list(/obj/structure/closet/crate/necropolis/glaurung/crusher)
|
||||
loot = list(/obj/structure/closet/crate/necropolis/glaurung)
|
||||
butcher_results = list(/obj/item/stack/ore/diamond = 5, /obj/item/stack/sheet/sinew = 5, /obj/item/stack/sheet/bone = 30)
|
||||
guaranteed_butcher_results = list(/obj/item/stack/sheet/animalhide/ashdrake = 10)
|
||||
medal_type = BOSS_MEDAL_DRAKE
|
||||
score_type = DRAKE_SCORE
|
||||
deathmessage = "collapses into a pile of bones, its flesh sloughing away."
|
||||
death_sound = 'sound/magic/demon_dies.ogg'
|
||||
songs = null
|
||||
move_force = MOVE_FORCE_NORMAL
|
||||
move_resist = MOVE_FORCE_NORMAL
|
||||
pull_force = MOVE_FORCE_NORMAL
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/glaurung/Initialize()
|
||||
smallsprite.Grant(src)
|
||||
. = ..()
|
||||
internal = new/obj/item/gps/internal/glaurung(src)
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/glaurung/proc/line_target(offset, range, atom/at = target)
|
||||
if(!at)
|
||||
return
|
||||
var/angle = ATAN2(at.x - src.x, at.y - src.y) + offset
|
||||
var/turf/T = get_turf(src)
|
||||
for(var/i in 1 to range)
|
||||
var/turf/check = locate(src.x + cos(angle) * i, src.y + sin(angle) * i, src.z)
|
||||
if(!check)
|
||||
break
|
||||
T = check
|
||||
return (getline(src, T) - get_turf(src))
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/glaurung/proc/fire_line(var/list/turfs)
|
||||
sleep(0)
|
||||
dragon_fire_line(src, turfs)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/glaurung/proc/fire_stream(var/atom/at = target)
|
||||
playsound(get_turf(src),'sound/magic/fireball.ogg', 200, TRUE)
|
||||
sleep(0)
|
||||
var/range = 20
|
||||
var/list/turfs = list()
|
||||
turfs = line_target(0, range, at)
|
||||
INVOKE_ASYNC(src, .proc/fire_line, turfs)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/glaurung/OpenFire()
|
||||
if(swooping)
|
||||
return
|
||||
ranged_cooldown = world.time + ranged_cooldown_time
|
||||
fire_stream()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/glaurung/triple_swoop()
|
||||
return null
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/glaurung/swoop_attack(fire_rain, atom/movable/manual_target, swoop_duration = 40)
|
||||
return null
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/dragon/glaurung/AltClickOn(atom/movable/A)
|
||||
if(!istype(A))
|
||||
to_chat(src, "<span class='warning'>Your wings are too damaged for old swoop maneuvers.</span>")
|
||||
return
|
||||
|
||||
/obj/item/gps/internal/glaurung
|
||||
icon_state = null
|
||||
gpstag = "Wise Signal"
|
||||
desc = "Something ancient lies this way."
|
||||
invisibility = 100
|
||||
@@ -0,0 +1,8 @@
|
||||
/mob/living/simple_animal/hostile/megafauna/hierophant
|
||||
loot = list(/obj/item/hierophant_club, /obj/item/borg/upgrade/modkit/wall)
|
||||
crusher_loot = list(/obj/item/hierophant_club, /obj/item/borg/upgrade/modkit/wall)
|
||||
songs = list("2610" = sound(file = 'sandcode/sound/ambience/dummyremix.ogg', repeat = 0, wait = 0, volume = 60, channel = CHANNEL_BOSSMUSIC), "1680" = sound(file = 'sandcode/sound/ambience/rollermobster.ogg', repeat = 0, wait = 0, volume = 60, channel = CHANNEL_BOSSMUSIC)) //Dummy originally made by Toby Fox, remix by Emsdache. Roller Mobster by Carpenter Brut.
|
||||
glorymessageshand = list("grabs the floating club by the hilt, and violently smashes it onto the ground, killing it!", "jumps onto the hierophant and rips off their beacon with one hand as it crackles and explodes!")
|
||||
glorymessagescrusher = list("violently chops the floating club with seemingly no effect, until it falls onto the ground limply!")
|
||||
glorymessagespka = list("shoots at the floating club in the middle of it's 'face', which seemingly overloads it until it explodes!")
|
||||
glorymessagespkabayonet = list("jumps on the hierophant and stabs it's beacon, the bizarre creature seemingly screaming until it crackles and explodes!")
|
||||
@@ -0,0 +1,333 @@
|
||||
/*
|
||||
KING OF GOATS
|
||||
The king of goat is inside a 9x9 arena protected by two guards while during stage one it is generally a cake walk the later stages however can prove extremely challenging and downright impossible for less skilled miners..
|
||||
The king goat is as indicated by his name the king of all goats and as such if you attempt to fight him you will learn why he is the king in the first place...
|
||||
It has no ranged attacks what so ever but makes up for it by being confined in a small space and having the ability to summon guards, charge at his enemy and do a aoe explosion attack which can prove devistating for most miners.
|
||||
The three stages of the king goat:
|
||||
Stage 1: The king goat is pretty much just a slightly more robust regular goat, the king will proceed to charge at you full force in the hopes of taking you out easily but can be easily defeated by even a unexperienced miner.
|
||||
Stage 2: This is where things start heating up. At this stage the king goat will become slightly larger and start doing special attacks which range from summoning guards to come to his aid to stomping his hooves on the ground causing the arena to shake and a aoe explosion to appear around him most miners do not make it pass this stage but if you do...
|
||||
Stage 3: Oh boy your in for it now at this stage the king goat will completly heal and grow slightly bigger and start glowing it has the exact same attacks as stage 2 but is much more intimidating if you can defeat him at stage three he will fall over dead on the ground and drop a ladder so you may now leave the arena but dont forget to grab the loot first!
|
||||
The loot:
|
||||
The goat gun: This weapon as the name implies fires goats at your enemies knocking them down and doing a bit of brute damage it self recharges and combined with the goat pope hat or king goat pelt can lead to some interesting shenigans,
|
||||
The king goat pelt: Hope you brought a knife cause your gonna need to butcher the king goats corpse to get this prize. Once you butcher the king goat you can grab his pelt and wear it on your head as armor, boasting decent bomb resistance and slightly better gun and laser resistance then the drake helm at the cost of slightly reduced melee protection this is THE prize to show who the king of lavaland really is around here! Also makes goats friendly towards you as long as you are wearing it for they will see you as their new king.
|
||||
Difficulty: Insanely Hard
|
||||
*/
|
||||
|
||||
//Visager's tracks 'Battle!' and 'Miniboss Fight' from the album 'Songs from an Unmade World 2' are available here
|
||||
//http://freemusicarchive.org/music/Visager/Songs_From_An_Unmade_World_2/ and are made available under the CC BY 4.0 Attribution license,
|
||||
//which is available for viewing here: https://creativecommons.org/licenses/by/4.0/legalcode
|
||||
|
||||
|
||||
//the king and his court
|
||||
/mob/living/simple_animal/hostile/megafauna/king
|
||||
name = "king of the goats"
|
||||
desc = "The oldest and wisest of the goats. King of his race, peerless in dignity and power. His golden fleece radiates nobility."
|
||||
icon = 'sandcode/icons/mob/king_of_goats.dmi'
|
||||
icon_state = "king_goat"
|
||||
icon_living = "king_goat"
|
||||
icon_dead = "king_goat_dead"
|
||||
faction = list("goat_king")
|
||||
speak = list("EHEHEHEHEH","eh?")
|
||||
speak_chance = 1
|
||||
attack_same = FALSE
|
||||
speak_emote = list("brays in a booming voice")
|
||||
emote_hear = list("brays in a booming voice")
|
||||
emote_see = list("stamps a mighty foot, shaking the surroundings")
|
||||
response_help_continuous = "placates"
|
||||
response_help_simple = "placate"
|
||||
response_harm_continuous = "assaults"
|
||||
response_harm_simple = "assault"
|
||||
attack_sound = 'sound/weapons/punch1.ogg'
|
||||
health = 500
|
||||
a_intent = INTENT_HARM
|
||||
sentience_type = SENTIENCE_BOSS
|
||||
stat_attack = DEAD
|
||||
wander = FALSE
|
||||
movement_type = GROUND
|
||||
maxHealth = 500
|
||||
armour_penetration = 35
|
||||
melee_damage_lower = 35
|
||||
melee_damage_upper = 55
|
||||
minbodytemp = 0
|
||||
maxbodytemp = INFINITY
|
||||
obj_damage = 400
|
||||
vision_range = 5
|
||||
aggro_vision_range = 18
|
||||
robust_searching = TRUE
|
||||
move_to_delay = 3
|
||||
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)
|
||||
minbodytemp = 0
|
||||
var/stun_chance = 5 //chance per attack to Weaken target
|
||||
glorymessageshand = list("grabs the goat by it's horns, then repeatedly knees it in the face until it's skull cracks open and it fucking dies!", "rips off one of the goat's horns bare-handed, then stabs through their skull with it, killing it!")
|
||||
glorymessagescrusher = list("slashes both of the goat's horns with their crusher, then chops it's face in half with it!")
|
||||
glorymessagespka = list("shoots at goat's maw, the goat seemingly gulping down the blast and exploding!", "kicks the goat into the air, then shoots it in the gut with their PKA's blast, showering everything in... goat guts!")
|
||||
glorymessagespkabayonet = list("repeatedly stabs through the goat's eye and skull with their PKAA's bayonet, until it finally gives up and lets go of their life!")
|
||||
gloryhealth = 50
|
||||
glorythreshold = 50
|
||||
crusher_loot = list(/obj/item/crusher_trophy/king_goat)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/king/ex_act(severity, target)
|
||||
switch (severity)
|
||||
if (1)
|
||||
adjustBruteLoss(100)
|
||||
|
||||
if (2)
|
||||
adjustBruteLoss(50)
|
||||
|
||||
if(3)
|
||||
adjustBruteLoss(25)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/king/phase2
|
||||
name = "emperor of the goats"
|
||||
desc = "The King of Kings, God amongst men, and your superior in every way."
|
||||
icon_state = "king_goat2"
|
||||
icon_living = "king_goat2"
|
||||
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab = 4, /obj/item/clothing/head/goatpelt/king = 1)
|
||||
health = 750
|
||||
maxHealth = 750
|
||||
armour_penetration = 50
|
||||
melee_damage_lower = 40
|
||||
melee_damage_upper = 60
|
||||
environment_smash = ENVIRONMENT_SMASH_RWALLS
|
||||
pixel_y = 5
|
||||
|
||||
var/spellscast = 0
|
||||
var/phase3 = FALSE
|
||||
var/sound_id = "goat"
|
||||
var/special_attacks = 0
|
||||
var/list/rangers = list()
|
||||
var/current_song = 'sandcode/sound/ambience/Visager-Battle.ogg'
|
||||
var/current_song_length = 1200
|
||||
stun_chance = 7
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/king/phase2/Initialize()
|
||||
. = ..()
|
||||
update_icon()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/king/Found(atom/A)
|
||||
if(isliving(A))
|
||||
return A
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/retaliate/goat/guard/Found(atom/A)
|
||||
if(isliving(A))
|
||||
return A
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/retaliate/goat/guard
|
||||
name = "honour guard"
|
||||
desc = "A very handsome and noble beast."
|
||||
icon = 'sandcode/icons/mob/king_of_goats.dmi'
|
||||
icon_state = "goat_guard"
|
||||
icon_living = "goat_guard"
|
||||
icon_dead = "goat_guard_dead"
|
||||
faction = list("goat_king")
|
||||
attack_same = FALSE
|
||||
sentience_type = SENTIENCE_BOSS
|
||||
stat_attack = DEAD
|
||||
wander = FALSE
|
||||
robust_searching = TRUE
|
||||
health = 125
|
||||
maxHealth = 125
|
||||
minbodytemp = 0
|
||||
maxbodytemp = INFINITY
|
||||
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)
|
||||
armour_penetration = 10
|
||||
melee_damage_lower = 10
|
||||
melee_damage_upper = 15
|
||||
|
||||
/mob/living/simple_animal/hostile/retaliate/goat/guard/master
|
||||
name = "master of the guard"
|
||||
desc = "A very handsome and noble beast - the most trusted of all the king's men."
|
||||
icon_state = "goat_guard_m"
|
||||
icon_living = "goat_guard_m"
|
||||
icon_dead = "goat_guard_m_dead"
|
||||
health = 200
|
||||
maxHealth = 200
|
||||
armour_penetration = 15
|
||||
melee_damage_lower = 15
|
||||
melee_damage_upper = 20
|
||||
move_to_delay = 3
|
||||
|
||||
/mob/living/simple_animal/hostile/retaliate/goat/guard/pope
|
||||
name = "Goat Pope"
|
||||
desc = "For what is a God without a pope to spread their holy words"
|
||||
icon_state = "goat_pope"
|
||||
icon_living = "goat_pope"
|
||||
icon_dead = "goat_pope_dead"
|
||||
health = 100
|
||||
maxHealth = 100
|
||||
armour_penetration = 25
|
||||
melee_damage_lower = 25
|
||||
melee_damage_upper = 30
|
||||
move_to_delay = 3
|
||||
loot = list(/obj/item/clothing/head/goatpope)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/king/Retaliate()
|
||||
..()
|
||||
if(stat == CONSCIOUS && prob(5))
|
||||
visible_message("<span class='warning'>\The [src] bellows indignantly, with a judgemental gleam in his eye.</span>")
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/king/phase2/Retaliate()
|
||||
set waitfor = FALSE
|
||||
..()
|
||||
if(spellscast < 5)
|
||||
if(prob(5) && move_to_delay >= 3) //speed buff
|
||||
spellscast++
|
||||
visible_message("<span class='cult'>\The [src] shimmers and seems to phase in and out of reality itself!</span>")
|
||||
move_to_delay = 1
|
||||
|
||||
else if(prob(5) && melee_damage_lower != 50) //damage buff
|
||||
spellscast++
|
||||
visible_message("<span class='cult'>\The [src]' horns grow larger and more menacing!</span>")
|
||||
melee_damage_lower = 50
|
||||
else if(prob(5)) //spawn adds
|
||||
spellscast++
|
||||
visible_message("<span class='cult'>\The [src] summons the imperial guard to his aid, and they appear in a flash!</span>")
|
||||
var/mob/living/simple_animal/hostile/retaliate/goat/guard/master/M = new(get_step(src,pick(GLOB.cardinals)))
|
||||
M.enemies |= enemies
|
||||
var/mob/living/simple_animal/hostile/retaliate/goat/guard/G = new(get_step(src,pick(GLOB.cardinals)))
|
||||
G.enemies |= enemies
|
||||
G = new(get_step(src,pick(GLOB.cardinals)))
|
||||
G.enemies |= enemies
|
||||
|
||||
else if(prob(5)) //EMP blast
|
||||
spellscast++
|
||||
visible_message("<span class='cult'>\The [src] disrupts nearby electrical equipment!</span>")
|
||||
empulse(get_turf(src), 5, 2, 0)
|
||||
|
||||
else if(prob(5) && melee_damage_type == BRUTE && !special_attacks) //elemental attacks
|
||||
spellscast++
|
||||
visible_message("<span class='cult'>\The [src]' horns flicker with holy white flames!</span>")
|
||||
melee_damage_type = BURN
|
||||
|
||||
else if(prob(5)) //earthquake spell
|
||||
visible_message("<B><span class='danger'>\The [src]' eyes begin to glow ominously as dust and debris in the area is kicked up in a light breeze!!</span></B>")
|
||||
stop_automated_movement = TRUE
|
||||
if(do_after(src, 6 SECONDS, src))
|
||||
var/health_holder = getBruteLoss()
|
||||
visible_message("<B><span class='cult'>\The [src] raises its fore-hooves and stomps them into the ground with incredible force!!</span></B>")
|
||||
explosion(get_step(src,pick(GLOB.cardinals)), -1, 2, 2, 3, 6)
|
||||
explosion(get_step(src,pick(GLOB.cardinals)), -1, 1, 4, 4, 6)
|
||||
explosion(get_step(src,pick(GLOB.cardinals)), -1, 3, 4, 3, 6)
|
||||
stop_automated_movement = FALSE
|
||||
spellscast++
|
||||
if(!(getBruteLoss() > health_holder))
|
||||
adjustBruteLoss(health_holder - getBruteLoss()) //our own magicks cannot harm us
|
||||
else
|
||||
visible_message("<span class='notice'>\The [src] loses concentration and huffs haughtily.</span>")
|
||||
stop_automated_movement = FALSE
|
||||
|
||||
else return
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/king/phase2/proc/phase3_transition()
|
||||
phase3 = TRUE
|
||||
spellscast = 0
|
||||
maxHealth = 750
|
||||
revive(TRUE)
|
||||
current_song = 'sandcode/sound/ambience/Visager-Miniboss_Fight.ogg'
|
||||
current_song_length = 1759
|
||||
var/sound/song_played = sound(current_song)
|
||||
for(var/mob/M in rangers)
|
||||
if(!M.client || !(M.client.prefs.toggles & SOUND_BOSS_MUSIC))
|
||||
continue
|
||||
M.stop_sound_channel(CHANNEL_BOSSMUSIC)
|
||||
rangers[M] = world.time + current_song_length
|
||||
M.playsound_local(null, null, 30, channel = CHANNEL_BOSSMUSIC, S = song_played)
|
||||
stun_chance = 10
|
||||
update_icon()
|
||||
visible_message("<span class='cult'>\The [src]' wounds close with a flash, and when he emerges, he's even larger than before!</span>")
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/king/phase2/update_icon()
|
||||
var/matrix/M = new
|
||||
if(phase3)
|
||||
icon_state = "king_goat3"
|
||||
icon_living = "king_goat3"
|
||||
M.Scale(1.5)
|
||||
else
|
||||
M.Scale(1.25)
|
||||
transform = M
|
||||
pixel_y = 10
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/king/phase2/Life()
|
||||
. = ..()
|
||||
if(stat != DEAD)
|
||||
var/sound/song_played = sound(current_song)
|
||||
|
||||
for(var/mob/M in range(10, src))
|
||||
if(!M.client || !(M.client.prefs.toggles & SOUND_BOSS_MUSIC))
|
||||
continue
|
||||
if(!(M in rangers) || world.time > rangers[M])
|
||||
M.stop_sound_channel(CHANNEL_BOSSMUSIC)
|
||||
rangers[M] = world.time + current_song_length
|
||||
M.playsound_local(null, null, 30, channel = CHANNEL_BOSSMUSIC, S = song_played)
|
||||
for(var/mob/L in rangers)
|
||||
if(get_dist(src, L) > 10)
|
||||
rangers -= L
|
||||
if(!L || !L.client)
|
||||
continue
|
||||
L.stop_sound_channel(CHANNEL_BOSSMUSIC)
|
||||
else
|
||||
for(var/mob/L in rangers)
|
||||
rangers -= L
|
||||
if(!L || !L.client)
|
||||
continue
|
||||
L.stop_sound_channel(CHANNEL_BOSSMUSIC)
|
||||
if(move_to_delay < 3)
|
||||
move_to_delay += 0.2
|
||||
if(!phase3 && ((health <= 150 && spellscast == 5) || stat == DEAD)) //begin phase 3, reset spell limit and heal
|
||||
phase3_transition()
|
||||
if(!.)
|
||||
return FALSE
|
||||
if(special_attacks >= 5 && melee_damage_type != BRUTE)
|
||||
visible_message("<span class='cult'>The energy surrounding \the [src]'s horns dissipates.</span>")
|
||||
melee_damage_type = BRUTE
|
||||
if(special_attacks >= 5 && melee_damage_lower == 50)
|
||||
visible_message("<span class='cult'>The [src]' horns shrink back down to normal size.</span>")
|
||||
melee_damage_lower = 40
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/king/proc/OnDeath()
|
||||
visible_message("<span class='cult'>\The [src] lets loose a terrific wail as its wounds close shut with a flash of light, and its eyes glow even brighter than before!</span>")
|
||||
new /mob/living/simple_animal/hostile/megafauna/king/phase2(get_turf(src))
|
||||
qdel(src)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/king/phase2/OnDeath()
|
||||
for(var/mob/L in rangers)
|
||||
rangers -= L
|
||||
if(!L || !L.client)
|
||||
continue
|
||||
L.stop_sound_channel(CHANNEL_BOSSMUSIC)
|
||||
if(phase3)
|
||||
visible_message("<span class='cult'>\The [src] shrieks as the seal on his power breaks and he starts to break apart!</span>")
|
||||
new /obj/structure/ladder/unbreakable/goat(loc)
|
||||
new /obj/item/gun/energy/goatgun(loc)
|
||||
new /obj/item/toy/plush/goatplushie/angry/kinggoat(loc) //If someone dies from this after beating the king goat im going to laugh
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/king/death()
|
||||
..()
|
||||
OnDeath()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/king/phase2/Destroy()
|
||||
for(var/mob/L in rangers)
|
||||
rangers -= L
|
||||
if(!L || !L.client)
|
||||
continue
|
||||
L.stop_sound_channel(CHANNEL_BOSSMUSIC)
|
||||
. = ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/king/AttackingTarget()
|
||||
. = ..()
|
||||
if(isliving(target))
|
||||
var/mob/living/L = target
|
||||
if(L.stat == DEAD)
|
||||
L.gib()
|
||||
if(prob(stun_chance))
|
||||
L.Stun(5)
|
||||
visible_message("<span class='warning'>\The [L] is bowled over by the impact of [src]'s attack!</span>")
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/king/phase2/AttackingTarget()
|
||||
. = ..()
|
||||
if(isliving(target))
|
||||
if(melee_damage_type != BRUTE)
|
||||
special_attacks++
|
||||
@@ -0,0 +1,49 @@
|
||||
/mob/living/simple_animal/hostile/megafauna/legion
|
||||
loot = list(/obj/item/stack/sheet/bone = 3)
|
||||
songs = list("3550" = sound(file = 'sandcode/sound/ambience/mastermind.ogg', repeat = 0, wait = 0, volume = 60, channel = CHANNEL_BOSSMUSIC), "1360" = sound(file = 'sandcode/sound/ambience/terrariaboss1.ogg', repeat = 0, wait = 0, volume = 60, channel = CHANNEL_BOSSMUSIC), "1560" = sound('sandcode/sound/ambience/megalovania.ogg', repeat = 0, wait = 0, volume = 60, channel = CHANNEL_BOSSMUSIC)) //Threading on some lines here with the DOOM 16 OST. But terraria should be fine, megalovania too.
|
||||
glorymessageshand = list("punches into the Legion's maw and rips off a floating skull, which they then proceed to use to bash the Legion until it dies!", "punches through both of the Legion's eyeholes with both hands, ripping out a bunch of tiny skulls and killing it!")
|
||||
glorymessagescrusher = list("slashes the Legion's maw, which falls on the ground as it dies!")
|
||||
glorymessagespka = list("parries a floating legion skulls with a pka shoot, which goes flying violently into the Legion, bursting through them and killing them in the process!")
|
||||
glorymessagespkabayonet = list("repeatedly stabs through the Legion's eyesocket, pulling out a bunch of dead skulls in the process and killing it!")
|
||||
glorythreshold = 50
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/legion/death()
|
||||
if(health > 0)
|
||||
return
|
||||
if(size > 1)
|
||||
adjustHealth(-maxHealth) //heal ourself to full in prep for splitting
|
||||
var/mob/living/simple_animal/hostile/megafauna/legion/L = new(loc)
|
||||
|
||||
L.maxHealth = round(maxHealth * 0.6,DAMAGE_PRECISION)
|
||||
maxHealth = L.maxHealth
|
||||
|
||||
L.health = L.maxHealth
|
||||
health = maxHealth
|
||||
|
||||
size--
|
||||
L.size = size
|
||||
|
||||
L.resize = L.size * 0.2
|
||||
transform = initial(transform)
|
||||
resize = size * 0.2
|
||||
|
||||
L.update_transform()
|
||||
update_transform()
|
||||
|
||||
L.faction = faction.Copy()
|
||||
|
||||
L.GiveTarget(target)
|
||||
|
||||
visible_message("<span class='boldannounce'>[src] splits in twain!</span>")
|
||||
else
|
||||
var/last_legion = TRUE
|
||||
for(var/mob/living/simple_animal/hostile/megafauna/legion/other in GLOB.mob_living_list)
|
||||
if(other != src)
|
||||
last_legion = FALSE
|
||||
break
|
||||
if(last_legion)
|
||||
loot = list(/obj/structure/closet/crate/necropolis/tendril/legion_loot)
|
||||
elimination = 0
|
||||
else if(prob(20))
|
||||
loot = list(/obj/structure/closet/crate/necropolis/tendril)
|
||||
..()
|
||||
@@ -0,0 +1,293 @@
|
||||
/**
|
||||
*LEGION
|
||||
*
|
||||
*Legion spawns from the necropolis gate in the far north of lavaland. It is the guardian of the Necropolis and emerges from within whenever an intruder tries to enter through its gate.
|
||||
*Whenever Legion emerges, everything in lavaland will receive a notice via color, audio, and text. This is because Legion is powerful enough to slaughter the entirety of lavaland with little effort. LOL
|
||||
*
|
||||
*It has three attacks.
|
||||
*Spawn Skull. Most of the time it will use this attack. Spawns a single legion skull.
|
||||
*Spawn Sentinel. The legion will spawn up to three sentinels, depending on its size.
|
||||
*CHARGE! The legion starts spinning and tries to melee the player. It will try to flick itself towards the player, dealing some damage if it hits.
|
||||
*
|
||||
*When Legion dies, it will split into three smaller skulls up to three times.
|
||||
*If you kill all of the smaller ones it drops a staff of storms, which allows its wielder to call and disperse ash storms at will and functions as a powerful melee weapon.
|
||||
*
|
||||
*Difficulty: Medium
|
||||
*
|
||||
*SHITCODE AHEAD. BE ADVISED. Also comment extravaganza
|
||||
*/
|
||||
/mob/living/simple_animal/hostile/megafauna/legion/hard
|
||||
name = "Enraged Legion"
|
||||
desc = "THE one in the many."
|
||||
icon = 'sandcode/icons/mob/lavaland/96x96megafauna.dmi'
|
||||
icon_state = "mega_legion"
|
||||
icon_living = "mega_legion"
|
||||
armour_penetration = 50
|
||||
melee_damage_lower = 25
|
||||
melee_damage_upper = 25
|
||||
speed = 5
|
||||
ranged = TRUE
|
||||
del_on_death = TRUE
|
||||
retreat_distance = 5
|
||||
minimum_distance = 5
|
||||
ranged_cooldown_time = 20
|
||||
pixel_y = -16
|
||||
pixel_x = -32
|
||||
|
||||
loot = list(/obj/item/stack/sheet/bone = 3)
|
||||
vision_range = 13
|
||||
wander = FALSE
|
||||
elimination = TRUE
|
||||
appearance_flags = 0
|
||||
mouse_opacity = MOUSE_OPACITY_ICON
|
||||
size = 3
|
||||
charging = FALSE
|
||||
true_spawn = TRUE
|
||||
|
||||
/obj/item/gps/internal/legion/hard
|
||||
icon_state = null
|
||||
gpstag = "Enraged Echoing Signal"
|
||||
desc = "The message screeches."
|
||||
invisibility = 100
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/legion/hard/Initialize()
|
||||
..()
|
||||
internal = new/obj/item/gps/internal/legion/hard(src)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/legion/hard/OpenFire(the_target)
|
||||
if(charging)
|
||||
return
|
||||
ranged_cooldown = world.time + ranged_cooldown_time
|
||||
switch(rand(4)) //Larger skulls use more attacks.
|
||||
if(0 to 2)
|
||||
create_legion_skull()
|
||||
if(3)
|
||||
charge_target()
|
||||
if(4)
|
||||
create_legion_turrets()
|
||||
|
||||
//SKULLS
|
||||
|
||||
///Attack proc. Spawns a singular legion skull.
|
||||
/mob/living/simple_animal/hostile/megafauna/legion/hard/proc/create_legion_skull()
|
||||
var/mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion/A = new(loc)
|
||||
A.GiveTarget(target)
|
||||
A.friends = friends
|
||||
A.faction = faction
|
||||
|
||||
//CHARGE
|
||||
|
||||
///Attack proc. Gives legion some movespeed buffs and switches the AI to melee. At lower sizes, this also throws the skull at the player.
|
||||
/mob/living/simple_animal/hostile/megafauna/legion/hard/proc/charge_target()
|
||||
visible_message("<span class='warning'><b>[src] charges!</b></span>")
|
||||
SpinAnimation(speed = 20, loops = 3, parallel = FALSE)
|
||||
ranged = FALSE
|
||||
retreat_distance = 0
|
||||
minimum_distance = 0
|
||||
set_varspeed(0)
|
||||
charging = TRUE
|
||||
addtimer(CALLBACK(src, .proc/reset_charge), 60)
|
||||
var/mob/living/L = target
|
||||
if(!istype(L) || L.stat != DEAD) //I know, weird syntax, but it just works.
|
||||
addtimer(CALLBACK(src, .proc/throw_thyself), 20)
|
||||
|
||||
///This is the proc that actually does the throwing. Charge only adds a timer for this.
|
||||
/mob/living/simple_animal/hostile/megafauna/legion/hard/proc/throw_thyself()
|
||||
playsound(src, 'sound/weapons/sonic_jackhammer.ogg', 50, TRUE)
|
||||
throw_at(target, 7, 1.1, src, FALSE, FALSE, CALLBACK(GLOBAL_PROC, .proc/playsound, src, 'sound/effects/meteorimpact.ogg', 50 * size, TRUE, 2), INFINITY)
|
||||
|
||||
///Deals some extra damage on throw impact.
|
||||
/mob/living/simple_animal/hostile/megafauna/legion/hard/throw_impact(mob/living/hit_atom, datum/thrownthing/throwingdatum)
|
||||
. = ..()
|
||||
if(istype(hit_atom))
|
||||
playsound(src, attack_sound, 100, TRUE)
|
||||
hit_atom.apply_damage(22 * size / 2) //It gets pretty hard to dodge the skulls when there are a lot of them. Scales down with size
|
||||
hit_atom.safe_throw_at(get_step(src, get_dir(src, hit_atom)), 2) //Some knockback. Prevent the legion from melee directly after the throw.
|
||||
|
||||
//TURRETS
|
||||
|
||||
///Attack proc. Creates up to three legion turrets on suitable turfs nearby.
|
||||
/mob/living/simple_animal/hostile/megafauna/legion/hard/proc/create_legion_turrets(minimum = 2, maximum = size * 2)
|
||||
playsound(src, 'sound/magic/RATTLEMEBONES.ogg', 100, TRUE)
|
||||
var/list/possiblelocations = list()
|
||||
for(var/turf/T in oview(src, 4)) //Only place the turrets on open turfs
|
||||
if(is_blocked_turf(T))
|
||||
continue
|
||||
possiblelocations += T
|
||||
for(var/i in 1 to min(rand(minimum, maximum), LAZYLEN(possiblelocations))) //Makes sure aren't spawning in nullspace.
|
||||
var/chosen = pick(possiblelocations)
|
||||
new /obj/structure/legionturret(chosen)
|
||||
possiblelocations -= chosen
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/legion/hard/GiveTarget(new_target)
|
||||
. = ..()
|
||||
if(target)
|
||||
wander = TRUE
|
||||
|
||||
///This makes sure that the legion door opens on taking damage, so you can't cheese this boss.
|
||||
/mob/living/simple_animal/hostile/megafauna/legion/hard/adjustHealth(amount, updating_health = TRUE, forced = FALSE)
|
||||
if(GLOB.necropolis_gate && true_spawn)
|
||||
GLOB.necropolis_gate.toggle_the_gate(null, TRUE) //very clever.
|
||||
return ..()
|
||||
|
||||
///In addition to parent functionality, this will also turn the target into a small legion if they are unconcious.
|
||||
/mob/living/simple_animal/hostile/megafauna/legion/hard/AttackingTarget()
|
||||
. = ..()
|
||||
if(. && ishuman(target))
|
||||
var/mob/living/L = target
|
||||
if(L.stat == UNCONSCIOUS)
|
||||
var/mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion/A = new(loc)
|
||||
A.infest(L)
|
||||
|
||||
///Resets the charge buffs.
|
||||
/mob/living/simple_animal/hostile/megafauna/legion/hard/reset_charge()
|
||||
ranged = TRUE
|
||||
retreat_distance = 5
|
||||
minimum_distance = 5
|
||||
set_varspeed(2)
|
||||
charging = FALSE
|
||||
|
||||
///Special snowflake death() here. Can only die if size is 1 or lower and HP is 0 or below.
|
||||
/mob/living/simple_animal/hostile/megafauna/legion/hard/death()
|
||||
//Make sure we didn't get cheesed
|
||||
if(health > 0)
|
||||
return
|
||||
if(Split())
|
||||
return
|
||||
//We check what loot we should drop.
|
||||
var/last_legion = TRUE
|
||||
for(var/mob/living/simple_animal/hostile/megafauna/legion/hard/other in GLOB.mob_living_list)
|
||||
if(other != src)
|
||||
last_legion = FALSE
|
||||
break
|
||||
if(last_legion)
|
||||
loot = list(/obj/structure/closet/crate/necropolis/legion/hard)
|
||||
elimination = FALSE
|
||||
else if(prob(80)) //80% chance for sick lootz!
|
||||
loot = list(/obj/structure/closet/crate/necropolis/tendril/legion_loot)
|
||||
if(!true_spawn)
|
||||
loot = null
|
||||
return ..()
|
||||
|
||||
///Splits legion into smaller skulls.
|
||||
/mob/living/simple_animal/hostile/megafauna/legion/hard/proc/Split()
|
||||
size--
|
||||
if(size < 1)
|
||||
return FALSE
|
||||
adjustHealth(-maxHealth) //We heal in preparation of the split
|
||||
switch(size) //Yay, switches
|
||||
if(3 to INFINITY)
|
||||
icon = initial(icon)
|
||||
pixel_x = initial(pixel_x)
|
||||
pixel_y = initial(pixel_y)
|
||||
maxHealth = initial(maxHealth)
|
||||
if(2)
|
||||
icon = 'sandcode/icons/mob/lavaland/64x64megafauna.dmi'
|
||||
pixel_x = -16
|
||||
pixel_y = -8
|
||||
maxHealth = 350
|
||||
if(1)
|
||||
icon = 'sandcode/icons/mob/lavaland/lavaland_monsters.dmi'
|
||||
pixel_x = 0
|
||||
pixel_y = 0
|
||||
maxHealth = 200
|
||||
visible_message("<span class='boldannounce'>This is getting out of hands. Now there are three of them!</span>")
|
||||
for(var/i in 1 to 2) //Create three skulls in total
|
||||
var/mob/living/simple_animal/hostile/megafauna/legion/hard/L = new(loc)
|
||||
L.setVarsAfterSplit(src)
|
||||
return TRUE
|
||||
|
||||
///Sets the variables for new legion skulls. Usually called after splitting.
|
||||
/mob/living/simple_animal/hostile/megafauna/legion/hard/proc/setVarsAfterSplit(var/mob/living/simple_animal/hostile/megafauna/legion/L)
|
||||
maxHealth = L.maxHealth
|
||||
updatehealth()
|
||||
size = L.size
|
||||
icon = L.icon
|
||||
pixel_x = L.pixel_x
|
||||
pixel_y = L.pixel_y
|
||||
faction = L.faction.Copy()
|
||||
GiveTarget(L.target)
|
||||
|
||||
///A basic turret that shoots at nearby mobs. Intended to be used for the legion megafauna.
|
||||
/obj/structure/legionturret
|
||||
name = "\improper Legion sentinel"
|
||||
desc = "The eye pierces your soul."
|
||||
icon = 'sandcode/icons/mob/lavaland/lavaland_monsters.dmi'
|
||||
icon_state = "legion_turret"
|
||||
light_power = 0.5
|
||||
light_range = 2
|
||||
max_integrity = 80
|
||||
luminosity = 6
|
||||
anchored = TRUE
|
||||
density = TRUE
|
||||
layer = ABOVE_OBJ_LAYER
|
||||
armor = list("melee" = 0, "bullet" = 0, "laser" = 100,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0)
|
||||
///What kind of projectile the actual damaging part should be.
|
||||
var/projectile_type = /obj/item/projectile/beam/legion
|
||||
///Time until the tracer gets shot
|
||||
var/initial_firing_time = 18
|
||||
///How long it takes between shooting the tracer and the projectile.
|
||||
var/shot_delay = 8
|
||||
///Compared with the targeted mobs. If they have the faction, turret won't shoot.
|
||||
var/faction = list("mining")
|
||||
|
||||
/obj/structure/legionturret/Initialize()
|
||||
. = ..()
|
||||
addtimer(CALLBACK(src, .proc/set_up_shot), initial_firing_time)
|
||||
|
||||
///Handles an extremely basic AI
|
||||
/obj/structure/legionturret/proc/set_up_shot()
|
||||
for(var/mob/living/L in oview(9, src))
|
||||
if(L.stat == DEAD || L.stat == UNCONSCIOUS)
|
||||
continue
|
||||
if(faction_check(faction, L.faction))
|
||||
continue
|
||||
fire(L)
|
||||
return
|
||||
fire(get_edge_target_turf(src, pick(GLOB.cardinals)))
|
||||
|
||||
///Called when attacking a target. Shoots a projectile at the turf underneath the target.
|
||||
/obj/structure/legionturret/proc/fire(atom/target)
|
||||
var/turf/T = get_turf(target)
|
||||
var/turf/T1 = get_turf(src)
|
||||
if(!T || !T1)
|
||||
return
|
||||
//Now we generate the tracer.
|
||||
var/angle = Get_Angle(T1, T)
|
||||
var/datum/point/vector/V = new(T1.x, T1.y, T1.z, 0, 0, angle)
|
||||
generate_tracer_between_points(V, V.return_vector_after_increments(6), /obj/effect/projectile/tracer/legion/tracer, 0, shot_delay, 0, 0, 0, null)
|
||||
playsound(src, 'sound/machines/airlockopen.ogg', 100, TRUE)
|
||||
addtimer(CALLBACK(src, .proc/fire_beam, angle), shot_delay)
|
||||
|
||||
///Called shot_delay after the turret shot the tracer. Shoots a projectile into the same direction.
|
||||
/obj/structure/legionturret/proc/fire_beam(angle)
|
||||
var/obj/item/projectile/ouchie = new projectile_type(loc)
|
||||
ouchie.firer = src
|
||||
ouchie.fire(angle)
|
||||
playsound(src, 'sound/effects/bin_close.ogg', 100, TRUE)
|
||||
QDEL_IN(src, 5)
|
||||
|
||||
///Used for the legion turret.
|
||||
/obj/item/projectile/beam/legion
|
||||
name = "blood pulse"
|
||||
hitsound = 'sound/magic/magic_missile.ogg'
|
||||
damage = 19
|
||||
range = 6
|
||||
eyeblur = 0
|
||||
light_color = LIGHT_COLOR_RED
|
||||
impact_effect_type = /obj/effect/temp_visual/kinetic_blast
|
||||
tracer_type = /obj/effect/projectile/tracer/legion
|
||||
muzzle_type = /obj/effect/projectile/tracer/legion
|
||||
impact_type = /obj/effect/projectile/tracer/legion
|
||||
hitscan = TRUE
|
||||
movement_type = UNSTOPPABLE
|
||||
|
||||
///Used for the legion turret tracer.
|
||||
/obj/effect/projectile/tracer/legion/tracer
|
||||
icon = 'sandcode/icons/effects/beam.dmi'
|
||||
icon_state = "blood_light"
|
||||
|
||||
///Used for the legion turret beam.
|
||||
/obj/effect/projectile/tracer/legion
|
||||
icon = 'sandcode/icons/effects/beam.dmi'
|
||||
icon_state = "blood"
|
||||
@@ -0,0 +1,178 @@
|
||||
/mob/living/simple_animal/hostile/megafauna
|
||||
var/glorykill = FALSE //CAN THIS MOTHERFUCKER BE SNAPPED IN HALF FOR HEALTH?
|
||||
var/list/glorymessageshand = list() //WHAT THE FUCK ARE THE MESSAGES SAID BY THIS FUCK WHEN HE'S GLORY KILLED WITH AN EMPTY HAND?
|
||||
var/list/glorymessagescrusher = list() //SAME AS ABOVE BUT CRUSHER
|
||||
var/list/glorymessagespka = list() //SAME AS ABOVE THE ABOVE BUT PKA
|
||||
var/list/glorymessagespkabayonet = list() //SAME AS ABOVE BUT WITH A HONKING KNIFE ON THE FUCKING THING
|
||||
var/gloryhealth = 200
|
||||
var/glorythreshold = 100
|
||||
var/list/songs = list()
|
||||
var/sound/chosensong
|
||||
var/chosenlength
|
||||
var/chosenlengthstring
|
||||
var/songend
|
||||
var/retaliated = FALSE
|
||||
var/retaliatedcooldowntime = 6000
|
||||
var/retaliatedcooldown
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/SetRecoveryTime(buffer_time, ranged_buffer_time)
|
||||
recovery_time = world.time + buffer_time
|
||||
ranged_cooldown = world.time + buffer_time
|
||||
if(ranged_buffer_time)
|
||||
ranged_cooldown = world.time + ranged_buffer_time
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna
|
||||
var/list/enemies = list()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/Found(atom/A)
|
||||
if(isliving(A))
|
||||
var/mob/living/L = A
|
||||
if(!L.stat)
|
||||
return L
|
||||
else
|
||||
enemies -= L
|
||||
else if(ismecha(A))
|
||||
var/obj/mecha/M = A
|
||||
if(M.occupant)
|
||||
return A
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/ListTargets()
|
||||
if(!enemies.len)
|
||||
return list()
|
||||
var/list/see = ..()
|
||||
see &= enemies // Remove all entries that aren't in enemies
|
||||
return see
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/proc/Retaliate()
|
||||
var/list/around = view(src, vision_range)
|
||||
for(var/atom/movable/A in around)
|
||||
if(A == src)
|
||||
continue
|
||||
if(isliving(A))
|
||||
var/mob/living/M = A
|
||||
if((faction_check_mob(M) && attack_same) || (!faction_check_mob(M)) || (!ismegafauna(M)))
|
||||
enemies |= M
|
||||
chosenlengthstring = pick(songs)
|
||||
chosenlength = text2num(chosenlengthstring)
|
||||
chosensong = songs[chosenlengthstring]
|
||||
if(chosensong && !songend)
|
||||
if(M.client.prefs.toggles & SOUND_BOSS_MUSIC)
|
||||
M.stop_sound_channel(CHANNEL_BOSSMUSIC)
|
||||
songend = chosenlength + world.time
|
||||
SEND_SOUND(M, chosensong) // so silence boss music will mute moosic for people who don't want that, or it just doesn't play at all if prefs disable it
|
||||
if(!retaliated)
|
||||
src.visible_message("<span class='userdanger'>[src] seems pretty pissed off at [M]!</span>")
|
||||
retaliated = TRUE
|
||||
retaliatedcooldown = world.time + retaliatedcooldowntime
|
||||
else if(ismecha(A))
|
||||
var/obj/mecha/M = A
|
||||
if(M.occupant && M.occupant.client)
|
||||
enemies |= M
|
||||
enemies |= M.occupant
|
||||
var/mob/living/O = M.occupant
|
||||
if(O.client.prefs.toggles & SOUND_BOSS_MUSIC)
|
||||
O.stop_sound_channel(CHANNEL_BOSSMUSIC)
|
||||
songend = chosenlength + world.time
|
||||
SEND_SOUND(O, chosensong)
|
||||
if(!retaliated)
|
||||
src.visible_message("<span class='userdanger'>[src] seems pretty pissed off at [M]!</span>")
|
||||
retaliated = TRUE
|
||||
retaliatedcooldown = world.time + retaliatedcooldowntime
|
||||
|
||||
for(var/mob/living/simple_animal/hostile/megafauna/H in around)
|
||||
if(faction_check_mob(H) && !attack_same && !H.attack_same)
|
||||
H.enemies |= enemies
|
||||
return 0
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/adjustHealth(amount, updating_health = TRUE, forced = FALSE)
|
||||
. = ..()
|
||||
if(. > 0 && stat == CONSCIOUS)
|
||||
Retaliate()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/Life()
|
||||
..()
|
||||
if(songend)
|
||||
if(world.time >= songend)
|
||||
for(var/mob/living/M in view(src, vision_range))
|
||||
if(client)
|
||||
if(M.client.prefs.toggles & SOUND_BOSS_MUSIC)
|
||||
M.stop_sound_channel(CHANNEL_BOSSMUSIC)
|
||||
songend = chosenlength + world.time
|
||||
SEND_SOUND(M, chosensong)
|
||||
if(health <= glorythreshold && !glorykill && stat != DEAD)
|
||||
glorykill = TRUE
|
||||
glory()
|
||||
if(retaliated)
|
||||
if(retaliatedcooldown < world.time)
|
||||
retaliated = FALSE
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/proc/glory()
|
||||
desc += "<br><b>[src] is staggered and can be glory killed!</b>"
|
||||
animate(src, color = "#00FFFF", time = 5)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/death()
|
||||
if(health > 0)
|
||||
return
|
||||
else
|
||||
for(var/mob/living/M in view(src, vision_range))
|
||||
if(M.client)
|
||||
M.stop_sound_channel(CHANNEL_BOSSMUSIC)
|
||||
animate(src, color = initial(color), time = 3)
|
||||
desc = initial(desc)
|
||||
var/datum/status_effect/crusher_damage/C = has_status_effect(STATUS_EFFECT_CRUSHERDAMAGETRACKING)
|
||||
var/crusher_kill = FALSE
|
||||
if(C && crusher_loot && C.total_damage >= maxHealth * 0.6)
|
||||
spawn_crusher_loot()
|
||||
crusher_kill = TRUE
|
||||
if(!(flags_1 & ADMIN_SPAWNED_1))
|
||||
var/tab = "megafauna_kills"
|
||||
if(crusher_kill)
|
||||
tab = "megafauna_kills_crusher"
|
||||
SSblackbox.record_feedback("tally", tab, 1, "[initial(name)]")
|
||||
if(!elimination) //used so the achievment only occurs for the last legion to die.
|
||||
grant_achievement(medal_type, score_type, crusher_kill)
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/AltClick(mob/living/carbon/slayer)
|
||||
if(glorykill)
|
||||
if(ranged)
|
||||
if(ranged_cooldown >= world.time)
|
||||
ranged_cooldown += 10
|
||||
else
|
||||
ranged_cooldown = 10 + world.time
|
||||
if(do_after(slayer, 10, needhand = TRUE, target = src, progress = FALSE) && (stat != DEAD))
|
||||
var/message
|
||||
if(!slayer.get_active_held_item() || (!istype(slayer.get_active_held_item(), /obj/item/kinetic_crusher) && !istype(slayer.get_active_held_item(), /obj/item/gun/energy/kinetic_accelerator)))
|
||||
message = pick(glorymessageshand)
|
||||
else if(istype(slayer.get_active_held_item(), /obj/item/kinetic_crusher))
|
||||
message = pick(glorymessagescrusher)
|
||||
else if(istype(slayer.get_active_held_item(), /obj/item/gun/energy/kinetic_accelerator))
|
||||
message = pick(glorymessagespka)
|
||||
var/obj/item/gun/energy/kinetic_accelerator/KA = get_active_held_item()
|
||||
if(KA && KA.bayonet)
|
||||
message = pick(glorymessagespka | glorymessagespkabayonet)
|
||||
if(message)
|
||||
visible_message("<span class='danger'><b>[slayer] [message]</b></span>")
|
||||
else
|
||||
visible_message("<span class='danger'><b>[slayer] does something generally considered brutal to [src]... Whatever that may be!</b></span>")
|
||||
adjustHealth(maxHealth, TRUE, TRUE)
|
||||
if(mob_biotypes & MOB_ORGANIC)
|
||||
new /obj/effect/gibspawner/generic(src.loc)
|
||||
else if(mob_biotypes & MOB_ROBOTIC)
|
||||
new /obj/effect/gibspawner/robot(src.loc)
|
||||
slayer.heal_overall_damage(gloryhealth,gloryhealth)
|
||||
else
|
||||
to_chat(slayer, "<span class='danger'>You fail to glory kill [src]!</span>")
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/devour(mob/living/L)
|
||||
if(!L)
|
||||
return
|
||||
visible_message(
|
||||
"<span class='danger'>[src] devours [L]!</span>",
|
||||
"<span class='userdanger'>You feast on [L], restoring your health!</span>")
|
||||
if(!is_station_level(z) || client) //NPC monsters won't heal while on station
|
||||
adjustBruteLoss(-L.maxHealth/2)
|
||||
if(L.client)
|
||||
L.stop_sound_channel(CHANNEL_AMBIENCE)
|
||||
L.gib()
|
||||
..()
|
||||
@@ -0,0 +1,285 @@
|
||||
/mob/living/simple_animal/hostile/megafauna/rogueprocess
|
||||
name = "Rogue Process"
|
||||
desc = "Once an experimental mecha carrying an advanced mining AI, now it's out for blood."
|
||||
health = 2500
|
||||
maxHealth = 2500
|
||||
movement_type = GROUND
|
||||
attack_verb_continuous = "drills"
|
||||
attack_verb_simple = "drill"
|
||||
attack_sound = 'sound/weapons/drill.ogg'
|
||||
icon = 'sandcode/icons/mob/lavaland/rogue.dmi'
|
||||
icon_state = "rogue"
|
||||
icon_living = "rogue"
|
||||
icon_dead = "rogue-broken"
|
||||
friendly_verb_continuous = "pokes"
|
||||
friendly_verb_simple = "poke"
|
||||
speak_emote = list("screeches")
|
||||
mob_biotypes = MOB_ROBOTIC
|
||||
melee_damage_lower = 30
|
||||
melee_damage_upper = 30
|
||||
speed = 1
|
||||
move_to_delay = 10
|
||||
ranged_cooldown_time = 80
|
||||
ranged = 1
|
||||
del_on_death = 0
|
||||
crusher_loot = list(/obj/structure/closet/crate/necropolis/rogue/crusher)
|
||||
loot = list(/obj/structure/closet/crate/necropolis/rogue)
|
||||
deathmessage = "sparkles and emits corrupted screams in agony, falling defeated on the ground."
|
||||
death_sound = 'sound/mecha/critdestr.ogg'
|
||||
anger_modifier = 0
|
||||
footstep_type = FOOTSTEP_MOB_HEAVY
|
||||
mob_biotypes = MOB_ROBOTIC
|
||||
songs = list("2930" = sound(file = 'sandcode/sound/ambience/mbrsystemshock.ogg', repeat = 0, wait = 0, volume = 60, channel = CHANNEL_BOSSMUSIC)) //System shock theme remix by Master Boot Record
|
||||
var/special = FALSE
|
||||
wander = FALSE
|
||||
faction = list("mining", "boss")
|
||||
weather_immunities = list("lava","ash")
|
||||
blood_volume = 0
|
||||
var/min_sparks = 1
|
||||
var/max_sparks = 4
|
||||
|
||||
/obj/item/gps/internal/rogueprocess
|
||||
icon_state = null
|
||||
gpstag = "Corrupted Signal"
|
||||
desc = "It's full of ransomware."
|
||||
invisibility = 100
|
||||
|
||||
/obj/item/projectile/plasma/rogue
|
||||
dismemberment = 0
|
||||
damage = 25
|
||||
pixels_per_second = TILES_TO_PIXELS(10)
|
||||
range = 21
|
||||
color = "#FF0000"
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/rogueprocess/Initialize()
|
||||
. = ..()
|
||||
internal = new /obj/item/gps/internal/rogueprocess(src)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/rogueprocess/adjustHealth(amount, updating_health, forced)
|
||||
. = ..()
|
||||
if(.)
|
||||
anger_modifier = round(clamp(((maxHealth - health) / 42),0,60))
|
||||
move_to_delay = clamp(round((src.health/src.maxHealth) * 10), 2.5, 8)
|
||||
wander = FALSE
|
||||
do_sparks(rand(min_sparks,max_sparks), FALSE, src)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/rogueprocess/OpenFire(target)
|
||||
if(special)
|
||||
return FALSE
|
||||
ranged_cooldown = world.time + min((ranged_cooldown_time - anger_modifier), 60)
|
||||
switch(anger_modifier)
|
||||
if(0 to 25)
|
||||
if(prob(50))
|
||||
INVOKE_ASYNC(src, .proc/plasmashot, target, FALSE)
|
||||
sleep(6)
|
||||
INVOKE_ASYNC(src, .proc/plasmashot, target, FALSE)
|
||||
sleep(4)
|
||||
INVOKE_ASYNC(src, .proc/plasmashot, target, FALSE)
|
||||
else
|
||||
INVOKE_ASYNC(src, .proc/shockwave, src.dir, 7, TRUE)
|
||||
if(25 to 50)
|
||||
if(prob(60))
|
||||
INVOKE_ASYNC(src, .proc/plasmaburst, target, FALSE)
|
||||
sleep(5)
|
||||
INVOKE_ASYNC(src, .proc/plasmaburst, target, TRUE)
|
||||
sleep(3)
|
||||
INVOKE_ASYNC(src, .proc/plasmashot, target, FALSE)
|
||||
sleep(3)
|
||||
if(prob(50))
|
||||
INVOKE_ASYNC(src, .proc/plasmashot, target, FALSE)
|
||||
else
|
||||
INVOKE_ASYNC(src, .proc/shockwave, WEST, 10, TRUE)
|
||||
INVOKE_ASYNC(src, .proc/shockwave, EAST, 10, TRUE)
|
||||
sleep(7)
|
||||
INVOKE_ASYNC(src, .proc/shockwave, NORTH, 10, TRUE)
|
||||
INVOKE_ASYNC(src, .proc/shockwave, SOUTH, 10, TRUE)
|
||||
if(50 to INFINITY)
|
||||
if(prob(65))
|
||||
if(prob(60))
|
||||
INVOKE_ASYNC(src, .proc/plasmaburst, target, FALSE)
|
||||
INVOKE_ASYNC(src, .proc/shockwave, src.dir, 15, FALSE)
|
||||
sleep(5)
|
||||
INVOKE_ASYNC(src, .proc/plasmaburst, target, FALSE)
|
||||
sleep(5)
|
||||
INVOKE_ASYNC(src, .proc/plasmaburst, target, FALSE)
|
||||
sleep(3)
|
||||
INVOKE_ASYNC(src, .proc/plasmaburst, target, FALSE)
|
||||
else
|
||||
var/turf/up = locate(x, y + 10, z)
|
||||
var/turf/down = locate(x, y - 10, z)
|
||||
var/turf/left = locate(x - 10, y, z)
|
||||
var/turf/right = locate(x + 10, y, z)
|
||||
INVOKE_ASYNC(src, .proc/plasmaburst, up, TRUE)
|
||||
INVOKE_ASYNC(src, .proc/plasmaburst, down, FALSE)
|
||||
sleep(3)
|
||||
INVOKE_ASYNC(src, .proc/plasmashot, left, FALSE)
|
||||
INVOKE_ASYNC(src, .proc/plasmashot, right, FALSE)
|
||||
sleep(10)
|
||||
if(prob(35))
|
||||
for(var/dire in GLOB.cardinals)
|
||||
INVOKE_ASYNC(src, .proc/shockwave, dire, 7, TRUE)
|
||||
else
|
||||
INVOKE_ASYNC(src, .proc/ultishockwave, 7, TRUE)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/rogueprocess/Move()
|
||||
. = ..()
|
||||
if(special)
|
||||
return FALSE
|
||||
playsound(src.loc, 'sound/mecha/mechmove01.ogg', 200, 1, 2, 1)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/rogueprocess/Bump(atom/A)
|
||||
. = ..()
|
||||
if(isturf(A) || isobj(A) && A.density)
|
||||
A.ex_act(EXPLODE_HEAVY)
|
||||
DestroySurroundings()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/rogueprocess/proc/plasmashot(atom/target, var/specialize = TRUE)
|
||||
var/path = get_dist(src, target)
|
||||
if(path > 2)
|
||||
if(!target)
|
||||
return
|
||||
visible_message("<span class='boldwarning'>[src] raises it's plasma cutter!</span>")
|
||||
if(specialize)
|
||||
special = TRUE
|
||||
sleep(3)
|
||||
var/turf/startloc = get_turf(src)
|
||||
var/obj/item/projectile/P = new /obj/item/projectile/plasma/rogue(startloc)
|
||||
playsound(src, 'sound/weapons/laser.ogg', 100, TRUE)
|
||||
P.preparePixelProjectile(target, startloc)
|
||||
P.firer = src
|
||||
P.original = target
|
||||
var/set_angle = Get_Angle(src, target)
|
||||
P.fire(set_angle)
|
||||
if(specialize)
|
||||
special = FALSE
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/rogueprocess/proc/plasmaburst(atom/target, var/specialize = TRUE)
|
||||
var/list/theline = get_dist(src, target)
|
||||
if(theline > 2)
|
||||
if(!target)
|
||||
return
|
||||
visible_message("<span class='boldwarning'>[src] raises it's tri-shot plasma cutter!</span>")
|
||||
if(specialize)
|
||||
special = TRUE
|
||||
var/ogangle = Get_Angle(src, target)
|
||||
sleep(7)
|
||||
var/turf/startloc = get_turf(src)
|
||||
var/obj/item/projectile/P = new /obj/item/projectile/plasma/rogue(startloc)
|
||||
var/turf/otherangle = (ogangle + 45)
|
||||
var/turf/otherangle2 = (ogangle - 45)
|
||||
playsound(src, 'sound/weapons/laser.ogg', 100, TRUE)
|
||||
P.preparePixelProjectile(target, startloc)
|
||||
P.firer = src
|
||||
P.original = target
|
||||
P.fire(ogangle)
|
||||
var/obj/item/projectile/X = new /obj/item/projectile/plasma/rogue(startloc)
|
||||
playsound(src, 'sound/weapons/laser.ogg', 100, TRUE)
|
||||
X.preparePixelProjectile(target, startloc)
|
||||
X.firer = src
|
||||
X.original = target
|
||||
X.fire(otherangle)
|
||||
var/obj/item/projectile/Y = new /obj/item/projectile/plasma/rogue(startloc)
|
||||
playsound(src, 'sound/weapons/laser.ogg', 100, TRUE)
|
||||
Y.preparePixelProjectile(target, startloc)
|
||||
Y.firer = src
|
||||
Y.original = target
|
||||
Y.fire(otherangle2)
|
||||
if(specialize)
|
||||
special = FALSE
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/rogueprocess/proc/knockdown(var/specialize = TRUE)
|
||||
visible_message("<span class='boldwarning'>[src] smashes into the ground!</span>")
|
||||
if(specialize)
|
||||
special = TRUE
|
||||
playsound(src,'sound/misc/crunch.ogg', 200, 1)
|
||||
var/list/hit_things = list()
|
||||
sleep(7)
|
||||
for(var/turf/T in oview(2, src))
|
||||
if(!T)
|
||||
if(specialize)
|
||||
special = FALSE
|
||||
return
|
||||
new /obj/effect/temp_visual/small_smoke/halfsecond(T)
|
||||
for(var/mob/living/L in T.contents)
|
||||
if(L != src && !(L in hit_things))
|
||||
if(!faction_check(faction, L.faction))
|
||||
var/throwtarget = get_edge_target_turf(src, get_dir(src, L))
|
||||
L.safe_throw_at(throwtarget, 10, 1, src)
|
||||
L.Stun(20)
|
||||
L.apply_damage_type(40, BRUTE)
|
||||
hit_things += L
|
||||
sleep(3)
|
||||
if(specialize)
|
||||
special = FALSE
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/rogueprocess/proc/shockwave(direction, range, var/specialize = TRUE)
|
||||
visible_message("<span class='boldwarning'>[src] smashes the ground in a general direction!!</span>")
|
||||
if(specialize)
|
||||
special = TRUE
|
||||
playsound(src,'sound/misc/crunch.ogg', 200, 1)
|
||||
sleep(5)
|
||||
var/list/hit_things = list()
|
||||
var/turf/T = get_turf(get_step(src, src.dir))
|
||||
var/ogdir = direction
|
||||
var/turf/otherT = get_step(T, turn(ogdir, 90))
|
||||
var/turf/otherT2 = get_step(T, turn(ogdir, -90))
|
||||
if(!T)
|
||||
if(specialize)
|
||||
special = FALSE
|
||||
return
|
||||
for(var/i in 1 to range)
|
||||
new /obj/effect/temp_visual/small_smoke/halfsecond(T)
|
||||
new /obj/effect/temp_visual/small_smoke/halfsecond(otherT)
|
||||
new /obj/effect/temp_visual/small_smoke/halfsecond(otherT2)
|
||||
for(var/mob/living/L in T.contents)
|
||||
if(L != src && !(L in hit_things))
|
||||
var/throwtarget = get_edge_target_turf(T, get_dir(T, L))
|
||||
L.safe_throw_at(throwtarget, 5, 1, src)
|
||||
L.Stun(10)
|
||||
L.apply_damage_type(25, BRUTE)
|
||||
hit_things += L
|
||||
for(var/mob/living/L in otherT.contents)
|
||||
if(L != src && !(L in hit_things))
|
||||
var/throwtarget = get_edge_target_turf(otherT, get_dir(otherT, L))
|
||||
L.safe_throw_at(throwtarget, 5, 1, src)
|
||||
L.Stun(10)
|
||||
L.apply_damage_type(25, BRUTE)
|
||||
hit_things += L
|
||||
for(var/mob/living/L in otherT2.contents)
|
||||
if(L != src && !(L in hit_things))
|
||||
var/throwtarget = get_edge_target_turf(otherT2, get_dir(otherT2, L))
|
||||
L.safe_throw_at(throwtarget, 5, 1, src)
|
||||
L.Stun(10)
|
||||
L.apply_damage_type(25, BRUTE)
|
||||
hit_things += L
|
||||
T = get_step(T, ogdir)
|
||||
otherT = get_step(otherT, ogdir)
|
||||
otherT2 = get_step(otherT2, ogdir)
|
||||
sleep(1.5)
|
||||
if(specialize)
|
||||
special = FALSE
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/rogueprocess/proc/ultishockwave(range, var/specialize = TRUE)
|
||||
visible_message("<span class='boldwarning'>[src] smashes the ground around them!!</span>")
|
||||
if(specialize)
|
||||
special = TRUE
|
||||
playsound(src,'sound/misc/crunch.ogg', 200, 1)
|
||||
sleep(10)
|
||||
var/list/hit_things = list()
|
||||
for(var/i in 1 to range)
|
||||
for(var/turf/T in (view(i, src) - view(i - 1, src)))
|
||||
if(!T)
|
||||
if(specialize)
|
||||
special = FALSE
|
||||
return
|
||||
new /obj/effect/temp_visual/small_smoke/halfsecond(T)
|
||||
for(var/mob/living/L in T.contents)
|
||||
if(L != src && !(L in hit_things) && !faction_check(L.faction, faction))
|
||||
var/throwtarget = get_edge_target_turf(T, get_dir(T, L))
|
||||
L.safe_throw_at(throwtarget, 5, 1, src)
|
||||
L.Stun(10)
|
||||
L.apply_damage_type(25, BRUTE)
|
||||
hit_things += L
|
||||
sleep(3)
|
||||
if(specialize)
|
||||
special = FALSE
|
||||
@@ -0,0 +1,363 @@
|
||||
/*
|
||||
Original PR made by sushifish on Russ Station. Bob joga just did a lazy ass port.
|
||||
SIF (Sprites and ideas by MetalGearMan)
|
||||
|
||||
Sif spawns randomly in lavaland when it can, in the form of a sword which the user needs to interact with in order to summon Sif.
|
||||
|
||||
Speical attacks:
|
||||
- When Sif's able to he will charge his current target with 200% increased speed for 1 second, getting right next to his target.
|
||||
- Sif can also do an AOE spin attack.
|
||||
|
||||
Links for videos on all of Sif's modes and attacks:
|
||||
|
||||
Summon: https://bungdeep.com/Sif/Sif_Summon.mp4
|
||||
Angered Stage: https://bungdeep.com/Sif/Sif_Angered.mp4
|
||||
Enraged Stage: https://bungdeep.com/Sif/Sif_Enraged.mp4
|
||||
|
||||
Projectile Dodge: https://bungdeep.com/Sif/Sif_Dodge.mp4
|
||||
|
||||
AOE Spin: https://bungdeep.com/Sif/Sif_Spin.mp4
|
||||
Charge: https://bungdeep.com/Sif/Sif_Charge.mp4
|
||||
Spin and Charge: https://bungdeep.com/Sif/Sif_Spin_and_charge.mp4
|
||||
|
||||
Death: https://bungdeep.com/Sif/Sif_Death.mp4
|
||||
|
||||
Sif has three stages:
|
||||
1. Normal state when it has health above 50%.
|
||||
2. When Sif reaches below 50% health it enters a angered state, which makes Sif's movement speed faster and attack speed slower,
|
||||
with increased usage of specials.
|
||||
3. At 20% health Sif is significantly slowed but constantly doing special attacks.
|
||||
|
||||
WHEN SIF IS ANGERED (Stage 2):
|
||||
- Sif's specials take 50% less time to recharge from (Normal = 100) to (Angered = 50)
|
||||
- Sif's attack speed decreased by 30% and movement speed increased by 50%
|
||||
|
||||
WHEN SIF IS ENRAGED (Stage 3):
|
||||
- Sif's specials take 60% less time to recharge from (Angered = 50) to (Enraged = 30)
|
||||
- Sif is way slower but does more damage, as well as chances to dodge projectiles and melee attacks more often.
|
||||
|
||||
When Sif dies, it leaves behind a:
|
||||
!! Sword Of The Forsaken !! -> Giant ass sword that does damage. Small chance of blocking hits and almost no chance to block projectiles.
|
||||
!! Necklace Of The Forsaken !! -> Works by instantly reviving or fully healing the user at their discretion (one time use and can be used when dead, knocked out or alive)
|
||||
!! Dark Energy !! (If killed with a kinetic crusher) -> A Kinetic Crusher attachment which performs a bash attack for 100 damage (only works on big boy mobs like megafaunas)
|
||||
Difficulty: Medium
|
||||
*/
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/sif
|
||||
name = "Great Brown Wolf Sif"
|
||||
desc = "Guardian of the abyss. Looks pretty pissed that you're here."
|
||||
health = 2000
|
||||
maxHealth = 2000
|
||||
movement_type = GROUND
|
||||
attack_verb_continuous = "slashes"
|
||||
attack_verb_simple = "slash"
|
||||
attack_sound = 'sandcode/sound/sif/sif_slash.ogg'
|
||||
icon_state = "Great_Brown_Wolf"
|
||||
icon_living = "Great_Brown_Wolf"
|
||||
icon_dead = ""
|
||||
friendly_verb_continuous = "stares down"
|
||||
friendly_verb_simple = "stare down"
|
||||
icon = 'sandcode/icons/mob/lavaland/sif.dmi'
|
||||
speak_emote = list("growls")
|
||||
armour_penetration = 50
|
||||
melee_damage_lower = 35
|
||||
melee_damage_upper = 35
|
||||
speed = 1.5
|
||||
pixel_x = -32 //Hit box perfectly centered
|
||||
pixel_y = -16
|
||||
move_to_delay = 3
|
||||
rapid_melee = 2
|
||||
melee_queue_distance = 10
|
||||
ranged = FALSE
|
||||
del_on_death = 1
|
||||
loot = list(/obj/structure/closet/crate/necropolis/sif)
|
||||
crusher_loot = list(/obj/structure/closet/crate/necropolis/sif/crusher)
|
||||
|
||||
deathmessage = "falls into the abyss."
|
||||
deathsound = 'sandcode/sound/sif/death_howl.ogg'
|
||||
var/can_special = 1 //Enables sif to do what he does best, spin and charge
|
||||
var/spinIntervals = 0 //Counts how many spins Sif does before setting spinning status to false
|
||||
var/spinning = FALSE //AOE spin special attack status
|
||||
var/charging = FALSE //dashing special attack status
|
||||
var/angered = FALSE //active at < 50% health
|
||||
var/enraged = FALSE //active at < 20% health
|
||||
var/stageTwo = FALSE
|
||||
var/stageThree = FALSE
|
||||
var/currentPower = 0 //Every few seconds this variable gets higher, when it gets high
|
||||
//enough it will use a special attack then reset the variable to 0w
|
||||
songs = list("2670" = sound(file = 'sandcode/sound/ambience/furidanger802.ogg', repeat = 0, wait = 0, volume = 60, channel = CHANNEL_BOSSMUSIC))
|
||||
glorymessageshand = list("climbs atop the wolf's head as it dangles weakly near the ground, ripping its left eye off and jumping down before punching through it's cranium!", "goes around the wolf and rips off their tail, using it as whip on the fiend")
|
||||
glorymessagescrusher = list("chops off the wolf's head by it's neck!")
|
||||
glorymessagespka = list("shoots at the wolf's eyes with their PKA, exploding them into giblets!")
|
||||
glorymessagespkabayonet = list("slides down below Sif, using their bayonet to rip it's stomach open!")
|
||||
var/list/hit_things = list()
|
||||
|
||||
/obj/item/gps/internal/sif
|
||||
icon_state = null
|
||||
gpstag = "Infinity Signal"
|
||||
desc = "No, it's not thanos."
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/sif/Initialize(mapload)
|
||||
. = ..()
|
||||
internal = new /obj/item/gps/internal/sif(src)
|
||||
|
||||
//Sword structure, used to summon sif.
|
||||
/obj/structure/sword/sif
|
||||
name = "Massive Glowing Sword"
|
||||
desc = "Sweet! A free sword!"
|
||||
max_integrity = 10000
|
||||
anchored = TRUE
|
||||
icon = 'sandcode/icons/mob/lavaland/sif_sword.dmi'
|
||||
icon_state = "Idle_Sword"
|
||||
layer = HIGH_OBJ_LAYER //Looks better when its over everything... cause its huge
|
||||
var/obj/item/gps/internal/geepm
|
||||
|
||||
/obj/structure/sword/sif/Initialize()
|
||||
. = ..()
|
||||
geepm = new /obj/item/gps/internal/sif(src)
|
||||
|
||||
//When the sword is touched it will spawn sif.
|
||||
/obj/structure/sword/sif/attack_hand(mob/user)
|
||||
icon_state = "Interact_Sword"
|
||||
playsound(get_turf(src.loc), 'sound/effects/curse1.ogg', 100, 1)
|
||||
spawn(30)
|
||||
if(!QDELETED(src))
|
||||
new /mob/living/simple_animal/hostile/megafauna/sif(get_turf(src.loc))
|
||||
visible_message("<span class='notice'>The ground shakes.</span>")
|
||||
playsound(get_turf(src.loc), 'sound/effects/curse3.ogg', 100, 1)
|
||||
playsound(get_turf(src.loc), 'sound/effects/meteorimpact.ogg', 100, 1)
|
||||
qdel(src)
|
||||
|
||||
//Sif's charge attack
|
||||
/mob/living/simple_animal/hostile/megafauna/sif/proc/rush()
|
||||
|
||||
//Target
|
||||
if(!target)
|
||||
return //Exit porc
|
||||
|
||||
var/chargeturf = get_turf(target)
|
||||
|
||||
//Targets turf
|
||||
if(!chargeturf)
|
||||
return //Exit proc
|
||||
|
||||
var/dir = get_dir(src, chargeturf)
|
||||
var/turf/T = get_ranged_target_turf(chargeturf, dir, 2)
|
||||
|
||||
//Turfs area
|
||||
if(!T)
|
||||
return //Exit proc
|
||||
|
||||
//Start charging
|
||||
charging = TRUE
|
||||
DestroySurroundings()
|
||||
walk(src, 0)
|
||||
setDir(dir)
|
||||
var/movespeed = 1
|
||||
walk_to(src, T, movespeed)
|
||||
var/atom/prevLoc = target.loc
|
||||
sleep((get_dist(src, T) * movespeed) + 1)
|
||||
src.loc = prevLoc
|
||||
walk(src, 0)
|
||||
charging = FALSE
|
||||
//Stop charging
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/sif/Move()
|
||||
//Move
|
||||
..()
|
||||
|
||||
//Can they perform these tasks?
|
||||
if(can_special == 1)
|
||||
|
||||
//Charging currentPower every step
|
||||
if(!charging || !spinning)
|
||||
src.currentPower += 2
|
||||
|
||||
//Sets sif's anger status.
|
||||
if(src.health <= 1000 && src.stageTwo == FALSE)
|
||||
angered()
|
||||
|
||||
//Sets sifs enrage status.
|
||||
if(src.health <= 400 && src.stageThree == FALSE)
|
||||
enraged()
|
||||
|
||||
//Whenever Sif moves he destroys walls in his way.
|
||||
if(src.angered == TRUE || src.enraged == TRUE)
|
||||
DestroySurroundings()
|
||||
|
||||
//Normally Sif will do a special when he has 100 currentPower.
|
||||
if(src.angered == FALSE && src.currentPower >= 100)
|
||||
special()
|
||||
|
||||
//Now requires 50 power when angery
|
||||
if(src.angered == TRUE && src.currentPower >= 50 && src.enraged == FALSE)
|
||||
special()
|
||||
|
||||
//Now requires 30 power when enraged
|
||||
if(src.enraged == TRUE && src.currentPower >= 30)
|
||||
special()
|
||||
|
||||
//visual effect
|
||||
if(src.charging == TRUE)
|
||||
new /obj/effect/temp_visual/decoy/fading(loc,src)
|
||||
DestroySurroundings()
|
||||
|
||||
//Sif's AOE spin attack
|
||||
/mob/living/simple_animal/hostile/megafauna/sif/proc/spinAttack()
|
||||
src.spinning = TRUE
|
||||
spin(5,2)// Spin me boi
|
||||
|
||||
//Chance to dodge projectiles when angered or enraged
|
||||
/mob/living/simple_animal/hostile/megafauna/sif/bullet_act(obj/item/projectile/P)
|
||||
var/passed = 0
|
||||
|
||||
if(angered)
|
||||
switch(rand(0,100))
|
||||
if(0 to 1)
|
||||
passed = 1
|
||||
|
||||
if(enraged)
|
||||
switch(rand(0,100))
|
||||
if(0 to 5)
|
||||
passed = 1
|
||||
|
||||
if(passed == 1)
|
||||
visible_message("<span class='danger'>[src] dodged the projectile!</span>", "<span class='userdanger'>You dodge the projectile!</span>")
|
||||
playsound(src, pick('sound/weapons/bulletflyby.ogg', 'sound/weapons/bulletflyby2.ogg', 'sound/weapons/bulletflyby3.ogg'), 300, 1)
|
||||
return 0
|
||||
|
||||
return ..()
|
||||
|
||||
//Sets Sif's angered stats
|
||||
/mob/living/simple_animal/hostile/megafauna/sif/proc/angered()
|
||||
src.angered = TRUE
|
||||
src.stageTwo = TRUE
|
||||
src.visible_message("<span class='userdanger'>[src] lets out a ear ripping howl!</span>", "<span class='userdanger'>[src] lets out an ear ripping roar!</span>")
|
||||
playsound(src, 'sandcode/sound/sif/howl.ogg', 100, 1)
|
||||
var/mob/living/L = target
|
||||
shake_camera(L, 4, 3)
|
||||
src.speed = 6
|
||||
src.move_to_delay = 2
|
||||
src.melee_damage_lower = 25
|
||||
src.melee_damage_upper = 25
|
||||
src.rapid_melee = 3
|
||||
|
||||
//Sets Sif's enraged stats
|
||||
/mob/living/simple_animal/hostile/megafauna/sif/proc/enraged()
|
||||
src.stageThree = TRUE
|
||||
src.enraged = TRUE
|
||||
src.visible_message("<span class='userdanger'>[src] lets out a ear ripping yelp!</span>", "<span class='userdanger'>[src] lets out an ear ripping yelp!</span>")
|
||||
playsound(src, 'sandcode/sound/sif/howl.ogg', 100, 1)
|
||||
var/mob/living/L = target
|
||||
shake_camera(L, 8, 6)
|
||||
src.speed = 3
|
||||
src.move_to_delay = 4
|
||||
src.melee_damage_lower = 30
|
||||
src.melee_damage_upper = 30
|
||||
src.rapid_melee = 4
|
||||
src.dodge_prob = 50
|
||||
|
||||
//Chooses a random special
|
||||
/mob/living/simple_animal/hostile/megafauna/sif/proc/special()
|
||||
src.currentPower = 0
|
||||
switch(rand(1,2))
|
||||
if(1)
|
||||
rush()
|
||||
if(2)
|
||||
spinAttack()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/sif/proc/default_attackspeed()
|
||||
if(stageTwo)
|
||||
src.move_to_delay = 2
|
||||
return 10
|
||||
if(stageThree)
|
||||
src.move_to_delay = 4
|
||||
return 4
|
||||
|
||||
src.move_to_delay = 3
|
||||
return 2
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/sif/do_attack_animation(atom/A, visual_effect_icon,used_item, no_effect)
|
||||
if(charging == FALSE)
|
||||
..()
|
||||
|
||||
//Attack speed delay
|
||||
//bob's note: everything here is well coded except this like why would you not just use changeNext_move()
|
||||
/mob/living/simple_animal/hostile/megafauna/sif/AttackingTarget()
|
||||
if(charging == FALSE)
|
||||
. = ..()
|
||||
if(.)
|
||||
recovery_time = world.time + 10
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/sif/Goto(target, delay, minimum_distance)
|
||||
if(charging == FALSE)
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/sif/MoveToTarget(list/possible_targets)
|
||||
if(charging == FALSE)
|
||||
..()
|
||||
|
||||
//Immune to explosions when spinning or charging
|
||||
/mob/living/simple_animal/hostile/megafauna/sif/ex_act(severity, target)
|
||||
return 0
|
||||
|
||||
//stop spinning if you lose the target
|
||||
/mob/living/simple_animal/hostile/megafauna/sif/LoseTarget()
|
||||
. = ..()
|
||||
if(spinning)
|
||||
icon_state = "Great_Brown_Wolf"
|
||||
src.spinIntervals = 0
|
||||
spinning = FALSE
|
||||
src.speed = default_attackspeed()
|
||||
hit_things = list()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/sif/Moved()
|
||||
|
||||
if(can_special == 1)
|
||||
|
||||
if(charging == TRUE)
|
||||
DestroySurroundings()
|
||||
|
||||
//Stop spinning
|
||||
if(src.spinIntervals == 5)
|
||||
icon_state = "Great_Brown_Wolf"
|
||||
src.spinIntervals = 0
|
||||
spinning = FALSE
|
||||
src.speed = default_attackspeed()
|
||||
hit_things = list()
|
||||
|
||||
//Start spinning
|
||||
if(spinning == TRUE)
|
||||
icon_state = "Great_Brown_Wolf_Spin"
|
||||
src.spinIntervals += 1
|
||||
if(isturf(src.loc) || isobj(src.loc) && src.loc.density)
|
||||
for(var/turf/T in view(1, src))
|
||||
new /obj/effect/temp_visual/small_smoke/halfsecond(T)
|
||||
for(var/mob/living/LM in view(1, src))
|
||||
if(!(LM in hit_things))
|
||||
LM.Stun(30, TRUE)
|
||||
hit_things += LM
|
||||
playsound(src, pick('sandcode/sound/sif/whoosh1.ogg', 'sandcode/sound/sif/whoosh2.ogg', 'sandcode/sound/sif/whoosh3.ogg'), 300, 1)
|
||||
playsound(src, 'sandcode/sound/sif/blade_spin.ogg', 400, 1)
|
||||
if(angered)
|
||||
src.speed = 6
|
||||
src.move_to_delay = 2
|
||||
|
||||
playsound(src, 'sound/effects/meteorimpact.ogg', 200, 1, 2, 1)
|
||||
..()
|
||||
|
||||
//Activated when sif collides with target when charging.
|
||||
/mob/living/simple_animal/hostile/megafauna/sif/Bump(atom/A)
|
||||
if(charging == TRUE)
|
||||
if(isturf(A) || isobj(A) && A.density)
|
||||
A.ex_act(EXPLODE_HEAVY)
|
||||
DestroySurroundings()
|
||||
if(isliving(A))
|
||||
var/mob/living/L = A
|
||||
L.visible_message("<span class='danger'>[src] stomps on [L]!</span>", "<span class='userdanger'>[src] stomps on you!</span>")
|
||||
src.forceMove(get_turf(L))
|
||||
L.apply_damage(20, BRUTE)
|
||||
playsound(get_turf(L), 'sandcode/sound/sif/sif_stomp.ogg', 400, 1)
|
||||
shake_camera(L, 4, 3)
|
||||
shake_camera(src, 2, 3)
|
||||
..()
|
||||
@@ -0,0 +1,5 @@
|
||||
/mob/living/simple_animal/hostile/asteroid/basilisk/watcher
|
||||
glorymessageshand = list("rips out both of the watcher's wings and shoves them aside, then kicks the downed body until it turns into mush!", "violently rips off one of the watcher's spikes, then stabs them repeatedly with it!")
|
||||
glorymessagespka = list("bashes the shit out of the watcher with their PKA, gushing blood everywhere!", "shoots both of the watcher's wings off, then sticks their PKA on their face and shoots, showering everything in gore!")
|
||||
glorymessagespkabayonet = list("stabs the watcher's eye repeatedly, turning it into a bloody mess!", "slices one wing after another off the watcher, in swift moves!")
|
||||
glorymessagescrusher = list("repeatedly chops the watcher with their crusher, turning it into bloody mush!", "mark detonates the watcher in close proximity, showering viscera everywhere!", "flips their Crusher around, ramming the handle up the Watcher's eye, impaling it, before smashing it against the ground brutally!")
|
||||
@@ -0,0 +1,277 @@
|
||||
#define BLOOD_CHARGE 1
|
||||
#define BLOODY_TRAP 2
|
||||
#define MEAT_SHIELD 3
|
||||
#define KNOCKDOWN 4
|
||||
|
||||
/**
|
||||
* # Candy
|
||||
*
|
||||
* Kind of like bubblegum's rebellious teenage son/daughter.
|
||||
* Has 4 attacks.
|
||||
* Charge - Charges at it's target.
|
||||
* Bloody Trap - Traps it's target between some walls, and then charges at them.
|
||||
* Meat Shield - Knockbacks all targets in the 3 tiles he faces, and then creates a wall.
|
||||
* Knockdown - Deals damage and knockbacks all targets in a 2 tile radius.
|
||||
*/
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/candy
|
||||
name = "Candy"
|
||||
desc = "In what passes as a hierarchy for slaughter demons, this one is prince."
|
||||
icon = 'sandcode/icons/mob/lavaland/lavaland_elites.dmi'
|
||||
icon_state = "candy"
|
||||
icon_living = "candy"
|
||||
icon_aggro = "candy"
|
||||
icon_dead = "candy_dead"
|
||||
icon_gib = "syndicate_gib"
|
||||
maxHealth = 800
|
||||
health = 800
|
||||
melee_damage_lower = 30
|
||||
melee_damage_upper = 30
|
||||
attack_verb_continuous = "punches"
|
||||
attack_verb_simple = "punch"
|
||||
attack_sound = 'sound/magic/demon_consume.ogg'
|
||||
speed = 1
|
||||
move_to_delay = 3
|
||||
mouse_opacity = MOUSE_OPACITY_ICON
|
||||
deathsound = 'sandcode/sound/misc/gorenest.ogg'
|
||||
deathmessage = " screams in agony, before falling headfirst onto the floor."
|
||||
loot_drop = /obj/item/bloodcrawlbottle
|
||||
speak_emote = list("gurgle")
|
||||
|
||||
attack_action_types = list(/datum/action/innate/elite_attack/bloodcharge,
|
||||
/datum/action/innate/elite_attack/bloody_trap,
|
||||
/datum/action/innate/elite_attack/meat_shield,
|
||||
/datum/action/innate/elite_attack/knockdown)
|
||||
glorymessageshand = list("tries punching Candy's head, but they parry it and grab their hand! However, another hard punch comes through with the other arm, this time killing the demon swiftly and exploding their skull!", "grabs Candy by their neck, then pressures into until it explodes and it's head comes flying off!")
|
||||
glorymessagescrusher = list("slashes Candy in half vertically with their crusher, each of the parts falling off onto the ground limply!")
|
||||
glorymessagespka = list("shoots at Candy's head, breaking their skull open and revealing their brain! Then, they bash the brain into mush with their PKA's stock!", "kicks Candy into the ground, and repeatedly slams their PKA against their skull until they finally die!")
|
||||
glorymessagespkabayonet = list("stabs through Candy's maw and lifts them into the air, shooting their PKA and exploding their head as the limp body falls off!")
|
||||
|
||||
/datum/action/innate/elite_attack/bloodcharge
|
||||
name = "Blood Charge"
|
||||
icon_icon = 'sandcode/icons/mob/actions/actions_elites.dmi'
|
||||
button_icon_state = "blood_charge"
|
||||
chosen_message = "<span class='boldwarning'>You will attempt to charge your target.</span>"
|
||||
chosen_attack_num = BLOOD_CHARGE
|
||||
|
||||
/datum/action/innate/elite_attack/bloody_trap
|
||||
name = "Bloody Trap"
|
||||
icon_icon = 'sandcode/icons/mob/actions/actions_elites.dmi'
|
||||
button_icon_state = "bloody_trap"
|
||||
chosen_message = "<span class='boldwarning'>You will attempt to trap your target.</span>"
|
||||
chosen_attack_num = BLOODY_TRAP
|
||||
|
||||
/datum/action/innate/elite_attack/meat_shield
|
||||
name = "Meat Shield"
|
||||
icon_icon = 'sandcode/icons/mob/actions/actions_elites.dmi'
|
||||
button_icon_state = "meat_shield"
|
||||
chosen_message = "<span class='boldwarning'>You will attempt to shield yourself.</span>"
|
||||
chosen_attack_num = MEAT_SHIELD
|
||||
|
||||
/datum/action/innate/elite_attack/knockdown
|
||||
name = "Knockdown"
|
||||
icon_icon = 'sandcode/icons/mob/actions/actions_elites.dmi'
|
||||
button_icon_state = "knockdown"
|
||||
chosen_message = "<span class='boldwarning'>You will knock down every mob around you.</span>"
|
||||
chosen_attack_num = KNOCKDOWN
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/candy/OpenFire()
|
||||
if(client)
|
||||
switch(chosen_attack)
|
||||
if(BLOOD_CHARGE)
|
||||
bloodcharge(target)
|
||||
if(BLOODY_TRAP)
|
||||
bloodytrap(target)
|
||||
if(MEAT_SHIELD)
|
||||
meatshield()
|
||||
if(KNOCKDOWN)
|
||||
knockdown()
|
||||
return
|
||||
var/aiattack = rand(1,4)
|
||||
switch(aiattack)
|
||||
if(BLOOD_CHARGE)
|
||||
bloodcharge(target)
|
||||
if(BLOODY_TRAP)
|
||||
bloodytrap(target)
|
||||
if(MEAT_SHIELD)
|
||||
meatshield()
|
||||
if(KNOCKDOWN)
|
||||
knockdown()
|
||||
|
||||
// Candy actions
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/candy/proc/bloodcharge(target)
|
||||
ranged_cooldown = world.time + 50
|
||||
var/dir_to_target = get_dir(get_turf(src), get_turf(target))
|
||||
var/turf/T = get_turf(src)
|
||||
playsound(src,'sound/magic/demon_attack1.ogg', 200, 1)
|
||||
visible_message("<span class='boldwarning'>[src] prepares to charge!</span>")
|
||||
for(var/i in 1 to 6)
|
||||
new /obj/effect/temp_visual/dir_setting/bloodsplatter/candy(T, get_dir(T, target))
|
||||
T = get_step(T, dir_to_target)
|
||||
sleep(1)
|
||||
addtimer(CALLBACK(src, .proc/blood_charge_2, dir_to_target, 0), 5)
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/candy/proc/bloodytrap(mob/target)
|
||||
playsound(src,'sound/magic/Blind.ogg', 200, 1)
|
||||
var/dir_to_target = get_dir(src, target)
|
||||
var/turf/T = get_step(src, dir_to_target)
|
||||
var/list/bline = getline(T, target.loc)
|
||||
if(bline.len > 6)
|
||||
return FALSE
|
||||
ranged_cooldown = world.time + 100
|
||||
visible_message("<span class='boldwarning'>[src] traps [target]!</span>")
|
||||
for(var/turf/J in view(1, target) - get_turf(target))
|
||||
new /obj/effect/temp_visual/bloodwall(J, src)
|
||||
sleep(5)
|
||||
src.bloodcharge(target)
|
||||
var/list/bloodwalls = list()
|
||||
for(var/d in GLOB.cardinals)
|
||||
var/turf/N = get_step(target, d)
|
||||
if(N == get_step(src, src.dir) || N == get_turf(src))
|
||||
continue
|
||||
else
|
||||
for(var/obj/effect/temp_visual/bloodwall/B in N.contents)
|
||||
bloodwalls += B
|
||||
var/obj/effect/temp_visual/bloodwall/chosen = pick(bloodwalls)
|
||||
visible_message("<span class='boldwarning'>One of the blood walls disappear!</span>")
|
||||
qdel(chosen)
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/candy/proc/meatshield()
|
||||
ranged_cooldown = world.time + 25
|
||||
playsound(src,'sound/magic/Blind.ogg', 200, 1)
|
||||
visible_message("<span class='boldwarning'>[src] raises a wall!</span>")
|
||||
var/turf/T = get_turf(get_step(src, src.dir))
|
||||
var/list/hit_things = list()
|
||||
new /obj/effect/temp_visual/bloodwall(T, src)
|
||||
for(var/mob/living/L in T.contents)
|
||||
if(L != src && !(L in hit_things))
|
||||
var/throwtarget = get_edge_target_turf(src, get_dir(src, L))
|
||||
L.safe_throw_at(throwtarget, 10, 1, src)
|
||||
L.Stun(20)
|
||||
hit_things += L
|
||||
var/turf/otherT = get_step(T, turn(src.dir, 90))
|
||||
for(var/mob/living/L in otherT.contents)
|
||||
if(L != src && !(L in hit_things))
|
||||
var/throwtarget = get_edge_target_turf(src, get_dir(src, L))
|
||||
L.safe_throw_at(throwtarget, 10, 1, src)
|
||||
L.Stun(20)
|
||||
hit_things += L
|
||||
if(otherT)
|
||||
new /obj/effect/temp_visual/bloodwall(otherT, src)
|
||||
otherT = get_step(T, turn(src.dir, -90))
|
||||
for(var/mob/living/L in otherT.contents)
|
||||
if(L != src && !(L in hit_things))
|
||||
var/throwtarget = get_edge_target_turf(src, get_dir(src, L))
|
||||
L.safe_throw_at(throwtarget, 10, 1, src)
|
||||
L.Stun(20)
|
||||
hit_things += L
|
||||
if(otherT)
|
||||
new /obj/effect/temp_visual/bloodwall(otherT, src)
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/candy/proc/knockdown()
|
||||
ranged_cooldown = world.time + 100
|
||||
playsound(src,'sound/misc/crunch.ogg', 200, 1)
|
||||
visible_message("<span class='boldwarning'>[src] clenches his fists and smashes the ground!</span>")
|
||||
var/list/hit_things = list()
|
||||
sleep(10)
|
||||
for(var/turf/T in view(1, src))
|
||||
new /obj/effect/temp_visual/small_smoke/halfsecond(T)
|
||||
for(var/mob/living/L in T.contents)
|
||||
if(L != src && !(L in hit_things))
|
||||
var/throwtarget = get_edge_target_turf(src, get_dir(src, L))
|
||||
L.safe_throw_at(throwtarget, 10, 1, src)
|
||||
L.Stun(20)
|
||||
L.adjustBruteLoss(50)
|
||||
var/source_turf = src.loc
|
||||
sleep(5)
|
||||
for(var/turf/T in view(2, source_turf) - view(1, source_turf))
|
||||
new /obj/effect/temp_visual/small_smoke/halfsecond(T)
|
||||
for(var/mob/living/L in T.contents)
|
||||
if(L != src && !(L in hit_things))
|
||||
var/throwtarget = get_edge_target_turf(src, get_dir(src, L))
|
||||
L.safe_throw_at(throwtarget, 10, 1, src)
|
||||
L.Stun(20)
|
||||
L.adjustBruteLoss(50)
|
||||
|
||||
// Candy helpers
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/candy/proc/blood_charge_2(var/move_dir, var/times_ran)
|
||||
if(times_ran >= 6)
|
||||
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.Stun(20) //substituting this for the Paralyze from the line above, because we don't have tg paralysis stuff
|
||||
L.adjustBruteLoss(50)
|
||||
addtimer(CALLBACK(src, .proc/blood_charge_2, move_dir, (times_ran + 1)), 2)
|
||||
|
||||
/obj/effect/temp_visual/dir_setting/bloodsplatter/candy
|
||||
duration = 10
|
||||
color = "#FF0000"
|
||||
|
||||
/obj/effect/temp_visual/bloodwall
|
||||
name = "blood wall"
|
||||
icon = 'icons/turf/walls/cult_wall.dmi'
|
||||
icon_state = "cult"
|
||||
color = "#FF0000"
|
||||
duration = 50
|
||||
smooth = SMOOTH_TRUE
|
||||
var/mob/living/caster
|
||||
|
||||
/obj/effect/temp_visual/bloodwall/Initialize(mapload, new_caster)
|
||||
. = ..()
|
||||
caster = new_caster
|
||||
queue_smooth_neighbors(src)
|
||||
queue_smooth(src)
|
||||
|
||||
/obj/effect/temp_visual/bloodwall/Destroy()
|
||||
queue_smooth_neighbors(src)
|
||||
return ..()
|
||||
|
||||
/obj/effect/temp_visual/bloodwall/CanPass(atom/movable/mover, turf/target)
|
||||
if(QDELETED(caster))
|
||||
return FALSE
|
||||
if(mover == caster.pulledby)
|
||||
return TRUE
|
||||
if(istype(mover, /obj/item/projectile))
|
||||
var/obj/item/projectile/P = mover
|
||||
if(P.firer == caster)
|
||||
return TRUE
|
||||
if(mover == caster)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
//loot
|
||||
|
||||
/obj/item/bloodcrawlbottle
|
||||
name = "bloodlust in a bottle"
|
||||
desc = "Drinking this will give you unimaginable powers... and mildly disgust you because of it's metallic taste."
|
||||
icon = 'icons/obj/wizard.dmi'
|
||||
icon_state = "vial"
|
||||
|
||||
/obj/item/bloodcrawlbottle/attack_self(mob/user)
|
||||
to_chat(user, "<span class='notice'>You drink the bottle's contents.</span>")
|
||||
var/obj/effect/proc_holder/spell/bloodcrawl/S = new /obj/effect/proc_holder/spell/bloodcrawl/
|
||||
user.mind.AddSpell(S)
|
||||
user.log_message("learned the spell bloodcrawl ([S])", LOG_ATTACK, color="orange")
|
||||
qdel(src)
|
||||
+188
@@ -0,0 +1,188 @@
|
||||
#define LAVA_MOAT 1
|
||||
#define LAVA_AROUND 2
|
||||
#define FIRE_SPEW 3
|
||||
#define FIRE_MOAT 4
|
||||
|
||||
/**
|
||||
* # Drakeling
|
||||
*
|
||||
* A small drake/dragon.
|
||||
* Has four attacks.
|
||||
* - Lava moat - Creates a moat of lava around themselves.
|
||||
* - Lava rivers - Creates lava rivers in all cardinal directions.
|
||||
* - Firespew - Spews fire in the direction they're facing.
|
||||
* - Fire moat - Spews fire in all directions.
|
||||
*/
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/drakeling
|
||||
name = "Drakeling"
|
||||
desc = "A small but still fearsome dragon."
|
||||
icon = 'sandcode/icons/mob/lavaland/lavaland_elites.dmi'
|
||||
icon_state = "ash_whelp"
|
||||
icon_living = "ash_whelp"
|
||||
icon_aggro = "ash_whelp"
|
||||
icon_dead = "ash_whelp_dead"
|
||||
icon_gib = "syndicate_gib"
|
||||
maxHealth = 800
|
||||
health = 800
|
||||
melee_damage_lower = 30
|
||||
melee_damage_upper = 30
|
||||
attack_verb_continuous = "bites"
|
||||
attack_verb_simple = "bite"
|
||||
attack_sound = 'sound/magic/demon_attack1.ogg'
|
||||
speed = 1
|
||||
move_to_delay = 3
|
||||
mouse_opacity = MOUSE_OPACITY_ICON
|
||||
deathsound = 'sound/magic/WandODeath.ogg'
|
||||
deathmessage = "'s wings flail weakly until he settles down, dead"
|
||||
loot_drop = /obj/item/borg/upgrade/modkit/fire
|
||||
speak_emote = list("huffs")
|
||||
|
||||
attack_action_types = list(/datum/action/innate/elite_attack/lavamoat,
|
||||
/datum/action/innate/elite_attack/lavaaround,
|
||||
/datum/action/innate/elite_attack/firespew,
|
||||
/datum/action/innate/elite_attack/firemoat)
|
||||
glorymessageshand = list("rips off the little dragon's horns, then shoves them into their mouth!", "grabs the drakeling's head and rips it off violently from their neck with their bare hands!")
|
||||
glorymessagescrusher = list("slashes the drakeling's head in half with their crusher, dividing it in two!")
|
||||
glorymessagespka = list("hits the drakeling's maw repeatedly with the stock of their PKA until it breaks off, then shoots it in the head for good measure!", "grabs the drakeling's neck, and shoots it's head off with their PKA!")
|
||||
glorymessagespkabayonet = list("kicks the drakeling onto the ground belly up, then slices their tummy open with the bayonet as it screams in agony!")
|
||||
|
||||
/datum/action/innate/elite_attack/lavamoat
|
||||
name = "Lava Moat"
|
||||
icon_icon = 'sandcode/icons/mob/actions/actions_elites.dmi'
|
||||
button_icon_state = "lava_moat"
|
||||
chosen_message = "<span class='boldwarning'>You will attempt to create a lava moat around you.</span>"
|
||||
chosen_attack_num = LAVA_MOAT
|
||||
|
||||
/datum/action/innate/elite_attack/lavaaround
|
||||
name = "Lava Rivers"
|
||||
icon_icon = 'sandcode/icons/mob/actions/actions_elites.dmi'
|
||||
button_icon_state = "lava_around"
|
||||
chosen_message = "<span class='boldwarning'>You will now create lava rivers at your cardinal directions.</span>"
|
||||
chosen_attack_num = LAVA_AROUND
|
||||
|
||||
/datum/action/innate/elite_attack/firespew
|
||||
name = "Fire Spew"
|
||||
icon_icon = 'sandcode/icons/mob/actions/actions_elites.dmi'
|
||||
button_icon_state = "fire_spew"
|
||||
chosen_message = "<span class='boldwarning'>You will now spew fire at your target.</span>"
|
||||
chosen_attack_num = FIRE_SPEW
|
||||
|
||||
/datum/action/innate/elite_attack/firemoat
|
||||
name = "Fire Moat"
|
||||
icon_icon = 'sandcode/icons/mob/actions/actions_elites.dmi'
|
||||
button_icon_state = "fire_moat"
|
||||
chosen_message = "<span class='boldwarning'>You will now spew fire at all cardinal directions.</span>"
|
||||
chosen_attack_num = FIRE_MOAT
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/drakeling/OpenFire()
|
||||
if(client)
|
||||
switch(chosen_attack)
|
||||
if(LAVA_MOAT)
|
||||
lava_moat(target)
|
||||
if(LAVA_AROUND)
|
||||
lava_around(target)
|
||||
if(FIRE_SPEW)
|
||||
fire_spew()
|
||||
if(FIRE_MOAT)
|
||||
fire_moat()
|
||||
return
|
||||
var/aiattack = rand(1,4)
|
||||
switch(aiattack)
|
||||
if(LAVA_MOAT)
|
||||
lava_moat(target)
|
||||
if(LAVA_AROUND)
|
||||
lava_around(target)
|
||||
if(FIRE_SPEW)
|
||||
fire_spew()
|
||||
if(FIRE_MOAT)
|
||||
fire_moat()
|
||||
|
||||
//Drakeling actions
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/drakeling/proc/lava_moat()
|
||||
ranged_cooldown = world.time + 25
|
||||
visible_message("<span class='boldwarning'>[src] spews lava around themselves! Get back!</span>")
|
||||
for(var/turf/T in oview(1, src))
|
||||
new /obj/effect/temp_visual/lava_warning(T)
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/drakeling/proc/lava_around()
|
||||
ranged_cooldown = world.time + 50
|
||||
for(var/d in GLOB.cardinals)
|
||||
INVOKE_ASYNC(src, .proc/lava_wall, d, 5)
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/drakeling/proc/fire_spew()
|
||||
ranged_cooldown = world.time + 25
|
||||
visible_message("<span class='boldwarning'>[src] spews fire!</span>")
|
||||
playsound(src,'sound/magic/Fireball.ogg', 200, 1)
|
||||
sleep(5)
|
||||
fire_wall(src.dir, 10)
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/drakeling/proc/fire_moat()
|
||||
ranged_cooldown = world.time + 100
|
||||
playsound(src,'sound/magic/Fireball.ogg', 200, 1)
|
||||
visible_message("<span class='boldwarning'>[src] violently puffs smoke!They're going to make a fire moat!</span>")
|
||||
sleep(5)
|
||||
for(var/d in GLOB.alldirs)
|
||||
INVOKE_ASYNC(src, .proc/fire_wall, d, 10)
|
||||
|
||||
// Drakeling helpers
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/drakeling/proc/fire_wall(dir, range)
|
||||
var/list/hitlist = list(src)
|
||||
var/turf/T = get_turf(src)
|
||||
for(var/i in 1 to range)
|
||||
new /obj/effect/hotspot(T)
|
||||
T.hotspot_expose(700,50,1)
|
||||
for(var/mob/living/L in T.contents)
|
||||
if(L in hitlist || (L == src))
|
||||
break
|
||||
else
|
||||
hitlist += L
|
||||
L.adjustFireLoss(20)
|
||||
to_chat(L, "<span class='userdanger'>You're hit by [src]'s fire breath!</span>")
|
||||
T = get_step(T, dir)
|
||||
sleep(1)
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/drakeling/proc/lava_wall(dir, range)
|
||||
var/turf/T = get_turf(src)
|
||||
for(var/i in 1 to range)
|
||||
new /obj/effect/temp_visual/lava_warning(T)
|
||||
T = get_step(T, dir)
|
||||
sleep(2)
|
||||
|
||||
/obj/effect/temp_visual/lava_warning
|
||||
icon_state = "lavastaff_warn"
|
||||
layer = BELOW_MOB_LAYER
|
||||
light_range = 2
|
||||
duration = 7
|
||||
|
||||
/obj/effect/temp_visual/lava_warning/ex_act()
|
||||
return
|
||||
|
||||
/obj/effect/temp_visual/lava_warning/Initialize(mapload, reset_time = 40)
|
||||
. = ..()
|
||||
INVOKE_ASYNC(src, .proc/fall, reset_time)
|
||||
src.alpha = 63.75
|
||||
animate(src, alpha = 255, time = duration)
|
||||
|
||||
/obj/effect/temp_visual/lava_warning/proc/fall(var/reset_time)
|
||||
var/turf/T = get_turf(src)
|
||||
playsound(T,'sound/magic/fleshtostone.ogg', 80, TRUE)
|
||||
sleep(duration)
|
||||
playsound(T,'sound/magic/fireball.ogg', 200, TRUE)
|
||||
for(var/mob/living/L in T.contents)
|
||||
if(istype(L, /mob/living/simple_animal/hostile/asteroid/elite/drakeling))
|
||||
continue
|
||||
L.adjustFireLoss(10)
|
||||
to_chat(L, "<span class='userdanger'>You fall directly into the pool of lava!</span>")
|
||||
|
||||
// deals damage to mechs
|
||||
for(var/obj/mecha/M in T.contents)
|
||||
M.take_damage(45, BRUTE, "melee", 1)
|
||||
|
||||
// changes turf to lava temporarily
|
||||
if(!istype(T, /turf/closed) && !istype(T, /turf/open/lava))
|
||||
var/lava_turf = /turf/open/lava/smooth
|
||||
var/reset_turf = T.type
|
||||
T.ChangeTurf(lava_turf, flags = CHANGETURF_INHERIT_AIR)
|
||||
addtimer(CALLBACK(T, /turf.proc/ChangeTurf, reset_turf, null, CHANGETURF_INHERIT_AIR), reset_time, TIMER_OVERRIDE|TIMER_UNIQUE)
|
||||
@@ -0,0 +1,43 @@
|
||||
/obj/structure/elite_tumor
|
||||
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,
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/drakeling,
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/candy,
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/minerpriest)
|
||||
|
||||
/obj/structure/elite_tumor/priest
|
||||
potentialspawns = list(/mob/living/simple_animal/hostile/asteroid/elite/minerpriest)
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite
|
||||
can_talk = TRUE
|
||||
speak_emote = list("growls")
|
||||
gloryhealth = 50
|
||||
glorymodifier = 0.625
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/death(gibbed)
|
||||
gibbed = FALSE
|
||||
..(gibbed)
|
||||
|
||||
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]. 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
|
||||
E.owner = user
|
||||
qdel(src)
|
||||
else
|
||||
to_chat(user, "<span class='info'>[src] only works on the corpse of a sentient lavaland elite.</span>")
|
||||
+259
@@ -0,0 +1,259 @@
|
||||
#define AXE_SLAM 1
|
||||
#define SUMMON_SHAMBLER 2
|
||||
#define DASH 3
|
||||
#define AXE_THROW 4
|
||||
|
||||
/**
|
||||
* # Necropolis priest
|
||||
*
|
||||
* Kind of like BD miner's son trying to impress their dad.
|
||||
* Has four attacks.
|
||||
* - Axe Slam - Slams his axe on the ground, hurting everyone is his direction in a 3 tile radius
|
||||
* - Summon Shambler - Summons a shambling miner that focuses on the target.
|
||||
* - Dash - Dashes in the target's general direction
|
||||
* - Axe Throw - Throws an axe at the target
|
||||
*/
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/minerpriest
|
||||
name = "Necropolis Priest"
|
||||
desc = "Once used to be a miner, now a worshipper of the necropolis."
|
||||
icon = 'sandcode/icons/mob/lavaland/lavaland_elites.dmi'
|
||||
icon_state = "minerpriest"
|
||||
icon_living = "minerpriest"
|
||||
icon_aggro = "minerpriest"
|
||||
icon_dead = "minerpriest_dead"
|
||||
icon_gib = "syndicate_gib"
|
||||
maxHealth = 800
|
||||
health = 800
|
||||
melee_damage_lower = 30
|
||||
melee_damage_upper = 30
|
||||
attack_verb_continuous = "slashes"
|
||||
attack_verb_simple = "slash"
|
||||
attack_sound = 'sound/weapons/slash.ogg'
|
||||
speed = 1
|
||||
move_to_delay = 2
|
||||
mouse_opacity = MOUSE_OPACITY_ICON
|
||||
deathsound = 'sound/voice/human/manlaugh1.ogg'
|
||||
deathmessage = "realizes what they've been doing all this time, and return to their true self."
|
||||
loot_drop = /obj/item/melee/diamondaxe
|
||||
speak_emote = list("yells")
|
||||
del_on_death = TRUE
|
||||
projectiletype = /obj/item/projectile/kinetic/axe
|
||||
attack_action_types = list(/datum/action/innate/elite_attack/axe_slam,
|
||||
/datum/action/innate/elite_attack/summon_shambler,
|
||||
/datum/action/innate/elite_attack/dash,
|
||||
/datum/action/innate/elite_attack/axe_throw)
|
||||
glorymessageshand = list("grabs the priest's arm and breaks it, exposing sharp bone which is promptly shoved inside their skull!", "punches into the priest's guts, ripping off their stomach and whatever else was inside!")
|
||||
glorymessagescrusher = list("chops the priest's leg off with their crusher, then uses it to beat their skull open while they're downed!")
|
||||
glorymessagespka = list("shoots at the priest's hand, exploding it and making them let go of their axe, which is promptly grabbed and slashes their neck open!", "kicks the priest on the ground, then shoots their guts and viscera off with a PKA blast to the chest!")
|
||||
glorymessagespkabayonet = list("stabs through the priest's heart and pulls it out, letting them see one last beat before they die!")
|
||||
|
||||
/datum/action/innate/elite_attack/axe_slam
|
||||
name = "Axe Slam"
|
||||
icon_icon = 'sandcode/icons/mob/actions/actions_elites.dmi'
|
||||
button_icon_state = "axe_slam"
|
||||
chosen_message = "<span class='boldwarning'>You will attempt to slam your axe.</span>"
|
||||
chosen_attack_num = AXE_SLAM
|
||||
|
||||
/datum/action/innate/elite_attack/summon_shambler
|
||||
name = "Summon Shambler"
|
||||
icon_icon = 'sandcode/icons/mob/actions/actions_elites.dmi'
|
||||
button_icon_state = "summon_shambler"
|
||||
chosen_message = "<span class='boldwarning'>You will attempt to summon a shambling miner.</span>"
|
||||
chosen_attack_num = SUMMON_SHAMBLER
|
||||
|
||||
/datum/action/innate/elite_attack/dash
|
||||
name = "Dash"
|
||||
icon_icon = 'sandcode/icons/mob/actions/actions_elites.dmi'
|
||||
button_icon_state = "dash"
|
||||
chosen_message = "<span class='boldwarning'>You will attempt to dash near your target.</span>"
|
||||
chosen_attack_num = DASH
|
||||
|
||||
/datum/action/innate/elite_attack/axe_throw
|
||||
name = "Axe Throw"
|
||||
icon_icon = 'sandcode/icons/mob/actions/actions_elites.dmi'
|
||||
button_icon_state = "axe_throw"
|
||||
chosen_message = "<span class='boldwarning'>You will attempt to throw your axe.</span>"
|
||||
chosen_attack_num = AXE_THROW
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/minerpriest/OpenFire()
|
||||
if(client)
|
||||
switch(chosen_attack)
|
||||
if(AXE_SLAM)
|
||||
axe_slam(target)
|
||||
if(SUMMON_SHAMBLER)
|
||||
summon_shambler(target)
|
||||
if(DASH)
|
||||
dash(target)
|
||||
if(AXE_THROW)
|
||||
axe_throw(target)
|
||||
return
|
||||
var/aiattack = rand(1,4)
|
||||
switch(aiattack)
|
||||
if(AXE_SLAM)
|
||||
axe_slam(target)
|
||||
if(SUMMON_SHAMBLER)
|
||||
summon_shambler(target)
|
||||
if(DASH)
|
||||
dash(target)
|
||||
if(AXE_THROW)
|
||||
axe_throw(target)
|
||||
|
||||
// priest actions
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/minerpriest/proc/axe_slam(target)
|
||||
ranged_cooldown = world.time + 30
|
||||
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 3)
|
||||
new /obj/effect/temp_visual/dragon_swoop/priest(T)
|
||||
T = get_step(T, dir_to_target)
|
||||
visible_message("<span class='boldwarning'>[src] prepares to slam his axe!</span>")
|
||||
sleep(5)
|
||||
playsound(src,'sound/misc/crunch.ogg', 200, 1)
|
||||
T = get_step(get_turf(src), dir_to_target)
|
||||
var/list/hit_things = list()
|
||||
visible_message("<span class='boldwarning'>[src] slams his axe!</span>")
|
||||
for(var/i in 1 to 3)
|
||||
for(var/mob/living/L in T.contents)
|
||||
if(faction_check_mob(L))
|
||||
return
|
||||
hit_things += L
|
||||
visible_message("<span class='boldwarning'>[src] slams his axe on [L]!</span>")
|
||||
to_chat(L, "<span class='userdanger'>[src] slams his axe on you!</span>")
|
||||
L.Stun(15)
|
||||
L.adjustBruteLoss(30)
|
||||
T = get_step(T, dir_to_target)
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/minerpriest/proc/summon_shambler(target)
|
||||
ranged_cooldown = world.time + 150
|
||||
visible_message("<span class='boldwarning'>[src] summons a minion!</span>")
|
||||
playsound(src,'sound/magic/CastSummon.ogg', 200, 1)
|
||||
var/list/turfs = list()
|
||||
for(var/turf/T in oview(2, src))
|
||||
turfs += T
|
||||
var/turf/pick1 = pick(turfs)
|
||||
new /obj/effect/temp_visual/small_smoke/halfsecond(pick1)
|
||||
var/mob/living/simple_animal/hostile/asteroid/miner/m1 = new /mob/living/simple_animal/hostile/asteroid/miner(pick1)
|
||||
m1.faction = faction.Copy()
|
||||
m1.GiveTarget(target)
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/minerpriest/proc/dash(atom/dash_target)
|
||||
ranged_cooldown = world.time + 20
|
||||
visible_message("<span class='boldwarning'>[src] dashes into the air!</span>")
|
||||
playsound(src,'sound/magic/blink.ogg', 200, 1)
|
||||
var/list/accessable_turfs = list()
|
||||
var/self_dist_to_target = 0
|
||||
var/turf/own_turf = get_turf(src)
|
||||
if(!QDELETED(dash_target))
|
||||
self_dist_to_target += get_dist(dash_target, own_turf)
|
||||
for(var/turf/open/O in RANGE_TURFS(4, own_turf))
|
||||
var/turf_dist_to_target = 0
|
||||
if(!QDELETED(dash_target))
|
||||
turf_dist_to_target += get_dist(dash_target, O)
|
||||
if(get_dist(src, O) <= 4 && turf_dist_to_target <= self_dist_to_target && !islava(O) && !ischasm(O))
|
||||
var/valid = TRUE
|
||||
for(var/turf/T in getline(own_turf, O))
|
||||
if(is_blocked_turf(T, TRUE))
|
||||
valid = FALSE
|
||||
continue
|
||||
if(valid)
|
||||
accessable_turfs[O] = turf_dist_to_target
|
||||
var/turf/target_turf
|
||||
if(!QDELETED(dash_target))
|
||||
var/closest_dist = 4
|
||||
for(var/t in accessable_turfs)
|
||||
if(accessable_turfs[t] < closest_dist)
|
||||
closest_dist = accessable_turfs[t]
|
||||
for(var/t in accessable_turfs)
|
||||
if(accessable_turfs[t] != closest_dist)
|
||||
accessable_turfs -= t
|
||||
if(!LAZYLEN(accessable_turfs))
|
||||
return
|
||||
target_turf = pick(accessable_turfs)
|
||||
var/turf/step_back_turf = get_step(target_turf, -(src.dir))
|
||||
new /obj/effect/temp_visual/small_smoke/halfsecond(step_back_turf)
|
||||
new /obj/effect/temp_visual/small_smoke/halfsecond(own_turf)
|
||||
forceMove(step_back_turf)
|
||||
return TRUE
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/minerpriest/proc/axe_throw(target)
|
||||
ranged_cooldown = world.time + 20
|
||||
visible_message("<span class='boldwarning'>[src] prepares to throw his axe!</span>")
|
||||
var/turf/targetturf = get_turf(target)
|
||||
playsound(src,'sound/weapons/fwoosh.wav', 200, 1)
|
||||
Shoot(targetturf)
|
||||
new /obj/item/melee/diamondaxe/priest(targetturf)
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/minerpriest/drop_loot()
|
||||
var/mob/living/carbon/human/H = new /mob/living/carbon/human(src.loc)
|
||||
if(src.client)
|
||||
H.client = src.client
|
||||
to_chat(H, "<span class='userdanger'>You have been finally enlightened. Serving the necropolis is not your duty anymore, thanks to whoever defeated you. You owe them a great debt.</span")
|
||||
to_chat(H, "<span class='big bold'>Note that you now share the loyalties of the one who defeated you. You are expected not to intentionally sabotage their faction unless commanded to!</span>")
|
||||
else
|
||||
H.adjustBruteLoss(200)
|
||||
H.equipOutfit(/datum/outfit/job/miner/equipped/priest)
|
||||
|
||||
// priest helpers
|
||||
/datum/outfit/job/miner/equipped/priest
|
||||
name = "Shaft Miner (Necropolis Priest)"
|
||||
shoes = /obj/item/clothing/shoes/bronze
|
||||
mask = /obj/item/clothing/mask/gas
|
||||
backpack_contents = list(
|
||||
/obj/item/flashlight/seclite=1,\
|
||||
/obj/item/kitchen/knife/combat/survival=1,
|
||||
/obj/item/mining_voucher=1,
|
||||
/obj/item/t_scanner/adv_mining_scanner/lesser=1,
|
||||
/obj/item/gun/energy/kinetic_accelerator=1,\
|
||||
/obj/item/stack/marker_beacon/ten=1,
|
||||
/obj/item/melee/diamondaxe = 1,
|
||||
/obj/item/clothing/head/bronze = 1,
|
||||
/obj/item/clothing/suit/bronze = 1)
|
||||
|
||||
/obj/effect/temp_visual/dragon_swoop/priest
|
||||
duration = 5
|
||||
color = rgb(255,0,0)
|
||||
|
||||
/obj/effect/temp_visual/dragon_swoop/priest/Initialize()
|
||||
. = ..()
|
||||
transform *= 0.33
|
||||
|
||||
/obj/item/projectile/kinetic/axe
|
||||
name = "kinetic axe"
|
||||
damage = 20
|
||||
damage_type = BRUTE
|
||||
color = "#00FFFF"
|
||||
|
||||
/obj/item/projectile/kinetic/axe/prehit(atom/target)
|
||||
return
|
||||
|
||||
//loot
|
||||
|
||||
/obj/item/melee/diamondaxe
|
||||
name = "Priest's Axe"
|
||||
desc = "Used to be a diamond pickaxe, now there's no pick, just axe."
|
||||
icon = 'sandcode/icons/obj/lavaland/artefacts.dmi'
|
||||
icon_state = "diamondaxe"
|
||||
lefthand_file = 'sandcode/icons/mob/inhands/weapons/axes_lefthand.dmi'
|
||||
righthand_file = 'sandcode/icons/mob/inhands/weapons/axes_righthand.dmi'
|
||||
item_state = "diamondaxe"
|
||||
attack_verb = list("slashed", "sliced", "torn", "ripped", "diced", "cut")
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
force = 20
|
||||
throwforce = 18
|
||||
embedding = list("embedded_pain_multiplier" = 3, "embed_chance" = 90, "embedded_fall_chance" = 50)
|
||||
armour_penetration = 50
|
||||
block_chance = 25
|
||||
sharpness = IS_SHARP
|
||||
hitsound = 'sound/weapons/slash.ogg'
|
||||
|
||||
/obj/item/melee/diamondaxe/Initialize()
|
||||
. = ..()
|
||||
AddComponent(/datum/component/butchering, 50, 100, null, null, TRUE)
|
||||
|
||||
/obj/item/melee/diamondaxe/priest
|
||||
|
||||
/obj/item/melee/diamondaxe/priest/Initialize()
|
||||
..()
|
||||
QDEL_IN(src, 30)
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/broodmother
|
||||
glorymessageshand = list("punches through the broodmother's womb, ripping out a little goliath which is promptly shoved on their mouth!", "rips off the broodmother's tentacles by hand, then knees their head until it caves in!")
|
||||
glorymessagescrusher = list("rams the broodmother's torso the hilt of their crusher, which they promptly lift up and let gravity impale the broodmother!")
|
||||
glorymessagespka = list("shoots the broodmother's face, exploding it!")
|
||||
glorymessagespkabayonet = list("stabs the broodmother's eye and gouges it out, shoving it into their maw, making them eat it!")
|
||||
@@ -0,0 +1,5 @@
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/herald
|
||||
glorymessageshand = list("grabs the herald by it's legs and smashes it repeatedly on the ground, bits and pieces of flesh flying off until it dies!")
|
||||
glorymessagescrusher = list("chops the herald's 'ear' with the crusher, then shoves the hilt of it so hard down their throat that it goes through their whole body and they fucking die!")
|
||||
glorymessagespka = list("parries a bolt of the herald with a PKA blast, which comes flying back onto them and slashes off their head!")
|
||||
glorymessagespkabayonet = list("stabs the herald repeatedly in the torso, then into their skull for good measure!")
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/legionnaire
|
||||
glorymessageshand = list("grabs the legionnaire's skull and rips it off, bashing them with it until they break apart and die!")
|
||||
glorymessagescrusher = list("chops off both of the legionnaire's legs with the crusher in one single move, then stabs through their angry flying head with the hilt of it!")
|
||||
glorymessagespka = list("shoots the legionnaire's skull which fucking explodes, and then shoots the ribcage of the angry body which also explodes!")
|
||||
glorymessagespkabayonet = list("stabs through the legionnaire's skull with the bayonet, which they promptly bash the rest of the body into dust with!")
|
||||
@@ -0,0 +1,6 @@
|
||||
/mob/living/simple_animal/hostile/asteroid/elite/pandora
|
||||
glorymessageshand = list("grabs the pandora and closes it for good!")
|
||||
glorymessagescrusher = list("chops the pandora by their neck, the head flying off!")
|
||||
glorymessagespka = list("shoots the pandora's head until it closes for good!")
|
||||
glorymessagespkabayonet = list("stabs through the pandora repeatedly, until it closes itself!")
|
||||
//at this point i'm legitimately tired i dont care aaaaaaaaaaa
|
||||
@@ -0,0 +1,5 @@
|
||||
/mob/living/simple_animal/hostile/asteroid/goldgrub
|
||||
glorymessageshand = list("rips out the goldgrub's eyes, and sticks them into his mouth hole!", "violently opens the goldgrub's mouth open, then sticks one hand inside and rips out their ore-filled stomach!")
|
||||
glorymessagespka = list("bashes the shit out of the golgrub with their PKA, gushing green blood everywhere!", "sticks their pka into the goldgrub's mouth and shoots, exploding it and showering everything in ore and gore!")
|
||||
glorymessagespkabayonet = list("grabs the goldgrub with one hand and slices their stomach with the pka's bayonet, spilling ore and guts everywhere!", "climbs on the goldgrub, and repeatedly stabs it's head with the bayonet, spilling green blood on the ground, until it stops moving!")
|
||||
glorymessagescrusher = list("chops the goldgrub's head off with their crusher!", "chops the goldgrub repeatedly with their crusher, until all that is left is a bunch of golden and green pieces of meat, as well as some ore.")
|
||||
@@ -0,0 +1,5 @@
|
||||
/mob/living/simple_animal/hostile/asteroid/goliath
|
||||
glorymessageshand = list("punches violently into the goliath's skull, ripping out what could be described as their brain!", "rips off one of the goliath's tentacles bare-handed, then whips them with it until they die in humiliation!", "stomps their boot hard down on the goliath's jaw, ripping one of its fangs off with their hand and stabbing it in the eye")
|
||||
glorymessagespka = list("climbs on top of the goliath, then shoots their skull open in a violent blast with their pka!")
|
||||
glorymessagespkabayonet = list("stabs the goliath's eyes out with their bayonet, then sticks them into the beast's mouth!", "slices off many of the tentacles of the goliath with their bayonet, until it finally gives out!")
|
||||
glorymessagescrusher = list("crushers the face of the goliath in one swift move with their crusher!")
|
||||
@@ -0,0 +1,8 @@
|
||||
/mob/living/simple_animal/hostile/asteroid/hivelord/legion
|
||||
glorymessageshand = list("rips out skulls from the legion, one by one, until it's mangled carcass finally disappears!", "punches the shit out of the legion, making it scream until it finally gives out!", "punches their hand inside the gut of the legion, ripping off his regenerative core!")
|
||||
glorymessagespka = list("grabs the legion by it's arm with one hand, then shoots their gut repeatedly with their PKA!", "bashes the legion's skulls hard with their pka, until they crack and go inside their cursed host!")
|
||||
glorymessagespkabayonet = list("stabs the legion's gut and pulls out their regenerative core!", "repeatedly stabs the legion in their \"head\" with the PKA's bayonet!", "rams the bayonet of their Kinetic Accelerator up the Legion's chin, lifting it up and then firing it, blowing its head off!")
|
||||
glorymessagescrusher = list("chops the legion's hip like it's timber, until it finally gives out!", "kicks the legion onto the ground, then chops their face apart with their crusher!")
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/hivelordbrood //just to be sure
|
||||
gloryhealth = 0
|
||||
@@ -0,0 +1,81 @@
|
||||
//A speedy, annoying and scaredy demon
|
||||
/mob/living/simple_animal/hostile/asteroid/imp
|
||||
name = "lava imp"
|
||||
desc = "Lowest on the hierarchy of slaughter demons, this one is still nothing to sneer at."
|
||||
icon = 'sandcode/icons/mob/lavaland/lavaland_monsters.dmi'
|
||||
icon_state = "imp"
|
||||
icon_living = "imp"
|
||||
icon_aggro = "imp"
|
||||
icon_dead = "imp_dead"
|
||||
icon_gib = "syndicate_gib"
|
||||
mob_biotypes = MOB_ORGANIC|MOB_BEAST
|
||||
move_to_delay = 4
|
||||
projectiletype = /obj/item/projectile/magic/impfireball
|
||||
projectilesound = 'sandcode/sound/misc/impranged.wav'
|
||||
ranged = 1
|
||||
ranged_message = "shoots a fireball"
|
||||
ranged_cooldown_time = 70
|
||||
throw_message = "does nothing against the hardened skin of"
|
||||
vision_range = 5
|
||||
speed = 1
|
||||
maxHealth = 150
|
||||
health = 150
|
||||
harm_intent_damage = 15
|
||||
obj_damage = 60
|
||||
melee_damage_lower = 15
|
||||
melee_damage_upper = 15
|
||||
attack_verb_continuous = "claws"
|
||||
attack_verb_simple = "claw"
|
||||
a_intent = INTENT_HARM
|
||||
speak_emote = list("groans")
|
||||
attack_sound = 'sandcode/sound/misc/impattacks.wav'
|
||||
aggro_vision_range = 15
|
||||
retreat_distance = 5
|
||||
gold_core_spawnable = HOSTILE_SPAWN
|
||||
crusher_loot = /obj/item/crusher_trophy/blaster_tubes/impskull
|
||||
loot = list()
|
||||
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab = 2, /obj/item/stack/sheet/bone = 4)
|
||||
robust_searching = FALSE
|
||||
death_sound = 'sandcode/sound/misc/impdies.wav'
|
||||
glorymessageshand = list("grabs the imp's eyes and rips them out, shoving the bloody imp aside!", "grabs and crushes the imp's skull apart with their bare hands!", "rips the imp's head clean off with their bare hands!")
|
||||
glorymessagespka = list("sticks their PKA into the imp's mouth and shoots it, showering everything in gore!", "bashes the imp's head into their chest with their PKA!", "shoots off both legs of the imp with their PKA!")
|
||||
glorymessagespkabayonet = list("slices the imp's head off by the neck with the PKA's bayonet!", "repeatedly stabs the imp in their gut with the PKA's bayonet!")
|
||||
glorymessagescrusher = list("chops the imp horizontally in half with their crusher in one swift move!", "chops off the imp's legs with their crusher and kicks their face hard, exploding it while they're in the air!", "slashes each of the imp's arms off by the shoulder with their crusher!")
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/imp/attacked_by(obj/item/I, mob/living/user)
|
||||
. = ..()
|
||||
playsound(src, 'sandcode/sound/misc/impinjured.wav', rand(25,100), -1) //HURT ME PLENTY
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/imp/bullet_act(obj/item/projectile/P)
|
||||
. = ..()
|
||||
playsound(src, 'sandcode/sound/misc/impinjured.wav', rand(25,100), -1)
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/imp/Aggro()
|
||||
. = ..()
|
||||
playsound(src, pick('sandcode/sound/misc/impsight.wav', 'sandcode/sound/misc/impsight2.wav'), rand(50,75), -1)
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/imp/LoseAggro()
|
||||
. = ..()
|
||||
playsound(src, pick('sandcode/sound/misc/impnearby.wav', 'sandcode/sound/misc/impnearby.wav'), rand(25, 60), -1)
|
||||
|
||||
/obj/item/projectile/magic/impfireball //bobyot y u no use child of fireball
|
||||
name = "demonic fireball" //because it fucking explodes and deals brute damage even when values are set to -1
|
||||
icon_state = "fireball"
|
||||
damage = 10
|
||||
damage_type = BURN
|
||||
nodamage = 0
|
||||
armour_penetration = 20
|
||||
var/firestacks = 5
|
||||
|
||||
/obj/item/projectile/magic/impfireball/on_hit(target)
|
||||
. = ..()
|
||||
if(iscarbon(target))
|
||||
var/mob/living/carbon/C = target
|
||||
C.adjust_fire_stacks(firestacks)
|
||||
C.IgniteMob()
|
||||
if(C.stat != DEAD && C.stat != UNCONSCIOUS)
|
||||
playsound(C, 'sandcode/sound/misc/doominjured.wav', 100, -1)
|
||||
else if(C.stat == DEAD)
|
||||
playsound(C, 'sandcode/sound/misc/doomdies.wav', 100, -1)
|
||||
else
|
||||
playsound(C, pick('sandcode/sound/misc/doomscream.wav', 'sandcode/sound/misc/doomscream2.wav'), 100, -1)
|
||||
@@ -0,0 +1,68 @@
|
||||
/mob/living/simple_animal/hostile/asteroid
|
||||
var/glorykill = FALSE //CAN THIS MOTHERFUCKER BE SNAPPED IN HALF FOR HEALTH?
|
||||
var/list/glorymessageshand = list() //WHAT THE FUCK ARE THE MESSAGES SAID BY THIS FUCK WHEN HE'S GLORY KILLED WITH AN EMPTY HAND?
|
||||
var/list/glorymessagescrusher = list() //SAME AS ABOVE BUT CRUSHER
|
||||
var/list/glorymessagespka = list() //SAME AS ABOVE THE ABOVE BUT PKA
|
||||
var/list/glorymessagespkabayonet = list() //SAME AS ABOVE BUT WITH A HONKING KNIFE ON THE FUCKING THING
|
||||
var/gloryhealth = 7.5
|
||||
var/glorymodifier = 1.5
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/Life()
|
||||
..()
|
||||
if(health <= (maxHealth/10 * glorymodifier) && !glorykill && stat != DEAD)
|
||||
glorykill = TRUE
|
||||
glory()
|
||||
else if(health > (maxHealth/10 * glorymodifier) && glorykill && stat != DEAD)
|
||||
glorykill = FALSE
|
||||
unglory()
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/proc/glory()
|
||||
desc += "<br><b>[src] is staggered and can be glory killed!</b>"
|
||||
animate(src, color = "#00FFFF", time = 5)
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/proc/unglory()
|
||||
desc = initial(desc)
|
||||
animate(src, color = initial(color), time = 5)
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/death(gibbed)
|
||||
animate(src, color = initial(color), time = 3)
|
||||
desc = initial(desc)
|
||||
SSblackbox.record_feedback("tally", "mobs_killed_mining", 1, type)
|
||||
var/datum/status_effect/crusher_damage/C = has_status_effect(STATUS_EFFECT_CRUSHERDAMAGETRACKING)
|
||||
if(C && crusher_loot && prob((C.total_damage/maxHealth) * crusher_drop_mod)) //on average, you'll need to kill 4 creatures before getting the item
|
||||
spawn_crusher_loot()
|
||||
..(gibbed)
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/AltClick(mob/living/carbon/slayer)
|
||||
if(glorykill)
|
||||
if(ranged)
|
||||
if(ranged_cooldown >= world.time)
|
||||
ranged_cooldown += 10
|
||||
else
|
||||
ranged_cooldown = 10 + world.time
|
||||
if(glorykill)
|
||||
if(do_after(slayer, 10, needhand = TRUE, target = src, progress = FALSE) && (stat != DEAD))
|
||||
var/message
|
||||
if(!slayer.get_active_held_item() || (!istype(slayer.get_active_held_item(), /obj/item/kinetic_crusher) && !istype(slayer.get_active_held_item(), /obj/item/gun/energy/kinetic_accelerator)))
|
||||
message = pick(glorymessageshand)
|
||||
else if(istype(slayer.get_active_held_item(), /obj/item/kinetic_crusher))
|
||||
message = pick(glorymessagescrusher)
|
||||
else if(istype(slayer.get_active_held_item(), /obj/item/gun/energy/kinetic_accelerator))
|
||||
message = pick(glorymessagespka)
|
||||
var/obj/item/gun/energy/kinetic_accelerator/KA = get_active_held_item()
|
||||
if(KA && KA.bayonet)
|
||||
message = pick(glorymessagespka | glorymessagespkabayonet)
|
||||
if(message)
|
||||
visible_message("<span class='danger'><b>[slayer] [message]</b></span>")
|
||||
else
|
||||
visible_message("<span class='danger'><b>[slayer] does something generally considered brutal to [src]... Whatever that may be!</b></span>")
|
||||
slayer.heal_overall_damage(gloryhealth,gloryhealth)
|
||||
playsound(src.loc, death_sound, 150, TRUE, -1)
|
||||
crusher_drop_mod *= 2
|
||||
adjustHealth(maxHealth, TRUE, TRUE)
|
||||
if(mob_biotypes & MOB_ORGANIC)
|
||||
new /obj/effect/gibspawner/generic(src.loc)
|
||||
else if(mob_biotypes & MOB_ROBOTIC)
|
||||
new /obj/effect/gibspawner/robot(src.loc)
|
||||
else
|
||||
to_chat(slayer, "<span class='danger'>You fail to glory kill [src]!</span>")
|
||||
@@ -0,0 +1,47 @@
|
||||
//A slow, melee, crazy miner.
|
||||
/mob/living/simple_animal/hostile/asteroid/miner
|
||||
name = "shambling miner"
|
||||
desc = "Consumed by the ash storm, this shell of a human being only seeks to harm those he once called coworkers."
|
||||
icon = 'sandcode/icons/mob/lavaland/lavaland_monsters.dmi'
|
||||
icon_state = "miner"
|
||||
icon_living = "miner"
|
||||
icon_aggro = "miner"
|
||||
icon_dead = "miner_dead"
|
||||
icon_gib = "syndicate_gib"
|
||||
mob_biotypes = MOB_ORGANIC|MOB_BEAST
|
||||
mouse_opacity = MOUSE_OPACITY_OPAQUE
|
||||
ranged = 0
|
||||
friendly_verb_continuous = "hugs"
|
||||
friendly_verb_simple = "hug"
|
||||
speak_emote = list("moans")
|
||||
speed = 1
|
||||
move_to_delay = 3
|
||||
maxHealth = 200
|
||||
health = 200
|
||||
obj_damage = 100
|
||||
melee_damage_lower = 20
|
||||
melee_damage_upper = 20
|
||||
attack_verb_continuous = "smashes"
|
||||
attack_verb_simple = "smash"
|
||||
attack_sound = 'sound/weapons/bladeslice.ogg'
|
||||
throw_message = "barely affects the"
|
||||
vision_range = 3
|
||||
aggro_vision_range = 7
|
||||
move_force = MOVE_FORCE_VERY_STRONG
|
||||
move_resist = MOVE_FORCE_VERY_STRONG
|
||||
pull_force = MOVE_FORCE_VERY_STRONG
|
||||
loot = list()
|
||||
crusher_loot = /obj/item/crusher_trophy/blaster_tubes/mask
|
||||
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/human = 2, /obj/item/stack/sheet/animalhide/human = 1, /obj/item/stack/sheet/bone = 1)
|
||||
robust_searching = FALSE
|
||||
footstep_type = FOOTSTEP_MOB_SHOE
|
||||
minimum_distance = 1
|
||||
glorymessageshand = list("grabs the miner's eyes and rips them out, shoving the bloody miner aside!", "grabs and crushes the miner's skull apart with their bare hands!", "rips the miner's head clean off with their bare hands!")
|
||||
glorymessagespka = list("sticks their PKA into the miner's mouth and shoots it, showering everything in gore!", "bashes the miner's head into their chest with their PKA!", "shoots off both legs of the miner with their PKA!")
|
||||
glorymessagespkabayonet = list("slices the imp's head off by the neck with the PKA's bayonet!", "repeatedly stabs the miner in their gut with the PKA's bayonet!")
|
||||
glorymessagescrusher = list("chops the miner horizontally in half with their crusher in one swift move!", "chops off the miner's legs with their crusher and kicks their face hard, exploding it while they're in the air!", "slashes each of the miner's arms off by the shoulder with their crusher!")
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/miner/death(gibbed)
|
||||
. = ..()
|
||||
if(prob(15))
|
||||
new /obj/item/kinetic_crusher(src.loc)
|
||||
Reference in New Issue
Block a user