mirror of
https://github.com/yogstation13/Yogstation.git
synced 2025-02-26 09:04:50 +00:00
Makes Jungleland Good (#22669)
* makes jungleland good * cooldown fix * tar king stuff
This commit is contained in:
@@ -108,6 +108,7 @@
|
||||
#define COLOR_VIOLET "#B900F7"
|
||||
#define COLOR_STRONG_VIOLET "#6927C5"
|
||||
#define COLOR_DARK_PURPLE "#551A8B"
|
||||
#define COLOR_TAR_PURPLE "#553F8A"
|
||||
|
||||
#define COLOR_ORANGE "#FF9900"
|
||||
#define COLOR_IRISH_ORANGE "#FF883E"
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#define NUM_E 2.71828183
|
||||
|
||||
#define PI 3.1416
|
||||
#define SQRT_2 1.414214
|
||||
#define INFINITY 1e31 //closer then enough
|
||||
|
||||
#define SHORT_REAL_LIMIT 16777216
|
||||
|
||||
@@ -79,6 +79,7 @@
|
||||
#define SPAN_CULTLARGE "cultlarge"
|
||||
#define SPAN_HELIUM "small"
|
||||
#define SPAN_PROGENITOR "progenitor"
|
||||
#define SPAN_COLOSSUS "colossus"
|
||||
|
||||
//bitflag #defines for return value of the radio() proc.
|
||||
#define ITALICS (1<<0)
|
||||
|
||||
@@ -18,15 +18,17 @@
|
||||
//cycles colors
|
||||
var/last_colour = 0
|
||||
var/color_cycle = FALSE
|
||||
var/fade_color
|
||||
var/list/hsv
|
||||
|
||||
/datum/component/after_image/Initialize(duration = 15, rest_time = 1, color_cycle = FALSE)
|
||||
/datum/component/after_image/Initialize(duration = 15, rest_time = 1, color_cycle = FALSE, fade_color)
|
||||
if(!ismovable(parent))
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
owner = parent
|
||||
src.rest_time = rest_time
|
||||
src.duration = duration
|
||||
src.color_cycle = color_cycle
|
||||
src.fade_color = fade_color
|
||||
last_colour = world.time
|
||||
|
||||
/datum/component/after_image/RegisterWithParent()
|
||||
@@ -75,7 +77,10 @@
|
||||
F.pixel_x = (traveled * x_modifier) + owner.pixel_x
|
||||
F.pixel_y = (traveled * y_modifier) + owner.pixel_y
|
||||
|
||||
//give them a random colours
|
||||
//give them colors
|
||||
if(fade_color)
|
||||
F.color = fade_color
|
||||
return
|
||||
if(!color_cycle)
|
||||
return
|
||||
if(!hsv)
|
||||
|
||||
@@ -32,9 +32,12 @@
|
||||
|
||||
/obj/item/grenade/plastic/Destroy()
|
||||
qdel(nadeassembly)
|
||||
if(target)
|
||||
UnregisterSignal(target, COMSIG_ATOM_UPDATE_OVERLAYS)
|
||||
target.update_appearance()
|
||||
target = null
|
||||
nadeassembly = null
|
||||
target = null
|
||||
..()
|
||||
return ..()
|
||||
|
||||
/obj/item/grenade/plastic/attackby(obj/item/I, mob/user, params)
|
||||
if(!nadeassembly && istype(I, /obj/item/assembly_holder))
|
||||
@@ -55,7 +58,7 @@
|
||||
nadeassembly = null
|
||||
update_appearance(UPDATE_ICON)
|
||||
return
|
||||
..()
|
||||
return ..()
|
||||
|
||||
/obj/item/grenade/plastic/prime()
|
||||
var/turf/location
|
||||
@@ -136,13 +139,17 @@
|
||||
I.throw_range = max(1, (I.throw_range - 3))
|
||||
I.embedding = I.embedding.setRating(embed_chance = 0)
|
||||
|
||||
target.add_overlay(plastic_overlay, TRUE)
|
||||
RegisterSignal(target, COMSIG_ATOM_UPDATE_OVERLAYS, PROC_REF(update_attached_overlays))
|
||||
target.update_appearance(UPDATE_OVERLAYS)
|
||||
if(!nadeassembly)
|
||||
to_chat(user, span_notice("You plant the bomb. Timer counting down from [det_time]."))
|
||||
addtimer(CALLBACK(src, PROC_REF(prime)), det_time*10)
|
||||
else
|
||||
qdel(src) //How?
|
||||
|
||||
/obj/item/grenade/plastic/proc/update_attached_overlays(atom/source, list/overlay_list)
|
||||
overlay_list += plastic_overlay
|
||||
|
||||
/obj/item/grenade/plastic/proc/shout_syndicate_crap(mob/M)
|
||||
if(!M)
|
||||
return
|
||||
@@ -194,6 +201,9 @@
|
||||
|
||||
/obj/item/grenade/plastic/c4/Destroy()
|
||||
qdel(wires)
|
||||
if(target)
|
||||
UnregisterSignal(target, COMSIG_ATOM_UPDATE_OVERLAYS)
|
||||
target.update_appearance(UPDATE_OVERLAYS)
|
||||
wires = null
|
||||
target = null
|
||||
return ..()
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
M.do_attack_animation(src, ATTACK_EFFECT_DISARM)
|
||||
playsound(src, 'sound/weapons/thudswoosh.ogg', 50, TRUE, -1)
|
||||
var/shove_dir = get_dir(M, src)
|
||||
if(!Move(get_step(src, shove_dir), shove_dir))
|
||||
if(move_resist > M.move_force || !Move(get_step(src, shove_dir), shove_dir))
|
||||
log_combat(M, src, "shoved", "failing to move it")
|
||||
M.visible_message(span_danger("[M.name] shoves [src]!"),
|
||||
span_danger("You shove [src]!"), span_hear("You hear aggressive shuffling!"), COMBAT_MESSAGE_RANGE, list(src))
|
||||
|
||||
@@ -325,6 +325,7 @@
|
||||
approaching_target = TRUE
|
||||
else
|
||||
approaching_target = FALSE
|
||||
set_glide_size(DELAY_TO_GLIDE_SIZE(delay))
|
||||
walk_to(src, target, minimum_distance, delay)
|
||||
|
||||
/mob/living/simple_animal/hostile/adjustHealth(amount, updating_health = TRUE, forced = FALSE)
|
||||
|
||||
@@ -87,7 +87,7 @@
|
||||
update_config_movespeed()
|
||||
update_movespeed(TRUE)
|
||||
|
||||
/mob/New()
|
||||
/mob/New(loc, ...)
|
||||
// This needs to happen IMMEDIATELY. I'm sorry :(
|
||||
GenerateTag()
|
||||
return ..()
|
||||
|
||||
@@ -155,7 +155,7 @@
|
||||
|
||||
var/diagonal = (direct & (direct - 1)) && mob.loc == n
|
||||
if(diagonal) //moved diagonally successfully
|
||||
add_delay *= 1.414214 // sqrt(2)
|
||||
add_delay *= SQRT_2 // sqrt(2)
|
||||
mob.set_glide_size(DELAY_TO_GLIDE_SIZE(add_delay))
|
||||
move_delay += add_delay
|
||||
if(.) // If mob is null here, we deserve the runtime
|
||||
|
||||
@@ -81,7 +81,7 @@
|
||||
L.forceMove(T)
|
||||
finalize_move(L, T)
|
||||
if(direction & (direction - 1)) //extra delay for diagonals
|
||||
add_delay *= 1.414214 // sqrt(2)
|
||||
add_delay *= SQRT_2 // sqrt(2)
|
||||
L.set_glide_size(DELAY_TO_GLIDE_SIZE(add_delay))
|
||||
move_delay += add_delay
|
||||
return TRUE
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
melee_damage_upper = 25
|
||||
ranged = TRUE
|
||||
ranged_cooldown = 5 SECONDS
|
||||
projectiletype = /obj/projectile/jungle/meduracha_spit
|
||||
projectiletype = /obj/projectile/reagent/meduracha_spit
|
||||
|
||||
var/list/anchors = list("SOUTH" = null, "NORTH" = null, "EAST" = null, "WEST" = null)
|
||||
|
||||
@@ -155,7 +155,7 @@
|
||||
melee_damage_upper = 0
|
||||
minimum_distance = 5
|
||||
ranged = TRUE
|
||||
ranged_cooldown = 20 SECONDS
|
||||
ranged_cooldown_time = 20 SECONDS
|
||||
move_to_delay = 10
|
||||
pixel_x = -32
|
||||
projectiletype = /obj/projectile/jungle/damage_orb
|
||||
@@ -168,7 +168,7 @@
|
||||
/mob/living/simple_animal/hostile/asteroid/yog_jungle/emeraldspider = 2,
|
||||
/mob/living/simple_animal/hostile/asteroid/yog_jungle/blobby = 2,
|
||||
/mob/living/simple_animal/hostile/asteroid/wasp/mosquito = 2
|
||||
)
|
||||
)
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/yog_jungle/alpha/alpha_dryad/Shoot(atom/targeted_atom)
|
||||
playsound(src, 'sound/magic/clockwork/narsie_attack.ogg', 80, 1)
|
||||
@@ -195,7 +195,7 @@
|
||||
max_spawn = 2
|
||||
spawnables = list(
|
||||
/mob/living/simple_animal/hostile/asteroid/yog_jungle/corrupted_dryad = 20
|
||||
)
|
||||
)
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/yog_jungle/alpha/alpha_dryad/corrupted/finish_shoot(atom/targeted_atom)
|
||||
. = ..()
|
||||
|
||||
@@ -537,6 +537,15 @@
|
||||
var/old_stage = 1
|
||||
var/alert_type = /atom/movable/screen/alert/status_effect/toxic_buildup
|
||||
|
||||
/datum/reagent/toxic_metabolites/reaction_mob(mob/living/exposed_mob, methods, reac_volume, show_message, permeability)
|
||||
if(isliving(exposed_mob) && exposed_mob.reagents)
|
||||
var/modifier = (100 - exposed_mob.getarmor(null, BIO)) / 100
|
||||
var/amount = round(max(reac_volume - exposed_mob.reagents.get_reagent_amount(type), 0) * modifier, 0.1) // no reagent duplication on mobs
|
||||
if(amount >= 0.5)
|
||||
exposed_mob.reagents.add_reagent(type, amount)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
// consumes 2 every 2 seconds
|
||||
/datum/reagent/toxic_metabolites/on_mob_life(mob/living/carbon/M)
|
||||
. = ..()
|
||||
|
||||
@@ -454,7 +454,7 @@
|
||||
icon = 'yogstation/icons/obj/jungle.dmi'
|
||||
|
||||
/obj/item/crusher_trophy/jungleland/aspect_of_tar
|
||||
name = "Aspect of tar"
|
||||
name = "aspect of tar"
|
||||
desc = "It pulsates with a corroding, everpresent energy."
|
||||
icon_state = "aspect_of_tar"
|
||||
denied_type = /obj/item/crusher_trophy/jungleland/aspect_of_tar
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
response_harm = "hits"
|
||||
maxHealth = 60
|
||||
health = 60
|
||||
speed = 2
|
||||
spacewalk = TRUE
|
||||
ranged = TRUE
|
||||
loot = list(/obj/item/organ/regenerative_core/dryad)
|
||||
@@ -64,6 +65,7 @@
|
||||
response_harm = "hits"
|
||||
maxHealth = 120
|
||||
health = 120
|
||||
speed = 2
|
||||
spacewalk = TRUE
|
||||
ranged = TRUE
|
||||
loot = list (/obj/item/organ/regenerative_core/dryad/corrupted)
|
||||
@@ -92,6 +94,7 @@
|
||||
response_harm = "hits"
|
||||
maxHealth = 100
|
||||
health = 100
|
||||
speed = 2
|
||||
spacewalk = TRUE
|
||||
|
||||
melee_damage_lower = 7.5
|
||||
@@ -165,6 +168,7 @@
|
||||
response_harm = "hits"
|
||||
maxHealth = 285
|
||||
health = 285
|
||||
speed = 2
|
||||
spacewalk = TRUE
|
||||
melee_damage_lower = 30
|
||||
melee_damage_upper = 30
|
||||
@@ -190,7 +194,7 @@
|
||||
/mob/living/simple_animal/hostile/asteroid/yog_jungle/skin_twister/Life()
|
||||
. = ..()
|
||||
if(!.) //dead
|
||||
return
|
||||
return
|
||||
|
||||
if(human_lure && prob(5))
|
||||
lure()
|
||||
@@ -245,7 +249,7 @@
|
||||
"[initial(picked.name)] nearly killed me, but I'm gonna bleed out", "Damned fauna", "Why fucking again?", "I have so many mats",
|
||||
"This is fucking insane", "I cannot believe this is happening to me", "Out of meds, out of supplies, out of fucking everything", "I'm running out of air",
|
||||
"HELP", "MINING", "MINING BASE",
|
||||
"If someone finds my body take the loot [pick("mango", "alpha", "delta", "beta", "omega" , "olive", "tango", "fiesta", "carp")] [rand(0,9)][rand(0,9)][rand(0,9)]", "HELP [pick(generate_code_phrase(TRUE))]"))
|
||||
"If someone finds my body take the loot [pick(GLOB.phonetic_alphabet)] [rand(0,9)][rand(0,9)][rand(0,9)]", "HELP [pick(generate_code_phrase(TRUE))]"))
|
||||
|
||||
/mob/living/simple_animal/hostile/asteroid/yog_jungle/skin_twister/proc/lure()
|
||||
if(!human_lure)
|
||||
@@ -294,6 +298,7 @@
|
||||
response_harm = "hits"
|
||||
maxHealth = 120
|
||||
health = 120
|
||||
speed = 1 // size (1-3) is added on top of this during initialize()
|
||||
spacewalk = TRUE
|
||||
loot = list(/obj/item/stack/sheet/slime)
|
||||
melee_damage_lower = 5
|
||||
@@ -307,6 +312,7 @@
|
||||
/mob/living/simple_animal/hostile/asteroid/yog_jungle/blobby/Initialize(mapload,spawned_size = 3)
|
||||
. = ..()
|
||||
current_size = clamp(spawned_size, 1, current_size)
|
||||
speed += current_size
|
||||
melee_damage_lower = melee_damage_lower * current_size
|
||||
melee_damage_upper = melee_damage_upper * current_size
|
||||
var/matrix/M = new
|
||||
@@ -362,6 +368,7 @@
|
||||
ranged_cooldown_time = 3 SECONDS //dashes faster
|
||||
|
||||
butcher_results = list(/obj/item/stinger = 1,/obj/item/stack/sheet/animalhide/weaver_chitin = 1, /obj/item/stack/sheet/sinew = 2)
|
||||
speed = 2
|
||||
spacewalk = TRUE
|
||||
alpha_type = /mob/living/simple_animal/hostile/asteroid/yog_jungle/alpha/alpha_yellowjacket/mosquito
|
||||
poison_per_attack = 0
|
||||
@@ -436,7 +443,7 @@
|
||||
desc = "A silky bundle of web that can entangle legs."
|
||||
icon = 'yogstation/icons/obj/jungle.dmi'
|
||||
armed = TRUE
|
||||
breakouttime = 30 //3 seconds. Long enough you'd rather not get hit, but not debilitating.
|
||||
breakouttime = 3 SECONDS //Long enough you'd rather not get hit, but not debilitating.
|
||||
item_flags = DROPDEL
|
||||
flags_1 = NONE
|
||||
trap_damage = 0
|
||||
@@ -488,6 +495,7 @@
|
||||
vision_range = 6
|
||||
minbodytemp = 0
|
||||
maxbodytemp = INFINITY
|
||||
speed = 3
|
||||
pressure_resistance = 100
|
||||
mob_size = MOB_SIZE_LARGE
|
||||
del_on_death = TRUE
|
||||
@@ -521,6 +529,18 @@
|
||||
maxHealth = 150
|
||||
melee_damage_lower = 15
|
||||
melee_damage_upper = 20
|
||||
var/mob/living/converted
|
||||
|
||||
/mob/living/simple_animal/hostile/tar/amalgamation/convert/New(loc, mob/living/new_convert, ...)
|
||||
if(new_convert)
|
||||
converted = new_convert
|
||||
new_convert.forceMove(src)
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/tar/amalgamation/convert/Destroy()
|
||||
if(converted)
|
||||
converted.forceMove(loc)
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/tar/dryad
|
||||
name = "Tar Dryad"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/obj/projectile/jungle
|
||||
icon = 'yogstation/icons/obj/jungle.dmi'
|
||||
speed = 3
|
||||
|
||||
/obj/projectile/jungle/heal_orb
|
||||
name = "Orb of healing"
|
||||
@@ -18,18 +19,8 @@
|
||||
return BULLET_ACT_FORCE_PIERCE
|
||||
return ..()
|
||||
|
||||
/obj/projectile/jungle/meduracha_spit
|
||||
/obj/projectile/reagent/meduracha_spit
|
||||
name = "Glob of toxic goo"
|
||||
icon_state = "meduracha_spit"
|
||||
damage = 20
|
||||
damage_type = TOX
|
||||
armor_flag = BIO
|
||||
|
||||
/obj/projectile/jungle/meduracha_spit/on_hit(atom/target, blocked)
|
||||
. = ..()
|
||||
if(!ishuman(target))
|
||||
return
|
||||
var/mob/living/carbon/human/H = target
|
||||
var/chance = 100 - H.getarmor(null,BIO)
|
||||
if(prob(max(10,chance * 0.75))) // higher chance than toxic water
|
||||
H.reagents.add_reagent(/datum/reagent/toxic_metabolites,15)
|
||||
transfer_methods = TOUCH
|
||||
reagents_list = list(/datum/reagent/toxic_metabolites = 10)
|
||||
|
||||
@@ -45,13 +45,11 @@
|
||||
duration = 80 SECONDS
|
||||
status_type = STATUS_EFFECT_REFRESH
|
||||
alert_type = /atom/movable/screen/alert/status_effect/corrupted_dryad
|
||||
var/health_multiplier = 1.5
|
||||
var/initial_health = 100
|
||||
var/health_bonus = 50
|
||||
|
||||
/datum/status_effect/corrupted_dryad/on_apply()
|
||||
. = ..()
|
||||
initial_health = owner.maxHealth
|
||||
owner.setMaxHealth(initial_health * health_multiplier)
|
||||
owner.setMaxHealth(owner.maxHealth + health_bonus)
|
||||
owner.adjustBruteLoss(-50)
|
||||
owner.adjustFireLoss(-50)
|
||||
owner.remove_CC()
|
||||
@@ -60,11 +58,10 @@
|
||||
SEND_SIGNAL(owner, COMSIG_ADD_MOOD_EVENT, "corruption", /datum/mood_event/corrupted_dryad)
|
||||
|
||||
/datum/status_effect/corrupted_dryad/on_remove()
|
||||
owner.setMaxHealth(initial_health)
|
||||
owner.setMaxHealth(owner.maxHealth - health_bonus)
|
||||
if(iscarbon(owner))
|
||||
var/mob/living/carbon/C = owner
|
||||
C.vomit(10, TRUE, TRUE, 3)
|
||||
owner.adjust_dizzy(30)
|
||||
C.vomit(10, TRUE, FALSE, 3)
|
||||
owner.adjust_jitter(30)
|
||||
REMOVE_TRAIT(owner, TRAIT_IGNOREDAMAGESLOWDOWN, id)
|
||||
SEND_SIGNAL(owner, COMSIG_ADD_MOOD_EVENT, "corruption", /datum/mood_event/corrupted_dryad_bad)
|
||||
|
||||
@@ -180,6 +180,8 @@
|
||||
desc = "A might pillar of ivory, untouched by time and corrosion. There is a large hole on the top, it's missing a key ingredient..."
|
||||
icon = 'yogstation/icons/obj/jungle32x48.dmi'
|
||||
icon_state = "tar_altar"
|
||||
move_resist = INFINITY // tar king kept moving it
|
||||
speech_span = SPAN_COLOSSUS
|
||||
layer = ABOVE_ALL_MOB_LAYER
|
||||
resistance_flags = INDESTRUCTIBLE
|
||||
anchored = TRUE
|
||||
@@ -197,8 +199,8 @@
|
||||
for(var/mob/living/L in range(7,src))
|
||||
shake_camera(L,1 SECONDS, 4)
|
||||
|
||||
animate(src,time = 15 SECONDS, color = "#1f0010")
|
||||
sleep(20 SECONDS)
|
||||
animate(src,time = 10 SECONDS, color = "#1f0010")
|
||||
sleep(12 SECONDS)
|
||||
visible_message(span_colossus("WHO DARES?"))
|
||||
|
||||
for(var/mob/living/L in range(7,src))
|
||||
@@ -245,7 +247,7 @@
|
||||
addtimer(CALLBACK(src,PROC_REF(explode)), delay)
|
||||
|
||||
/obj/structure/herb/explosive_shrooms/proc/explode()
|
||||
dyn_explosion(get_turf(src),4)
|
||||
dyn_explosion(get_turf(src), 2, flame_range = 3) // nuh uh you don't get to destroy firing pins inside PKAs and plasmacutters
|
||||
if(src && !QDELETED(src))
|
||||
qdel(src)
|
||||
|
||||
|
||||
@@ -2,7 +2,14 @@
|
||||
#define IMPALE_ATTACK "implae"
|
||||
#define RUNE_ATTACK "rune"
|
||||
#define TAR_ATTACK "tar"
|
||||
#define TELEPORT_ATTACK "teleport"
|
||||
#define STAGE_TRANSITION "transition"
|
||||
|
||||
#define STAGE_MID 1
|
||||
#define STAGE_END 2
|
||||
#define STAGE_DEAD 3
|
||||
|
||||
#define ENRAGED_TRAIT "enraged"
|
||||
#define ENRAGE_LIMIT 2
|
||||
|
||||
#define DIRECTION_MATRIX list("NORTH" = 0 , "EAST" = 0, "SOUTH" = 0, "WEST" = 0, "NORTHEAST" = 0 , "SOUTHEAST" = 0 , "SOUTHWEST" = 0, "NORTHWEST" = 0)
|
||||
#define ATTACK_MATRIX list(SLASH_ATTACK = DIRECTION_MATRIX, RUNE_ATTACK = DIRECTION_MATRIX, IMPALE_ATTACK = DIRECTION_MATRIX)
|
||||
@@ -14,6 +21,7 @@
|
||||
maxHealth = 2000
|
||||
icon_state = "tar_king"
|
||||
icon_living = "tar_king"
|
||||
icon_dead = "tar_king_chaser"
|
||||
icon = 'yogstation/icons/mob/jungle64x64.dmi'
|
||||
health_doll_icon = "tar_king"
|
||||
mob_biotypes = (MOB_ORGANIC | MOB_HUMANOID)
|
||||
@@ -25,34 +33,38 @@
|
||||
gps_name = "Murky Signal"
|
||||
ranged = TRUE
|
||||
faction = list("tar", "boss")
|
||||
speak_emote = list("roars")
|
||||
speed = 2
|
||||
move_to_delay = 2
|
||||
speak_emote = list("echoes")
|
||||
speed = 3
|
||||
move_to_delay = 3
|
||||
pixel_x = -16
|
||||
pixel_y = -16
|
||||
del_on_death = TRUE
|
||||
deathmessage = "falls to the ground, decaying into a puddle of tar."
|
||||
deathsound = "bodyfall"
|
||||
deathsound = 'sound/hallucinations/far_noise.ogg'
|
||||
do_footstep = TRUE
|
||||
ranged_cooldown_time = 10 SECONDS
|
||||
del_on_death = FALSE
|
||||
ranged_cooldown_time = 4 SECONDS
|
||||
armour_penetration = 40
|
||||
dodge_prob = 0
|
||||
loot = list(/obj/item/clothing/head/yogs/tar_king_crown = 1, /obj/item/gem/tarstone = 1, /obj/item/demon_core = 1)
|
||||
crusher_loot = list(/obj/item/crusher_trophy/jungleland/aspect_of_tar = 1,/obj/item/clothing/head/yogs/tar_king_crown = 1, /obj/item/gem/tarstone = 1, /obj/item/demon_core = 1)
|
||||
music_component = /datum/component/music_player/battle
|
||||
music_path = /datum/music/sourced/battle/tar_king
|
||||
|
||||
var/list/attack_adjustments = list()
|
||||
var/last_done_attack = 0
|
||||
var/list/attack_stack = list()
|
||||
var/stage = 0
|
||||
var/enraged = 0
|
||||
|
||||
var/list/orbitals = list(0,120,240,60,180,300)
|
||||
var/orbital_theta_per_tick = 15
|
||||
var/orbital_range = 4
|
||||
var/list/orbitals = list(0,180,240) // second orbital gets set back -60 degrees to align with the others in stage 3
|
||||
var/orbital_theta_per_tick = 10
|
||||
var/orbital_range = 6
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/tar_king/Initialize()
|
||||
. = ..()
|
||||
START_PROCESSING(SSfastprocess,src)
|
||||
AddComponent(/datum/component/after_image, 0.5 SECONDS, 0.5, FALSE, COLOR_TAR_PURPLE)
|
||||
say("You..!", spans = list(SPAN_COLOSSUS), ignore_spam = TRUE)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/tar_king/Life(seconds_per_tick, times_fired)
|
||||
. = ..()
|
||||
@@ -62,82 +74,190 @@
|
||||
if(prob(25) && target)
|
||||
spawn_tar_shrine()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/tar_king/death(gibbed, list/force_grant)
|
||||
if(health > 0 || stage >= STAGE_DEAD) // still alive or already died
|
||||
return
|
||||
say("You..", spans = list(SPAN_COLOSSUS), ignore_spam = TRUE) // needs to be said before the actual dying part
|
||||
. = ..()
|
||||
stage = STAGE_DEAD
|
||||
var/obj/effect/dusting_anim/dust_effect = new(loc, ref(src))
|
||||
filters += filter(type = "displace", size = 256, render_source = "*snap[ref(src)]")
|
||||
animate(src, alpha = 0, color = COLOR_TAR_PURPLE, time = 2 SECONDS, easing = (EASE_IN | SINE_EASING))
|
||||
walk(src, 0)
|
||||
QDEL_IN(dust_effect, 2 SECONDS)
|
||||
QDEL_IN(src, 2 SECONDS)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/tar_king/FindTarget(list/possible_targets, HasTargetsList)
|
||||
if(stage >= STAGE_DEAD)
|
||||
return // dead
|
||||
return ..()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/tar_king/AttackingTarget()
|
||||
if(isliving(target))
|
||||
var/mob/living/victim = target
|
||||
if(victim.stat && !HAS_TRAIT(victim, TRAIT_NODEATH))
|
||||
devour(victim)
|
||||
return
|
||||
if(attack_stack.len) // currently doing a combo
|
||||
return
|
||||
face_atom(target)
|
||||
if(stage >= STAGE_MID && prob(40)) // start doing occasional stabs in the second stage
|
||||
sword_stab(melee_damage_upper, 3 + stage)
|
||||
else
|
||||
sword_cleave(get_dir(src, target), min(90 + stage * 90, 270), melee_damage_upper, stage >= STAGE_MID) // cleave between 90 and 270 degrees based on stage
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/tar_king/devour(mob/living/new_convert)
|
||||
say(pick("Useless..", "Weak.."), spans = list(SPAN_COLOSSUS), ignore_spam = TRUE)
|
||||
if(ishuman(new_convert))
|
||||
new_convert.death()
|
||||
new_convert.visible_message(span_warning("[src] reanimates [new_convert] as a new convert!"))
|
||||
new /mob/living/simple_animal/hostile/tar/amalgamation/convert(new_convert.loc, new_convert)
|
||||
else
|
||||
new_convert.visible_message("[src] crumbles to dust!")
|
||||
new_convert.dust(drop_items = TRUE)
|
||||
target = null
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/tar_king/proc/sword_cleave(attack_dir, arc_size = 90, damage = 40, extra_range = FALSE)
|
||||
if(!target)
|
||||
CRASH("Tar King attacking null target!")
|
||||
var/turfs_count = round(arc_size / 90, 1)
|
||||
var/turf/king_turf = get_turf(src)
|
||||
if(stage == STAGE_END || !Adjacent(target)) // teleport to the target if too far away
|
||||
do_teleport(src, get_step(get_turf(target), turn(attack_dir, stage == STAGE_END ? rand(360) : 180)))
|
||||
Beam(king_turf, "purple_lightning", time = 0.5 SECONDS)
|
||||
SLEEP_CHECK_DEATH(0.1 SECONDS)
|
||||
var/turf/cleave_turf
|
||||
var/cleave_dir
|
||||
for(var/i in -min(turfs_count, 3) to min(turfs_count, 4))
|
||||
cleave_dir = turn(attack_dir, i * 45)
|
||||
cleave_turf = get_step(king_turf, cleave_dir)
|
||||
new /obj/effect/better_animated_temp_visual/tar_king_chaser_impale(cleave_turf, src, damage)
|
||||
if(extra_range && !ISDIAGONALDIR(cleave_dir) && (turfs_count == 1 || abs(i) < turfs_count))
|
||||
new /obj/effect/better_animated_temp_visual/tar_king_chaser_impale(get_step(cleave_turf, cleave_dir), src, damage)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/tar_king/proc/sword_stab(damage = 15, stab_range = 5)
|
||||
if(!target)
|
||||
CRASH("Tar King attacking null target!")
|
||||
var/turf/target_turf = get_turf(target)
|
||||
var/turf/sword_turf = get_turf(src)
|
||||
var/delta_x = target_turf.x - sword_turf.x
|
||||
var/delta_y = target_turf.y - sword_turf.y
|
||||
if(stage == STAGE_END || (delta_x && delta_y)) // if the path to the target is diagonal, teleport to a position where it has a horizontal/vertical path
|
||||
if(stage == STAGE_END)
|
||||
if(prob(50))
|
||||
delta_x = pick(-2, 2)
|
||||
delta_y = 0
|
||||
else
|
||||
delta_x = 0
|
||||
delta_y = pick(-2, 2)
|
||||
else
|
||||
if(abs(delta_x) > abs(delta_y))
|
||||
delta_x = 0
|
||||
delta_y = min(abs(delta_y), 2) * SIGN(delta_y)
|
||||
else
|
||||
delta_x = min(abs(delta_x), 2) * SIGN(delta_x)
|
||||
delta_y = 0
|
||||
target_turf = locate(sword_turf.x + delta_x, sword_turf.y + delta_y, target_turf.z)
|
||||
do_teleport(src, target_turf, forced = TRUE)
|
||||
Beam(sword_turf, "purple_lightning", time = 0.5 SECONDS)
|
||||
sword_turf = get_turf(src)
|
||||
face_atom(target)
|
||||
SLEEP_CHECK_DEATH(0.1 SECONDS)
|
||||
else
|
||||
face_atom(target)
|
||||
var/stab_dir = get_dir(src, target)
|
||||
var/turn_size = ISDIAGONALDIR(stab_dir) ? 45 : 90
|
||||
for(var/i = 1; i <= stab_range; i++)
|
||||
SLEEP_CHECK_DEATH(0.1 SECONDS)
|
||||
if(stage >= STAGE_MID && i != 1 && i != stab_range) // 3 wide in the last stage
|
||||
new /obj/effect/better_animated_temp_visual/tar_king_chaser_impale(get_step(sword_turf, turn(stab_dir, turn_size)), src, damage)
|
||||
new /obj/effect/better_animated_temp_visual/tar_king_chaser_impale(get_step(sword_turf, turn(stab_dir, -turn_size)), src, damage)
|
||||
sword_turf = get_step(sword_turf, stab_dir)
|
||||
new /obj/effect/better_animated_temp_visual/tar_king_chaser_impale(sword_turf, src, damage)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/tar_king/process()
|
||||
if(stat == DEAD)
|
||||
if(stat == DEAD || stage >= STAGE_DEAD)
|
||||
STOP_PROCESSING(SSfastprocess, src)
|
||||
return
|
||||
if(!attack_stack.len) // stage transition
|
||||
check_stage()
|
||||
process_orbitals()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/tar_king/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
|
||||
. = ..()
|
||||
if(iscarbon(hit_atom))
|
||||
sword_hit(list(get_turf(hit_atom)))
|
||||
return
|
||||
/mob/living/simple_animal/hostile/megafauna/tar_king/proc/enrage()
|
||||
enraged++
|
||||
say(enraged == 1 ? "Hmm.." : "You dare..", spans = list(SPAN_COLOSSUS), ignore_spam = TRUE)
|
||||
if(enraged >= ENRAGE_LIMIT)
|
||||
ADD_TRAIT(src, TRAIT_SHIELDBUSTER, ENRAGED_TRAIT) // prevents cheesing the boss by parrying it forever
|
||||
addtimer(CALLBACK(src, PROC_REF(end_enrage)), 10 SECONDS, TIMER_UNIQUE|TIMER_OVERRIDE)
|
||||
|
||||
if(isstructure(hit_atom))
|
||||
qdel(hit_atom)
|
||||
return
|
||||
|
||||
if(isclosedturf(hit_atom))
|
||||
SSexplosions.medturf += get_turf(hit_atom)
|
||||
/mob/living/simple_animal/hostile/megafauna/tar_king/proc/end_enrage(callout = FALSE)
|
||||
if(!enraged)
|
||||
return
|
||||
if(callout && enraged >= ENRAGE_LIMIT)
|
||||
say(pick("Fool..!", "You thought me defeated..?"), spans = list(SPAN_COLOSSUS), ignore_spam = TRUE) // mock the player for their hubris
|
||||
enraged--
|
||||
if(!enraged)
|
||||
REMOVE_TRAIT(src, TRAIT_SHIELDBUSTER, ENRAGED_TRAIT)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/tar_king/Goto(target, delay, minimum_distance)
|
||||
if(!attack_stack.len)
|
||||
return ..()
|
||||
else
|
||||
else
|
||||
walk(src,0)
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/tar_king/proc/add_mob_profile(mob/living/L)
|
||||
attack_adjustments[L.real_name] = ATTACK_MATRIX
|
||||
RegisterSignal(L,COMSIG_MOVABLE_MOVED,PROC_REF(react_after_move))
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/tar_king/proc/react_after_move(mob/living/L, old_loc, target_dir, forced)
|
||||
if(!last_done_attack || last_done_attack == TAR_ATTACK ||last_done_attack == TELEPORT_ATTACK)
|
||||
if(!last_done_attack || last_done_attack == TAR_ATTACK || last_done_attack == RUNE_ATTACK)
|
||||
return
|
||||
var/angle_dir_target = dir2angle(target_dir)
|
||||
angle_dir_target = angle_dir_target == 0 ? 360 : angle_dir_target
|
||||
var/chosen_dir = angle2dir(angle_dir_target - dir2angle(get_dir(src,L)))
|
||||
attack_adjustments[L.real_name][last_done_attack][uppertext(dir2text(chosen_dir))] += 1
|
||||
last_done_attack = 0
|
||||
last_done_attack = 0
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/tar_king/Shoot()
|
||||
if (stage == 0 && health < 1500)
|
||||
SetRecoveryTime(20 SECONDS)
|
||||
stage++
|
||||
stage_transition()
|
||||
return
|
||||
else if (stage == 1 && health < 1000)
|
||||
SetRecoveryTime(20 SECONDS,0)
|
||||
stage++
|
||||
stage_transition()
|
||||
return
|
||||
else if (stage == 2 && health < 500)
|
||||
SetRecoveryTime(20 SECONDS,0)
|
||||
stage++
|
||||
stage_transition()
|
||||
return
|
||||
if(attack_stack.len)
|
||||
return
|
||||
var/list/combo = forge_combo()
|
||||
SetRecoveryTime( 1 SECONDS + ((health/maxHealth) * 1 SECONDS),0)
|
||||
|
||||
for(var/move as anything in combo)
|
||||
attack_stack += move
|
||||
return
|
||||
attack_stack = forge_combo()
|
||||
SetRecoveryTime((2 - stage / 2) SECONDS, 0)
|
||||
|
||||
while(attack_stack.len)
|
||||
walk(src,0)
|
||||
switch(move)
|
||||
switch(attack_stack[1])
|
||||
if(SLASH_ATTACK)
|
||||
slash_attack_chain()
|
||||
if(IMPALE_ATTACK)
|
||||
impale_attack_chain()
|
||||
if(RUNE_ATTACK)
|
||||
rune_attack_chain()
|
||||
if(TELEPORT_ATTACK)
|
||||
teleport_attack_chain()
|
||||
attack_stack -= move
|
||||
Goto(target,move_to_delay,minimum_distance)
|
||||
SLEEP_CHECK_DEATH(1 SECONDS)
|
||||
attack_stack.Cut(1, 2)
|
||||
//INVOKE_ASYNC(src, PROC_REF(Goto), target, move_to_delay, minimum_distance)
|
||||
SLEEP_CHECK_DEATH((0.5 - stage / 4) SECONDS)
|
||||
if(check_stage())
|
||||
return
|
||||
if(!target || QDELETED(target))
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/tar_king/proc/check_stage()
|
||||
if(stage < STAGE_END && health < 800)
|
||||
stage = STAGE_END
|
||||
speed = 2
|
||||
move_to_delay = 2
|
||||
ranged_cooldown_time = 2 SECONDS
|
||||
orbitals[2] -= 60 // move it back so all 3 orbitals are evenly spaced
|
||||
say(pick("Die..!", "Enough..!"), spans = list(SPAN_COLOSSUS), ignore_spam = TRUE)
|
||||
stage_transition()
|
||||
return TRUE
|
||||
else if(stage < STAGE_MID && health < 1500)
|
||||
stage = STAGE_MID
|
||||
ranged_cooldown_time = 3 SECONDS
|
||||
say(pick("Ah.. a worthy opponent..!", "A challenge..!"), spans = list(SPAN_COLOSSUS), ignore_spam = TRUE)
|
||||
stage_transition()
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/tar_king/proc/spawn_tar_shrine()
|
||||
var/list/pickable_turfs = list()
|
||||
@@ -167,11 +287,11 @@
|
||||
adjustment_amount += 4
|
||||
|
||||
var/dist = get_dist(src,L)
|
||||
if(dist > 3)
|
||||
visible_message(span_colossus("Coward!"))
|
||||
if(dist > 4 && move == SLASH_ATTACK)
|
||||
var/step_dir = pick(GLOB.alldirs)
|
||||
var/turf/new_loc = get_step(L,step_dir)
|
||||
Move(new_loc,get_dir(src,new_loc))
|
||||
say("Coward..!", spans = list(SPAN_COLOSSUS), ignore_spam = TRUE)
|
||||
|
||||
var/adjusted_dir = get_dir(src,L)
|
||||
|
||||
@@ -179,7 +299,7 @@
|
||||
add_mob_profile(L)
|
||||
for(var/i = 0; i < adjustment_amount; i++)
|
||||
var/direction = pickweightAllowZero(attack_adjustments[L.real_name][move])
|
||||
var/actual_direction
|
||||
var/actual_direction
|
||||
actual_direction = turn(text2dir(direction),dir2angle(get_dir(src,L)))
|
||||
if(!actual_direction || prob(35))
|
||||
actual_direction = get_dir(src,L)
|
||||
@@ -189,155 +309,164 @@
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/tar_king/proc/forge_combo()
|
||||
var/list/combo = list()
|
||||
var/list/possible_moves = list(SLASH_ATTACK,IMPALE_ATTACK,RUNE_ATTACK,TELEPORT_ATTACK)
|
||||
for(var/i = 0 ; i < 3; i++)
|
||||
combo += pick_n_take(possible_moves)
|
||||
var/last_move = ""
|
||||
for(var/i = 0; i < 3 + stage * 2; i++) // 3-7 attacks in the combo based on current stage
|
||||
last_move = pick(list(SLASH_ATTACK, IMPALE_ATTACK, RUNE_ATTACK) - last_move) // don't do the same attack twice
|
||||
combo += last_move
|
||||
return combo
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/tar_king/proc/slash_attack_chain()
|
||||
slash_attack_telegraph()
|
||||
SLEEP_CHECK_DEATH(0.25 SECONDS)
|
||||
/mob/living/simple_animal/hostile/megafauna/tar_king/proc/slash_attack_chain(arc_size = 90)
|
||||
slash_attack_telegraph(arc_size)
|
||||
SLEEP_CHECK_DEATH(0.3 SECONDS)
|
||||
react(SLASH_ATTACK)
|
||||
SLEEP_CHECK_DEATH(0.25 SECONDS)
|
||||
slash_attack_finish()
|
||||
|
||||
SLEEP_CHECK_DEATH(0.3 SECONDS)
|
||||
slash_attack_finish()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/tar_king/proc/slash_attack_telegraph()
|
||||
visible_message(span_colossus("En-Ghar!"))
|
||||
animate(src,0.25 SECONDS,transform = turn(matrix(),30))
|
||||
say("En-Ghar..!", spans = list(SPAN_COLOSSUS), ignore_spam = TRUE)
|
||||
animate(src, 0.6 SECONDS, transform = turn(matrix(), 30))
|
||||
sword_cleave(dir, 90, 15, TRUE)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/tar_king/proc/slash_attack_finish()
|
||||
animate(src,0.25 SECONDS,transform = initial(transform))
|
||||
animate(src, 0.2 SECONDS, transform = initial(transform))
|
||||
new /obj/effect/tar_king/slash(get_turf(src),src,dir)
|
||||
SLEEP_CHECK_DEATH(4)
|
||||
var/affected_turfs = list()
|
||||
affected_turfs += get_step(src,turn(dir,-45))
|
||||
affected_turfs += get_step(src,dir)
|
||||
affected_turfs += get_step(src,turn(dir,45))
|
||||
sword_hit(affected_turfs)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/tar_king/proc/impale_attack_chain()
|
||||
impale_attack_telegraph()
|
||||
SLEEP_CHECK_DEATH(0.25 SECONDS)
|
||||
SLEEP_CHECK_DEATH(0.3 SECONDS)
|
||||
react(IMPALE_ATTACK)
|
||||
SLEEP_CHECK_DEATH(0.25 SECONDS)
|
||||
SLEEP_CHECK_DEATH(0.3 SECONDS)
|
||||
impale_attack_finish()
|
||||
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/tar_king/proc/impale_attack_telegraph()
|
||||
visible_message(span_colossus("Et-Tyr!"))
|
||||
say("Et-Tyr..!", spans = list(SPAN_COLOSSUS), ignore_spam = TRUE)
|
||||
INVOKE_ASYNC(src, PROC_REF(sword_stab), 15, 5 + stage)
|
||||
switch(dir)
|
||||
if(NORTH)
|
||||
animate(src,0.25 SECONDS,pixel_y = initial(pixel_y) - 10)
|
||||
animate(src,0.2 SECONDS,pixel_y = initial(pixel_y) - 10)
|
||||
if(SOUTH)
|
||||
animate(src,0.25 SECONDS,pixel_y = initial(pixel_y) + 10)
|
||||
animate(src,0.2 SECONDS,pixel_y = initial(pixel_y) + 10)
|
||||
if(EAST)
|
||||
animate(src,0.25 SECONDS,pixel_x = initial(pixel_y) - 10)
|
||||
animate(src,0.2 SECONDS,pixel_x = initial(pixel_y) - 10)
|
||||
if(WEST)
|
||||
animate(src,0.25 SECONDS,pixel_x = initial(pixel_y) + 10)
|
||||
animate(src,0.2 SECONDS,pixel_x = initial(pixel_y) + 10)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/tar_king/proc/impale_attack_finish()
|
||||
new /obj/effect/tar_king/impale(get_turf(src),src,dir)
|
||||
SLEEP_CHECK_DEATH(4)
|
||||
var/affected_turfs = list()
|
||||
affected_turfs += get_turf(src)
|
||||
affected_turfs += get_step(src,dir)
|
||||
affected_turfs += get_step(get_step(src,dir),dir)
|
||||
sword_hit(affected_turfs)
|
||||
animate(src,0.25 SECONDS,pixel_x = initial(pixel_x),pixel_y = initial(pixel_y))
|
||||
SLEEP_CHECK_DEATH(2)
|
||||
animate(src, 0.2 SECONDS, pixel_x = initial(pixel_x), pixel_y = initial(pixel_y))
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/tar_king/proc/rune_attack_chain()
|
||||
rune_attack_telegraph()
|
||||
SLEEP_CHECK_DEATH(0.25 SECONDS)
|
||||
react(RUNE_ATTACK)
|
||||
SLEEP_CHECK_DEATH(0.25 SECONDS)
|
||||
rune_attack_finish()
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/tar_king/proc/rune_attack_telegraph()
|
||||
visible_message(span_colossus("Atu'Rakhtar!"))
|
||||
animate(src,0.5 SECONDS, color = "#ff002f")
|
||||
new /obj/effect/tar_king/rune_attack(get_turf(src),src,get_dir(src,target))
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/tar_king/proc/rune_attack_finish()
|
||||
animate(src,0.5 SECONDS, color = initial(color))
|
||||
SLEEP_CHECK_DEATH(8)
|
||||
for(var/mob/living/carbon/C in (range(2,src) - range(1,src)))
|
||||
var/limb_to_hit = C.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))
|
||||
C.apply_damage(25, BURN, limb_to_hit, C.run_armor_check(limb_to_hit, MAGIC, null, null, armour_penetration), wound_bonus = CANT_WOUND)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/tar_king/proc/teleport_attack_chain()
|
||||
/mob/living/simple_animal/hostile/megafauna/tar_king/proc/rune_attack_chain(direct_teleport = TRUE, chain_length = 0)
|
||||
new /obj/effect/tar_king/orb_in(get_turf(src),src,dir)
|
||||
var/obj/closest
|
||||
var/cached_dist = INFINITY
|
||||
|
||||
if(GLOB.tar_pits.len > 1)
|
||||
for(var/obj/structure/tar_pit/TP as anything in GLOB.tar_pits)
|
||||
var/dist = get_dist(target,TP)
|
||||
if(dist < cached_dist)
|
||||
cached_dist = dist
|
||||
closest = TP
|
||||
else
|
||||
if(!GLOB.tar_pits.len)
|
||||
return
|
||||
closest = GLOB.tar_pits[1]
|
||||
|
||||
if(!closest || cached_dist > 7)
|
||||
return
|
||||
var/turf/target_turf = get_turf(target)
|
||||
var/turf/start_turf
|
||||
|
||||
visible_message(span_colossus("Ishakt-Tarim!"))
|
||||
SLEEP_CHECK_DEATH(0.5 SECONDS)
|
||||
Move(get_turf(closest))
|
||||
visible_message(span_colossus("Atyr!"))
|
||||
throw_at(target,get_dist(target,src),4, spin = FALSE)
|
||||
if(direct_teleport)
|
||||
start_turf = get_turf(src)
|
||||
else
|
||||
var/distance_to_target
|
||||
var/list/available_pits = list()
|
||||
for(var/obj/structure/tar_pit/pit as anything in GLOB.tar_pits)
|
||||
distance_to_target = get_dist(pit, target)
|
||||
if(distance_to_target > 8) // too far away from the target
|
||||
continue
|
||||
if(distance_to_target < 2) // too close to the target
|
||||
continue
|
||||
available_pits += pit
|
||||
|
||||
if(available_pits.len)
|
||||
start_turf = get_turf(pick(available_pits))
|
||||
else if(get_dist(src, target) > 2)
|
||||
start_turf = get_turf(src)
|
||||
else // pick a random turf in the area and hope for the best
|
||||
var/area/target_area = get_area(target)
|
||||
start_turf = pick(target_area.turfs_by_zlevel[target_turf])
|
||||
|
||||
// moving rune effect that travels towards where the tar king will be
|
||||
var/obj/effect/tar_king/rune_attack/tar_telegraph = new(target_turf, null, get_dir(src, target))
|
||||
tar_telegraph.pixel_x += ((start_turf.x - target_turf.x) * 32)
|
||||
tar_telegraph.pixel_y += ((start_turf.y - target_turf.y) * 32)
|
||||
|
||||
animate(
|
||||
tar_telegraph,
|
||||
0.7 SECONDS,
|
||||
FALSE,
|
||||
pixel_x = initial(tar_telegraph.pixel_x),
|
||||
pixel_y = initial(tar_telegraph.pixel_y),
|
||||
easing = SINE_EASING | EASE_OUT
|
||||
)
|
||||
|
||||
icon_state = "tar_king_chaser"
|
||||
if(!direct_teleport) // just go straight to the target
|
||||
var/turf/original = get_turf(src)
|
||||
do_teleport(src, start_turf, forced = TRUE)
|
||||
playsound(src,'sound/magic/blind.ogg', 125, 1, -5) //make a sound
|
||||
Beam(original, "purple_lightning", time = 0.5 SECONDS)
|
||||
say("Ishakt-Tarim..!", spans = list(SPAN_COLOSSUS), ignore_spam = TRUE)
|
||||
|
||||
SLEEP_CHECK_DEATH(1 SECONDS)
|
||||
do_teleport(src, target_turf, forced = TRUE)
|
||||
Beam(start_turf, "purple_lightning", time = 0.5 SECONDS)
|
||||
say("Atyr..!", spans = list(SPAN_COLOSSUS), ignore_spam = TRUE)
|
||||
|
||||
SLEEP_CHECK_DEATH(0.2 SECONDS)
|
||||
playsound(src,'sound/magic/blind.ogg', 125, 1, -5) //make a sound
|
||||
for(var/mob/living/carbon/victim in range(2, src))
|
||||
if(victim == src)
|
||||
continue
|
||||
if(victim.check_shields(src, 25, "rune magic", MELEE_ATTACK, armour_penetration, BRUTE))
|
||||
enrage()
|
||||
continue
|
||||
else
|
||||
end_enrage(TRUE)
|
||||
var/limb_to_hit = victim.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))
|
||||
victim.apply_damage(25, BURN, limb_to_hit, victim.run_armor_check(limb_to_hit, MAGIC, null, null, armour_penetration), wound_bonus = CANT_WOUND)
|
||||
playsound(victim,'sound/weapons/sear.ogg', 50, 1, -4)
|
||||
|
||||
if(chain_length < stage && get_dist(src, target) > 1)
|
||||
rune_attack_chain(TRUE, chain_length + 1)
|
||||
else
|
||||
SLEEP_CHECK_DEATH(0.5 SECONDS)
|
||||
icon_state = "tar_king"
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/tar_king/proc/process_orbitals()
|
||||
var/orbitals_shown = 3
|
||||
switch(maxHealth - health)
|
||||
if(500 to 1000)
|
||||
orbitals_shown += 1
|
||||
if(1000 to 1500)
|
||||
orbitals_shown += 2
|
||||
if(1500 to 2000)
|
||||
orbitals_shown += 3
|
||||
|
||||
for(var/i in 1 to 5)
|
||||
var/orbitals_shown = 1 + stage
|
||||
|
||||
for(var/i in 1 to orbitals.len)
|
||||
orbitals[i] += orbital_theta_per_tick
|
||||
|
||||
for(var/i in 1 to orbitals_shown)
|
||||
var/xcoord = loc.x + orbital_range * cos(orbitals[i])
|
||||
var/ycoord = loc.y + orbital_range * sin(orbitals[i])
|
||||
var/turf/located = locate(xcoord,ycoord,loc.z)
|
||||
var/obj/effect/better_animated_temp_visual/tar_king_chaser_impale/T = new(located, src)
|
||||
T.damage = 10
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/tar_king/proc/sword_hit(list/turfs)
|
||||
for(var/turf/T as anything in turfs)
|
||||
for(var/mob/living/carbon/C in T.contents)
|
||||
var/limb_to_hit = C.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))
|
||||
C.apply_damage(15, BRUTE, limb_to_hit, C.run_armor_check(limb_to_hit, MELEE, null, null, armour_penetration), wound_bonus = CANT_WOUND)
|
||||
|
||||
new /obj/effect/better_animated_temp_visual/tar_king_chaser_impale(located, src, 10)
|
||||
|
||||
/mob/living/simple_animal/hostile/megafauna/tar_king/proc/stage_transition()
|
||||
walk(src,0)
|
||||
SetRecoveryTime(10 SECONDS, 0)
|
||||
icon_state = "tar_king_chaser"
|
||||
for(var/i in 0 to stage)
|
||||
new /obj/effect/temp_visual/tar_king_chaser(loc, src, target, 1)
|
||||
attack_stack += "STAGE_TRANSITION"
|
||||
SLEEP_CHECK_DEATH(15 SECONDS)
|
||||
attack_stack += STAGE_TRANSITION
|
||||
SLEEP_CHECK_DEATH(10 SECONDS)
|
||||
icon_state = "tar_king"
|
||||
attack_stack -= "STAGE_TRANSITION"
|
||||
attack_stack -= STAGE_TRANSITION
|
||||
|
||||
/obj/effect/better_animated_temp_visual/tar_king_chaser_impale
|
||||
duration = 9
|
||||
duration = 10
|
||||
icon = 'yogstation/icons/effects/32x48.dmi'
|
||||
animated_icon_state = "tar_king_special"
|
||||
name = "incoming doom"
|
||||
desc = "Run while you still can!"
|
||||
var/damage
|
||||
var/bursting
|
||||
var/mob/living/caster
|
||||
var/bursting
|
||||
|
||||
/obj/effect/better_animated_temp_visual/tar_king_chaser_impale/Initialize(mapload, new_caster)
|
||||
/obj/effect/better_animated_temp_visual/tar_king_chaser_impale/Initialize(mapload, new_caster, new_damage)
|
||||
. = ..()
|
||||
caster = new_caster
|
||||
damage = new_damage
|
||||
var/static/list/loc_connections = list(
|
||||
COMSIG_ATOM_ENTERED = PROC_REF(on_entered),
|
||||
)
|
||||
@@ -349,10 +478,10 @@
|
||||
if(!T)
|
||||
return
|
||||
playsound(T,pick('sound/weapons/sword3.ogg','sound/weapons/sword4.ogg','sound/weapons/sword5.ogg'), 125, 1, -5) //make a sound
|
||||
sleep(0.45 SECONDS)
|
||||
sleep(0.6 SECONDS) // needs to line up with the sprite's animation
|
||||
bursting = TRUE
|
||||
do_damage(T)
|
||||
sleep(0.1 SECONDS)
|
||||
do_damage(T)
|
||||
sleep(0.1 SECONDS) // slightly forgiving so that you don't hit yourself twice on the same tile
|
||||
bursting = FALSE
|
||||
|
||||
/obj/effect/better_animated_temp_visual/tar_king_chaser_impale/proc/on_entered(datum/source, atom/movable/AM, ...)
|
||||
@@ -362,27 +491,35 @@
|
||||
/obj/effect/better_animated_temp_visual/tar_king_chaser_impale/proc/do_damage(turf/T)
|
||||
if(!damage)
|
||||
return
|
||||
for(var/mob/living/L in T.contents) //find and damage mobs...
|
||||
if((caster && caster.faction_check_mob(L)) || L.stat == DEAD || L == caster)
|
||||
for(var/mob/living/victim in T.contents) //find and damage mobs...
|
||||
if((caster && caster.faction_check_mob(victim)) || victim.stat == DEAD || victim == caster)
|
||||
continue
|
||||
playsound(L,pick('sound/weapons/sword1.ogg','sound/weapons/sword2.ogg'), 50, 1, -4)
|
||||
to_chat(L, span_userdanger("You're struck by a [name]!"))
|
||||
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))
|
||||
var/armor = L.run_armor_check(limb_to_hit, MELEE, "Your armor absorbs [src]!", "Your armor blocks part of [src]!", 50, "Your armor was penetrated by [src]!")
|
||||
L.apply_damage(damage, BRUTE, limb_to_hit, armor, wound_bonus = CANT_WOUND)
|
||||
var/mob/living/simple_animal/hostile/megafauna/tar_king/king_of_tar = caster
|
||||
if(victim.check_shields(caster, damage, name, MELEE_ATTACK, 50, BRUTE))
|
||||
if(istype(king_of_tar))
|
||||
king_of_tar.enrage()
|
||||
continue
|
||||
else
|
||||
if(istype(king_of_tar))
|
||||
king_of_tar.end_enrage(TRUE)
|
||||
playsound(victim, pick('sound/weapons/sword1.ogg','sound/weapons/sword2.ogg'), 50, 1, -4)
|
||||
to_chat(victim, span_userdanger("You're struck by a [name]!"))
|
||||
var/limb_to_hit = victim.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))
|
||||
var/armor = victim.run_armor_check(limb_to_hit, MELEE, "Your armor absorbs [src]!", "Your armor blocks part of [src]!", 50, "Your armor was penetrated by [src]!")
|
||||
victim.apply_damage(damage, BRUTE, limb_to_hit, armor, wound_bonus = CANT_WOUND)
|
||||
if(caster)
|
||||
log_combat(caster, L, "struck with a [name]")
|
||||
log_combat(caster, victim, "struck with a [name]")
|
||||
|
||||
for(var/obj/mecha/M in T.contents) //also damage mechs.
|
||||
if(M.occupant)
|
||||
if(caster && caster != M && caster.faction_check_mob(M.occupant))
|
||||
for(var/obj/mecha/mech in T.contents) //also damage mechs.
|
||||
if(mech.occupant)
|
||||
if(caster && caster != mech && caster.faction_check_mob(mech.occupant))
|
||||
continue
|
||||
to_chat(M.occupant, span_userdanger("Your [M.name] is struck by a [name]!"))
|
||||
playsound(M,'sound/weapons/sword2.ogg', 50, 1, -4)
|
||||
M.take_damage(damage, BRUTE, 0, 0)
|
||||
to_chat(mech.occupant, span_userdanger("Your [mech.name] is struck by a [name]!"))
|
||||
playsound(mech,'sound/weapons/sword2.ogg', 50, 1, -4)
|
||||
mech.take_damage(damage, BRUTE, MELEE, 0)
|
||||
|
||||
/obj/effect/temp_visual/tar_king_chaser
|
||||
duration = 15 SECONDS
|
||||
duration = 10 SECONDS
|
||||
var/mob/living/target //what it's following
|
||||
var/turf/targetturf //what turf the target is actually on
|
||||
var/moving_dir //what dir it's moving in
|
||||
@@ -442,5 +579,10 @@
|
||||
targetturf = get_turf(target)
|
||||
|
||||
/obj/effect/temp_visual/tar_king_chaser/proc/make_blast()
|
||||
var/obj/effect/better_animated_temp_visual/tar_king_chaser_impale/T = new(loc, caster)
|
||||
T.damage = damage
|
||||
new /obj/effect/better_animated_temp_visual/tar_king_chaser_impale(loc, caster, damage)
|
||||
|
||||
/obj/item/gps/internal/tar_king
|
||||
icon_state = null
|
||||
gpstag = "Murky Signal"
|
||||
desc = "There's something flickering in the dark."
|
||||
invisibility = 100
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Reference in New Issue
Block a user