Makes Jungleland Good (#22669)

* makes jungleland good

* cooldown fix

* tar king stuff
This commit is contained in:
SapphicOverload
2024-12-28 23:25:08 -05:00
committed by GitHub
parent a653b8b5dd
commit 747ea866b2
19 changed files with 395 additions and 215 deletions

View File

@@ -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"

View File

@@ -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

View File

@@ -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)

View File

@@ -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)

View File

@@ -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 ..()

View File

@@ -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))

View File

@@ -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)

View File

@@ -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 ..()

View File

@@ -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

View File

@@ -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

View File

@@ -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)
. = ..()

View File

@@ -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)
. = ..()

View File

@@ -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

View File

@@ -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"

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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