From daca99898124f7ce927ceb804e4957bb83828b2c Mon Sep 17 00:00:00 2001 From: Qwertytoforty <52090703+Qwertytoforty@users.noreply.github.com> Date: Sat, 30 Jul 2022 15:22:28 -0400 Subject: [PATCH] [TM READY] Ports lavaland elites from TG. (#18448) * startup, expect like 50 unneeded icons, not bug free:tm: * Hope works. Cloak works. Buffs for AI controlled. Faction fix. * map speed buffs, fixes resummon health decay * Adds roles. Adds Mirror walk. Nerfs revival, especialy for non antag summoned. * I am denser than bluespace ore * x2 antag cooldown, update desc for cloak * removes 66% burn damage resist from elites * honestly just knock that down * herald not speaking right, fuckup with max hp fix * Thanks hal! Co-authored-by: Charlie <69320440+hal9000PR@users.noreply.github.com> * changes, changes, and more changes, oh my! * Update code/datums/status_effects/buffs.dm Co-authored-by: Charlie <69320440+hal9000PR@users.noreply.github.com> * GC stuff * oh, and just one more thing * no gibtonite gaming * Huston we have a FUCKING PROBLEM * oopsy doopsy * but just one more thing (again, gc stuff) * Lets all elites speak their mind * NO LAVA * grab ghost, legion charge red. * dust the dusting from the code * no mirror cargo shuttle crossing * need to stop making small changes, x2 broodmother * herald no longer crashes the MC * Lower broodmother cooldown, herald down 5 brute and , legionare gets more smoke and thermals, pandora gets chasers * remove extra brackets, x 2 on aoe squares * pandora now respects factions * fixes teleporting to tumor if reactivated by someone else. Herald has light, boost elites make message * requested changes * mirroring a wanted change Co-authored-by: AffectedArc07 <25063394+AffectedArc07@users.noreply.github.com> Co-authored-by: Charlie <69320440+hal9000PR@users.noreply.github.com> Co-authored-by: AffectedArc07 <25063394+AffectedArc07@users.noreply.github.com> --- .../lavaland_surface_elite_tumor.dmm | 132 +++++ code/__DEFINES/role_preferences.dm | 2 + code/__DEFINES/rolebans.dm | 3 +- code/__DEFINES/status_effects.dm | 1 + code/__HELPERS/traits.dm | 1 + code/_globalvars/lists/objects.dm | 1 + code/_globalvars/traits.dm | 3 +- code/datums/action.dm | 4 + code/datums/ruins/lavaland.dm | 8 + code/datums/status_effects/buffs.dm | 48 ++ code/game/gamemodes/cult/cult_items.dm | 8 + code/game/jobs/job_exp.dm | 1 + .../objects/items/weapons/melee/energy.dm | 2 + code/game/objects/structures/mirror.dm | 3 + code/modules/client/preference/preferences.dm | 1 + code/modules/clothing/clothing.dm | 17 + .../clothing/under/accessories/accessory.dm | 6 + .../hostile/megafauna/hierophant.dm | 2 +- .../hostile/mining/elites/elite.dm | 460 ++++++++++++++++++ .../mining/elites/goliath_broodmother.dm | 284 +++++++++++ .../hostile/mining/elites/herald.dm | 336 +++++++++++++ .../hostile/mining/elites/legionnaire.dm | 346 +++++++++++++ .../hostile/mining/elites/pandora.dm | 238 +++++++++ .../simple_animal/hostile/mining/mining.dm | 3 +- config/example/config.toml | 1 + icons/mob/actions/actions_elites.dmi | Bin 0 -> 11655 bytes icons/mob/lavaland/lavaland_elites.dmi | Bin 0 -> 21371 bytes icons/mob/screen_alert.dmi | Bin 64351 -> 65157 bytes icons/mob/ties.dmi | Bin 22340 -> 23844 bytes icons/obj/clothing/ties_overlay.dmi | Bin 4141 -> 5669 bytes icons/obj/lavaland/artefacts.dmi | Bin 26348 -> 26788 bytes icons/obj/lavaland/elite_trophies.dmi | Bin 0 -> 1057 bytes icons/obj/lavaland/legionnaire_bonfire.dmi | Bin 0 -> 1184 bytes icons/obj/lavaland/tumor.dmi | Bin 0 -> 988 bytes paradise.dme | 5 + 35 files changed, 1912 insertions(+), 4 deletions(-) create mode 100644 _maps/map_files/RandomRuins/LavaRuins/lavaland_surface_elite_tumor.dmm create mode 100644 code/modules/mob/living/simple_animal/hostile/mining/elites/elite.dm create mode 100644 code/modules/mob/living/simple_animal/hostile/mining/elites/goliath_broodmother.dm create mode 100644 code/modules/mob/living/simple_animal/hostile/mining/elites/herald.dm create mode 100644 code/modules/mob/living/simple_animal/hostile/mining/elites/legionnaire.dm create mode 100644 code/modules/mob/living/simple_animal/hostile/mining/elites/pandora.dm create mode 100644 icons/mob/actions/actions_elites.dmi create mode 100644 icons/mob/lavaland/lavaland_elites.dmi create mode 100644 icons/obj/lavaland/elite_trophies.dmi create mode 100644 icons/obj/lavaland/legionnaire_bonfire.dmi create mode 100644 icons/obj/lavaland/tumor.dmi diff --git a/_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_elite_tumor.dmm b/_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_elite_tumor.dmm new file mode 100644 index 00000000000..62721ec4f3d --- /dev/null +++ b/_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_elite_tumor.dmm @@ -0,0 +1,132 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"a" = ( +/turf/template_noop, +/area/template_noop) +"k" = ( +/obj/structure/elite_tumor, +/obj/effect/mapping_helpers/no_lava, +/turf/simulated/floor/plating/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors) +"q" = ( +/obj/effect/decal/remains/human, +/obj/effect/mapping_helpers/no_lava, +/turf/simulated/floor/plating/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors) +"u" = ( +/obj/effect/mapping_helpers/no_lava, +/turf/simulated/floor/plating/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors) +"E" = ( +/obj/item/stack/ore/iron, +/obj/effect/mapping_helpers/no_lava, +/turf/simulated/floor/plating/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors) +"M" = ( +/obj/item/stack/ore/glass/basalt, +/obj/effect/mapping_helpers/no_lava, +/turf/simulated/floor/plating/asteroid/basalt/lava_land_surface, +/area/lavaland/surface/outdoors) +"V" = ( +/obj/effect/mapping_helpers/no_lava, +/turf/template_noop, +/area/template_noop) + +(1,1,1) = {" +a +a +a +a +a +a +a +a +a +"} +(2,1,1) = {" +a +V +V +V +V +V +V +V +a +"} +(3,1,1) = {" +a +V +u +E +u +u +u +V +a +"} +(4,1,1) = {" +a +V +u +u +u +u +q +V +a +"} +(5,1,1) = {" +a +V +u +u +k +u +u +V +a +"} +(6,1,1) = {" +a +V +u +M +u +u +u +V +a +"} +(7,1,1) = {" +a +V +u +u +u +u +u +V +a +"} +(8,1,1) = {" +a +V +V +V +V +V +V +V +a +"} +(9,1,1) = {" +a +a +a +a +a +a +a +a +a +"} diff --git a/code/__DEFINES/role_preferences.dm b/code/__DEFINES/role_preferences.dm index b7bc7864e62..89847fe1246 100644 --- a/code/__DEFINES/role_preferences.dm +++ b/code/__DEFINES/role_preferences.dm @@ -41,6 +41,7 @@ #define ROLE_DEATHSQUAD "deathsquad" #define ROLE_EVENTMISC "eventmisc" #define ROLE_GHOST "ghost role" +#define ROLE_ELITE "lavaland elite" // Misc jobban categories #define ROLEBAN_AHUD "AntagHUD" @@ -64,6 +65,7 @@ GLOBAL_LIST_INIT(special_roles, list( ROLE_REV = /datum/game_mode/revolution, // Revolutionary ROLE_SENTIENT, // Sentient animal ROLE_DEMON, // Slaguther demon + ROLE_ELITE, // Lavaland Elite ROLE_NINJA, // Space ninja ROLE_TRADER, // Trader ROLE_TRAITOR = /datum/game_mode/traitor, // Traitor diff --git a/code/__DEFINES/rolebans.dm b/code/__DEFINES/rolebans.dm index 4ac9aac00f3..ec5dd31daa8 100644 --- a/code/__DEFINES/rolebans.dm +++ b/code/__DEFINES/rolebans.dm @@ -25,5 +25,6 @@ GLOBAL_LIST_INIT(other_roles, list( ROLE_ERT, ROLE_GHOST, ROLEBAN_AHUD, - ROLEBAN_RECORDS + ROLEBAN_RECORDS, + ROLE_ELITE )) diff --git a/code/__DEFINES/status_effects.dm b/code/__DEFINES/status_effects.dm index 602dd47b76a..e2ccb39f534 100644 --- a/code/__DEFINES/status_effects.dm +++ b/code/__DEFINES/status_effects.dm @@ -44,6 +44,7 @@ #define STATUS_EFFECT_CHAINSAW_SLAYING /datum/status_effect/chainsaw_slaying // Stun immunity, very slight damage resistance +#define STATUS_EFFECT_HOPE /datum/status_effect/hope // Healing that scales when injured (but not in deep crit), and nice messages to keep the hope ///////////// // DEBUFFS // diff --git a/code/__HELPERS/traits.dm b/code/__HELPERS/traits.dm index dcd979ee1fd..922200948bb 100644 --- a/code/__HELPERS/traits.dm +++ b/code/__HELPERS/traits.dm @@ -193,6 +193,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_NOPAIN "no_pain" #define TRAIT_FORCE_DOORS "force_doors" #define TRAIT_AI_UNTRACKABLE "AI_untrackable" +#define TRAIT_ELITE_CHALLENGER "elite_challenger" //***** ITEM TRAITS *****// /// Show what machine/door wires do when held. diff --git a/code/_globalvars/lists/objects.dm b/code/_globalvars/lists/objects.dm index ee2fb9b16a1..e0a881643a7 100644 --- a/code/_globalvars/lists/objects.dm +++ b/code/_globalvars/lists/objects.dm @@ -43,6 +43,7 @@ GLOBAL_LIST_INIT(meteor_list, list()) //list of all meteors GLOBAL_LIST_INIT(poi_list, list()) //list of points of interest for observe/follow GLOBAL_LIST_INIT(active_jammers, list()) // List of active radio jammers GLOBAL_LIST_EMPTY(ladders) +GLOBAL_LIST_EMPTY(mirrors) //list of all mirrors and mirror shields. GLOBAL_LIST_INIT(active_diseases, list()) //List of Active disease in all mobs; purely for quick referencing. diff --git a/code/_globalvars/traits.dm b/code/_globalvars/traits.dm index d32ced24403..fa009ae3102 100644 --- a/code/_globalvars/traits.dm +++ b/code/_globalvars/traits.dm @@ -66,7 +66,8 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_NOPAIN" = TRAIT_NOPAIN, "TRAIT_FORCE_DOORS" = TRAIT_FORCE_DOORS, "TRAIT_EMOTE_MUTE" = TRAIT_EMOTE_MUTE, - "TRAIT_AI_UNTRACKABLE" = TRAIT_AI_UNTRACKABLE + "TRAIT_AI_UNTRACKABLE" = TRAIT_AI_UNTRACKABLE, + "TRAIT_ELITE_CHALLENGER" = TRAIT_ELITE_CHALLENGER ), /obj/item = list( "TRAIT_SHOW_WIRE_INFO" = TRAIT_SHOW_WIRE_INFO, diff --git a/code/datums/action.dm b/code/datums/action.dm index c6267235683..e2328f7ac99 100644 --- a/code/datums/action.dm +++ b/code/datums/action.dm @@ -518,6 +518,10 @@ name = "View Storage" +/datum/action/item_action/accessory/herald + name = "Mirror Walk" + desc = "Use near a mirror to enter it" + //Preset for spells /datum/action/spell_action check_flags = 0 diff --git a/code/datums/ruins/lavaland.dm b/code/datums/ruins/lavaland.dm index 66181ae282c..13f4a628d58 100644 --- a/code/datums/ruins/lavaland.dm +++ b/code/datums/ruins/lavaland.dm @@ -214,6 +214,14 @@ suffix = "lavaland_surface_puzzle.dmm" cost = 5 +/datum/map_template/ruin/lavaland/tumor + name = "Elite Tumor" + id = "tumor" + description = "The victor freed, the loser the next fighter. The ghosts, the endless spectators. And thus the cycle loops..." + suffix = "lavaland_surface_elite_tumor.dmm" + cost = 5 + always_place = TRUE + /datum/map_template/ruin/lavaland/monster_nest name = "Monster Nest" id = "monsternest" diff --git a/code/datums/status_effects/buffs.dm b/code/datums/status_effects/buffs.dm index 80e64bba326..77530cd2778 100644 --- a/code/datums/status_effects/buffs.dm +++ b/code/datums/status_effects/buffs.dm @@ -412,3 +412,51 @@ H.physiology.brute_mod /= 0.8 H.physiology.burn_mod /=0.8 H.physiology.stamina_mod /= 0.8 + +/datum/status_effect/hope + id = "hope" + duration = -1 + tick_interval = 2 SECONDS + status_type = STATUS_EFFECT_UNIQUE + alert_type = /obj/screen/alert/status_effect/hope + +/obj/screen/alert/status_effect/hope + name = "Hope." + desc = "A ray of hope beyond dispair." + icon_state = "hope" + +/datum/status_effect/hope/tick() + if(owner.stat == DEAD || owner.health <= HEALTH_THRESHOLD_DEAD) // No dead healing, or healing in dead crit + return + if(owner.health > 50) + if(prob(0.5)) + hope_message() + return + var/heal_multiplier = min(3, ((50 - owner.health) / 50 + 1)) // 1 hp at 50 health, 2 at 0, 3 at -50 + owner.adjustBruteLoss(-heal_multiplier * 0.5) + owner.adjustFireLoss(-heal_multiplier * 0.5) + owner.adjustOxyLoss(-heal_multiplier) + if(prob(heal_multiplier * 2)) + hope_message() + +/datum/status_effect/hope/proc/hope_message() + var/list/hope_messages = list("You are filled with [pick("hope", "determination", "strength", "peace", "confidence", "robustness")].", + "Don't give up!", + "You see your [pick("friends", "family", "coworkers", "self")] [pick("rooting for you", "cheering you on", "worrying about you")].", + "You can't give up now, keep going!", + "But you refused to die!", + "You have been through worse, you can do this!", + "People need you, do not [pick("give up", "stop", "rest", "pass away", "falter", "lose hope")] yet!", + "This person is not nearly as robust as you!", + "You ARE robust, don't let anyone tell you otherwise!", + "[owner], don't lose hope, the future of the station depends on you!", + "Do not follow the light yet!") + var/list/un_hopeful_messages = list("DON'T FUCKING DIE NOW COWARD!", + "Git Gud, [owner]", + "I bet a [pick("vox", "vulp", "nian", "tajaran", "baldie")] could do better than you!", + "You hear people making fun of you for getting robusted.") + if(prob(99)) + to_chat(owner, "[pick(hope_messages)]") + else + to_chat(owner, "[pick(un_hopeful_messages)]") + diff --git a/code/game/gamemodes/cult/cult_items.dm b/code/game/gamemodes/cult/cult_items.dm index 87e168731ed..b270227a8f9 100644 --- a/code/game/gamemodes/cult/cult_items.dm +++ b/code/game/gamemodes/cult/cult_items.dm @@ -444,6 +444,14 @@ /// Shatter threshold for Energy weapons var/energy_threshold = 20 +/obj/item/shield/mirror/Initialize(mapload) + . = ..() + GLOB.mirrors += src + +/obj/item/shield/mirror/Destroy() + GLOB.mirrors -= src + return ..() + /** * Reflect/Block/Shatter proc. * diff --git a/code/game/jobs/job_exp.dm b/code/game/jobs/job_exp.dm index 7c355ce61c0..9b88f119835 100644 --- a/code/game/jobs/job_exp.dm +++ b/code/game/jobs/job_exp.dm @@ -20,6 +20,7 @@ GLOBAL_LIST_INIT(role_playtime_requirements, list( ROLE_NINJA = 20, ROLE_MORPH = 5, ROLE_DEMON = 5, + ROLE_ELITE = 5, // DUO ANTAGS ROLE_GUARDIAN = 20, diff --git a/code/game/objects/items/weapons/melee/energy.dm b/code/game/objects/items/weapons/melee/energy.dm index d5476bd11b8..b7bf841d5a2 100644 --- a/code/game/objects/items/weapons/melee/energy.dm +++ b/code/game/objects/items/weapons/melee/energy.dm @@ -285,6 +285,8 @@ var/swiping = FALSE /obj/item/melee/energy/cleaving_saw/nemesis_effects(mob/living/user, mob/living/target) + if(istype(target, /mob/living/simple_animal/hostile/asteroid/elite)) // you get the bonus damage, but the bleed buildup is too much. + return var/datum/status_effect/saw_bleed/B = target.has_status_effect(STATUS_EFFECT_SAWBLEED) if(!B) if(!active) //This isn't in the above if-check so that the else doesn't care about active diff --git a/code/game/objects/structures/mirror.dm b/code/game/objects/structures/mirror.dm index 725b557a78b..493e41ab4c6 100644 --- a/code/game/objects/structures/mirror.dm +++ b/code/game/objects/structures/mirror.dm @@ -22,9 +22,11 @@ pixel_x = -32 if(WEST) pixel_x = 32 + GLOB.mirrors += src /obj/structure/mirror/Destroy() QDEL_LIST_ASSOC_VAL(ui_users) + GLOB.mirrors -= src return ..() /obj/structure/mirror/attack_hand(mob/user) @@ -48,6 +50,7 @@ if(desc == initial(desc)) desc = "Oh no, seven years of bad luck!" broken = TRUE + GLOB.mirrors -= src /obj/structure/mirror/screwdriver_act(mob/user, obj/item/I) . = TRUE diff --git a/code/modules/client/preference/preferences.dm b/code/modules/client/preference/preferences.dm index df07c138759..94e84c318f9 100644 --- a/code/modules/client/preference/preferences.dm +++ b/code/modules/client/preference/preferences.dm @@ -14,6 +14,7 @@ GLOBAL_LIST_INIT(special_role_times, list( //minimum age (in days) for accounts ROLE_ALIEN = 21, ROLE_DEMON = 21, ROLE_SENTIENT = 21, + ROLE_ELITE = 21, // ROLE_GANG = 21, ROLE_NINJA = 21, ROLE_GSPIDER = 21, diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index 50ff83049ce..da9e05fddd6 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -711,6 +711,23 @@ BLIND // can't see anything QDEL_LIST(accessories) return ..() + +/obj/item/clothing/under/dropped(mob/user, silent) + ..() + if(!ishuman(user)) + return + var/mob/living/carbon/human/H = user + if(H.get_item_by_slot(slot_w_uniform) == src) + for(var/obj/item/clothing/accessory/A in accessories) + A.attached_unequip() + +/obj/item/clothing/under/equipped(mob/user, slot, initial) + if(!ishuman(user)) + return + if(slot == slot_w_uniform) + for(var/obj/item/clothing/accessory/A in accessories) + A.attached_equip() + /* * # can_attach_accessory * diff --git a/code/modules/clothing/under/accessories/accessory.dm b/code/modules/clothing/under/accessories/accessory.dm index db8bbdfa676..55c13758203 100644 --- a/code/modules/clothing/under/accessories/accessory.dm +++ b/code/modules/clothing/under/accessories/accessory.dm @@ -99,6 +99,12 @@ return //we aren't an object on the ground so don't call parent ..() +/obj/item/clothing/accessory/proc/attached_unequip(mob/user) // If we need to do something special when clothing is removed from the user + return + +/obj/item/clothing/accessory/proc/attached_equip(mob/user) // If we need to do something special when clothing is removed from the user + return + /obj/item/clothing/accessory/blue name = "blue tie" icon_state = "bluetie" 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 dba9400ac8a..1022756f7a9 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm @@ -673,7 +673,7 @@ Difficulty: Hard return for(var/mob/living/L in T.contents - hit_things) //find and damage mobs... hit_things += L - if((friendly_fire_check && caster && caster.faction_check_mob(L)) || L.stat == DEAD) + if((friendly_fire_check && caster && L.faction_check_mob(caster)) || L.stat == DEAD) continue L.flash_screen_color("#660099", 1) playsound(L,'sound/weapons/sear.ogg', 50, TRUE, -4) diff --git a/code/modules/mob/living/simple_animal/hostile/mining/elites/elite.dm b/code/modules/mob/living/simple_animal/hostile/mining/elites/elite.dm new file mode 100644 index 00000000000..e43e6b4cd3b --- /dev/null +++ b/code/modules/mob/living/simple_animal/hostile/mining/elites/elite.dm @@ -0,0 +1,460 @@ +#define TUMOR_INACTIVE 0 +#define TUMOR_ACTIVE 1 +#define TUMOR_PASSIVE 2 + +//Elite mining mobs +/mob/living/simple_animal/hostile/asteroid/elite + name = "elite" + desc = "An elite monster, found in one of the strange tumors on lavaland." + icon = 'icons/mob/lavaland/lavaland_elites.dmi' + faction = list("boss") + robust_searching = TRUE + ranged_ignores_vision = TRUE + ranged = TRUE + obj_damage = 30 + vision_range = 6 + aggro_vision_range = 18 + environment_smash = ENVIRONMENT_SMASH_NONE //This is to prevent elites smashing up the mining station (entirely), we'll make sure they can smash minerals fine below. + harm_intent_damage = 0 //Punching elites gets you nowhere + stat_attack = UNCONSCIOUS + layer = LARGE_MOB_LAYER + has_laser_resist = FALSE + universal_speak = TRUE + sentience_type = SENTIENCE_BOSS + var/chosen_attack = 1 + var/list/attack_action_types = list() + var/obj/loot_drop = null + var/revive_cooldown = FALSE + +//Gives player-controlled variants the ability to swap attacks +/mob/living/simple_animal/hostile/asteroid/elite/Initialize(mapload) + . = ..() + for(var/action_type in attack_action_types) + var/datum/action/innate/elite_attack/attack_action = new action_type() + attack_action.Grant(src) + +//Prevents elites from attacking members of their faction (can't hurt themselves either) and lets them mine rock with an attack despite not being able to smash walls. + +/mob/living/simple_animal/hostile/asteroid/elite/examine(mob/user) + . = ..() + if(del_on_death) + . += "However, this one appears appears less wild in nature, and calmer around people." + +/mob/living/simple_animal/hostile/asteroid/elite/AttackingTarget() + if(istype(target, /mob/living/simple_animal/hostile)) + var/mob/living/simple_animal/hostile/M = target + if(faction_check_mob(M)) + return FALSE + if(istype(target, /obj/structure/elite_tumor)) + var/obj/structure/elite_tumor/T = target + if(T.mychild == src && T.activity == TUMOR_PASSIVE) + var/response = alert(src, "Re-enter the tumor?","Despawn yourself?", "Yes", "No") + if(response == "No" || QDELETED(src) || !Adjacent(T)) + return + T.clear_activator(src) + T.mychild = null + T.activity = TUMOR_INACTIVE + T.icon_state = "advanced_tumor" + qdel(src) + return FALSE + . = ..() + if(ismineralturf(target)) + var/turf/simulated/mineral/M = target + M.gets_drilled() + if(istype(target, /obj/mecha)) + var/obj/mecha/M = target + M.take_damage(50, BRUTE, MELEE, 1) + if(. && isliving(target)) //Taken from megafauna. This exists purely to stop someone from cheesing a weaker melee fauna by letting it get punched. + var/mob/living/L = target + if(L.stat != DEAD) + if(!client && ranged && ranged_cooldown <= world.time) + OpenFire() + + +/mob/living/simple_animal/hostile/asteroid/elite/proc/revive_multiplier() //If on lavaland, return 1, or 1x cooldown. 10 if revived by a non antag, 2 if by an antag. 1 otherwise + if(is_mining_level(z)) + return 1 + if(revive_cooldown) + return 10 + if(del_on_death) + return 2 + return 1 + +/mob/living/simple_animal/hostile/asteroid/elite/adjustHealth(damage, updating_health) + . = ..() + if(del_on_death) + maxHealth -= damage / 3 + +/mob/living/simple_animal/hostile/asteroid/elite/ex_act(severity, origin) //No surrounding the tumor with gibtonite and one shotting them. + switch(severity) + if(EXPLODE_DEVASTATE) + adjustBruteLoss(75) + + if(EXPLODE_HEAVY) + adjustBruteLoss(50) + + if(EXPLODE_LIGHT) + adjustBruteLoss(25) + + +/*Basic setup for elite attacks, based on Whoneedspace's megafauna attack setup. +While using this makes the system rely on OnFire, it still gives options for timers not tied to OnFire, and it makes using attacks consistent accross the board for player-controlled elites.*/ + +/datum/action/innate/elite_attack + name = "Elite Attack" + icon_icon = 'icons/mob/actions/actions_elites.dmi' + button_icon_state = "" + background_icon_state = "bg_default" + ///The displayed message into chat when this attack is selected + var/chosen_message + ///The internal attack ID for the elite's OpenFire() proc to use + var/chosen_attack_num = 0 + +/datum/action/innate/elite_attack/New(Target) + . = ..() + button.maptext = "" + button.maptext_x = 8 + button.maptext_y = 0 + button.maptext_width = 24 + button.maptext_height = 12 + return button + +/datum/action/innate/elite_attack/process() + if(owner == null) + STOP_PROCESSING(SSfastprocess, src) + qdel(src) + return + UpdateButton() + +/datum/action/innate/elite_attack/proc/UpdateButton(status_only = FALSE) + if(status_only) + return + var/mob/living/simple_animal/hostile/asteroid/elite/elite_owner = owner + var/timeleft = max(elite_owner.ranged_cooldown - world.time, 0) + if(timeleft == 0) + button.maptext = "" + else + button.maptext = "[round(timeleft/10, 0.1)]" + +/datum/action/innate/elite_attack/Grant(mob/living/L) + if(istype(L, /mob/living/simple_animal/hostile/asteroid/elite)) + START_PROCESSING(SSfastprocess, src) + return ..() + return FALSE + +/datum/action/innate/elite_attack/Activate() + var/mob/living/simple_animal/hostile/asteroid/elite/elite_owner = owner + elite_owner.chosen_attack = chosen_attack_num + to_chat(elite_owner, chosen_message) + +//The Pulsing Tumor, the actual "spawn-point" of elites, handles the spawning, arena, and procs for dealing with basic scenarios. + +/obj/structure/elite_tumor + name = "pulsing tumor" + desc = "An odd, pulsing tumor sticking out of the ground. You feel compelled to reach out and touch it..." + resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF + icon = 'icons/obj/lavaland/tumor.dmi' + icon_state = "tumor" + pixel_x = -16 + light_color = LIGHT_COLOR_BLOOD_MAGIC + light_range = 3 + anchored = TRUE + density = FALSE + var/activity = TUMOR_INACTIVE + var/boosted = FALSE + var/times_won = 0 + var/mob/living/carbon/human/activator = null + var/mob/living/simple_animal/hostile/asteroid/elite/mychild = null + var/gps + ///List of all potentially spawned elites + var/potentialspawns = list( + /mob/living/simple_animal/hostile/asteroid/elite/broodmother, + /mob/living/simple_animal/hostile/asteroid/elite/pandora, + /mob/living/simple_animal/hostile/asteroid/elite/legionnaire, + /mob/living/simple_animal/hostile/asteroid/elite/herald, + ) + +/obj/structure/elite_tumor/attack_hand(mob/user, list/modifiers) + . = ..() + if(!ishuman(user)) + return + switch(activity) + if(TUMOR_PASSIVE) + // Prevents the user from being forcemoved back and forth between two elite arenas. + if(HAS_TRAIT(src, TRAIT_ELITE_CHALLENGER)) + user.visible_message("[user] reaches for [src] with [user.p_their()] arm, but nothing happens.", + "You reach for [src] with your arm... but nothing happens.") + return + activity = TUMOR_ACTIVE + user.visible_message("[src] convulses as [user]'s arm enters its radius. Uh-oh...", + "[src] convulses as your arm enters its radius. Your instincts tell you to step back.") + make_activator(user) + if(boosted) + mychild.playsound_local(get_turf(mychild), 'sound/magic/cult_spell.ogg', 40, 0) + to_chat(mychild, "Someone has activated your tumor. You will be returned to fight shortly, get ready!") + addtimer(CALLBACK(src, .proc/return_elite), 3 SECONDS) + INVOKE_ASYNC(src, .proc/arena_checks) + if(TUMOR_INACTIVE) + if(HAS_TRAIT(src, TRAIT_ELITE_CHALLENGER)) + user.visible_message("[user] reaches for [src] with [user.p_their()] arm, but nothing happens.", + "You reach for [src] with your arm... but nothing happens.") + return + activity = TUMOR_ACTIVE + var/mob/dead/observer/elitemind = null + visible_message("[src] begins to convulse. Your instincts tell you to step back.") + make_activator(user) + if(!boosted) + addtimer(CALLBACK(src, .proc/spawn_elite), 3 SECONDS) + return + visible_message("Something within [src] stirs...") + var/list/candidates = SSghost_spawns.poll_candidates("Do you want to play as a lavaland elite?", ROLE_ELITE, TRUE, 10 SECONDS, source = src) + if(length(candidates)) + audible_message("The stirring sounds increase in volume!") + elitemind = pick(candidates) + SEND_SOUND(elitemind, 'sound/magic/cult_spell.ogg') + to_chat(elitemind, "You have been chosen to play as a Lavaland Elite.\nIn a few seconds, you will be summoned on Lavaland as a monster to fight your activator, in a fight to the death.\n\ + Your attacks can be switched using the buttons on the top left of the HUD, and used by clicking on targets or tiles similar to a gun.\n\ + While the opponent might have an upper hand with powerful mining equipment and tools, you have great power normally limited by AI mobs.\n\ + If you want to win, you'll have to use your powers in creative ways to ensure the kill. It's suggested you try using them all as soon as possible.\n\ + Should you win, you'll receive extra information regarding what to do after. Good luck!") + addtimer(CALLBACK(src, .proc/spawn_elite, elitemind), 10 SECONDS) + else + visible_message("The stirring stops, and nothing emerges. Perhaps try again later.") + activity = TUMOR_INACTIVE + clear_activator(user) + +/obj/structure/elite_tumor/proc/spawn_elite(mob/dead/observer/elitemind) + var/selectedspawn = pick(potentialspawns) + mychild = new selectedspawn(loc) + visible_message("[mychild] emerges from [src]!") + playsound(loc,'sound/effects/phasein.ogg', 200, 0, 50, TRUE, TRUE) + if(boosted) + mychild.key = elitemind.key + mychild.sentience_act() + notify_ghosts("\A [mychild] has been awakened in \the [get_area(src)]!", enter_link="(Click to help)", source = mychild, action = NOTIFY_FOLLOW) + icon_state = "tumor_popped" + RegisterSignal(mychild, COMSIG_PARENT_QDELETING, .proc/onEliteLoss) + INVOKE_ASYNC(src, .proc/arena_checks) + +/obj/structure/elite_tumor/proc/return_elite() + mychild.forceMove(loc) + visible_message("[mychild] emerges from [src]!") + playsound(loc,'sound/effects/phasein.ogg', 200, 0, 50, TRUE, TRUE) + mychild.revive() + if(boosted) + mychild.maxHealth = mychild.maxHealth * 2.5 + mychild.health = mychild.maxHealth + mychild.grab_ghost() + notify_ghosts("\A [mychild] has been challenged in \the [get_area(src)]!", enter_link="(Click to help)", source = mychild, action = NOTIFY_FOLLOW) + +/obj/structure/elite_tumor/Initialize(mapload) + . = ..() + gps = new /obj/item/gps/internal/tumor(src) + START_PROCESSING(SSobj, src) + +/obj/structure/elite_tumor/Destroy() + STOP_PROCESSING(SSobj, src) + QDEL_NULL(gps) + if(activator) + clear_activator(activator) + if(mychild) + clear_activator(mychild) + return ..() + +/obj/structure/elite_tumor/proc/make_activator(mob/user) + if(activator) + return + activator = user + ADD_TRAIT(user, TRAIT_ELITE_CHALLENGER, "activation") + RegisterSignal(user, COMSIG_PARENT_QDELETING, .proc/clear_activator) + +/obj/structure/elite_tumor/proc/clear_activator(mob/source) + SIGNAL_HANDLER + if(source == activator) + activator = null + else + mychild = null + REMOVE_TRAIT(source, TRAIT_ELITE_CHALLENGER, "clear activation") + UnregisterSignal(source, COMSIG_PARENT_QDELETING) + +/obj/structure/elite_tumor/process() + if(!isturf(loc)) + return + + for(var/mob/living/simple_animal/hostile/asteroid/elite/elitehere in loc) + if(elitehere == mychild && activity == TUMOR_PASSIVE) + mychild.adjustHealth(-mychild.maxHealth * 0.025) + var/obj/effect/temp_visual/heal/H = new /obj/effect/temp_visual/heal(get_turf(mychild)) + H.color = "#FF0000" + +/obj/structure/elite_tumor/attackby(obj/item/attacking_item, mob/user, params) + . = ..() + if(istype(attacking_item, /obj/item/organ/internal/regenerative_core) && activity == TUMOR_INACTIVE && !boosted) + var/obj/item/organ/internal/regenerative_core/core = attacking_item + visible_message("As [user] drops the core into [src], [src] appears to swell.") + icon_state = "advanced_tumor" + boosted = TRUE + set_light(6) + qdel(core) + return TRUE + +/obj/structure/elite_tumor/examine(mob/user) + . = ..() + if(boosted) + . += "this one glows with a strong intensity" + +/obj/structure/elite_tumor/proc/arena_checks() + if(activity != TUMOR_ACTIVE || QDELETED(src)) + return + INVOKE_ASYNC(src, .proc/fighters_check) //Checks to see if our fighters died. + INVOKE_ASYNC(src, .proc/arena_trap) //Gets another arena trap queued up for when this one runs out. + INVOKE_ASYNC(src, .proc/border_check) //Checks to see if our fighters got out of the arena somehow. + addtimer(CALLBACK(src, .proc/arena_checks), 5 SECONDS) + +/obj/structure/elite_tumor/proc/fighters_check() + if(QDELETED(mychild) || mychild.stat == DEAD) + onEliteLoss() + return + if(QDELETED(activator) || activator.stat == DEAD || (activator.health <= HEALTH_THRESHOLD_DEAD)) + onEliteWon() + +/obj/structure/elite_tumor/proc/arena_trap() + 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 + +/obj/structure/elite_tumor/proc/border_check() + if(activator != null && get_dist(src, activator) >= 12) + activator.forceMove(loc) + visible_message("[activator] suddenly reappears above [src]!") + playsound(loc,'sound/effects/phasein.ogg', 200, 0, 50, TRUE, TRUE) + if(mychild != null && get_dist(src, mychild) >= 12) + mychild.forceMove(loc) + visible_message("[mychild] suddenly reappears above [src]!") + playsound(loc,'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("[src] begins to convulse violently before beginning to dissipate.") + visible_message("As [src] closes, something is forced up from down below.") + var/obj/structure/closet/crate/necropolis/tendril/lootbox = new /obj/structure/closet/crate/necropolis/tendril(loc) + if(boosted) + if(mychild.loot_drop != null && prob(50)) + new mychild.loot_drop(lootbox) + else + new /obj/item/tumor_shard(lootbox) + SSblackbox.record_feedback("tally", "Player controlled Elite loss", 1, mychild.name) + else + SSblackbox.record_feedback("tally", "AI controlled Elite loss", 1, mychild.name) + qdel(src) + +/obj/structure/elite_tumor/proc/onEliteWon() + activity = TUMOR_PASSIVE + if(activator) + clear_activator(activator) + mychild.revive() + if(boosted) + SSblackbox.record_feedback("tally", "Player controlled Elite win", 1, mychild.name) + times_won++ + mychild.maxHealth = mychild.maxHealth * 0.4 + mychild.health = mychild.maxHealth + var/sound/elite_sound = sound('sound/magic/wandodeath.ogg') + var/turf/T = get_turf(src) + for(var/mob/M in GLOB.player_list) + if(M.z == z && M.client) + to_chat(M, "Thunder rumbles. Light glows in the distance. Something big happened... somewhere.") + M.playsound_local(T, null, 100, FALSE, 0, FALSE, pressure_affected = FALSE, S = elite_sound) + M.flash_screen_color("#FF0000", 2.5 SECONDS) + else + SSblackbox.record_feedback("tally", "AI controlled Elite win", 1, mychild.name) + if(times_won == 1) + mychild.playsound_local(get_turf(mychild), 'sound/magic/cult_spell.ogg', 40, 0) + to_chat(mychild, "") + to_chat(mychild, "Your max health has been halved, but can now heal by standing on your tumor. Note, it's your only way to heal.\n\ + 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!") + to_chat(mychild, "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!") + +/obj/item/tumor_shard + name = "tumor shard" + desc = "A strange, sharp, crystal shard from an odd tumor on Lavaland. Stabbing the corpse of a lavaland elite with this will revive them, assuming their soul still lingers. Revived lavaland elites only have half their max health, but are completely loyal to their reviver." + icon = 'icons/obj/lavaland/artefacts.dmi' + icon_state = "crevice_shard" + throwforce = 5 + w_class = WEIGHT_CLASS_SMALL + throw_speed = 3 + throw_range = 5 + +/obj/item/tumor_shard/afterattack(atom/target, mob/user, proximity_flag) + . = ..() + if(istype(target, /mob/living/simple_animal/hostile/asteroid/elite) && proximity_flag) + var/mob/living/simple_animal/hostile/asteroid/elite/E = target + if(E.stat != DEAD || E.sentience_type != SENTIENCE_BOSS || !E.key) + user.visible_message("It appears [E] is unable to be revived right now. Perhaps try again later.") + return + E.faction = list("\ref[user]") + E.friends += user + E.revive() + user.visible_message("[user] stabs [E] with [src], reviving it.") + SEND_SOUND(E, 'sound/magic/cult_spell.ogg') + to_chat(E, "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.") + to_chat(E, "Note that you now share the loyalties of [user]. You are expected not to intentionally sabotage their faction unless commanded to!") + if(user.mind.special_role) + E.maxHealth = 300 + E.health = 300 + else + E.maxHealth = 200 + E.health = 200 + E.revive_cooldown = TRUE + E.sentience_type = SENTIENCE_ORGANIC + E.del_on_death = TRUE + qdel(src) + else + to_chat(user, "[src] only works on the corpse of a sentient lavaland elite.") + +/obj/effect/temp_visual/elite_tumor_wall + name = "magic wall" + icon = 'icons/turf/walls/hierophant_wall_temp.dmi' + icon_state = "hierophant_wall_temp-0" + base_icon_state = "hierophant_wall_temp" + smoothing_flags = SMOOTH_BITMASK + smoothing_groups = list(SMOOTH_GROUP_HIERO_WALL) + canSmoothWith = list(SMOOTH_GROUP_HIERO_WALL) + duration = 50 + layer = BELOW_MOB_LAYER + plane = GAME_PLANE + color = rgb(255,0,0) + light_range = MINIMUM_USEFUL_LIGHT_RANGE + light_color = LIGHT_COLOR_PURE_RED + var/activator + var/ourelite + +/obj/effect/temp_visual/elite_tumor_wall/Initialize(mapload, new_caster) + . = ..() + if(smoothing_flags & (SMOOTH_CORNERS|SMOOTH_BITMASK)) + QUEUE_SMOOTH_NEIGHBORS(src) + QUEUE_SMOOTH(src) + +/obj/effect/temp_visual/elite_tumor_wall/Destroy() + if(smoothing_flags & (SMOOTH_CORNERS|SMOOTH_BITMASK)) + QUEUE_SMOOTH_NEIGHBORS(src) + return ..() + +/obj/effect/temp_visual/elite_tumor_wall/CanPass(atom/movable/mover, border_dir) + . = ..() + if(mover == ourelite || mover == activator) + return FALSE + +/obj/item/gps/internal/tumor + icon_state = null + gpstag = "Cancerous Signal" + desc = "Ghosts in a fauna? That's cancerous!" + invisibility = 100 diff --git a/code/modules/mob/living/simple_animal/hostile/mining/elites/goliath_broodmother.dm b/code/modules/mob/living/simple_animal/hostile/mining/elites/goliath_broodmother.dm new file mode 100644 index 00000000000..f81d74f8506 --- /dev/null +++ b/code/modules/mob/living/simple_animal/hostile/mining/elites/goliath_broodmother.dm @@ -0,0 +1,284 @@ +#define TENTACLE_PATCH 1 +#define SPAWN_CHILDREN 2 +#define RAGE 3 +#define CALL_CHILDREN 4 + +/** + * # Goliath Broodmother + * + * A stronger, faster variation of the goliath. Has the ability to spawn baby goliaths, which it can later detonate at will. + * When it's health is below half, tendrils will spawn randomly around it. When it is below a quarter of health, this effect is doubled. + * It's attacks are as follows: + * - Spawns a 3x3/plus shape of tentacles on the target location + * - Spawns 2 baby goliaths on its tile, up to a max of 8. Children blow up when they die. + * - The broodmother lets out a noise, and is able to move faster for 6.5 seconds. + * - Summons your children around you. + * The broodmother is a fight revolving around stage control, as the activator has to manage the baby goliaths and the broodmother herself, along with all the tendrils. + */ + +/mob/living/simple_animal/hostile/asteroid/elite/broodmother + name = "goliath broodmother" + desc = "An example of sexual dimorphism, this female goliath looks much different than the males of her species. She is, however, just as dangerous, if not more." + gender = FEMALE + icon_state = "broodmother" + icon_living = "broodmother" + icon_aggro = "broodmother" + icon_dead = "egg_sac" + icon_gib = "syndicate_gib" + maxHealth = 1000 + health = 1000 + melee_damage_lower = 30 + melee_damage_upper = 30 + armour_penetration = 30 + attacktext = "beats down on" + attack_sound = 'sound/weapons/punch1.ogg' + throw_message = "does nothing to the rocky hide of the" + speed = 2 + move_to_delay = 5 + mob_biotypes = MOB_ORGANIC|MOB_BEAST + mouse_opacity = MOUSE_OPACITY_ICON + deathmessage = "explodes into gore!" + loot_drop = /obj/item/crusher_trophy/broodmother_tongue + + attack_action_types = list(/datum/action/innate/elite_attack/tentacle_patch, + /datum/action/innate/elite_attack/spawn_children, + /datum/action/innate/elite_attack/rage, + /datum/action/innate/elite_attack/call_children) + + var/rand_tent = 0 + var/list/mob/living/simple_animal/hostile/asteroid/elite/broodmother_child/children_list = list() + +/datum/action/innate/elite_attack/tentacle_patch + name = "Tentacle Patch" + button_icon_state = "tentacle_patch" + chosen_message = "You are now attacking with a patch of tentacles." + chosen_attack_num = TENTACLE_PATCH + +/datum/action/innate/elite_attack/spawn_children + name = "Spawn Children" + button_icon_state = "spawn_children" + chosen_message = "You will spawn two children at your location to assist you in combat. You can have up to 8." + chosen_attack_num = SPAWN_CHILDREN + +/datum/action/innate/elite_attack/rage + name = "Rage" + button_icon_state = "rage" + chosen_message = "You will temporarily increase your movement speed." + chosen_attack_num = RAGE + +/datum/action/innate/elite_attack/call_children + name = "Call Children" + button_icon_state = "call_children" + chosen_message = "You will summon your children to your location." + chosen_attack_num = CALL_CHILDREN + +/mob/living/simple_animal/hostile/asteroid/elite/broodmother/Destroy() + for(var/mob/living/simple_animal/hostile/asteroid/elite/broodmother_child/C in children_list) + C.mother = null + children_list.Cut() + children_list = null + return ..() + +/mob/living/simple_animal/hostile/asteroid/elite/broodmother/OpenFire() + if(client) + switch(chosen_attack) + if(TENTACLE_PATCH) + tentacle_patch(target) + if(SPAWN_CHILDREN) + spawn_children() + if(RAGE) + rage() + if(CALL_CHILDREN) + call_children() + return + var/aiattack = rand(1,4) + switch(aiattack) + if(TENTACLE_PATCH) + tentacle_patch(target) + if(SPAWN_CHILDREN) + spawn_children() + if(RAGE) + rage() + if(CALL_CHILDREN) + call_children() + +/mob/living/simple_animal/hostile/asteroid/elite/broodmother/Life(seconds, times_fired) + . = ..() + if(!.) //Checks if they are dead as a rock. + return + if(health < maxHealth * 0.5 && rand_tent < world.time) + rand_tent = world.time + 30 + var/tentacle_amount = 5 + if(health < maxHealth * 0.25) + tentacle_amount = 10 + var/tentacle_loc = spiral_range_turfs(5, get_turf(src)) + for(var/i in 1 to tentacle_amount) + var/turf/t = pick_n_take(tentacle_loc) + new /obj/effect/temp_visual/goliath_tentacle/broodmother(t, src) + +/mob/living/simple_animal/hostile/asteroid/elite/broodmother/proc/tentacle_patch(target) + ranged_cooldown = world.time + 2.5 SECONDS * revive_multiplier() + var/tturf = get_turf(target) + if(!isturf(tturf)) + return + visible_message("[src] digs its tentacles under [target]!") + new /obj/effect/temp_visual/goliath_tentacle/broodmother/patch(tturf, src) + +/mob/living/simple_animal/hostile/asteroid/elite/broodmother/proc/spawn_children(target) + ranged_cooldown = world.time + 3 SECONDS * revive_multiplier() + visible_message("The ground churns behind [src]!") + for(var/i in 1 to 2) + if(length(children_list) >= 8) + return + var/mob/living/simple_animal/hostile/asteroid/elite/broodmother_child/newchild = new /mob/living/simple_animal/hostile/asteroid/elite/broodmother_child(loc) + newchild.GiveTarget(target) + newchild.faction = faction.Copy() + visible_message("[newchild] appears below [src]!") + newchild.mother = src + children_list += newchild + +/mob/living/simple_animal/hostile/asteroid/elite/broodmother/proc/rage() + ranged_cooldown = world.time + 5 SECONDS * revive_multiplier() + visible_message("[src] starts picking up speed!") + color = "#FF0000" + speed = 0 + move_to_delay = 3 + addtimer(CALLBACK(src, .proc/reset_rage), 65) + +/mob/living/simple_animal/hostile/asteroid/elite/broodmother/proc/reset_rage() + color = "#FFFFFF" + speed = 2 + move_to_delay = 5 + +/mob/living/simple_animal/hostile/asteroid/elite/broodmother/proc/call_children() + ranged_cooldown = world.time + 4 SECONDS * revive_multiplier() + visible_message("The ground shakes near [src]!") + var/list/directions = GLOB.cardinal.Copy() + GLOB.diagonals.Copy() + for(var/mob/child in children_list) + var/spawndir = pick_n_take(directions) + var/turf/T = get_step(src, spawndir) + if(T) + child.forceMove(T) + 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. +/mob/living/simple_animal/hostile/asteroid/elite/broodmother_child + name = "baby goliath" + desc = "A young goliath recently born from it's mother. While they hatch from eggs, said eggs are incubated in the mother until they are ready to be born." + icon = 'icons/mob/lavaland/lavaland_monsters.dmi' + icon_state = "goliath_baby" + icon_living = "goliath_baby" + 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 + attacktext = "bashes against" + attack_sound = 'sound/weapons/punch1.ogg' + throw_message = "does nothing to the rocky hide of the" + speed = 2 + move_to_delay = 5 + mob_biotypes = MOB_ORGANIC|MOB_BEAST + mouse_opacity = MOUSE_OPACITY_ICON + deathmessage = "falls to the ground." + status_flags = CANPUSH + var/mob/living/simple_animal/hostile/asteroid/elite/broodmother/mother = null + + +/mob/living/simple_animal/hostile/asteroid/elite/broodmother_child/Destroy() + if(!QDELETED(mother)) + mother.children_list -= src + mother = null + return ..() + +/mob/living/simple_animal/hostile/asteroid/elite/broodmother_child/OpenFire(target) + ranged_cooldown = world.time + 40 + var/tturf = get_turf(target) + if(!isturf(tturf)) + return + if(get_dist(src, target) <= 7)//Screen range check, so it can't attack people off-screen + visible_message("[src] digs its tentacles under [target]!") + new /obj/effect/temp_visual/goliath_tentacle/broodmother(tturf, src) + +/mob/living/simple_animal/hostile/asteroid/elite/broodmother_child/death() + . = ..() + if(!QDELETED(mother)) + mother.children_list -= src + visible_message("[src] explodes!") + explosion(src, flame_range = 3, adminlog = FALSE) + new /obj/item/stack/sheet/animalhide/goliath_hide(loc) + new /obj/effect/gibspawner/human(get_turf(src)) + qdel(src) + +//Tentacles stun WAY less compared to regular variant, to balance being able to use them much more often. Also, 10 more damage. +/obj/effect/temp_visual/goliath_tentacle/broodmother/trip() + var/latched = FALSE + for(var/mob/living/L in loc) + if((!QDELETED(spawner) && spawner.faction_check_mob(L)) || L.stat == DEAD) + continue + visible_message("[src] grabs hold of [L]!") + L.Stun(1 SECONDS) + L.adjustBruteLoss(rand(20,25)) + latched = TRUE + if(!latched) + retract() + else + deltimer(timerid) + timerid = addtimer(CALLBACK(src, .proc/retract), 1 SECONDS, TIMER_STOPPABLE) + +/obj/effect/temp_visual/goliath_tentacle/broodmother/patch/Initialize(mapload, new_spawner) + . = ..() + INVOKE_ASYNC(src, .proc/createpatch) + +/obj/effect/temp_visual/goliath_tentacle/broodmother/patch/proc/createpatch() + var/tentacle_locs = spiral_range_turfs(1, get_turf(src)) + for(var/T in tentacle_locs) + new /obj/effect/temp_visual/goliath_tentacle/broodmother(T, spawner) + var/list/directions = GLOB.cardinal.Copy() + for(var/i in directions) + var/turf/T = get_step(get_turf(src), i) + T = get_step(T, i) + new /obj/effect/temp_visual/goliath_tentacle/broodmother(T, spawner) + +// Broodmother's loot: Broodmother Tongue +/obj/item/crusher_trophy/broodmother_tongue + name = "broodmother tongue" + desc = "The tongue of a broodmother. If attached a certain way, makes for a suitable crusher trophy. It also feels very spongey, I wonder what would happen if you squeezed it?..." + icon = 'icons/obj/lavaland/elite_trophies.dmi' + icon_state = "broodmother_tongue" + denied_type = /obj/item/crusher_trophy/broodmother_tongue + bonus_value = 25 + /// Time at which the item becomes usable again + var/use_time + +/obj/item/crusher_trophy/broodmother_tongue/effect_desc() + return "mark detonation to have a [bonus_value]% chance to summon a patch of goliath tentacles at the target's location" + +/obj/item/crusher_trophy/broodmother_tongue/on_mark_detonation(mob/living/target, mob/living/user) + if(rand(1, 100) <= bonus_value && target.stat != DEAD) + new /obj/effect/temp_visual/goliath_tentacle/broodmother/patch(get_turf(target), user) + +/obj/item/crusher_trophy/broodmother_tongue/attack_self(mob/user) + if(!isliving(user)) + return + var/mob/living/living_user = user + if(use_time > world.time) + to_chat(living_user, "The tongue looks dried out. You'll need to wait longer to use it again.") + return + else if("lava" in living_user.weather_immunities) + to_chat(living_user, "You stare at the tongue. You don't think this is any use to you.") + return + living_user.weather_immunities += "lava" + to_chat(living_user, "You squeeze the tongue, and some transluscent liquid shoots out all over you.") + addtimer(CALLBACK(src, .proc/remove_lava, living_user), 10 SECONDS) + use_time = world.time + 60 SECONDS + +/obj/item/crusher_trophy/broodmother_tongue/proc/remove_lava(mob/living/user) + user.weather_immunities -= "lava" + +#undef TENTACLE_PATCH +#undef SPAWN_CHILDREN +#undef RAGE +#undef CALL_CHILDREN diff --git a/code/modules/mob/living/simple_animal/hostile/mining/elites/herald.dm b/code/modules/mob/living/simple_animal/hostile/mining/elites/herald.dm new file mode 100644 index 00000000000..84337f2d341 --- /dev/null +++ b/code/modules/mob/living/simple_animal/hostile/mining/elites/herald.dm @@ -0,0 +1,336 @@ +#define HERALD_TRISHOT 1 +#define HERALD_DIRECTIONALSHOT 2 +#define HERALD_TELESHOT 3 +#define HERALD_MIRROR 4 + +/** + * # Herald + * + * A slow-moving projectile user with a few tricks up it's sleeve. Less unga-bunga than Colossus, with more cleverness in it's fighting style. + * As it's health gets lower, the amount of projectiles fired per-attack increases. + * It's attacks are as follows: + * - Fires three projectiles in a given direction. + * - Fires a spread in every cardinal and diagonal direction at once, then does it again after a bit. + * - Shoots a single, golden bolt. Wherever it lands, the herald will be teleported to the location. + * - Spawns a mirror which reflects projectiles directly at the target. + * Herald is a more concentrated variation of the Colossus fight, having less projectiles overall, but more focused attacks. + */ + +/mob/living/simple_animal/hostile/asteroid/elite/herald + name = "herald" + desc = "A monstrous beast which fires deadly projectiles at threats and prey." + icon_state = "herald" + icon_living = "herald" + icon_aggro = "herald" + icon_dead = "herald_dying" + icon_gib = "syndicate_gib" + maxHealth = 1000 + health = 1000 + melee_damage_lower = 20 + melee_damage_upper = 20 + light_power = 5 + light_range = 2 + light_color = "#FF0000" + attacktext = "preaches to" + attack_sound = 'sound/magic/ratvar_attack.ogg' + throw_message = "doesn't affect the purity of" + speed = 2 + move_to_delay = 10 + mouse_opacity = MOUSE_OPACITY_ICON + death_sound = 'sound/misc/demon_dies.ogg' + deathmessage = "begins to shudder as it becomes transparent..." + loot_drop = /obj/item/clothing/accessory/necklace/herald_cloak + + + attack_action_types = list(/datum/action/innate/elite_attack/herald_trishot, + /datum/action/innate/elite_attack/herald_directionalshot, + /datum/action/innate/elite_attack/herald_teleshot, + /datum/action/innate/elite_attack/herald_mirror) + + var/mob/living/simple_animal/hostile/asteroid/elite/herald/mirror/my_mirror = null + var/is_mirror = FALSE + +/mob/living/simple_animal/hostile/asteroid/elite/herald/death() + . = ..() + if(!is_mirror) + addtimer(CALLBACK(src, .proc/become_ghost), 0.8 SECONDS) + if(my_mirror) + QDEL_NULL(my_mirror) + + +/mob/living/simple_animal/hostile/asteroid/elite/herald/Destroy() + if(my_mirror) + QDEL_NULL(my_mirror) + return ..() + +/mob/living/simple_animal/hostile/asteroid/elite/herald/proc/become_ghost() + icon_state = "herald_ghost" + +/mob/living/simple_animal/hostile/asteroid/elite/herald/say(message, bubble_type, list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE, forced = null, filterproof = null) + . = ..() + playsound(get_turf(src), 'sound/magic/clockwork/invoke_general.ogg', 20, TRUE) + +/datum/action/innate/elite_attack/herald_trishot + name = "Triple Shot" + button_icon_state = "herald_trishot" + chosen_message = "You are now firing three shots in your chosen direction." + chosen_attack_num = HERALD_TRISHOT + +/datum/action/innate/elite_attack/herald_directionalshot + name = "Circular Shot" + button_icon_state = "herald_directionalshot" + chosen_message = "You are firing projectiles in all directions." + chosen_attack_num = HERALD_DIRECTIONALSHOT + +/datum/action/innate/elite_attack/herald_teleshot + name = "Teleport Shot" + button_icon_state = "herald_teleshot" + chosen_message = "You will now fire a shot which teleports you where it lands." + chosen_attack_num = HERALD_TELESHOT + +/datum/action/innate/elite_attack/herald_mirror + name = "Summon Mirror" + button_icon_state = "herald_mirror" + chosen_message = "You will spawn a mirror which duplicates your attacks." + chosen_attack_num = HERALD_MIRROR + +/mob/living/simple_animal/hostile/asteroid/elite/herald/OpenFire() + if(client) + switch(chosen_attack) + if(HERALD_TRISHOT) + herald_trishot(target) + my_mirror?.herald_trishot(target) + if(HERALD_DIRECTIONALSHOT) + herald_directionalshot() + my_mirror?.herald_directionalshot() + if(HERALD_TELESHOT) + herald_teleshot(target) + my_mirror?.herald_teleshot(target) + if(HERALD_MIRROR) + herald_mirror() + return + var/aiattack = rand(1,4) + switch(aiattack) + if(HERALD_TRISHOT) + herald_trishot(target) + my_mirror?.herald_trishot(target) + if(HERALD_DIRECTIONALSHOT) + herald_directionalshot() + my_mirror?.herald_directionalshot() + if(HERALD_TELESHOT) + herald_teleshot(target) + my_mirror?.herald_teleshot(target) + if(HERALD_MIRROR) + herald_mirror() + +/mob/living/simple_animal/hostile/asteroid/elite/herald/proc/shoot_projectile(turf/marker, set_angle, is_teleshot, is_trishot) + var/turf/startloc = get_turf(src) + if(!is_teleshot) + var/obj/item/projectile/H = new /obj/item/projectile/herald(startloc) + H.preparePixelProjectile(marker, marker, src) + H.firer = src + H.firer_source_atom = src + if(target) + H.original = target + H.fire(set_angle) + if(is_trishot) + shoot_projectile(marker, set_angle + 15, FALSE, FALSE) + shoot_projectile(marker, set_angle - 15, FALSE, FALSE) + else + var/obj/item/projectile/H = new /obj/item/projectile/herald/teleshot(startloc) + H.preparePixelProjectile(marker, marker, startloc) + H.firer = src + H.firer_source_atom = src + if(target) + H.original = target + H.fire(set_angle) + +/mob/living/simple_animal/hostile/asteroid/elite/herald/proc/herald_trishot(target) + ranged_cooldown = world.time + 3 SECONDS * revive_multiplier() + playsound(get_turf(src), 'sound/magic/clockwork/invoke_general.ogg', 20, TRUE) + var/target_turf = get_turf(target) + var/angle_to_target = get_angle(src, target_turf) + 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) + addtimer(CALLBACK(src, .proc/shoot_projectile, target_turf, angle_to_target, FALSE, TRUE), 0.4 SECONDS) + if(health < maxHealth * 0.5 && !is_mirror) + playsound(get_turf(src), 'sound/magic/clockwork/invoke_general.ogg', 20, TRUE) + addtimer(CALLBACK(src, .proc/shoot_projectile, target_turf, angle_to_target, FALSE, TRUE), 1 SECONDS) + addtimer(CALLBACK(src, .proc/shoot_projectile, target_turf, angle_to_target, FALSE, TRUE), 1.2 SECONDS) + addtimer(CALLBACK(src, .proc/shoot_projectile, target_turf, angle_to_target, FALSE, TRUE), 1.4 SECONDS) + +/mob/living/simple_animal/hostile/asteroid/elite/herald/proc/herald_circleshot(offset) + var/static/list/directional_shot_angles = list(1, 45, 90, 135, 180, 225, 270, 315) //Trust me, use 1. It really doesn't like zero. + for(var/i in directional_shot_angles) + shoot_projectile(get_turf(src), i + offset, FALSE, FALSE) + +/mob/living/simple_animal/hostile/asteroid/elite/herald/proc/unenrage() + if(stat == DEAD || is_mirror) + return + icon_state = "herald" + +/mob/living/simple_animal/hostile/asteroid/elite/herald/proc/herald_directionalshot() + ranged_cooldown = world.time + 3 SECONDS * revive_multiplier() + if(!is_mirror) + icon_state = "herald_enraged" + playsound(get_turf(src), 'sound/magic/clockwork/invoke_general.ogg', 20, TRUE) + addtimer(CALLBACK(src, .proc/herald_circleshot, 0), 0.5 SECONDS) + if(health < maxHealth * 0.5 && !is_mirror) + addtimer(CALLBACK(src, .proc/herald_circleshot, 22.5), 1.5 SECONDS) + addtimer(CALLBACK(src, .proc/unenrage), 20) + +/mob/living/simple_animal/hostile/asteroid/elite/herald/proc/herald_teleshot(target) + ranged_cooldown = world.time + 3 SECONDS * revive_multiplier() + playsound(get_turf(src), 'sound/magic/clockwork/invoke_general.ogg', 20, TRUE) + var/target_turf = get_turf(target) + var/angle_to_target = get_angle(src, target_turf) + shoot_projectile(target_turf, angle_to_target, TRUE, FALSE) + +/mob/living/simple_animal/hostile/asteroid/elite/herald/proc/herald_mirror() + ranged_cooldown = world.time + 4 SECONDS * revive_multiplier() + playsound(get_turf(src), 'sound/magic/clockwork/invoke_general.ogg', 20, TRUE) + if(my_mirror != null) + QDEL_NULL(my_mirror) + var/mob/living/simple_animal/hostile/asteroid/elite/herald/mirror/new_mirror = new /mob/living/simple_animal/hostile/asteroid/elite/herald/mirror(loc) + my_mirror = new_mirror + my_mirror.my_master = src + my_mirror.faction = faction.Copy() + +/mob/living/simple_animal/hostile/asteroid/elite/herald/mirror + name = "herald's mirror" + desc = "This fiendish work of magic copies the herald's attacks. Seems logical to smash it." + health = 60 + maxHealth = 60 + icon_state = "herald_mirror" + icon_aggro = "herald_mirror" + deathmessage = "shatters violently!" + death_sound = 'sound/effects/glassbr1.ogg' + del_on_death = TRUE + is_mirror = TRUE + move_resist = MOVE_FORCE_OVERPOWERING // no dragging your mirror around + flying = TRUE + var/mob/living/simple_animal/hostile/asteroid/elite/herald/my_master = null + +/mob/living/simple_animal/hostile/asteroid/elite/herald/mirror/Initialize(mapload) + . = ..() + toggle_ai(AI_OFF) + +/mob/living/simple_animal/hostile/asteroid/elite/herald/mirror/Destroy() + my_master?.my_mirror = null + my_master = null + . = ..() + +/obj/item/projectile/herald + name = "death bolt" + icon_state = "chronobolt" + damage = 15 + armour_penetration = 30 + speed = 2 + +/obj/item/projectile/herald/teleshot + name = "golden bolt" + damage = 0 + color = rgb(255,255,102) + +/obj/item/projectile/herald/prehit(atom/target) + if(ismob(target) && ismob(firer)) + var/mob/living/mob_target = target + if(mob_target.faction_check_mob(firer)) + nodamage = TRUE + damage = 0 + return + if(mob_target.buckled && mob_target.stat == DEAD) + mob_target.dust() //no body cheese + +/obj/item/projectile/herald/on_hit(atom/target, blocked = FALSE) + . = ..() + if(ismineralturf(target)) + var/turf/simulated/mineral/M = target + M.gets_drilled() + +/obj/item/projectile/herald/teleshot/on_hit(atom/target, blocked = FALSE) + . = ..() + if(!istype(target, /mob/living/simple_animal/hostile/asteroid/elite/herald)) + firer.forceMove(get_turf(src)) + + +//Herald's loot: Cloak of the Prophet + +/obj/item/clothing/accessory/necklace/herald_cloak + name = "cloak of the prophet" + desc = "A cloak which lts you travel through a perfect reflection of the world." + icon = 'icons/obj/lavaland/elite_trophies.dmi' + icon_state = "herald_cloak" + item_state = "herald_cloak" + item_color = "herald_cloak" + slot_flags = SLOT_TIE + allow_duplicates = FALSE + actions_types = list(/datum/action/item_action/accessory/herald) + +/obj/item/clothing/accessory/necklace/herald_cloak/attack_self() + if(has_suit) + mirror_walk() + +/obj/item/clothing/accessory/necklace/herald_cloak/proc/mirror_walk() + var/found_mirror = FALSE + var/list/mirrors_to_use = list() + var/list/areaindex = list() + var/obj/starting_mirror = null + + for(var/obj/i in GLOB.mirrors) + var/turf/T = get_turf(i) + if(!is_teleport_allowed(i.z)) + continue + if(T.z != usr.z) //No crossing zlvls + continue + if(istype(i, /obj/item/shield/mirror) && !iscultist(usr)) //No teleporting to cult bases + continue + if(istype(i, /obj/structure/mirror)) + var/obj/structure/mirror/B = i + if(B.broken) + return + var/tmpname = T.loc.name + if(areaindex[tmpname]) + tmpname = "[tmpname] ([++areaindex[tmpname]])" + else + areaindex[tmpname] = 1 + mirrors_to_use[tmpname] = i + if(get_dist(src, i) > 1) + continue + found_mirror = TRUE + starting_mirror = i + + if(!found_mirror) + to_chat(usr, "You are not close enough to a working mirror to teleport!") + return + var/input_mirror = input(usr, "Choose a mirror to teleport to.", "Mirror to Teleport to") as null|anything in mirrors_to_use + var/obj/chosen = mirrors_to_use[input_mirror] + if(chosen == null) + return + usr.visible_message("[usr] starts to crawl into [starting_mirror]...", \ + "You start to crawl into the [starting_mirror]...") + if(do_after(usr, 2 SECONDS, target = usr)) + var/turf/destination = get_turf(chosen) + if(QDELETED(chosen) || !usr|| HAS_TRAIT(usr, TRAIT_HANDS_BLOCKED) || !chosen || (get_dist(src, starting_mirror) > 1 || destination.z != usr.z)) + return + usr.visible_message("[usr] crawls into the [starting_mirror], and [usr.p_they()] disappear into it!", \ + "You crawl into the [starting_mirror]...") + usr.forceMove(destination) + usr.visible_message("[usr] crawls out of [chosen], causing it to shatter!", \ + "You crawl out of your own reflection, shattering the mirror!") + if(istype(chosen, /obj/structure/mirror)) + var/obj/structure/mirror/M = chosen + M.obj_break("brute") + else if(istype(chosen, /obj/item/shield/mirror)) + var/turf/T = get_turf(usr) + new /obj/effect/temp_visual/cult/sparks(T) + playsound(T, 'sound/effects/glassbr3.ogg', 100) + if(isliving(chosen.loc)) + var/mob/living/shatterer = loc + shatterer.Weaken(6 SECONDS) + qdel(chosen) + +#undef HERALD_TRISHOT +#undef HERALD_DIRECTIONALSHOT +#undef HERALD_TELESHOT +#undef HERALD_MIRROR diff --git a/code/modules/mob/living/simple_animal/hostile/mining/elites/legionnaire.dm b/code/modules/mob/living/simple_animal/hostile/mining/elites/legionnaire.dm new file mode 100644 index 00000000000..a9c4a697604 --- /dev/null +++ b/code/modules/mob/living/simple_animal/hostile/mining/elites/legionnaire.dm @@ -0,0 +1,346 @@ +#define LEGIONNAIRE_CHARGE 1 +#define HEAD_DETACH 2 +#define BONFIRE_TELEPORT 3 +#define SPEW_SMOKE 4 + +/** + * # Legionnaire + * + * A towering skeleton, embodying the power of Legion. + * As it's health gets lower, the head does more damage. + * It's attacks are as follows: + * - Charges at the target after a telegraph, throwing them across the arena should it connect. + * - Legionnaire's head detaches, attacking as it's own entity. Has abilities of it's own later into the fight. Once dead, regenerates after a brief period. If the skill is used while the head is off, it will be killed. + * - Leaves a pile of bones at your location. Upon using this skill again, you'll swap locations with the bone pile. + * - Spews a cloud of smoke from it's maw, wherever said maw is. + * A unique fight incorporating the head mechanic of legion into a whole new beast. Combatants will need to make sure the tag-team of head and body don't lure them into a deadly trap. + */ + +/mob/living/simple_animal/hostile/asteroid/elite/legionnaire + name = "legionnaire" + desc = "A towering skeleton, embodying the terrifying power of Legion." + icon_state = "legionnaire" + icon_living = "legionnaire" + icon_aggro = "legionnaire" + icon_dead = "legionnaire_dead" + icon_gib = "syndicate_gib" + maxHealth = 1000 + health = 1000 + melee_damage_lower = 35 + melee_damage_upper = 35 + attacktext = "slashes its arms at" + attack_sound = 'sound/weapons/bladeslice.ogg' + throw_message = "doesn't affect the sturdiness of" + speed = 0.5 //Since it is mainly melee, this *should* be right + move_to_delay = 3 + mouse_opacity = MOUSE_OPACITY_ICON + death_sound = 'sound/hallucinations/wail.ogg' + deathmessage = "'s arms reach out before it falls apart onto the floor, lifeless." + sight = SEE_MOBS // So it can see through smoke / charge through walls like the kool aid man. + var/datum/effect_system/smoke_spread/bad/smoke + loot_drop = /obj/item/crusher_trophy/legionnaire_spine + + attack_action_types = list(/datum/action/innate/elite_attack/legionnaire_charge, + /datum/action/innate/elite_attack/head_detach, + /datum/action/innate/elite_attack/bonfire_teleport, + /datum/action/innate/elite_attack/spew_smoke) + + var/mob/living/simple_animal/hostile/asteroid/elite/legionnairehead/myhead = null + var/obj/structure/legionnaire_bonfire/mypile = null + var/has_head = TRUE + /// Whether or not the legionnaire is currently charging, used to deny movement input if he is + var/charging = FALSE + +/datum/action/innate/elite_attack/legionnaire_charge + name = "Legionnaire Charge" + button_icon_state = "legionnaire_charge" + chosen_message = "You will attempt to grab your opponent and throw them." + chosen_attack_num = LEGIONNAIRE_CHARGE + +/datum/action/innate/elite_attack/head_detach + name = "Release Head" + button_icon_state = "head_detach" + chosen_message = "You will now detach your head or kill it if it is already released." + chosen_attack_num = HEAD_DETACH + +/datum/action/innate/elite_attack/bonfire_teleport + name = "Bonfire Teleport" + button_icon_state = "bonfire_teleport" + chosen_message = "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." + chosen_attack_num = BONFIRE_TELEPORT + +/datum/action/innate/elite_attack/spew_smoke + name = "Spew Smoke" + button_icon_state = "spew_smoke" + chosen_message = "Your head will spew smoke in an area, wherever it may be." + chosen_attack_num = SPEW_SMOKE + +/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/Destroy() + myhead = null + mypile = null + return ..() + +/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/OpenFire() + if(client) + switch(chosen_attack) + if(LEGIONNAIRE_CHARGE) + legionnaire_charge(target) + if(HEAD_DETACH) + head_detach(target) + if(BONFIRE_TELEPORT) + bonfire_teleport() + if(SPEW_SMOKE) + spew_smoke() + return + var/aiattack = rand(1,4) + switch(aiattack) + if(LEGIONNAIRE_CHARGE) + legionnaire_charge(target) + if(HEAD_DETACH) + head_detach(target) + if(BONFIRE_TELEPORT) + bonfire_teleport() + if(SPEW_SMOKE) + spew_smoke() + +/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/Move() + if(charging) + return FALSE + return ..() + +/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/MiddleClickOn(atom/A) + . = ..() + if(!myhead) + return + var/turf/T = get_turf(A) + if(T) + myhead.LoseTarget() + myhead.Goto(T, myhead.move_to_delay) + +/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/proc/legionnaire_charge(target) + ranged_cooldown = world.time + 4 SECONDS * revive_multiplier() + charging = TRUE + var/dir_to_target = get_dir(get_turf(src), get_turf(target)) + var/turf/T = get_step(get_turf(src), dir_to_target) + for(var/i in 1 to 6) + new /obj/effect/temp_visual/dragon_swoop/legionnaire(T) + T = get_step(T, dir_to_target) + playsound(src, 'sound/misc/demon_attack1.ogg', 200, 1) + visible_message("[src] prepares to charge!") + 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) + if(times_ran >= 6) + charging = FALSE + return + var/turf/T = get_step(get_turf(src), move_dir) + if(ismineralturf(T)) + var/turf/simulated/mineral/M = T + M.gets_drilled() + if(T.density) + charging = FALSE + return + for(var/obj/structure/window/W in T.contents) + charging = FALSE + return + for(var/obj/machinery/door/D in T.contents) + if(D.density) + 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) + if(faction_check_mob(L)) + return + hit_things += L + visible_message("[src] tramples and kicks [L]!") + to_chat(L, "[src] tramples you and kicks you away!") + L.throw_at(throwtarget, 10, 1, src) + L.KnockDown(1 SECONDS) + L.adjustBruteLoss(melee_damage_upper) + addtimer(CALLBACK(src, .proc/legionnaire_charge_to, move_dir, (times_ran + 1)), 0.7) + +/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/proc/head_detach(target) + ranged_cooldown = world.time + 1 SECONDS * revive_multiplier() + if(myhead != null) + myhead.adjustBruteLoss(600) + return + if(has_head) + has_head = FALSE + icon_state = "legionnaire_headless" + icon_living = "legionnaire_headless" + icon_aggro = "legionnaire_headless" + visible_message("[src]'s head flies off!") + var/mob/living/simple_animal/hostile/asteroid/elite/legionnairehead/newhead = new /mob/living/simple_animal/hostile/asteroid/elite/legionnairehead(loc) + newhead.GiveTarget(target) + newhead.faction = faction.Copy() + myhead = newhead + myhead.body = src + if(health < maxHealth * 0.25) + myhead.melee_damage_lower = 40 + myhead.melee_damage_upper = 40 + else if(health < maxHealth * 0.5) + myhead.melee_damage_lower = 30 + myhead.melee_damage_upper = 30 + +/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/proc/onHeadDeath() + myhead = null + addtimer(CALLBACK(src, .proc/regain_head), 5 SECONDS) + +/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/proc/regain_head() + has_head = TRUE + if(stat == DEAD) + return + icon_state = "legionnaire" + icon_living = "legionnaire" + icon_aggro = "legionnaire" + visible_message("The top of [src]'s spine leaks a black liquid, forming into a skull!") + +/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/proc/bonfire_teleport() + ranged_cooldown = world.time + 0.5 SECONDS * revive_multiplier() + if(isnull(mypile)) + var/obj/structure/legionnaire_bonfire/newpile = new /obj/structure/legionnaire_bonfire(loc) + mypile = newpile + mypile.myowner = src + playsound(get_turf(src),'sound/items/fultext_deploy.ogg', 200, 1) + visible_message("[src] summons a bonfire on [get_turf(src)]!") + return + else + var/turf/legionturf = get_turf(src) + var/turf/pileturf = get_turf(mypile) + if(legionturf == pileturf) + QDEL_NULL(mypile) + return + playsound(pileturf,'sound/items/fultext_deploy.ogg', 200, 1) + playsound(legionturf,'sound/items/fultext_deploy.ogg', 200, 1) + visible_message("[src] melts down into a burning pile of bones!") + forceMove(pileturf) + visible_message("[src] forms from the bonfire!") + mypile.forceMove(legionturf) + +/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/proc/spew_smoke() + ranged_cooldown = world.time + 3 SECONDS * revive_multiplier() + var/smoke_location = null + if(isnull(myhead)) + smoke_location = src + else + smoke_location = myhead + if(myhead != null) + myhead.visible_message("[myhead] spews smoke from its maw!") + else if(!has_head) + visible_message("[src] spews smoke from the tip of their spine!") + else + visible_message("[src] spews smoke from its maw!") + var/datum/effect_system/smoke_spread/smoke = new + smoke.set_up(6, 0, smoke_location) + smoke.attach(smoke_location) + smoke.start() + +//The legionnaire's head. Basically the same as any legion head, but we have to tell our creator when we die so they can generate another head. +/mob/living/simple_animal/hostile/asteroid/elite/legionnairehead + name = "legionnaire head" + desc = "The legionnaire's head floating by itself. One shouldn't get too close, though once it sees you, you really don't have a choice." + icon_state = "legionnaire_head" + icon_living = "legionnaire_head" + icon_aggro = "legionnaire_head" + icon_dead = "legionnaire_dead" + icon_gib = "syndicate_gib" + maxHealth = 200 + health = 200 + melee_damage_lower = 20 + melee_damage_upper = 20 + attacktext = "bites at" + attack_sound = 'sound/hallucinations/growl1.ogg' + throw_message = "simply misses" + speed = 0 + move_to_delay = 2 + del_on_death = 1 + deathmessage = "crumbles away!" + faction = list() + ranged = FALSE + var/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/body = null + +/mob/living/simple_animal/hostile/asteroid/elite/legionnairehead/death() + . = ..() + if(body) + body.onHeadDeath() + +//The legionnaire's bonfire, which can be swapped positions with. Also sets flammable living beings on fire when they walk over it. +/obj/structure/legionnaire_bonfire + name = "bone pile" + desc = "A pile of bones which seems to occasionally move a little. It's probably a good idea to smash them." + icon = 'icons/obj/lavaland/legionnaire_bonfire.dmi' + icon_state = "bonfire" + max_integrity = 100 + move_resist = MOVE_FORCE_EXTREMELY_STRONG + anchored = TRUE + density = FALSE + light_range = 4 + light_color = LIGHT_COLOR_RED + var/mob/living/simple_animal/hostile/asteroid/elite/legionnaire/myowner = null + +/obj/structure/legionnaire_bonfire/Crossed(datum/source, atom/movable/mover) + if(isobj(source)) + var/obj/object = source + object.fire_act(1000, 500) + if(isliving(source)) + var/mob/living/fire_walker = source + fire_walker.adjust_fire_stacks(5) + fire_walker.IgniteMob() + +/obj/structure/legionnaire_bonfire/Destroy() + if(myowner != null) + myowner.mypile = null + . = ..() + +//The visual effect which appears in front of legionnaire when he goes to charge. +/obj/effect/temp_visual/dragon_swoop/legionnaire + duration = 10 + +/obj/effect/temp_visual/dragon_swoop/legionnaire/Initialize(mapload) + . = ..() + transform *= 0.33 + +// Legionnaire's loot: Legionnaire Spine + +/obj/item/crusher_trophy/legionnaire_spine + name = "legionnaire spine" + desc = "The spine of a legionnaire. With some creativity, you could use it as a crusher trophy. Alternatively, shaking it might do something as well." + icon = 'icons/obj/lavaland/elite_trophies.dmi' + icon_state = "legionnaire_spine" + denied_type = /obj/item/crusher_trophy/legionnaire_spine + bonus_value = 25 + /// Time at which the item becomes usable again + var/next_use_time + +/obj/item/crusher_trophy/legionnaire_spine/effect_desc() + return "mark detonation to have a [bonus_value]% chance to summon a loyal legion skull" + +/obj/item/crusher_trophy/legionnaire_spine/on_mark_detonation(mob/living/target, mob/living/user) + if(!prob(bonus_value) || target.stat == DEAD) + return + var/mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion/A = new /mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion(user.loc) + A.GiveTarget(target) + A.friends += user + A.faction = user.faction.Copy() + +/obj/item/crusher_trophy/legionnaire_spine/attack_self(mob/user) + if(!isliving(user)) + return + var/mob/living/LivingUser = user + if(next_use_time > world.time) + LivingUser.visible_message("[LivingUser] shakes the [src], but nothing happens...") + to_chat(LivingUser, "You need to wait longer to use this again.") + return + LivingUser.visible_message("[LivingUser] shakes the [src] and summons a legion skull!") + var/mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion/LegionSkull = new /mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion(LivingUser.loc) + LegionSkull.friends += LivingUser + LegionSkull.faction = LivingUser.faction.Copy() + next_use_time = world.time + 4 SECONDS + +#undef LEGIONNAIRE_CHARGE +#undef HEAD_DETACH +#undef BONFIRE_TELEPORT +#undef SPEW_SMOKE diff --git a/code/modules/mob/living/simple_animal/hostile/mining/elites/pandora.dm b/code/modules/mob/living/simple_animal/hostile/mining/elites/pandora.dm new file mode 100644 index 00000000000..f8ce3ae9bc8 --- /dev/null +++ b/code/modules/mob/living/simple_animal/hostile/mining/elites/pandora.dm @@ -0,0 +1,238 @@ +#define CHASER_BURST 1 +#define MAGIC_BOX 2 +#define PANDORA_TELEPORT 3 +#define AOE_SQUARES 4 +#define MAX_CHASERS 3 + +/** + * # Pandora + * + * A box with a similar design to the Hierophant which trades large, single attacks for more frequent smaller ones. + * As it's health gets lower, the time between it's attacks decrease. + * It's attacks are as follows: + * - Fires hierophant blasts in a straight line. Can only fire in a straight line in 8 directions, being the diagonals and cardinals. + * - Creates a box of hierophant blasts around the target. If they try to run away to avoid it, they'll very likely get hit. + * - Teleports the pandora from one location to another, almost identical to Hierophant. + * - Spawns a 7x7 AOE at the location of choice, spreading out from the center. + * Pandora's fight mirrors Hierophant's closely, but has stark differences in attack effects. Instead of long-winded dodge times and long cooldowns, Pandora constantly attacks the opponent, but leaves itself open for attack. + */ + +/mob/living/simple_animal/hostile/asteroid/elite/pandora + name = "pandora" + desc = "A large magic box with similar power and design to the Hierophant. Once it opens, it's not easy to close it." + icon_state = "pandora" + icon_living = "pandora" + icon_aggro = "pandora" + icon_dead = "pandora_dead" + icon_gib = "syndicate_gib" + + maxHealth = 1000 + health = 1000 + melee_damage_lower = 15 + melee_damage_upper = 15 + attacktext = "smashes into the side of" + attack_sound = 'sound/weapons/sonic_jackhammer.ogg' + throw_message = "merely dinks off of the" + ranged_cooldown_time = 20 + speed = 2 + move_to_delay = 10 + mouse_opacity = MOUSE_OPACITY_ICON + death_sound = 'sound/magic/repulse.ogg' + deathmessage = "'s lights flicker, before its top part falls down." + loot_drop = /obj/item/clothing/accessory/necklace/pandora_hope + + attack_action_types = list(/datum/action/innate/elite_attack/chaser_burst, + /datum/action/innate/elite_attack/magic_box, + /datum/action/innate/elite_attack/pandora_teleport, + /datum/action/innate/elite_attack/aoe_squares) + + var/sing_shot_length = 8 + var/cooldown_time = 2 SECONDS + var/chaser_speed = 3 + var/recalculation_speed = 4 //How many times chasers moves before recalculating + +/datum/action/innate/elite_attack/chaser_burst + name = "Chaser Burst" + button_icon_state = "singular_shot" + chosen_message = "You fire a chaser after all mobs in view." + chosen_attack_num = CHASER_BURST + +/datum/action/innate/elite_attack/magic_box + name = "Magic Box" + button_icon_state = "magic_box" + chosen_message = "You are now attacking with a box of magic squares." + chosen_attack_num = MAGIC_BOX + +/datum/action/innate/elite_attack/pandora_teleport + name = "Line Teleport" + button_icon_state = "pandora_teleport" + chosen_message = "You will now teleport to your target." + chosen_attack_num = PANDORA_TELEPORT + +/datum/action/innate/elite_attack/aoe_squares + name = "AOE Blast" + button_icon_state = "aoe_squares" + chosen_message = "Your attacks will spawn an AOE blast at your target location." + chosen_attack_num = AOE_SQUARES + +/mob/living/simple_animal/hostile/asteroid/elite/pandora/OpenFire() + if(client) + switch(chosen_attack) + if(CHASER_BURST) + chaser_burst(target) + if(MAGIC_BOX) + magic_box(target) + if(PANDORA_TELEPORT) + pandora_teleport(target) + if(AOE_SQUARES) + aoe_squares(target) + return + var/aiattack = rand(1,4) + switch(aiattack) + if(CHASER_BURST) + chaser_burst(target) + if(MAGIC_BOX) + magic_box(target) + if(PANDORA_TELEPORT) + pandora_teleport(target) + if(AOE_SQUARES) + aoe_squares(target) + +/mob/living/simple_animal/hostile/asteroid/elite/pandora/Life(seconds, times_fired) + . = ..() + if(health >= maxHealth * 0.5) + cooldown_time = 2 SECONDS * revive_multiplier() + chaser_speed = 3 + recalculation_speed = 4 + return + if(health < maxHealth * 0.5 && health > maxHealth * 0.25) + cooldown_time = 1.5 SECONDS * revive_multiplier() + chaser_speed = 2 + recalculation_speed = 3 + return + else + chaser_speed = 1 + cooldown_time = 1 SECONDS * revive_multiplier() + recalculation_speed = 2 + +/mob/living/simple_animal/hostile/asteroid/elite/pandora/proc/chaser_burst(target) + ranged_cooldown = world.time + cooldown_time * 2 + var/active_chasers = 0 + for(var/mob/living/M in orange(7, src)) + if(M.faction_check_mob(src)) + continue + if(active_chasers >= MAX_CHASERS) + return + var/obj/effect/temp_visual/hierophant/chaser/C = new(loc, src, M, chaser_speed, FALSE) + C.moving = 2 + C.standard_moving_before_recalc = recalculation_speed + C.moving_dir = text2dir(pick("NORTH", "SOUTH", "EAST", "WEST")) + active_chasers += 1 + +/mob/living/simple_animal/hostile/asteroid/elite/pandora/proc/singular_shot_line(procsleft, angleused, turf/T) + if(procsleft <= 0) + return + new /obj/effect/temp_visual/hierophant/blast/damaging/pandora(T, src, TRUE) + T = get_step(T, angleused) + procsleft = procsleft - 1 + addtimer(CALLBACK(src, .proc/singular_shot_line, procsleft, angleused, T), cooldown_time * 0.1) + +/mob/living/simple_animal/hostile/asteroid/elite/pandora/proc/magic_box(target) + ranged_cooldown = world.time + cooldown_time + var/turf/T = get_turf(target) + for(var/t in spiral_range_turfs(3, T)) + if(get_dist(t, T) > 1) + new /obj/effect/temp_visual/hierophant/blast/damaging/pandora(t, src, TRUE) + +/mob/living/simple_animal/hostile/asteroid/elite/pandora/proc/pandora_teleport(target) + var/turf/turf_target = get_turf(target) + if(!(turf_target in view(12, src))) + return + ranged_cooldown = world.time + cooldown_time * 2 + var/turf/source = get_turf(src) + new /obj/effect/temp_visual/hierophant/telegraph(turf_target, src) + new /obj/effect/temp_visual/hierophant/telegraph(source, src) + playsound(source,'sound/machines/airlock_open.ogg', 200, 1) + addtimer(CALLBACK(src, .proc/pandora_teleport_2, turf_target, source), 2) + +/mob/living/simple_animal/hostile/asteroid/elite/pandora/proc/pandora_teleport_2(turf/T, turf/source) + new /obj/effect/temp_visual/hierophant/telegraph/teleport(T, src) + new /obj/effect/temp_visual/hierophant/telegraph/teleport(source, src) + for(var/t in RANGE_TURFS(1, T)) + new /obj/effect/temp_visual/hierophant/blast/damaging/pandora(t, src, TRUE) + for(var/t in RANGE_TURFS(1, source)) + new /obj/effect/temp_visual/hierophant/blast/damaging/pandora(t, src, TRUE) + animate(src, alpha = 0, time = 2, easing = EASE_OUT) //fade out + visible_message("[src] fades out!") + set_density(FALSE) + addtimer(CALLBACK(src, .proc/pandora_teleport_3, T), 2) + +/mob/living/simple_animal/hostile/asteroid/elite/pandora/proc/pandora_teleport_3(turf/T) + forceMove(T) + animate(src, alpha = 255, time = 2, easing = EASE_IN) //fade IN + set_density(TRUE) + visible_message("[src] fades in!") + +/mob/living/simple_animal/hostile/asteroid/elite/pandora/proc/aoe_squares(target) + ranged_cooldown = world.time + cooldown_time * 2 + var/turf/T = get_turf(target) + new /obj/effect/temp_visual/hierophant/blast/damaging/pandora(T, src, TRUE) + var/max_size = 3 + addtimer(CALLBACK(src, .proc/aoe_squares_2, T, 0, max_size), 2) + +/mob/living/simple_animal/hostile/asteroid/elite/pandora/proc/aoe_squares_2(turf/T, ring, max_size) + if(ring > max_size) + return + for(var/t in spiral_range_turfs(ring, T)) + if(get_dist(t, T) == ring) + new /obj/effect/temp_visual/hierophant/blast/damaging/pandora(t, src, TRUE) + addtimer(CALLBACK(src, .proc/aoe_squares_2, T, (ring + 1), max_size), cooldown_time * 0.1) + +//The specific version of hiero's squares pandora uses +/obj/effect/temp_visual/hierophant/blast/damaging/pandora + damage = 30 + monster_damage_boost = FALSE + friendly_fire_check = TRUE + + +//Pandora's loot: Hope //Hope I know what to make it do +/obj/item/clothing/accessory/necklace/pandora_hope + name = "Hope" + desc = "Found at the bottom of Pandora. After all the evil was released, this was the only thing left inside." + icon = 'icons/obj/lavaland/elite_trophies.dmi' + icon_state = "hope" + item_state = "hope" + item_color = "hope" + slot_flags = SLOT_TIE + allow_duplicates = FALSE + resistance_flags = FIRE_PROOF + +/obj/item/clothing/accessory/necklace/pandora_hope/on_attached(obj/item/clothing/under/S, mob/user) + . = ..() + if(isliving(user)) + var/mob/living/M = user + M.apply_status_effect(STATUS_EFFECT_HOPE) + +/obj/item/clothing/accessory/necklace/pandora_hope/on_removed(mob/user) + . = ..() + if(isliving(user)) + var/mob/living/M = user + M.remove_status_effect(STATUS_EFFECT_HOPE) + +/obj/item/clothing/accessory/necklace/pandora_hope/attached_unequip() + if(isliving(usr)) + var/mob/living/M = usr + M.remove_status_effect(STATUS_EFFECT_HOPE) + return ..() + +/obj/item/clothing/accessory/necklace/pandora_hope/attached_equip() + if(isliving(usr)) + var/mob/living/M = usr + M.apply_status_effect(STATUS_EFFECT_HOPE) + return ..() + +#undef CHASER_BURST +#undef MAGIC_BOX +#undef PANDORA_TELEPORT +#undef AOE_SQUARES +#undef MAX_CHASERS diff --git a/code/modules/mob/living/simple_animal/hostile/mining/mining.dm b/code/modules/mob/living/simple_animal/hostile/mining/mining.dm index d5f60384e1f..2e6ad1055ef 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining/mining.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining/mining.dm @@ -22,6 +22,7 @@ mob_size = MOB_SIZE_LARGE var/icon_aggro = null var/crusher_drop_mod = 25 + var/has_laser_resist = TRUE //If we want the mob to have 66% resist from burn damage projectiles /mob/living/simple_animal/hostile/asteroid/Aggro() ..() @@ -37,7 +38,7 @@ /mob/living/simple_animal/hostile/asteroid/bullet_act(obj/item/projectile/P)//Reduces damage from most projectiles to curb off-screen kills if(!stat) Aggro() - if(P.damage < 30 && P.damage_type != BRUTE) + if(P.damage < 30 && P.damage_type != BRUTE && has_laser_resist) P.damage = (P.damage / 3) visible_message("[P] has a reduced effect on [src]!") ..() diff --git a/config/example/config.toml b/config/example/config.toml index d549b745ad9..82cd6208323 100644 --- a/config/example/config.toml +++ b/config/example/config.toml @@ -699,6 +699,7 @@ active_lava_ruins = [ "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_cube.dmm", "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_cultaltar.dmm", "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_dead_ratvar.dmm", + "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_elite_tumor.dmm", "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_fountain_hall.dmm", "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_monster_nest.dmm", "_maps/map_files/RandomRuins/LavaRuins/lavaland_surface_pizzaparty.dmm", diff --git a/icons/mob/actions/actions_elites.dmi b/icons/mob/actions/actions_elites.dmi new file mode 100644 index 0000000000000000000000000000000000000000..814b637611927e98c835faa51db598d4d6b1a8da GIT binary patch literal 11655 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 E0TK(05dZ)H literal 0 HcmV?d00001 diff --git a/icons/mob/screen_alert.dmi b/icons/mob/screen_alert.dmi index a45d4b060ee4bf8a2192ce1202bc7268d3c1a3dc..5b65a8175f1f53284e83feb91e219b602b6666f5 100644 GIT binary patch delta 10784 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 W#|QXT*C|5)`lBSTF85v59QJ?U>uMPQ diff --git a/icons/mob/ties.dmi b/icons/mob/ties.dmi index e399e5e3a8b6f2b6d88500a1f13041ca4bc56d28..f6834ccacc288c5215a32bb08ec1812ca26b98db 100644 GIT binary patch delta 3524 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 PRzUZj(cLo;-M`;WZ-jJIL2~s$Kw~Wc z08KlFQ2+q>Mhpx|b~}fUx*VO99G#c|09T6c7WO6Ztl*t};sA{~f-6t@pgXthO(`ie zBj3Qw%G|&dX+rpg#Kj#!n2>CLPI3ZfM@?WChT%u3 z;lAS*Q3ijLul{*0a)jy#8fCWaiivh>5u}pNXexh>&Go`{kBv~dV6v%4x#{N`#LzYE zq{I5$%1?27Ac&qP*81-?JBGax2iruqLoeUWcH-u{48u_qHcDJ==Tm(|+I1Y*}vj9kdo}(Ta@^Z+^6!JrpL^qg{-N2=_&IhVUcs9L9%N==F6& z+)q~4ivGcmBVbj&7B7@^#y8f2-vDcMdy}e)-;QV2k59nr|6(L@60}DO+we5f2^4%o8RKFE+GcDb((8iDsRT+r%@I3=)#W1DblCrw{kpT2SvW} zExcQjUVP9qJiK~)udrpYaqNxo;1!Z~2N?Va_YT#RJRqN3I%2ZdN!*C2=L0}<5E~ev zE$zcY0B0McjMdr-6sS}Hh(JQt06@r500ICX*Es_~M#>tU|Az+u+eM!NTuwFSYa>eV zXr~i%Vq!(miqLJaYZGdyPWnsrOcS_hv6_L<%Kf*+L=k6Jw zF56eeB^=2g{6NAY=SuBPNEDat=T52y4&3Emz@v+YSoYch!}S9tnH-{O6aw^^SV8DE zV^1zH6%ULetHd02T<;UTlJv(R!fU(GKUXmT_q6tf<~GhfkZB`~_v+?W7aiAEMtVgb z-_oKE*p?h8BRV-HMMfUmC}Tg{sRO7W;>n6qz;dX9dowoetfbmtVa2^p`(DY-nT5jY&5>kns0=K zoHe^U97lX54@xWdez_B#QcJBZ`fjchA^5z`bKq&yi)1os{!zN3fVC|D!I#M$m+|4x z&k+O3bvs@t#RSi0>3S?>{|%I0@RA{NR0J*_?lYQ&v!f^8KQez`P`d0S!mbq4(9dyw zb^)qmcJYH@iJ=cC8T4f6n1>=a*wuTHRNb|}SmMhYbl?;ogz$j;DyFrAUxk&(O;yj5 zko<|s+o1+#7>rn&{S{x&Kat++PMVy0M40ZM&aCzhL;B4xrkuz(4lOSh_TLAUIiUvc z?~AwO)9*J)Vq^Z9aW$8YEbcxh3izS4*Zoj1kN&xn@|)2V{LdbVc6M(OOf2xeb^QF_ zUYJ&qC_4^~!K9w+sPSa`lWb5lxY;@htlT1EwR@2L*r z80gtZH9i`vlzB0m&p*|#y#scgQu3wl>^oh8*>_om%1uJW>*!V0=GJ}jEwXpxgbP!m z<^povuSCIh#!Gk0r5T5esSONZeO74F>Wz_LE#{Y|&N$&_;T}v~t}Hh3>_eZeydQGx z=FXc@N~dv6T5|S*g)Po4Yxw4yn037epC3ibOa|=uR}ZChsl?M@Yn|YFn%$M9U{|5D z!YuD}?Yw;;J$BI3l+~1H!9qhWrc$(wieM)zf|Pr$uY}zERwi?=H@hcEw_UDThgo8% zJtnAGWYm78wH5}?9kq~W>dxk~zLfj*k^yHOHU8(9|J-Eo9Qx6_25}WC98L4lL6j~^lP=N)q_>0wuplUiD7}h;p-V?fXbOlJ zdWQr7DWO9s2?;N}@3nKjbKZI9dw<-sd*|-l`R(ldW_Rb6iIFZN_#zkp0LHs_v`qnk ziqfS5=;_9F z44c~@U}@&6@-@R@2VPsV-UBafz`UI#ACQ=_i$*;5Ui%r|$x zU5xIXRru>V8SyLEos6l>20NkK0tBf_KzEKxaY44^$?z8I~m9`w?u!t%IBF&To%>CSCMn zNyg}>KX)nsWy!5nf7IYPz->sQ6)Wbq82(mEO@b~_&IR4GW86^7c5}Zinx#Mi{zk@b zev$k;)o)6tBKjRT;lU^2AluxQW%_lNw%M$SRrujyyt*Uk7yr8(9Kz`MWx)%J$}BYm z567llwI&AR5_p(%a^RwD`*#JG?VuA7SbJ=;TUISDC%rGiYqZge1X2e2Zx5lWb^w4q z;jZ@02O*j3Gq9)Z&e@Q>iK9K*M&H>8|7@T;S4PvL3 z%hcAvsaDThR#`0VHY42_8$<0FIoVsPJ!WmfD<;{;S4C}#kk0s7pNbdckwN%UJ7yD| zLS7i9{@U9!2sU0iiYO|PmH8VgH-xT(8waD+($PyatVr>W6(*KMe=a~9>;$lgzovqG zlBEL@+y6;mK#M4!6n->QJK20ND?w==uArKP9?gjO#TgW;I{es}X;dWTVw%J2TwIAY znl`yBAlN!H=lGP>*RhGIrb?evL#5MsZGLotR5!q z^R#^E%-1MI4Q0vRnOCM}MaJC+gq~jmy7Bwo>Ea6$AdV~k6^T@kvQvQX(aTE#%Dnlc z%h1ubC-kzEQ4|=d3P*HTj8(}hTpEkl_s{xs3Tz7sHq6c%%0G`S$HNVTr`L~jtu{9BZmD4@UIFOrpRA(OUh!&&Hly3YLAHd`;yOV)-AH8R>B$!d(mi_ zgg{kR8}4rBAa#_M4bv-S0qF5_fo@{N(L9`t59FSN$(yVBtQ`EwdO`>G%hxo2%M&rp z#Bo4WAmx_VYm!p1dS810k4Mu=uQ`B*cf5OGrie4tkrO21K@RP+19Bw9p>_iEApkH) z#j>)Aj9W*o?|d=a(b=xLUMD4w6CD8A1Rq$tZ@D#ED{LUsP4(*rl9Q9ykB*LnSm;wH zclFDPfuK;ek9PFBx3B|e*?8T9m=(rkjc3Lzh-m+Z!$=g{ys- z)m&uFm+R16_Z&&J;A#F7oqRvJj*b4zJEoaWG!7>bIkj*UYy|^uJ&6@44N~NKe!_ur z@=8&^0L!+2Kz`=;`RR?YqJjrcidA1v5%C>W;Vz$SuLmxE0}Fy$Vdvr!=N$x~9n#n3 z##_$PHNt+`?+R~QpKQ*RAKjbu2~eMqU#yvY??`)C?0aOX;%qVbvJ&^3`qvgRxW6mr zVi08AD!(>uCM*XUlln!@BB4y(9M20S}a1 z@u;rp3Z>2Cn$JA5D{<6aQ-k@fU+OW1q`z;|U8zia0yzMcrNk2`YN{=$$q>7z6W$RS ztr=PZh+WyhG$ce1Jg>hlme_7d^}n(FpJ@Mo6{KQumC}x5Q^QrImX;!?X#(vU$b#oI}78k0@S^^lni_VU=SDzQb;M|Cq zzMt_FX)-MWvl(11IVQf79YTCa~PJXyu%ovK>Fuit7b-|KoG_|TC6dP_B@Qp`(a9+Z~y`~Y<20K9e zmF#5HhbD|nzS=KzH+UhOJ``OW71Iu@u91gIks zqvPW-2N<{jH#c`J%A_L*RqE9c!ru}vxN%heunQyB7>eO9AW@+@R405s4l3(4pfG25 zQW05QbPG+IX-Ar^HB?D|c0 z?x!bsUe-En_#sV1S9H8|r#NtBv1(0|8qm&p;w-JPde@T5WUw|Yo_>Qg^Xhb$FrxbZ zWTk&(Hs3%8A-3C()p(8wRZe*y%1BC=?{h$|j)?|a6V1%bJ{A?}bvB}}dM3-ToIcwd zRX^JsoFC0i|1J-%CYF2>fDU+1%~`sA7CEVETxaD*$37tS6;KO)z$G<)C8=&Uv7P>< zq{QG?rpkSGPR^-G@;GbgTbhWz9ok20F>2OR0;%D*eoZ}=;#MOF%JR_vm#%(_bY6Zw z&GYBa0Yq)BQb0h!_-KR?W-Ya@beKr+nHV(>UiiWMOc|=2g6-)CwRP@_8jzUy&lo^L zLmRjhJ=lL|slMz@k(tMpqi*Z!f}+|4UoZ>A|NN<^uRoyJ%Ndhc7Xjj&ob(+VpQ>;< zqCRb(=9TgZ`;eGQvgstP*ErzHYMQG~!5pM3$x{21=CK0jN{5ppY>{i&G5x=avK#=? zCTH4keQbExO(5d%5|e<&>!v2P%o~AV<(UAscs|t^!n*MexY5$&gZXyl^+T*10Qb-U z0f+Z@RiIB55a%$})-wu#!xkd**+$)G+NM&In<_+XMdNHTR#t89uk| z>_UFe3=Bk49I>#tcu85AbEwd`4$3^f_1&W0bIt2|*lMqlCQr-Z&((r~I^zqoH}=G{ zBfOmo->k1JDS7zt5!hkG$5yi-J*gq8w?+7#nc)@|>J%CK+kz|*7Z(u)!&_qPT24;F zT6rwbD!h+-{WLGANL3Uu8*A3xQyqe8tU9@-qwU!k-jfYL2%EIwjU5bf-}QH{gR!^^nh~9j3m8-|(6a+9b`_VDQ@yJbip#7Pv2u6mu#Vc6`=P0f4l$ zwC?V1NR9^VZKC6h??^&CEIu!q`2E=ZbI6qljE2?L5i~+y^``iT{?V|O78#|otgDFO zQseBRePv4b_t-&AWvERHlsnIaK1JF#iiMhz3;GopDgQk+BPUYZj;J1$|au4I2Yv2#nwugntq zI1kvFtMCTE6`4FKCI7upC@#rozFCF&Y{P}nk^PH?Wya(L)%=u~$n(V{pBgw17YS~z z#0=0s*IHg)MzByD8X9J8)V*uMiWd4PMGyyE6Nw4gg!7OPGA8U&3?*>si?tA8{2f&N zJ3Y63Tcn;XTF_-@^X)zrUN5)C!v-kQfs^v3!X{1C;Emw|;~Z%@d3oQ3Zq~KQ8i~Q% zR#s^&TG-`*{P70=Lg#WF>n)+lC{C(?*`ac)7D)F{lsVzg6A8o?6oqpt=FgB>m|x(3 zVF8-05Ap~BG)VEn;hg_4ooxcI}UiUD6ea=Ze`D*Wl@b82iua*6SuJFvk zggKzX1MTsCU_Wa^G%9)ybxZps8<>!H9Q`u zW7%jC^QM+vo)cNkj5!&;hJORup{)zY;--|s;Kqd*u5|{7#;M`DzJrsZ$Cz{e#WXpZ ztf6gY(1D>>Wc8R@S3O18@@{jmUF9Zf#R)KKIkG)5QB^t)a9twK?X@lu;ZjwbuaLk~ zKimBcvPq$`UL}ZP$8XUJAZ>%pmLjgs6LW5qF#v*1teF||FMV1*#y>arV5<#3B#ZXc zQ0{v0uc7i7XckY`<_fD9R}DNlVH5TH&D43gPrWRCV!Mqk70W%p|Le~GuO27LD%}E0 zE%!|I3%^4+n}>xil$M!AM4HGONHP3bAZ%&JnU8^|m)mrQmL9Fao9K=wUNU;>HSnds zeMjWt{W zl3SQ|YK%a_KQY6#Yn)v7$OWcm#zhSpK*6unQpSs^apLkW{07~g_tmh|<*q?9cy z#MvqJC|o5Qo}s{q=KMW0mLLwWrgiiE7mUhS zfvYZ6)Rvf**jFlS?8@~W`w3NMpKNtmq8^JU+n$XS4Sw>5=rt`Tdph)FE@8g54G`43 zZ`kJ=*&&esXgUO#YvYqRGn#A$KC+>F?>K?;W>T|!&Z8)f>}RR5a(4#4T&2pL5|3=M z*CY*#F{3UfF7{fj0Nz456Lx=~ zW8(c1+H5xkLS?P@x&tiydmQsWoJj9JpK2Burc(o{O736^mPovQ@<+-%-m|k)Bl30x zmZ|ik4Y>%I6L9WD2%h``b)@{V@s`qdShLVpC~y>dG+yZ(w|)tW57Sv+qI&;ux&QXmCoN1C< zR@p*!6;a&f{@qC^+S;D1zjN&fnoo&9ZFQ@Gw|QI2O4?ev8z!*fX2Oe!-Dgl6GMumi z2@bh{5bNs^hs@-KNrsU|zFZ-F9J3!;z^0&;qo^PY=Vurr@)LAB{t<0reOLTUWCoVx zftbNm)YrDblZ4Y?$)5gd=E+#=^l+Ptosm11v1;l2asL3tiZ;b?;t~%fF#M2~m$gF##SuP^w2R1M~DLSBZd@fS8i zz)rOPLw;IbD47B(JYjx9en!8*t?~GtSKTVtjAuQiYoPFUT(k2Diifh$7;GMHu9>=#{iatb2m%ua;C*p`ou2Eu@8wD zMp8&Q9<&84+^k!*fJaj30^qJvk+9|22eN>}gt5KW_xf$Ii!jyI*%=zRQ*@r0)s+aY zn9Rp+U_nl9NpUgl`@2>QKl%FI6-@;Rgava-r~sQAZPj=0n-BVlV^D%Z#(d zLR(qsEojIVa7Qca8Kmk1%!X}W3@)FLe|Q)E-L@z}u~T^L zN!%!>kn-JSt=xA}S`;@RC;)^wo4bka2^sc%3amS?ZzV2Dad#A-beB@5R9THzRtlIL z$9GYur=xGvp+-JeFz|+MU|vaVKISliEed{GV@u5FECu!o>nV%Zt~*<9vu1kD8#qlV znQO)2Fw$;`P`S>Xl--R=AtAqv`V{J3e9z}o-gZ&$Mt{k+IZgqv9qr|%*%bxsWBbga z+cCf76lf`H3>l7te`IW@0DYnw(mIHy{?waoFT+RFW>3fizHljP$aQ&nXz(;(olQ0n z-H{M(x&djn+SsA+=`vTEnCTx|?yUuXtK2A5#q_Y9=DVvu-Xz!@3vW``JM}QV@K!?> z6HHJ}V&f)+L}9`k+u1QZfw)B)jSy*39FM;?A~EEGeS@?^uIoq3h+firFr7e?RCDMk k=y#rz?$Upkmq?mAqQ*bEtkP8}WlIssR>@NGR3l?8gc2TvFjSTvS(3pR%h(bUvXk|RMp?!_cH^}# zgY3&NlVwtgVaS-p%sai`_s9Fa$MJpd_q@k(U)On^_jTOY^}EjF{GI1{-EroohR1ou zc>w@8ZfvA)0RSBAA@G^!2)qArv(cRWLOsaJ)=%FR>g?<8G6LEe`2Nnh^BazZ@kvDBL3J%8>^R-+{!UO&p?FWi3<_yLnU}(XU&I5%iCkk zAaZe)?4R+a+tjjDvcr)JfE3pUPeWzcC2*0uu91)diotIYE7~J%(fdRF0aJM<;6lH4 zpkQZO#_0AGv~_`S*wVX&C&1idDejeDCyH-URPs+r*;y$Vnku2qbY@kZa1$`jdzCCI z2aYwMa_CpI+hw6H3g~n_(@<+!nf4T*(^;WTlpF077ztUL$rd43>#$uSyePUkU zHYrX`SkHlX+_YqpYwQlz!bfT3vnLE1aPbfB_&lyuqjO7rg2*eiO4Z@6EJ@b03ve#Q-z8EOJLk< z^ai>oUNmP6y=YCA8hty4jws||e=TokXII{BN*Eu141a*wY4G@^FgC=^hPcOj#&|kV zeD>RAh{h360AzNDUy!ux2xB$|mXz$s^`9Xes#@=~zVX9st&eafxMrH&Kr2XTZdm#g zhrHI^%`UuYeBK>*-iJ6p#IY&7gS)=I;?RYm7=%r)JS1rrS?9Q_g;7f3%ID;A7(1j< z{*F7q#YB)rEkaNSBR$?1)f*Bo7Oo57u)#*FZ94qSMH0>7C`WjmT~+BAjTE&=zG+jS zY&(^u`nT0|1%a3ff|kPg)Rlc0W*vGyB7`>_3u-BrS&?YZ!A3puctuDzO6gJKx_7R)rb(hk92-UrS_U(FETxX6ZviXxSO;a|3bsJ zxXL~PeGG=7)|SZYH@{Ps56nu8mL`)aCru?6NYV7n7Zu&6VXPFaQ>4=HsaT_~ zi#TIvu5jH~u%PHXC)wnFvVtX2`Q+(VnxSkm(KO6@ki*=;GiUknvzUkX&?p%K55gzf zYexA1-!Hl8OKNeSuW-!FYK@V&@TEIaU{Yop@!H5&tXEN%6@_;^5&U-V82cf^j1_QKK*Sj3w+KTt-gLgLhg@H^i)HQ5-3q~6jMQ#@z+~2+4a$j zgKw`H5~VJfWf(eL8fx?rzw9FyZY=9N`nKt}fj;nyC;623wV?|W(7Dix;{;XA(}TP^ zP>B4B#A4u{k!x+ekK3P&gG@e`olfLy0b+;N;fs9hE#FdK;}oT8iizvJ!^s_xxd*(Kxga28vBz71@R9@5eBn;QvGe!9AA@T@ChqyT&yFp58)fI(h8 zA{ZaV`HIc#e`WQ*ko+&GKGK?=kj^EX7y(rN@k)_b%SH@QZ%CqD>r^@4=Wt1W`?x&3 zTfOYm*)TUu{iA!)a7Ok)eqGc;8A{wgSXqqYh6rib4-wkl`mnl^7>2kt@&V_(WCzrt z(KN6!B4}yGN??fPzcit!9d=Fp`q&59dU_~j%nSKp%T0Z2B{XyJwbMacK5uc95{J3D z`NKPR?kwz&8N;X3sNTjp_nlK^O~jK;PX;Uqw-GxqQqA%X zQ!2wIi`oKHN8O!2R9INpVN#$CL7Ej@uC~SQ=xeqICRgjJ|8@yv?ATm(&L=LnR4YC) zM}m0QcOqJL&Z8lLK3b5I<3arLC20P%niqbVUZGIM3BEZ+k3Wrfx!KU(^J{UkFm zI7nvb4tv7q=AqU0od;UJ6qTG%o!=eHg5b!X!PJD-6sT@S^x6kH0})F&u|>w~hTsbZ z8BQl^(aD{8w_(zxOsqLm&!#q?=+PG z5>aiz@0c_aFd7I}4-*j*x~gh8tRj^l{~CBx(-x4k^j*s2R}`}RUsJ=s_ZnMCF`tLl z(?yx>%yK!jdKKa2>K|NhMt%-NStI=Y>p!AUAe*4kOF!$cBiqrv4&SsI${##O!mDB z+jKA+Do|5$T9#~QuZGP@C%ID#vV%50;CyT}1BIhH+@){uhWnw+&UTaOG+HqR?$R9d%$aksp@HY}EGe7^Vf}&!I>rh4$Sfrw|Lbdi8tvokrZ!mAiJA*ba z4qa=_A%@i1xDj?AJP#JHLO{}~CGR4ID2s5MsLMgK;^@m|$?D;048#_R-jTmU6#H+m z#bgO_@p3hMpkCrxEk!Do>bu;1w24Vue_vFjH$Ok`Lc+J9W>y$|ZRDU}edZ+GRR15n z?C%e{x%C{)+F8jsgS+_dqvUaoK3Cjco}M@k zy`fQ&iC4c2KOx`f$X%Sd0vOHER&Od2#N^lp5{}b9C&C-&`an3oXO+zkw&)h4(859* zb>8mRbyR>oaqSbds@mZ0P^o}`Fj=uT)HB?=A+8pcF)T#7lcS?IFCQOq_uGUoeWPJ$ zAXWanj*b&pL&J6N$K3eT)cNS>XkStrrFoiTG@oSred^Ns%>C>q`8b{BZN!(RgK3)o z{a*A2&Y^;9{HY1Y)^cJ?%r)=IN~Vos*gn&5ePiR~P|Z0F4SVIGl=gOQA)%wuw^Gv6 z&!3PtO)FQXY?htLM3)FAG$1!~VDUvw>5+bBiUiCcPXAg-DPXrudMi=Ty( z{n9Zz)dooVu%=pkW<&%>T+ie2nHl+BF?KKzW^W?GYa9@OesOE_;4yJpa@0;XiUPQq z*u-P)C76m4s4%_ipZ4B`(y9j!mfWC_lGi)y;X>w*-tl<{0Vm8k4 z>F1{Dgk*y81`F1z?}+V6RS4_LsCaYM$4}kqmv# zwSl)r`c54W=NWpQ46`Q>Iue==EI~9(XCU1lo*jC!aO1dk!o%*=TzorvrBR+SZXZoi)CGt=28x6#S^JRF zzsGu^Us2|ASt5r)06PSDQ@l+Pk?TzA)brnO*YK+xhcZt%P?l#$kMl(VuMP)s0n*q1 zvoiDlE>We;r@g&E9tGdUYs9|Jmo#JND~7*|^7wa-bxI>p0s`fW^Pa0<`@}R<8e9i% zx?1@N-rW8o;A=;gA&}ju9WskH4%_~6!=*>VK z7i>%(nJw$Mglv-Z7`9I$AEa}aYsDmBOEn9hPNsTC2!uzw4poeXx|J#`+neeMKL2^6 zJINnexKrYdHRE8L_ND(^#P;9DoOOW}z0V~8ko)g5;6Gig_}KTQuWmRr;l6o-&|fL< z*}#@hKMO4j?6pU-8-d(%S@#o{Hn2LY^8IBir;*(jOT%X!=RZyh$cvpE(4j$2OWU$j rZ~HPGV4P$q06^bA!T5h;{=ouF_G7icdt}RBe*=sSO!ZN>9!CBhmjtp2 diff --git a/icons/obj/lavaland/artefacts.dmi b/icons/obj/lavaland/artefacts.dmi index 0408962f9cc6b5c1dd98fa8b7561a2ed66581a58..d4a75fd23c737d58a1bafb95a18f0974e9e24013 100644 GIT binary patch delta 5718 zcmY*ccQjj#`@c4|M~&79t<_pxMvWL%ikelUh`m>}C04Emm7->iQbLXDi=t*JV!f!< zVbtEMHWe$9@74GG{`lpboRgFDtouBl=kt8-dLLQ-cd~@bWWtHUVqk&OYHldiwN%jx zj0Dd;{S1{;ezqEK3oRSY@QPVEfjtB4=IFpOLfU72b-zH~81t`UjgyB|^iX%z2Zu)w zyX}V(M*~)O+1W+xANg|?nFe{Td^E2Xxl`lhR53=izPfu#P*;_f$1BLat5+?#Fnrd!GF6ixPz$K_$7Pi{m-y1$eV zZyrCj&d-jfCDNkdVKW{qR-DDEqVr>;LDD~NtSV0#zBs32W55nh1$)RmyOO9|#3ivv zm%J%fl>GQa!tioA?@U_fe2J`F^tD^N4dgbc-We>Qv_+uyfT!XwBoV%!&Jq zvYQ`0-);J4VjvYbbYjc#+cECwxxT~hLq$}Gxp8;}r$#oDNKoxMs7UP z6@$n7b2CtLaByJadr|`Lj!zE{%PuV___6O=v8?xzj!v-Ap&EyL~5k`-}|^XD}?q~%JO( zoC*PS9nVHzMEiU_X$|rE|NL%lI!QOsDsjHxxY;hXnIBv;H%z7 z^`*>P9GC*Ny2eK9YjS%6%0V3aF765YZRgPlwultGmQIeJmNw6}HkVq}-Ii_$0fZ6| zZ~158Hg-dNl_!r0N!HdghxRQtOHZRD>G0G zTD@)RaI%*#U%Fb2VtRk;$!F>N^1e66D<*-9UsH-cevIoX^B0hj{CbZCWKsF*B5f04 z#vB^EkU#p%CjFNE2-(GL_m{pOBX<^-V>N+ zi%KQ|0TQ4U$4fVkFftM(3dTDF&W3;pMlgH4>Nz$|i4S4rFQnjxXADR9Y>jqMsN&}| zffpWCeooo$C*hG!xmjRjmi9-zI7|H6mb8S#9VaKJJE&?3nZ6fyS-7)tg_|Mt&OC*f zpSM5d&;WZ&dRmq`8OTSzlT=4&>=@B-R-Wn2&>Pp~!Br&)X+uLptRpB2D$UPnm+c35 zx^&6XVVCp!u8{-&N-3{i|6#yptVcDID4#8_CCF-}6OCTZya#LG-1^x{AFhgt&7^FG z7`By-taaR)SUA_Z{@F@ugmJCa2oRyAt=*gpp$7zMKh2m0w7jS(Rz@oMAe%w)6K3qH zfM__J_ubGDi)8cDRb=h>tEs7rKD&ubIaK!foz_xjIH%PQ)Osu$<&jq^x3ZTj8#jA6 z9jBEIc4AGuK(Od+THpIoi+J4z7(i)t+eW93jGLQj8z`bj!|vuCca}#$Nil$(GB?m1;D4!oeX0V*nWL#dhlV`}zix|$(Wc}uq{C>{g+-nLAFuQ*7k}L~ z^%xO^A9WiLzvJI<2x9{LKe8I^zG>`y7UsJP*n%G0P$) z0tW!=Z2)IFmYa?^2gUP(HX&YV=N z8fv4F_=hNPmx&ZH5avMq!#_C}CO$|RzkHA}vRnE792m=c z+A6qWKmP;~G%xoan!%CjsKLCUQ)FFp9wI6$)!`H0+M`<+4}WQ@gGUbEmY!D(haVnh z`hkSjGAh#2d%MS2mIHyRz;dt1kYs0%QBYhoiu8x;N$${|C~09Q>U zf|y?46Dnsl-c81WgasOP-U!7nWwCJRYan;QE}A{{oxa?KMDLr?@sW>J1O*wJ1~|QO zF9a500WJ0bE|mUbjOc*7RQv??YBA!tM{dn5?^`*;=p?;e$v*4@wxNaOs>=x>4z){j zxd`Y*7mI&nEv&nXtb4*;=SJ65RXsO0bFl5ZoZx-)9ay~jbdY?fGV&sfFQf;mo!=}L zxx1Doxi^Y+`s!ylT!t5K8i-rd+zP0-Bi%(b|B)8{8=69m(v}n1kfHA|Qz(2E7qGST zDqM{FH1A4j2WSVoNA6cX+3>HiIC+M4LBX?#8zu8yMnuW z%%{5+*K9VA+0T}wdsg5EfY|WE4JSwc8Z2-)I5~vwxkE@hVeWAZ1$LI&LP~a ze|G6jrI1QXVgge>-#;a|f7ai3R81>mCX^QiR!|-d7`f70zIBCN{2>LAPh(CfA9~^U zeJ1v^`<+j2=v#Q$m86jVOBYCR@K^g{WBIicAM&#OkEi^jH5p~lNu2scE8f~|weHvO zIUt>fi)OxR_3*gZz;}%=e&%YhqRm+2qr@u2Z5EoYX?t1DAL>dlFoynY24066P3Hrn zRXFKvU@i36*xG4&t3BGtrEHH-2PIv{biF1I*$UK*YsC!4CopoKA_+@a5Cz33Q^=%c z`qig%F7^-K2K97LuC}i{P3JG}JZ}bvni0NQ6ZI{$l=&mRQf3m*LQQjQx3!imOp!X} zyVE;0U;odiknBF0Dq?QPPF!uSRMZ5tPkC5FjP}KkwfVfzv-fdrA$cw=_DM->_{$5SJmqW^T-~a6d6m=#;Xz1Zc7-z`c{tv1j5NX#9_duUE9JzizUPG(;cjccJWne8IA`d6`LD91aHr zeMb3uRfp|tmNQ4Q%26F=@4*&7Y}5;c?y(LO`aNp)mq*36qAJMT&HV{;^u z|CEA4rv3Ld8O;?G=6?D)<}Ip`t=0*ipWmO98l+w*uOeQZnvxq_R#db(EY5R02(Kc} zU)czoq^lSxbNO6u-TmDRq8mc;xWJ&JQdwH+E&yX}_hbP#A#{J68jt#*(ZLXm{YEBe zMxQ}~z2zO?IY-n)p1CZf#Uwau>@l}fn1p4z^t0Wtf$idYfT(gYLyZiL(xk z-SE7e>mF>+s&*!=*FFDFCiDU$+U!pd+$U?U3a;HOm~419>CII?*{Z{i7#;8M3+EM% zaslb(W)e@Hbj)1Mx@WUV_lyu&>`dV^T=s9Cq{W;x;&)oGI`df(V|bcdw9Cx&RcEF9 zrCrEquAWDqI_xay4lkZD`&>XnMf`=n`~Fsk;q4?p6^Tvu=xHwv6eIwHiRI)n8ZRHc zDrn)l!BBKK?*@Et7&1S;&e)3pK!BR_-W|0EJ%}%Z7@bWCTa%h!Q1_D&nZ(D{A`^;= zBikk8f|efI_Y}TWymZOS`U{G(o2*VaKV#F>0mX(!?YBJf`^??JTGr(#vv97R1`|V} zJ&EK0(1S@3oi{p{iicMo)ai>U7R^s5`I(z_X9=H40#pYNXeLYx$p*=5-hbso={0Y6 z9Az%Gf`Wp(0C}#R7=;Ke+K^6@!q?P71!0;hFu8aILI*k>)^(j$)cVrP$*X-*O0v&) z;xxYQ4<#bTiP|}Al({0TG&7KzI8@7|kvu_8Bsl`43>mlj;wp`a&P__am$-L|krCs= zGbtM&dhi{|Sf2?zS^astnqWML*E&aKtA1bTidxms*7EztOA-kRf3JUid*@uhdmv2y zP2{Aw6_UtqrFVx^@Rrv`68@xkG3{Lq7AA7r&IKpIG7;!`H6wF<&c8;RFWgD}M~qa` zI3b@*I|fCXhpsnfH89?6%;y$Y=aR)&kfwBLE?r6YbBT$u5w%{?y)LqJ>%;X+3~1aDY@q!z?i92Zgr8-fL6tNAbQKPeyIZ=-i5M?P436WLX!3_@jpU_YcQ zzL^R1f|NQXOLK_3gayi6A-e#z^!?&cYS6iJ|J{LN7ILR_x~|s+{G7H2YhEIxjl!2S zXj{8+S06svNlsL`rdFic9?)9gwDC3JunE;O{^7JI0s(9!s6g5_>NAQS~z9XI2hY zN+3D6x1dz;o*e=utCuM|`tDs$V?mZfN;ONoYE=UEJXT-!LKi3!qny74PzJYXv(Ch+& zZ_$9Jmn&4BDcan(eRdC2_-kCzRrxwCfc)qg%O_g^Lp5yK*U@dH%!0-wT)ScG)^-Ys z<^S%HZ#BxJ3EBDcn^?eR&H3|ra63!_v-?amg81`mY!ltAKM}h`zo;WQ}Q4$z`+wC*j#g}=J$nN9V}pdU!p)&frrkI?S%V11 zm1h)Sri*wP-q&vlhNkO;j!~$ceMg(^<9r~0lJ4z9^VcdbA&arAM)Z%0#kPjzoTB9xv7Nv`V4u_ z^c@c&tAusG9Ohr;=~B*(fu9v*{KCDdhYZGp1XN!QS-maYG-7S28g4pnmFw=u|GehF+ogHPL zz3%RJ`u%=?Jg?X1^}N2{&w9T<vf2%ay9nWl7rq1vKkdv4q?Sn%Eqy7$t!I>~ zN)TYHbQ#lp$PrpPdmXloKnslFlC3AMS0aCL=$z^EZ69{()GAeYFYo2lec4<>@#^sv zE7YTAO{Z=Fii%sYOe$xihr>FCze;e_1*uqJNI`G-p9_3ex^_k1YYO(wSi|vA?DfGf zkNOhYWG%|rz*{M;Z9R-%@M2>DwV{abbs23bIQ!Qn`h&i{5Om7s|JJ402Wj?vu2A4G4-rbr|5ES*e9{Jwkm4p~}f?)MA zGm4JL7y=KT(Py#bh*lGwA5YtT_|f&_et-`5(zl`pwK*S* zzOR*)^j(9lx=+t55B5*_=FQob%VRI*=$}2Cu^lda?S5Mm-=YHZcTM%&(yWwRi{*wp z<8xv-fk54zqV>Ayv*-&+6c>xtUzmr6B@{1rh1Gn`qG~dgqk9;-AV)`>uZ0$@7!8gz z6@l!^Z2SRz zyC0tE_oB04iZ;hs)Z-`AlP9ri96#TZ!1KC-Ys*u*uMWA-uI>C>`tjXDs7mb)l+{N( z!z^j$TLcL?l_^;UiBT3c1JPauI`{Y4Jm+guKE~w^ zzpH+6j|j9gIWc0j-C1Z>ZTa5+JBpOvmnP-%- z<=(-HiU;?^ts*u}*Xce};SsJ4-$nC2g#_x--n=LXKYX`S<`NpAE&h!I*UpYmjzISy z_K?gBaQPKW^Mh1{UJF;IANxNmmt?j6TW(Uv8DxD`HpeAZde2w&bVq+`g`dY`s1`4KR9{gOa zT{J(f*d0;98iFAGH)fDHL$9VsEYWMC8=y-{c-;^8*la zGujHFjOTKhTyNhX9pp}LQZ}arep!PtfwR%3!Jn)QQ*L;OD8z&|*{G2%3dxy*v&WXi zt_~b7_NBFp8O*H_5`g8zPN;APZH2m3qmkV4dr&xy+=)pC3`4q~{L8fpB7HVwWCGis zJ~)OVkwokC510x#DAaT-Oe;V_&a6}bL{Qe_37vQ_c9S~jC#;x@wYh0#L*un>;}8Dx zRavE*eJlP?mGW(Dre@W@ewWD)o=`DA=@oi`CRKuCJ*15#>`=y$HeD_MA*LaRoW}e* zr?$m}UpW!ucMwuga2O2C4dZKs-UMoYCEjCD_nvadz&@N7M?GV$!I7ik#|9i*sgiPc=bRG5Ka4s{ zbD{dFrM{oWWG*X`RaQv-S@!k$Zq(2YEk(O~KJF}Ws=PoiouGXtX1;aI0foXS9P@Wk z@imeNQ^j5xYv9_!EJHz{fIX$!-*7Gv^>-$^99=V{42ms4f8p%VOmBu+y+-&CaR;8f z2lI))gikz@!kp2d?@Ry)l5P<08W*_asSw#lF1>Zr_VT#K=$ zbSOPK@iizX_&er@ zw8!E;R8}Ez%oKa9pE)jWC0f(N8LGAD`Mek4q2w55+F;$^bM;5umeV#ij!8rUCkeca zS+lq0{$T-D5Skj@`PkUmgPQ=3vQN-r!dY|?~6UcGwt?7>*r>t#j-K4v$*ywTNt z6!D$7X?AU`q6Bt4u+j65QAp6{eNfdAA5ibHdF_*^VM|Q?&tq@?66)e%>HP=3DJQ|r zMG77qit&e+jY;Un)(h;AOQxvJB`FDsR=6rwAP*4`b3rF2Y_&K)p9PH9xf;ZMwvkGv zqkxy;z5;3iun#d3n@ro>8XN>KCRsykxENdXhy8l-U_*IK24cYwq^z>0vX%87y(* zizJ8V>9*`CKo*ymmrES6M2*|)7Hp-(e{uQ{0~R(DdoBo|WZk3j;z2FKaBm+xVe?8} zj#IojO1%AQ^Uef}4kUNN{@>)B-SSb*pB-7*ol}`yIAgn4VR>cb<#F?EfSoE#-^cy) zxgeGhiIe3k7JaBPTB#GKKSQV-B8J@=#=BJUHZ)w2+KRvO;cy;> z_NlQ%x#}b2Y(luge&t_v?2|yZuN0LFk%cz@v47F6sI@}(hYs! zmR4s8yVc8>B1oqpoUIsC@Ix}-UX50TH~&^5`eXsNcH{Q#5QXv;B>tlHn1==}ohTF- z)|LVRo290KsKSfjWXvK>r zw43g;@yy)_<|&^D4LC-^oE5vnHMk|)QQUxrHxMJ^THuTJjq}78Z(R?kM2N>-B&GRn zq&$04=Fa+bIB6obfsR99IwEQDJc+YxIWV&w#s1@WGBY4~6bXwQ?y+_zft&NaP{uBU&xLf;+XgM(6$;LfBsCt-unm~*T=hSHZ zm}r=Jq-M3QsS52^0X#m8M#|)f|0Z$&`tb?N=ozuYP6TR;QXRa~%s*w(10#QV+;61Y z=&Q1gWO?H4u0^34W&=VrcrX@QXN))5Wxp*+&;ZJEOGUn0Ul+eE{&g}Z^t+)tcafMsc$vI9~hR(^s95VtQ%BdoudD> zwx`^Pro>CIYT=w(?LiX37p`37KG*4LR{3-3(CL!|r`C}rdhWQq`r*#hFw-GJAfbQy z?LW;>DwakG-?~)CUO0;Ws9g#ITx|VrtGB3l&H5yitJNd#uG!*Lifu}qC(%D(?vUL+^Y$jyvD_bk;P zJ>cMT_DXqMf0hthN&tNwczDJq0N~EtoQ*+Bm}@cW6_R0i=1U=^YtlQht82+uS|M9i zDJpc&&kMw1+rm#4M6vQG>ef+wIk9b2QqoNfXztzry0km*9t?=Ra_7^3C7fVXB^eR&Y~e8E%tq1V-wW`c1mska3%*Fo2td zuPX(*d8J4Gr7e)|-3TizMkH~U?1V&{?xpwMduQQW+0q+vj{_f7)pR9t)#^Al7Nwys zsWr21G?h~GZr~TX@;PQYE9YX0Y+02>Py7+{eJIN-y)UFN7=Z;Sdp6ls?XveFd z+g~c+(l;dVV)CTYBb_R#k$?)xO$LbGA?(e*t7lTHZM#?OGEjx!yPv=SB8uXcL=Dxl@ z5{RRbu?X{j^5d@O&YtZYXd}}yEb6J&F%%*nz-kmz%+1&mz4@=sr8w2sBIK1{9zPD! z`DAd;zFzI1smm{5&4`}^*TCSIGh%Nln|m{5_khVvrK7r6@<6zbM~omuezJ2?5dL;oO*~}D4y>^_NTR)i_k+k7l?W81`8G!d=AeZDNR0XepL0`X9 z%Wt^eiK}_Zbf5{oz`28rpCb-t0?59t9yH^@q&TUyp&bFub(6<`uY-7#3zuuQgYJzH zErCq{1gM_tX{z6SMD`kiaz286@o(lQ&s|(CzmOMHObq7ZvM}Z#`j5`yhGw!hH$Gpk z+Kh3LV#{lN+;SONoX;@0;jklwk>GB-x{-a#9P|m1&QDe#*JgltS~m1gX}wM?5}_+( ztN-#^tN^`7Pu>|c^p&s4f;MES5Z^l(MDP4aK5a;qD#Vy66~a!Xo*$MCvApLpOI{@6 z8>~(XisdntImhhBeceYRx5|Rs<)x>P#x)qltynAgJ3%^0c5i^ZM8v~N{CaDX+jI12 zHaF9ZUD zjr?l$#jn>rH!<^Ua8BzaMqtj4Lq1Y^Gs4wP=HJDKl5mfL-^tmPXus^+cMXngq50@3 zh%yBS#a2EfW2jAA;5-Y^9t6bT+50%V##8qSth=cu#88dP!T5AqJbu0mBp$gseEA`H zGTxomYWRB0V`1{PZtWeF!}cOHMN040^VB7tLl(7q?i!(-Vg%+yacrW8Je@eCgm(~Gt*PE%%;4R=B?tHG^RCWRmJ&S1O^)V!<-3(tc^z3 zYeh;sFtk_~9Zg;vb-b~cm{rqmnn9%cmo9s|{WlL8w<&%9-zxv#DJg(jg~ob6$oR^B z1_VGvo5qJ;_-A|VwI4#^mnOe5=yO5XBkxM?GQ*VLkoX=lwLc+Fb>sZ*uQoatV8^>e}{>Trn*$K)=WxA@p(A4bk3(|tx~@I|8a1S+JLO;v6t zR_XedQ-zYrK1-qoYVGhdjlnZ+cbe0pw0iTfHCZ^vEWC~@?%#2tM@%UVYm=vG@63oj y2>##S^UgYYEHBiB=`^~+0`-N+wJvmx2xF&IJ#TPUAOQdXdO%OhNV7=8CgeZFRbQ$A diff --git a/icons/obj/lavaland/elite_trophies.dmi b/icons/obj/lavaland/elite_trophies.dmi new file mode 100644 index 0000000000000000000000000000000000000000..d194c93853dbb4e72d876448831b8b49e26b25f3 GIT binary patch literal 1057 zcmV++1m63JP)p-Q{{a90|NqPY|6gBUIyyRFURy^+Lwa{}E-foZ7#-GxjH6Uri9kkHASA%R zz()W8dKLs@3II9)0FxyWNX}0%00001bW%=J06^y0W&i*Hsd`jcbVOxyV{&P5bZKvH z004NLb&tUgf-n$7&+S(H?*HlHcWkjwjT{({GK|Kpz?1vE8-IgDBhRj-RPskxT zAlas=R_%YY)9F+eKcCMjk9To6d}RW>jen&)-p8#2>+uO3BC#GH!P~awJS;ARNaFnX z(>~ruIJ!9eLYBZ2pn{U>ne zVf8PBdyj%RJnZ|t9Bxl>K;?#S%(CeeebUX0oQ$l z!T21cG)(-_W-#&$iT++{Bee}nHxm*d@ZdGT)4;^%`+KP+OzTOzha&+^|E>Wg!NlkL zdjy5h(}W8JI>txL;YkDf7LU*O|Cl|5#^fQe4igyr7Y*=u48M1NzV{0#Y=IP+Ez*&o zANwZ_`k+R>dv1|I8|$7MtQ=_y4W^4MjsJ$d9AeCgR;^mKYSpU2X0np;Z#Vqiic!q-LgANU4C^{C z%eKwSR+Qnk-O4feBuX+gE0owkQgAh`B=fv2B^gj5&=h2_vDeZBMYnXp@;F;}mdUtb2MMJzpK=KX^|H%&jRsk+8EB|x>rzsS@I3C+lG-EWUD*ylh0d!JM zQvg8b*k%9#0C;*-Sad{Xb7OL8aCB*JZU6vyoKseCa&`CgQ*iP1AzGbOXA7${=M#hF%= zn41b>n*l{ra}q0oOd}mQYE+1_111ADmK^Y)k+E1D#1kK~zYI?bW}I;#L#} z@S6gOOtr9B0aDpu$tcypBDo!pXS8(K_^hs{o+x#i)Yz=0<0!=rJC=O&Pdid*XtTwP z((S&&KF}T;48|Ck2Z+1h{jTw~h0e!VdVN!?v7M_{dy(f}ULW*#H*^N_(Y)K~?rt#p z#)~6)<=VKu$}c##-P`ezyz*1yyC3rlZ+^b`Wqc&BTwf%=P|aL*ZX5K3>Tdq+*3dOg z6&PmbwrLtUuX2%@O@_8&k1)c<@r!q@(<#-pcLP~zVb&wn>Qo|75a^-qnzzM%2ec=Um; zL+%;>`7Y3rWX10P?et!Imp}YVM?PR-^j2n;q;^K1Ocy<8s0?Yt0e@bb(K821{i^p~ zb|kwC%VT!QYytLA?OZ4w#p%#@&kP^ zE#x^D`k+yVM)Wt%=06#!4*-nGb0c3q31~g9)^Nu#&oBzPWco@+JUhcj54^4qqG#PNM z+ yJM$b}D={n1|HOX%N}C<t?z|7mE?*IS*0d!JMQvg8b*k%9#0FQc9Sad{Xb7OL8aCB*JZU6vy zoKseCa&`CgQ*iP1KjUr>;mf?cN}m$HJZp9|PC02^pL(N_(H(EtDfs!2paRA_6*MuQuh;K0N*4FZmw{4^zHAo0Ol z5(6SJh@XQk{=gTI%=0Ba0lOriR|Dk3e6#^CfF!{9mO(-SvS~17djh>3B#n5U^M6VJ z{1nY&&tdP$-l1&@d(B(HMmaq3djd(k)jiHn&j*0^C0Oqh`Nt9@@S0Dr^UL|=J;(2c(Uz>nyPZ|%Ron|Fw9@yqYx1!flh5xg}H_)k7yQs_0$ znpuACw58zuE#S}0Cz8SpKN#>NAjB(+4}5TNc*lz{c4O3C1^!1r2durZN_jYVXK_Qb z&*m|PPdqCGrIc(1r8>+zneHz4H@M={)#mddMDQ2cPM+~QhC_jj<}tiqzC-z4w0w_Q zzD~@td`T{)d{tG|zoE8m&opS;?{Aw`7#?HLTHw%G2EeT-qcmL&god&VT5C2w(*U2O zi?aIzWqj=q)c!#257hoZ?GM!cK