diff --git a/code/__DEFINES/status_effects.dm b/code/__DEFINES/status_effects.dm index d9f5f22f79c..4c1ac003864 100644 --- a/code/__DEFINES/status_effects.dm +++ b/code/__DEFINES/status_effects.dm @@ -35,6 +35,7 @@ #define STATUS_EFFECT_BLOODDRUNK /datum/status_effect/blooddrunk //Stun immunity and greatly reduced damage taken +#define STATUS_EFFECT_DASH /datum/status_effect/dash // Grants the ability to dash, expiring after a few secodns #define STATUS_EFFECT_SPEEDLEGS /datum/status_effect/speedlegs //Handles cling speed boost and chemical cost. @@ -70,6 +71,8 @@ #define STATUS_EFFECT_SAWBLEED /datum/status_effect/saw_bleed //if the bleed builds up enough, takes a ton of damage +#define STATUS_EFFECT_GROUNDPOUND /datum/status_effect/stacking/ground_pound //if hit twice, the third attack will fling the target + #define STATUS_EFFECT_TELEPORTSICK /datum/status_effect/teleport_sickness //increasing debuffs as you rapidly teleport. #define STATUS_EFFECT_PACIFIED /datum/status_effect/pacifism //forces the pacifism trait diff --git a/code/datums/beam.dm b/code/datums/beam.dm index dab9cbbf6a8..00c3ecdb79b 100644 --- a/code/datums/beam.dm +++ b/code/datums/beam.dm @@ -131,6 +131,33 @@ ..() A.ex_act(1) +/obj/effect/ebeam/disintegration_telegraph + alpha = 100 + layer = ON_EDGED_TURF_LAYER + +/obj/effect/ebeam/disintegration + layer = ON_EDGED_TURF_LAYER + +/obj/effect/ebeam/disintegration/Crossed(atom/A, oldloc) + ..() + if(!isliving(A)) + return + var/mob/living/L = A + var/damage = 50 + if(L.stat == DEAD) + visible_message("[L] is disintegrated by the beam!") + L.dust() + if(isliving(owner.origin)) + var/mob/living/O = owner.origin + if(faction_check(O.faction, L.faction, FALSE)) + return + damage = 70 - ((O.health / O.maxHealth) * 20) + playsound(L,'sound/weapons/sear.ogg', 50, TRUE, -4) + to_chat(L, "You're struck by a disintegration laser!") + var/limb_to_hit = L.get_organ(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, LASER) + L.apply_damage(damage, BURN, limb_to_hit, armor) + /atom/proc/Beam(atom/BeamTarget,icon_state="b_beam",icon='icons/effects/beam.dmi',time=50, maxdistance=10,beam_type=/obj/effect/ebeam,beam_sleep_time=3) var/datum/beam/newbeam = new(src,BeamTarget,icon,icon_state,time,maxdistance,beam_type,beam_sleep_time) INVOKE_ASYNC(newbeam, /datum/beam.proc/Start) diff --git a/code/datums/status_effects/buffs.dm b/code/datums/status_effects/buffs.dm index 77530cd2778..12628c3addb 100644 --- a/code/datums/status_effects/buffs.dm +++ b/code/datums/status_effects/buffs.dm @@ -134,6 +134,18 @@ if(islist(owner.stun_absorption) && owner.stun_absorption["blooddrunk"]) owner.remove_stun_absorption("blooddrunk") +/obj/screen/alert/status_effect/dash + name = "Dash" + desc = "Your have the ability to dash!" + icon = 'icons/mob/actions/actions.dmi' + icon_state = "genetic_jump" + +/datum/status_effect/dash + id = "dash" + duration = 5 SECONDS + tick_interval = 0 + alert_type = /obj/screen/alert/status_effect/dash + /datum/status_effect/bloodswell id = "bloodswell" duration = 30 SECONDS diff --git a/code/datums/status_effects/debuffs.dm b/code/datums/status_effects/debuffs.dm index a7bd33b82e2..75e8fd87a1e 100644 --- a/code/datums/status_effects/debuffs.dm +++ b/code/datums/status_effects/debuffs.dm @@ -137,6 +137,33 @@ else new /obj/effect/temp_visual/bleed(get_turf(owner)) +/datum/status_effect/stacking/ground_pound + id = "ground_pound" + tick_interval = 5 SECONDS + stack_threshold = 3 + max_stacks = 3 + reset_ticks_on_stack = TRUE + var/mob/living/simple_animal/hostile/asteroid/big_legion/latest_attacker + +/datum/status_effect/stacking/ground_pound/on_creation(mob/living/new_owner, stacks_to_apply, mob/living/attacker) + . = ..() + if(.) + latest_attacker = attacker + +/datum/status_effect/stacking/ground_pound/add_stacks(stacks_added, mob/living/attacker) + . = ..() + if(.) + latest_attacker = attacker + if(stacks != stack_threshold) + return TRUE + +/datum/status_effect/stacking/ground_pound/stacks_consumed_effect() + flick("legion-smash", latest_attacker) + addtimer(CALLBACK(latest_attacker, /mob/living/simple_animal/hostile/asteroid/big_legion/.proc/throw_mobs), 1 SECONDS) + +/datum/status_effect/stacking/ground_pound/on_remove() + latest_attacker = null + /datum/status_effect/teleport_sickness id = "teleportation sickness" duration = 30 SECONDS diff --git a/code/datums/status_effects/status_effect.dm b/code/datums/status_effects/status_effect.dm index 590888b2c43..d8c4ebc3298 100644 --- a/code/datums/status_effects/status_effect.dm +++ b/code/datums/status_effects/status_effect.dm @@ -169,12 +169,7 @@ var/max_stacks //stacks cannot exceed this amount var/consumed_on_threshold = TRUE //if status should be removed once threshold is crossed var/threshold_crossed = FALSE //set to true once the threshold is crossed, false once it falls back below - var/overlay_file - var/underlay_file - var/overlay_state // states in .dmi must be given a name followed by a number which corresponds to a number of stacks. put the state name without the number in these state vars - var/underlay_state // the number is concatonated onto the string based on the number of stacks to get the correct state name - var/mutable_appearance/status_overlay - var/mutable_appearance/status_underlay + var/reset_ticks_on_stack = FALSE //resets the current tick timer if a stack is gained /datum/status_effect/stacking/proc/threshold_cross_effect() //what happens when threshold is crossed @@ -208,9 +203,9 @@ /datum/status_effect/stacking/proc/add_stacks(stacks_added) if(stacks_added > 0 && !can_gain_stacks()) return FALSE - owner.cut_overlay(status_overlay) - owner.underlays -= status_underlay stacks += stacks_added + if(reset_ticks_on_stack) + tick_interval = world.time + initial(tick_interval) if(stacks > 0) if(stacks >= stack_threshold && !threshold_crossed) //threshold_crossed check prevents threshold effect from occuring if changing from above threshold to still above threshold threshold_crossed = TRUE @@ -223,13 +218,9 @@ if(stacks_added > 0) tick_interval += delay_before_decay //refreshes time until decay stacks = min(stacks, max_stacks) - status_overlay.icon_state = "[overlay_state][stacks]" - status_underlay.icon_state = "[underlay_state][stacks]" - owner.add_overlay(status_overlay) - owner.underlays += status_underlay else fadeout_effect() - qdel(src) //deletes status if stacks fall under one + qdel(src) //deletes status if stacks fall under one return /datum/status_effect/stacking/on_creation(mob/living/new_owner, stacks_to_apply) . = ..() @@ -239,25 +230,6 @@ /datum/status_effect/stacking/on_apply() if(!can_have_status()) return FALSE - status_overlay = mutable_appearance(overlay_file, "[overlay_state][stacks]") - status_underlay = mutable_appearance(underlay_file, "[underlay_state][stacks]") - var/icon/I = icon(owner.icon, owner.icon_state, owner.dir) - var/icon_height = I.Height() - status_overlay.pixel_x = -owner.pixel_x - status_overlay.pixel_y = FLOOR(icon_height * 0.25, 1) - status_overlay.transform = matrix() * (icon_height/world.icon_size) //scale the status's overlay size based on the target's icon size - status_underlay.pixel_x = -owner.pixel_x - status_underlay.transform = matrix() * (icon_height/world.icon_size) * 3 - status_underlay.alpha = 40 - owner.add_overlay(status_overlay) - owner.underlays += status_underlay - return ..() - -/datum/status_effect/stacking/Destroy() - if(owner) - owner.cut_overlay(status_overlay) - owner.underlays -= status_underlay - QDEL_NULL(status_overlay) return ..() /// Status effect from multiple sources, when all sources are removed, so is the effect diff --git a/code/modules/mining/equipment/kinetic_crusher.dm b/code/modules/mining/equipment/kinetic_crusher.dm index 957a6e9a53e..08ae7a1f3bc 100644 --- a/code/modules/mining/equipment/kinetic_crusher.dm +++ b/code/modules/mining/equipment/kinetic_crusher.dm @@ -90,6 +90,14 @@ . = ..() if(!wielded) return + if(user.has_status_effect(STATUS_EFFECT_DASH) && user.a_intent == INTENT_HELP) + if(user.throw_at(target, range = 3, speed = 3, spin = FALSE, diagonals_first = TRUE)) + playsound(src, 'sound/effects/stealthoff.ogg', 50, 1, 1) + user.visible_message("[user] dashes!") + else + to_chat(user, "Something prevents you from dashing!") + user.remove_status_effect(STATUS_EFFECT_DASH) + return if(!proximity_flag && charged)//Mark a target, or mine a tile. var/turf/proj_turf = user.loc if(!isturf(proj_turf)) @@ -348,6 +356,20 @@ /obj/item/crusher_trophy/miner_eye/on_mark_detonation(mob/living/target, mob/living/user) user.apply_status_effect(STATUS_EFFECT_BLOODDRUNK) +//legion + +/obj/item/crusher_trophy/empowered_legion_skull + name = "empowered legion skull" + desc = "A powerful looking skull with glowing red eyes." + icon_state = "ashen_skull" + denied_type = /obj/item/crusher_trophy/empowered_legion_skull + +/obj/item/crusher_trophy/empowered_legion_skull/effect_desc() + return "mark detonation grants the ability to dash a short distance on help intent" + +/obj/item/crusher_trophy/empowered_legion_skull/on_mark_detonation(mob/living/target, mob/living/user) + user.apply_status_effect(STATUS_EFFECT_DASH) + //ash drake /obj/item/crusher_trophy/tail_spike desc = "A spike taken from an ash drake's tail. Suitable as a trophy for a kinetic crusher." diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm index 526053b3c15..65cc8cee9c0 100644 --- a/code/modules/mob/living/simple_animal/hostile/hostile.dm +++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm @@ -59,6 +59,8 @@ wanted_objects = typecacheof(wanted_objects) /mob/living/simple_animal/hostile/Destroy() + if(lose_patience_timer_id) + deltimer(lose_patience_timer_id) targets_from = null target = null return ..() @@ -507,6 +509,8 @@ //These two procs handle losing our target if we've failed to attack them for //more than lose_patience_timeout deciseconds, which probably means we're stuck /mob/living/simple_animal/hostile/proc/GainPatience() + if(QDELING(src)) + return if(lose_patience_timeout) LosePatience() lose_patience_timer_id = addtimer(CALLBACK(src, .proc/LoseTarget), lose_patience_timeout, TIMER_STOPPABLE) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/ancient_robot.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/ancient_robot.dm index 9a2f40660c1..d69402d348c 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/ancient_robot.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/ancient_robot.dm @@ -71,7 +71,7 @@ Difficulty: Hard del_on_death = TRUE loot = list(/obj/structure/closet/crate/necropolis/ancient) crusher_loot = list(/obj/structure/closet/crate/necropolis/ancient/crusher) - internal_type = /obj/item/gps/internal/ancient + internal_gps = /obj/item/gps/internal/ancient medal_type = BOSS_MEDAL_ROBOT score_type = ROBOT_SCORE deathmessage = "explodes into a shower of alloys" diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm index dd9eb59770d..12fe34e1163 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/blood_drunk_miner.dm @@ -44,7 +44,7 @@ Difficulty: Medium wander = FALSE del_on_death = TRUE blood_volume = BLOOD_VOLUME_NORMAL - internal_type = /obj/item/gps/internal/miner + internal_gps = /obj/item/gps/internal/miner medal_type = BOSS_MEDAL_MINER var/obj/item/melee/energy/cleaving_saw/miner/miner_saw var/time_until_next_transform = 0 diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm index 57cad951ec1..5875e70ae67 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm @@ -59,7 +59,7 @@ Difficulty: Hard var/enrage_till = 0 var/enrage_time = 70 var/revving_charge = FALSE - internal_type = /obj/item/gps/internal/bubblegum + internal_gps = /obj/item/gps/internal/bubblegum medal_type = BOSS_MEDAL_BUBBLEGUM score_type = BUBBLEGUM_SCORE deathmessage = "sinks into a pool of blood, fleeing the battle. You've won, for now... " diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm index 261b007ffa6..456f3725448 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm @@ -47,7 +47,7 @@ Difficulty: Very Hard pixel_x = -32 del_on_death = TRUE universal_speak = TRUE - internal_type = /obj/item/gps/internal/colossus + internal_gps = /obj/item/gps/internal/colossus medal_type = BOSS_MEDAL_COLOSSUS score_type = COLOSSUS_SCORE crusher_loot = list(/obj/structure/closet/crate/necropolis/colossus/crusher) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm index f90e0d6374c..f776ad641b7 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm @@ -55,7 +55,7 @@ Difficulty: Medium butcher_results = list(/obj/item/stack/ore/diamond = 5, /obj/item/stack/sheet/sinew = 5, /obj/item/stack/sheet/animalhide/ashdrake = 10, /obj/item/stack/sheet/bone = 30) var/swooping = NONE var/player_cooldown = 0 - internal_type = /obj/item/gps/internal/dragon + internal_gps = /obj/item/gps/internal/dragon medal_type = BOSS_MEDAL_DRAKE score_type = DRAKE_SCORE deathmessage = "collapses into a pile of bones, its flesh sloughing away." diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm index 6d96d6aaeaf..5d26805365d 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm @@ -58,7 +58,7 @@ Difficulty: Hard loot = list(/obj/item/hierophant_club) crusher_loot = list(/obj/item/hierophant_club, /obj/item/crusher_trophy/vortex_talisman) wander = FALSE - internal_type = /obj/item/gps/internal/hierophant + internal_gps = /obj/item/gps/internal/hierophant medal_type = BOSS_MEDAL_HIEROPHANT score_type = HIEROPHANT_SCORE del_on_death = TRUE diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm index d9701363d14..17f798ac163 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm @@ -18,38 +18,43 @@ Difficulty: Medium /mob/living/simple_animal/hostile/megafauna/legion name = "Legion" - health = 800 - maxHealth = 800 - icon_state = "legion" - icon_living = "legion" + health = 2500 + maxHealth = 2500 + icon_state = "mega_legion" + icon_living = "mega_legion" desc = "One of many." - icon = 'icons/mob/lavaland/legion.dmi' + icon = 'icons/mob/lavaland/96x96megafauna.dmi' attacktext = "chomps" attack_sound = 'sound/misc/demon_attack1.ogg' speak_emote = list("echoes") armour_penetration_percentage = 50 - melee_damage_lower = 25 - melee_damage_upper = 25 + melee_damage_lower = 40 + melee_damage_upper = 40 wander = FALSE speed = 2 ranged = TRUE del_on_death = TRUE retreat_distance = 5 minimum_distance = 5 + pixel_x = -32 ranged_cooldown_time = 20 - var/size = 5 var/charging = FALSE - internal_type = /obj/item/gps/internal/legion + var/firing_laser = FALSE + internal_gps = /obj/item/gps/internal/legion medal_type = BOSS_MEDAL_LEGION score_type = LEGION_SCORE - pixel_y = -90 - pixel_x = -75 - loot = list(/obj/item/stack/sheet/bone = 3) + loot = list(/obj/item/staff/storm) + crusher_loot = list(/obj/item/staff/storm, /obj/item/crusher_trophy/empowered_legion_skull) vision_range = 13 elimination = TRUE appearance_flags = 0 mouse_opacity = MOUSE_OPACITY_ICON stat_attack = UNCONSCIOUS // Overriden from /tg/ - otherwise Legion starts chasing its minions + appearance_flags = 512 + +/mob/living/simple_animal/hostile/megafauna/legion/Initialize(mapload) + . = ..() + transform *= 2 /mob/living/simple_animal/hostile/megafauna/legion/AttackingTarget() . = ..() @@ -61,81 +66,108 @@ Difficulty: Medium /mob/living/simple_animal/hostile/megafauna/legion/OpenFire(the_target) if(world.time >= ranged_cooldown && !charging) - if(prob(75)) - var/mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion/A = new(loc) - A.GiveTarget(target) - A.friends = friends - A.faction = faction - ranged_cooldown = world.time + ranged_cooldown_time - else + if(prob(30)) visible_message("[src] charges!") SpinAnimation(speed = 20, loops = 5, parallel = FALSE) ranged = FALSE retreat_distance = 0 minimum_distance = 0 + move_to_delay = 2 speed = 0 charging = TRUE - spawn(50) - reset_charge() + ranged_cooldown = world.time + 3 SECONDS + SLEEP_CHECK_DEATH(3 SECONDS) + set_ranged() + else if(prob(60)) + firing_laser = TRUE + var/beam_angle = get_angle(src, locate(target.x - 1, target.y, target.z)) // -1 to account for the legion sprite offset. + var/turf/target_location = locate(x + (50 * sin(beam_angle)), y + (50 * cos(beam_angle)), z) + var/beam_time = 0.25 SECONDS + ((health / maxHealth) SECONDS) + playsound(loc, 'sound/effects/basscannon.ogg', 200, TRUE) + Beam(target_location, icon_state = "death_laser", time = beam_time, maxdistance = INFINITY, beam_type = /obj/effect/ebeam/disintegration_telegraph) + addtimer(CALLBACK(src, .proc/fire_disintegration_laser, target_location), beam_time) + ranged_cooldown = world.time + beam_time + 2 SECONDS + SLEEP_CHECK_DEATH(beam_time + 2 SECONDS) + firing_laser = FALSE + else if(prob(40)) + var/mob/living/simple_animal/hostile/asteroid/big_legion/A = new(loc) + A.GiveTarget(target) + A.friends = friends + A.faction = faction + visible_message("A monstrosity emerges from [src]", + "You summon a big [A]!") + ranged_cooldown = world.time + 5 SECONDS + else + var/mob/living/simple_animal/hostile/asteroid/hivelord/legion/tendril/A = new(loc) + A.GiveTarget(target) + A.friends = friends + A.faction = faction + visible_message("A [A] emerges from [src]!", + "You summon a [A]!") + ranged_cooldown = world.time + 2 SECONDS -/mob/living/simple_animal/hostile/megafauna/legion/proc/reset_charge() +/mob/living/simple_animal/hostile/megafauna/legion/MoveToTarget() + if(firing_laser) + return + ..() + +/mob/living/simple_animal/hostile/megafauna/legion/Move() + if(firing_laser) + return FALSE + . = ..() + +/mob/living/simple_animal/hostile/megafauna/legion/Goto(target, delay, minimum_distance) + if(firing_laser) + return + ..() + +/mob/living/simple_animal/hostile/megafauna/legion/proc/set_ranged() ranged = TRUE retreat_distance = 5 minimum_distance = 5 + move_to_delay = 2 speed = 2 charging = FALSE -/mob/living/simple_animal/hostile/megafauna/legion/can_die() - return ..() && health <= 0 +/mob/living/simple_animal/hostile/megafauna/legion/proc/fire_disintegration_laser(location) + playsound(loc, 'sound/weapons/marauder.ogg', 200, TRUE) + Beam(location, icon_state = "death_laser", time = 2 SECONDS, maxdistance = INFINITY, beam_type = /obj/effect/ebeam/disintegration) + for(var/turf/t in getline(src, location)) + if(ismineralturf(t)) + var/turf/simulated/mineral/M = t + M.gets_drilled(src) + for(var/mob/living/M in t) + if(faction_check(M.faction, faction, FALSE)) + continue -/mob/living/simple_animal/hostile/megafauna/legion/death() - if(!can_die()) - return FALSE - if(size > 1) - adjustHealth(-maxHealth) //heal ourself to full in prep for splitting - var/mob/living/simple_animal/hostile/megafauna/legion/L = new(loc) - - L.maxHealth = maxHealth * 0.6 - maxHealth = L.maxHealth - - L.health = L.maxHealth - health = maxHealth - - size-- - L.size = size - - L.resize = L.size * 0.2 - transform = initial(transform) - resize = size * 0.2 - - L.update_transform() - update_transform() - - L.faction = faction.Copy() - - L.GiveTarget(target) - - visible_message("[src] splits in twain!") - return FALSE // not dead - else - // this must come before the parent call due to the setting of `loot` here - var/last_legion = TRUE - for(var/mob/living/simple_animal/hostile/megafauna/legion/other in GLOB.mob_list) - if(other != src) - last_legion = FALSE - break - if(last_legion) - loot = list(/obj/item/staff/storm) - elimination = FALSE - else if(prob(5)) - loot = list(/obj/structure/closet/crate/necropolis/tendril) - if(!true_spawn) - loot = null - return ..() + if(M.stat == DEAD) + visible_message("[M] is disintegrated by the beam!") + M.dust() + else if(M != src) + playsound(M,'sound/weapons/sear.ogg', 50, TRUE, -4) + to_chat(M, "You're struck by a disintegration laser!") + var/limb_to_hit = M.get_organ(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 = M.run_armor_check(limb_to_hit, LASER) + M.apply_damage(70 - ((health / maxHealth) * 20), BURN, limb_to_hit, armor) /mob/living/simple_animal/hostile/megafauna/legion/Process_Spacemove(movement_dir = 0) return 1 +/mob/living/simple_animal/hostile/megafauna/legion/adjustHealth(amount, updating_health = TRUE) + . = ..() + if(QDELETED(src)) + return + if(.) + var/matrix/M = new + resize = 1 + (health / maxHealth) + M.Scale(resize, resize) + transform = M + if(amount > 0 && prob(33)) + var/mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion/A = new(loc) + A.GiveTarget(target) + A.friends = friends + A.faction = faction + /obj/item/gps/internal/legion icon_state = null gpstag = "Echoing Signal" diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm index 69b8098542b..485b1ec0b3a 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm @@ -33,7 +33,6 @@ var/elimination = FALSE var/anger_modifier = 0 var/obj/item/gps/internal_gps - var/internal_type var/recovery_time = 0 var/true_spawn = TRUE // if this is a megafauna that should grant achievements, or have a gps signal var/nest_range = 10 @@ -42,8 +41,8 @@ /mob/living/simple_animal/hostile/megafauna/Initialize(mapload) . = ..() - if(internal_type && true_spawn) - internal = new internal_type(src) + if(internal_gps && true_spawn) + internal = new internal_gps(src) for(var/action_type in attack_action_types) var/datum/action/innate/megafauna_attack/attack_action = new action_type() attack_action.Grant(src) diff --git a/code/modules/mob/living/simple_animal/hostile/mining/hivelord.dm b/code/modules/mob/living/simple_animal/hostile/mining/hivelord.dm index a6fefabc5c5..35b76e65849 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining/hivelord.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining/hivelord.dm @@ -279,42 +279,51 @@ can_infest_dead = TRUE //Legion that spawns Legions -/mob/living/simple_animal/hostile/big_legion - name = "legion" - desc = "One of many." +/mob/living/simple_animal/hostile/asteroid/big_legion + name = "big legion" + desc = "This monstrosity has clearly been corrupting for centuries, and is looking for a fight. Rumours claim it is capable of throwing the strongest of miners and his name is Billy." icon = 'icons/mob/lavaland/64x64megafauna.dmi' icon_state = "legion" icon_living = "legion" - icon_dead = "legion" - health = 450 - maxHealth = 450 - melee_damage_lower = 20 - melee_damage_upper = 20 - anchored = FALSE - AIStatus = AI_ON - stop_automated_movement = FALSE + icon_dead = "legion-dead" + health = 350 + maxHealth = 350 + melee_damage_lower = 30 + melee_damage_upper = 30 wander = TRUE - maxbodytemp = INFINITY layer = MOB_LAYER - del_on_death = TRUE + move_force = MOVE_FORCE_VERY_STRONG + move_resist = MOVE_FORCE_VERY_STRONG + pull_force = MOVE_FORCE_VERY_STRONG sentience_type = SENTIENCE_BOSS attack_sound = 'sound/misc/demon_attack1.ogg' - loot = list(/obj/item/organ/internal/regenerative_core/legion = 3, /obj/effect/mob_spawn/human/corpse/damaged/legioninfested = 5) - move_to_delay = 14 - vision_range = 5 - aggro_vision_range = 9 - speed = 3 - faction = list("mining") - weather_immunities = list("lava","ash") - obj_damage = 30 - environment_smash = ENVIRONMENT_SMASH_STRUCTURES - see_in_dark = 8 - lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE + speed = 0 +/mob/living/simple_animal/hostile/asteroid/big_legion/AttackingTarget() + if(!isliving(target)) + return ..() + var/mob/living/L = target + var/datum/status_effect/stacking/ground_pound/G = L.has_status_effect(STATUS_EFFECT_GROUNDPOUND) + if(!G) + L.apply_status_effect(STATUS_EFFECT_GROUNDPOUND, 1, src) + return ..() + if(G.add_stacks(stacks_added = 1, attacker = src)) + return ..() -/mob/living/simple_animal/hostile/big_legion/Initialize(mapload) - .=..() - AddComponent(/datum/component/spawner, list(/mob/living/simple_animal/hostile/asteroid/hivelord/legion), 200, faction, "peels itself off from", 3) +/mob/living/simple_animal/hostile/asteroid/big_legion/proc/throw_mobs() + playsound(src, 'sound/effects/meteorimpact.ogg', 200, TRUE, 2, TRUE) + for(var/mob/living/L in range(3, src)) + if(faction_check(faction, L.faction, FALSE)) + continue + + L.visible_message("[L] was thrown by [src]!", + "You feel a strong force throwing you!", + "You hear a thud.") + var/atom/throw_target = get_edge_target_turf(L, get_dir(src, get_step_away(L, src))) + L.throw_at(throw_target, 4, 4) + var/limb_to_hit = L.get_organ(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(def_zone = limb_to_hit, attack_flag = MELEE, armour_penetration_percentage = 50) + L.apply_damage(40, BRUTE, limb_to_hit, armor) //Tendril-spawned Legion remains, the charred skeletons of those whose bodies sank into laval or fell into chasms. /obj/effect/mob_spawn/human/corpse/charredskeleton diff --git a/icons/effects/beam.dmi b/icons/effects/beam.dmi index 930781e2f36..f3195929c8c 100644 Binary files a/icons/effects/beam.dmi and b/icons/effects/beam.dmi differ diff --git a/icons/mob/lavaland/64x64megafauna.dmi b/icons/mob/lavaland/64x64megafauna.dmi index 428a433f1cd..2a8077f1ab5 100644 Binary files a/icons/mob/lavaland/64x64megafauna.dmi and b/icons/mob/lavaland/64x64megafauna.dmi differ diff --git a/icons/obj/lavaland/artefacts.dmi b/icons/obj/lavaland/artefacts.dmi index d4a75fd23c7..32eeb480a37 100644 Binary files a/icons/obj/lavaland/artefacts.dmi and b/icons/obj/lavaland/artefacts.dmi differ