Elite buffs / Highlander mode for arena (#19166)

* Elite buffs / Highlander mode for arena

* whoops forgot to push this

* Apply suggestions from code review

Co-authored-by: Farie82 <farie82@users.noreply.github.com>

* removes unused list, proximity component

* range_edge_turfs

* comment

* Apply suggestions from code review

Co-authored-by: Farie82 <farie82@users.noreply.github.com>

* ARENA_RADIUS

* Apply suggestions from code review

Co-authored-by: Farie82 <farie82@users.noreply.github.com>

* last changes

* Update code/modules/mob/living/simple_animal/hostile/mining/elites/elite.dm

Co-authored-by: Farie82 <farie82@users.noreply.github.com>

Co-authored-by: Farie82 <farie82@users.noreply.github.com>
This commit is contained in:
Qwertytoforty
2022-10-24 21:47:43 +02:00
committed by GitHub
co-authored by Farie82
parent a6ba421e21
commit 2c5d9ffb43
7 changed files with 82 additions and 30 deletions
@@ -297,10 +297,9 @@ Difficulty: Hard
arena_cooldown = world.time + initial(arena_cooldown)
for(var/d in GLOB.cardinal)
INVOKE_ASYNC(src, .proc/arena_squares, T, d)
for(var/t in RANGE_TURFS(11, T))
if(t && get_dist(t, T) == 11)
new /obj/effect/temp_visual/hierophant/wall(t, src)
new /obj/effect/temp_visual/hierophant/blast(t, src, FALSE)
for(var/t in RANGE_EDGE_TURFS(11, T))
new /obj/effect/temp_visual/hierophant/wall(t, src)
new /obj/effect/temp_visual/hierophant/blast(t, src, FALSE)
if(get_dist(src, T) >= 11) //hey you're out of range I need to get closer to you!
INVOKE_ASYNC(src, .proc/blink, T)
@@ -1,6 +1,7 @@
#define TUMOR_INACTIVE 0
#define TUMOR_ACTIVE 1
#define TUMOR_PASSIVE 2
#define ARENA_RADIUS 12
//Elite mining mobs
/mob/living/simple_animal/hostile/asteroid/elite
@@ -174,6 +175,9 @@ While using this makes the system rely on OnFire, it still gives options for tim
/mob/living/simple_animal/hostile/asteroid/elite/herald,
)
///List of invaders that have teleportes into the arena *multiple times*. They will be suffering.
var/list/invaders = list()
/obj/structure/elite_tumor/attack_hand(mob/user, list/modifiers)
. = ..()
if(!ishuman(user))
@@ -234,6 +238,7 @@ While using this makes the system rely on OnFire, it still gives options for tim
icon_state = "tumor_popped"
RegisterSignal(mychild, COMSIG_PARENT_QDELETING, .proc/onEliteLoss)
INVOKE_ASYNC(src, .proc/arena_checks)
AddComponent(/datum/component/proximity_monitor, ARENA_RADIUS) //Boots out humanoid invaders. Minebots / random fauna / that colossus you forgot to clear away allowed.
/obj/structure/elite_tumor/proc/return_elite()
mychild.forceMove(loc)
@@ -246,6 +251,7 @@ While using this makes the system rely on OnFire, it still gives options for tim
mychild.grab_ghost()
notify_ghosts("\A [mychild] has been challenged in \the [get_area(src)]!", enter_link="<a href=?src=[UID()];follow=1>(Click to help)</a>", source = mychild, action = NOTIFY_FOLLOW)
INVOKE_ASYNC(src, .proc/arena_checks)
AddComponent(/datum/component/proximity_monitor, ARENA_RADIUS)
/obj/structure/elite_tumor/Initialize(mapload)
. = ..()
@@ -255,6 +261,7 @@ While using this makes the system rely on OnFire, it still gives options for tim
/obj/structure/elite_tumor/Destroy()
STOP_PROCESSING(SSobj, src)
QDEL_NULL(gps)
invaders.Cut()
if(activator)
clear_activator(activator)
if(mychild)
@@ -322,23 +329,40 @@ While using this makes the system rely on OnFire, it still gives options for tim
var/turf/tumor_turf = get_turf(src)
if(loc == null)
return
for(var/tumor_range_turfs in RANGE_TURFS(12, tumor_turf))
if(get_dist(tumor_range_turfs, tumor_turf) == 12)
var/obj/effect/temp_visual/elite_tumor_wall/newwall
newwall = new /obj/effect/temp_visual/elite_tumor_wall(tumor_range_turfs, src)
newwall.activator = activator
newwall.ourelite = mychild
for(var/tumor_range_turfs in RANGE_EDGE_TURFS(ARENA_RADIUS, tumor_turf))
var/obj/effect/temp_visual/elite_tumor_wall/newwall
newwall = new /obj/effect/temp_visual/elite_tumor_wall(tumor_range_turfs, src)
newwall.activator = activator
newwall.ourelite = mychild
/obj/structure/elite_tumor/proc/border_check()
if(activator != null && get_dist(src, activator) >= 12)
if(activator != null && get_dist(src, activator) >= ARENA_RADIUS)
activator.forceMove(loc)
visible_message("<span class='warning'>[activator] suddenly reappears above [src]!</span>")
playsound(loc,'sound/effects/phasein.ogg', 200, 0, 50, TRUE, TRUE)
if(mychild != null && get_dist(src, mychild) >= 12)
if(mychild != null && get_dist(src, mychild) >= ARENA_RADIUS)
mychild.forceMove(loc)
visible_message("<span class='warning'>[mychild] suddenly reappears above [src]!</span>")
playsound(loc,'sound/effects/phasein.ogg', 200, 0, 50, TRUE, TRUE)
/obj/structure/elite_tumor/HasProximity(atom/movable/AM)
if(!ishuman(AM) && !isrobot(AM))
return
var/mob/living/M = AM
if(M == activator)
return
if(M in invaders)
to_chat(M, "<span class='colossus'><b>You dare to try to break the sanctity of our arena? SUFFER...</b></span>")
for(var/i in 1 to 4)
M.apply_status_effect(STATUS_EFFECT_VOID_PRICE) /// Hey kids, want 60 brute damage, increased by 40 each time you do it? Well, here you go!
else
to_chat(M, "<span class='userdanger'>Only spectators are allowed, while the arena is in combat...</span>")
invaders += M
var/list/valid_turfs = RANGE_EDGE_TURFS(ARENA_RADIUS + 1, src)
M.forceMove(pick(valid_turfs)) //Doesn't check for lava. Don't cheese it.
playsound(M, 'sound/effects/phasein.ogg', 200, 0, 50, TRUE, TRUE)
/obj/structure/elite_tumor/proc/onEliteLoss()
playsound(loc,'sound/effects/tendril_destroyed.ogg', 200, 0, 50, TRUE, TRUE)
visible_message("<span class='warning'>[src] begins to convulse violently before beginning to dissipate.</span>")
@@ -382,6 +406,7 @@ While using this makes the system rely on OnFire, it still gives options for tim
Bear in mind, if anyone interacts with your tumor, you'll be resummoned here to carry out another fight. In such a case, you will regain your full max health.\n\
Also, be weary of your fellow inhabitants, they likely won't be happy to see you!</b>")
to_chat(mychild, "<span class='big bold'>Note that you are a lavaland monster, and thus not allied to the station. You should not cooperate or act friendly with any station crew unless under extreme circumstances!</span>")
qdel(GetComponent(/datum/component/proximity_monitor))
/obj/item/tumor_shard
name = "tumor shard"
@@ -405,7 +430,7 @@ While using this makes the system rely on OnFire, it still gives options for tim
E.revive()
user.visible_message("<span class='notice'>[user] stabs [E] with [src], reviving it.</span>")
SEND_SOUND(E, 'sound/magic/cult_spell.ogg')
to_chat(E, "<span class='userdanger'>You have been revived by [user]. While you can't speak to them, you owe [user] a great debt. Assist [user.p_them()] in achieving [user.p_their()] goals, regardless of risk.</span>")
to_chat(E, "<span class='userdanger'>You have been revived by [user], and 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>")
if(user.mind.special_role)
E.maxHealth = 300
@@ -450,7 +475,7 @@ While using this makes the system rely on OnFire, it still gives options for tim
/obj/effect/temp_visual/elite_tumor_wall/CanPass(atom/movable/mover, border_dir)
. = ..()
if(mover == ourelite || mover == activator)
if(isliving(mover))
return FALSE
/obj/item/gps/internal/tumor
@@ -458,3 +483,8 @@ While using this makes the system rely on OnFire, it still gives options for tim
gpstag = "Cancerous Signal"
desc = "Ghosts in a fauna? That's cancerous!"
invisibility = 100
#undef TUMOR_INACTIVE
#undef TUMOR_ACTIVE
#undef TUMOR_PASSIVE
#undef ARENA_RADIUS
@@ -143,7 +143,7 @@
color = "#FF0000"
speed = 0
move_to_delay = 3
addtimer(CALLBACK(src, .proc/reset_rage), 65)
addtimer(CALLBACK(src, .proc/reset_rage), 5 SECONDS)
/mob/living/simple_animal/hostile/asteroid/elite/broodmother/proc/reset_rage()
color = "#FFFFFF"
@@ -159,7 +159,7 @@
var/turf/T = get_step(src, spawndir)
if(T)
child.forceMove(T)
child.revive() // at most this is a 29 hp heal.
child.revive() // at most this is a 49 hp heal.
playsound(src, 'sound/effects/bamf.ogg', 100, 1)
//The goliath's children. Pretty weak, simple mobs which are able to put a single tentacle under their target when at range.
@@ -172,10 +172,11 @@
icon_aggro = "goliath_baby"
icon_dead = "goliath_baby_dead"
icon_gib = "syndicate_gib"
maxHealth = 30
health = 30
melee_damage_lower = 5
melee_damage_upper = 5
maxHealth = 50
health = 50
melee_damage_lower = 12.5
melee_damage_upper = 12.5
armour_penetration_percentage = 50
attacktext = "bashes against"
attack_sound = 'sound/weapons/punch1.ogg'
throw_message = "does nothing to the rocky hide of the"
@@ -221,6 +222,7 @@
continue
visible_message("<span class='danger'>[src] grabs hold of [L]!</span>")
L.Stun(1 SECONDS)
L.KnockDown(2.5 SECONDS)
L.adjustBruteLoss(rand(20,25))
latched = TRUE
if(!latched)
@@ -28,6 +28,7 @@
health = 1000
melee_damage_lower = 20
melee_damage_upper = 20
armour_penetration_percentage = 50
light_power = 5
light_range = 2
light_color = "#FF0000"
@@ -151,7 +152,7 @@
var/target_turf = get_turf(target)
var/angle_to_target = get_angle(src, target_turf)
say("Pray")
SLEEP_CHECK_DEATH(0.75 SECONDS)// no point blank instant shotgun.
SLEEP_CHECK_DEATH(0.5 SECONDS)// no point blank instant shotgun.
shoot_projectile(target_turf, angle_to_target, FALSE, TRUE)
addtimer(CALLBACK(src, .proc/shoot_projectile, target_turf, angle_to_target, FALSE, TRUE), 0.2 SECONDS)
if(health < maxHealth * 0.5 && !is_mirror)
@@ -28,6 +28,7 @@
health = 1000
melee_damage_lower = 35
melee_damage_upper = 35
armour_penetration_percentage = 50
attacktext = "slashes its arms at"
attack_sound = 'sound/weapons/bladeslice.ogg'
throw_message = "doesn't affect the sturdiness of"
@@ -66,7 +67,7 @@
/datum/action/innate/elite_attack/bonfire_teleport
name = "Bonfire Teleport"
button_icon_state = "bonfire_teleport"
chosen_message = "<span class='boldwarning'>You will leave a bonfire. Second use will let you swap positions with it indefintiely. Using this move on the same tile as your active bonfire removes it.</span>"
chosen_message = "<span class='boldwarning'>You will leave a bonfire. Second use will let you swap positions with it indefintiely. Using this move on the same tile as your active bonfire removes it.</span>"
chosen_attack_num = BONFIRE_TELEPORT
/datum/action/innate/elite_attack/spew_smoke
@@ -129,7 +130,7 @@
visible_message("<span class='danger'>[src] prepares to charge!</span>")
addtimer(CALLBACK(src, .proc/legionnaire_charge_to, dir_to_target, 0), 4)
/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/proc/legionnaire_charge_to(move_dir, times_ran)
/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/proc/legionnaire_charge_to(move_dir, times_ran, list/hit_targets = list())
if(times_ran >= 6)
charging = FALSE
return
@@ -147,21 +148,30 @@
if(D.density)
charging = FALSE
return
if(T.x > world.maxx - 2 || T.x < 2) //Keep them from runtiming
charging = FALSE
return
if(T.y > world.maxy - 2 || T.y < 2)
charging = FALSE
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)
for(var/mob/living/L in T.contents - src)
if(faction_check_mob(L))
charging = FALSE
return
hit_things += L
visible_message("<span class='danger'>[src] tramples and kicks [L]!</span>")
to_chat(L, "<span class='userdanger'>[src] tramples you and kicks you away!</span>")
L.throw_at(throwtarget, 10, 1, src)
L.KnockDown(1 SECONDS)
L.adjustBruteLoss(25)
addtimer(CALLBACK(src, .proc/legionnaire_charge_to, move_dir, (times_ran + 1)), 0.7)
L.Weaken(1 SECONDS) //Pain Train has no breaks.
if(L in hit_targets)
L.adjustBruteLoss(15)
else
hit_targets += L
L.adjustBruteLoss(25)
addtimer(CALLBACK(src, .proc/legionnaire_charge_to, move_dir, (times_ran + 1), hit_targets), 0.7)
/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/proc/head_detach(target)
ranged_cooldown = world.time + 1 SECONDS * revive_multiplier()
@@ -222,7 +232,7 @@
mypile.forceMove(legionturf)
/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/proc/spew_smoke()
ranged_cooldown = world.time + 3 SECONDS * revive_multiplier()
ranged_cooldown = world.time + 2.5 SECONDS * revive_multiplier()
var/smoke_location = null
if(isnull(myhead))
smoke_location = src
@@ -30,6 +30,7 @@
health = 1000
melee_damage_lower = 15
melee_damage_upper = 15
armour_penetration_percentage = 50
attacktext = "smashes into the side of"
attack_sound = 'sound/weapons/sonic_jackhammer.ogg'
throw_message = "merely dinks off of the"