From 774c07cd9bd44872b386567e8b9d1a0bb3e98981 Mon Sep 17 00:00:00 2001
From: John Willard <53777086+JohnFulpWillard@users.noreply.github.com>
Date: Mon, 13 Apr 2026 19:05:57 -0400
Subject: [PATCH] Basic mob stat panel gutting (#95543)
## About The Pull Request
Changes Guardian HUD to use action buttons instead of HUD elements,
which means their buttons
1. Can now be moved
2. Can be binded
Other Holoparasite HUD changes:
1- Moves some special buttons like explosive's explosion ability to be
where the "Toggle Mode" button typically is, to be consistent with some
other modes (assassin, gas) that also works like their unique ability.
2- Gives non-dextrous holoparasites the ability to move floors, since
they float.
3- Fixes dextrous holoparasites having 2 health HUDs
4- Moves "Check Guardian Type" verb to a new action button meant to
mimick the Antag UI Info button.
Gives Soulscythes a Combat mode indicator
Locks Revenant's combat mode indicator (cause it does nothing)
Adds another hoverable HUD element, basic mobs can now hover over their
healthdoll to see their Health %
Adds a Unit Test to ensure all basic mobs have a HUD that shows some
form of health & combat mode (unless unnecessary like Revenants), to not
lose any information from basic mob conversion now that they lose the
stat panel.
## Why It's Good For The Game
This is yet another supplement of
https://github.com/tgstation/tgstation/pull/95383 - Removing stat panel
entries for all basic mobs is a great move towards lessening the
reliance of mobs on the stat panel.
This is also just good QoL for Holoparasites, especially since their
stat panel had 2 entries for "Master HP" and your "Own" HP, despite
Holoparasites not even having their own HP at all.
## Changelog
:cl:
qol: Holoparasites' abilities are now action buttons, so you can rebind
or move them.
qol: Holoparasites now have floor change buttons.
fix: Holoparasites and Soulscythes now have a combat mode indicator.
fix: Dextrous holoparasites now have their inventory slot again while
non-dextrous had it taken away (not that they could use it).
/:cl:
---
code/__DEFINES/hud.dm | 7 ++
code/__DEFINES/traits/declarations.dm | 2 +-
code/_onclick/hud/generic_dextrous.dm | 12 ++-
code/_onclick/hud/guardian.dm | 35 +++-----
code/_onclick/hud/hud.dm | 3 +
code/_onclick/hud/screen_objects/alert.dm | 6 --
code/_onclick/hud/screen_objects/guardian.dm | 68 ----------------
.../hud/screen_objects/screen_objects.dm | 33 +++++++-
code/_onclick/hud/soulscythe.dm | 4 +
code/_onclick/hud/voidwalker.dm | 1 +
code/datums/actions/mobs/guardians.dm | 77 ++++++++++++++++++
code/datums/components/life_link.dm | 9 +-
code/modules/mob/living/basic/basic.dm | 5 --
code/modules/mob/living/basic/boss/boss.dm | 1 +
.../mob/living/basic/guardian/guardian.dm | 29 +++++--
.../basic/guardian/guardian_types/assassin.dm | 43 +++-------
.../basic/guardian/guardian_types/charger.dm | 5 +-
.../basic/guardian/guardian_types/dextrous.dm | 15 +++-
.../guardian/guardian_types/explosive.dm | 1 +
.../basic/guardian/guardian_types/gaseous.dm | 2 +-
.../guardian/guardian_types/protector.dm | 2 +-
.../basic/guardian/guardian_types/ranged.dm | 3 +-
.../living/basic/guardian/guardian_verbs.dm | 9 --
.../basic/space_fauna/revenant/_revenant.dm | 2 +-
code/modules/mob/living/living.dm | 1 +
code/modules/mob/mob_defines.dm | 2 +-
code/modules/unit_tests/huds.dm | 23 ++++++
icons/hud/64x16_actions.dmi | Bin 3443 -> 4854 bytes
icons/hud/guardian.dmi | Bin 13153 -> 13719 bytes
tgstation.dme | 2 +-
30 files changed, 232 insertions(+), 170 deletions(-)
delete mode 100644 code/_onclick/hud/screen_objects/guardian.dm
create mode 100644 code/datums/actions/mobs/guardians.dm
diff --git a/code/__DEFINES/hud.dm b/code/__DEFINES/hud.dm
index 7bbd3b5fc6c..d00c7ac066e 100644
--- a/code/__DEFINES/hud.dm
+++ b/code/__DEFINES/hud.dm
@@ -361,6 +361,13 @@
#define ui_ghost_language_menu "SOUTH:6,CENTER+4:22"
#define ui_ghost_floor_changer "SOUTH:6,CENTER+4:7"
+//Holoparasites
+#define ui_guardian_floor_changer "EAST-1:28,SOUTH+1:7"
+#define ui_guardian_communication "CENTER-2:16,SOUTH+0:5"
+#define ui_guardian_manifest "CENTER-1:16,SOUTH+0:5"
+#define ui_guardian_recall "CENTER+0:16,SOUTH+0:5"
+#define ui_guardian_special "CENTER+1:16,SOUTH+0:5"
+
//Voidwalker
#define ui_voidwalker_left_of_hands "CENTER+-2:16,SOUTH+0:5"
diff --git a/code/__DEFINES/traits/declarations.dm b/code/__DEFINES/traits/declarations.dm
index e3c4bdd8f77..77b96215a44 100644
--- a/code/__DEFINES/traits/declarations.dm
+++ b/code/__DEFINES/traits/declarations.dm
@@ -1527,7 +1527,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
* (This may be changed later but I chose to do it this way to avoid messing up interactions which require combat mode)
*/
#define TRAIT_COMBAT_MODE_SKIP_INTERACTION "combat_mode_skip_interaction"
-// bars change of combat mode
+///Prevents the user from swapping combat intent.
#define TRAIT_COMBAT_MODE_LOCK "combat_mode_lock"
///A "fake" effect that should not be subject to normal effect removal methods (like the effect remover component)
diff --git a/code/_onclick/hud/generic_dextrous.dm b/code/_onclick/hud/generic_dextrous.dm
index 8a7950cfe63..a0faa532533 100644
--- a/code/_onclick/hud/generic_dextrous.dm
+++ b/code/_onclick/hud/generic_dextrous.dm
@@ -1,3 +1,9 @@
+/datum/hud/dextrous
+ ///Boolean on whether to give the generic combat indicator
+ var/give_generic_combat = TRUE
+ ///Boolean on whether to give a health doll.
+ var/give_health_doll = TRUE
+
//Used for normal mobs that have hands.
/datum/hud/dextrous/initialize_screen_objects()
. = ..()
@@ -11,12 +17,14 @@
build_hand_slots()
add_screen_object(/atom/movable/screen/pull, HUD_MOB_PULL, HUD_GROUP_STATIC, ui_style, ui_below_throw)
- add_screen_object(/atom/movable/screen/combattoggle/flashy, HUD_MOB_INTENTS, HUD_GROUP_INFO, ui_style, ui_movi)
+ if(give_generic_combat)
+ add_screen_object(/atom/movable/screen/combattoggle/flashy, HUD_MOB_INTENTS, HUD_GROUP_INFO, ui_style, ui_movi)
+ if(give_health_doll)
+ add_screen_object(/atom/movable/screen/healthdoll/living, HUD_MOB_HEALTHDOLL, HUD_GROUP_INFO)
add_screen_object(/atom/movable/screen/floor_changer, HUD_MOB_FLOOR_CHANGER, HUD_GROUP_STATIC, ui_style, ui_above_movement)
add_screen_object(/atom/movable/screen/zone_sel, HUD_MOB_ZONE_SELECTOR, HUD_GROUP_STATIC, ui_style)
add_screen_object(/atom/movable/screen/area_creator, HUD_MOB_AREA_CREATOR, HUD_GROUP_STATIC, ui_style)
add_screen_object(/atom/movable/screen/memories, HUD_MOB_MEMORIES, HUD_GROUP_STATIC, ui_style)
- add_screen_object(/atom/movable/screen/healthdoll/living, HUD_MOB_HEALTHDOLL, HUD_GROUP_INFO)
if(HAS_TRAIT(mymob, TRAIT_CAN_THROW_ITEMS))
add_screen_object(/atom/movable/screen/throw_catch, HUD_MOB_THROW, HUD_GROUP_HOTKEYS, ui_style, ui_drop_throw)
diff --git a/code/_onclick/hud/guardian.dm b/code/_onclick/hud/guardian.dm
index cabe261b14e..18b1b985ccb 100644
--- a/code/_onclick/hud/guardian.dm
+++ b/code/_onclick/hud/guardian.dm
@@ -1,35 +1,19 @@
-/datum/hud/guardian
- ui_style = 'icons/hud/guardian.dmi'
- inventory_slots = list(/datum/inventory_slot/guardian_storage)
-
/datum/hud/guardian/initialize_screen_objects()
. = ..()
- add_screen_object(/atom/movable/screen/pull, HUD_MOB_PULL, HUD_GROUP_STATIC, ui_style)
- add_screen_object(/atom/movable/screen/guardian/manifest, HUD_GUARDIAN_MANIFEST, ui_loc = ui_hand_position(RIGHT_HANDS))
- add_screen_object(/atom/movable/screen/guardian/recall, HUD_GUARDIAN_RECALL, ui_loc = ui_hand_position(LEFT_HANDS))
- add_screen_object(/atom/movable/screen/guardian/toggle_light, HUD_GUARDIAN_LIGHT)
- add_screen_object(/atom/movable/screen/guardian/communicate, HUD_GUARDIAN_COMMUNICATE)
-
+ add_screen_object(/atom/movable/screen/pull, HUD_MOB_PULL, HUD_GROUP_STATIC, 'icons/hud/guardian.dmi')
+ add_screen_object(/atom/movable/screen/floor_changer, HUD_MOB_FLOOR_CHANGER, HUD_GROUP_STATIC, ui_style, ui_below_throw)
add_screen_object(/atom/movable/screen/healths/guardian, HUD_MOB_HEALTH, HUD_GROUP_INFO)
+ add_screen_object(/atom/movable/screen/combattoggle/flashy, HUD_MOB_INTENTS, HUD_GROUP_STATIC, ui_style, ui_loc = ui_zonesel)
- var/mob/living/basic/guardian/owner = mymob
- if (istype(owner))
- add_screen_object(owner.toggle_button_type, HUD_GUARDIAN_TOGGLE, ui_loc = ui_storage1)
+///Dextrous subtype for only dextrous holoparasites. Can hold things hence the inventory slot.
+/datum/hud/dextrous/guardian
+ inventory_slots = list(/datum/inventory_slot/guardian_storage)
+ give_health_doll = FALSE
/datum/hud/dextrous/guardian/initialize_screen_objects()
. = ..()
- add_screen_object(/atom/movable/screen/pull, HUD_MOB_PULL, HUD_GROUP_STATIC, ui_style)
- add_screen_object(/atom/movable/screen/guardian/communicate, HUD_GUARDIAN_COMMUNICATE, ui_loc = ui_sstore1)
- add_screen_object(/atom/movable/screen/guardian/manifest, HUD_GUARDIAN_MANIFEST, ui_loc = ui_belt)
- add_screen_object(/atom/movable/screen/guardian/recall, HUD_GUARDIAN_RECALL, ui_loc = ui_back)
- add_screen_object(/atom/movable/screen/guardian/toggle_light, HUD_GUARDIAN_LIGHT)
-
add_screen_object(/atom/movable/screen/healths/guardian, HUD_MOB_HEALTH, HUD_GROUP_INFO)
- var/mob/living/basic/guardian/owner = mymob
- if (istype(owner))
- add_screen_object(owner.toggle_button_type, HUD_GUARDIAN_TOGGLE, ui_loc = ui_storage2)
-
/datum/hud/dextrous/guardian/persistent_inventory_update()
if(!mymob)
return
@@ -40,7 +24,7 @@
var/mob/living/basic/guardian/dextrous/dex_guardian = mymob
if(hud_shown)
if(dex_guardian.internal_storage)
- dex_guardian.internal_storage.screen_loc = ui_id
+ dex_guardian.internal_storage.screen_loc = ui_back
dex_guardian.client.screen += dex_guardian.internal_storage
else
if(dex_guardian.internal_storage)
@@ -51,4 +35,5 @@
name = "internal storage"
icon_state = "suit_storage"
slot_id = ITEM_SLOT_DEX_STORAGE
- screen_loc = ui_id
+ screen_loc = ui_back
+
diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm
index 3ac3685874d..4f917217706 100644
--- a/code/_onclick/hud/hud.dm
+++ b/code/_onclick/hud/hud.dm
@@ -58,6 +58,8 @@ GLOBAL_LIST_INIT(available_ui_styles, list(
/// If this client is being shown atmos debug overlays or not
var/atmos_debug_overlays = FALSE
+ ///Boolean on whether they need at least a healths or healdoll, for unit tests.
+ var/needs_health_indicator = TRUE
/// The color to use for the screentips.
/// This is updated by the preference for cheaper reads than would be
/// had with a proc call, especially on one of the hottest procs in the game (MouseEntered).
@@ -303,6 +305,7 @@ GLOBAL_LIST_INIT(available_ui_styles, list(
hud_used = new_hud
new_hud.build_action_groups()
+
/**
* Shows this hud's hud to some mob
*
diff --git a/code/_onclick/hud/screen_objects/alert.dm b/code/_onclick/hud/screen_objects/alert.dm
index ca4fcc22f80..6a79bf6b0e9 100644
--- a/code/_onclick/hud/screen_objects/alert.dm
+++ b/code/_onclick/hud/screen_objects/alert.dm
@@ -754,12 +754,6 @@
//GUARDIANS
-/atom/movable/screen/alert/canstealth
- name = "Stealth Ready"
- desc = "You are ready to enter stealth!"
- icon_state = "guardian_canstealth"
- alerttooltipstyle = "parasite"
-
/atom/movable/screen/alert/status_effect/instealth
name = "In Stealth"
desc = "You are in stealth and your next attack will do bonus damage!"
diff --git a/code/_onclick/hud/screen_objects/guardian.dm b/code/_onclick/hud/screen_objects/guardian.dm
deleted file mode 100644
index 41282bc45ed..00000000000
--- a/code/_onclick/hud/screen_objects/guardian.dm
+++ /dev/null
@@ -1,68 +0,0 @@
-/atom/movable/screen/guardian
- icon = 'icons/hud/guardian.dmi'
- mouse_over_pointer = MOUSE_HAND_POINTER
-
-/atom/movable/screen/guardian/manifest
- name = "Manifest"
- desc = "Spring forth into battle!"
- icon_state = "manifest"
-
-/atom/movable/screen/guardian/manifest/Click()
- if(isguardian(usr))
- var/mob/living/basic/guardian/user = usr
- user.manifest()
-
-/atom/movable/screen/guardian/recall
- name = "Recall"
- desc = "Return to your user."
- icon_state = "recall"
-
-/atom/movable/screen/guardian/recall/Click()
- if(isguardian(usr))
- var/mob/living/basic/guardian/user = usr
- user.recall()
-
-/atom/movable/screen/guardian/toggle_mode
- name = "Toggle Mode"
- desc = "Switch between ability modes."
- icon_state = "toggle"
-
-/atom/movable/screen/guardian/toggle_mode/Click()
- if(isguardian(usr))
- var/mob/living/basic/guardian/user = usr
- user.toggle_modes()
-
-/atom/movable/screen/guardian/toggle_mode/inactive
- icon_state = "notoggle" //greyed out so it doesn't look like it'll work
-
-/atom/movable/screen/guardian/toggle_mode/assassin
- name = "Toggle Stealth"
- desc = "Enter or exit stealth."
- icon_state = "stealth"
-
-/atom/movable/screen/guardian/toggle_mode/gases
- name = "Toggle Gas"
- desc = "Switch between possible gases."
- icon_state = "gases"
-
-/atom/movable/screen/guardian/communicate
- name = "Communicate"
- desc = "Communicate telepathically with your user."
- icon_state = "communicate"
- screen_loc = ui_back
-
-/atom/movable/screen/guardian/communicate/Click()
- if(isguardian(usr))
- var/mob/living/basic/guardian/user = usr
- user.communicate()
-
-/atom/movable/screen/guardian/toggle_light
- name = "Toggle Light"
- desc = "Glow like star dust."
- icon_state = "light"
- screen_loc = ui_inventory
-
-/atom/movable/screen/guardian/toggle_light/Click()
- if(isguardian(usr))
- var/mob/living/basic/guardian/user = usr
- user.toggle_light()
diff --git a/code/_onclick/hud/screen_objects/screen_objects.dm b/code/_onclick/hud/screen_objects/screen_objects.dm
index e21dd0bc2dc..7631674c460 100644
--- a/code/_onclick/hud/screen_objects/screen_objects.dm
+++ b/code/_onclick/hud/screen_objects/screen_objects.dm
@@ -864,7 +864,6 @@ INITIALIZE_IMMEDIATE(/atom/movable/screen) // I hate this place
/atom/movable/screen/healthdoll
name = "health doll"
screen_loc = ui_healthdoll
- mouse_over_pointer = MOUSE_HAND_POINTER
/atom/movable/screen/healthdoll/Click()
if (iscarbon(usr))
@@ -877,9 +876,41 @@ INITIALIZE_IMMEDIATE(/atom/movable/screen) // I hate this place
/atom/movable/screen/healthdoll/living
icon_state = "fullhealth0"
screen_loc = ui_living_healthdoll
+ ///The image we create on New to use for showing mob's HP on hover. It uses a separate image as to not be cut off by `alpha_mask_filter`.
+ var/image/health_overlay
+ ///Boolean on whether a mouse is being hovered over us right now.
+ var/hovering = FALSE
var/filtered = FALSE //so we don't repeatedly create the mask of the mob every update
+/atom/movable/screen/healthdoll/living/New(loc, ...)
+ . = ..()
+ health_overlay = image(loc = src, layer = src.layer+0.1)
+
+/atom/movable/screen/healthdoll/living/Destroy()
+ QDEL_NULL(health_overlay)
+ return ..()
+
+/atom/movable/screen/healthdoll/living/update_overlays()
+ . = ..()
+ if(hovering)
+ . |= health_overlay
+
+/atom/movable/screen/healthdoll/living/MouseEntered(location,control,params)
+ if(usr != get_mob())
+ return
+ . = ..()
+ hovering = TRUE
+ update_appearance(UPDATE_ICON)
+
+/atom/movable/screen/healthdoll/living/MouseExited(location, control, params)
+ if(usr != get_mob())
+ return
+ . = ..()
+ hovering = FALSE
+ update_appearance(UPDATE_ICON)
+
/atom/movable/screen/healthdoll/human
+ mouse_over_pointer = MOUSE_HAND_POINTER
/// Tracks components of our doll, each limb is a separate atom in our vis_contents
VAR_PRIVATE/list/atom/movable/screen/limbs
/// Lazylist, tracks all body zones that are wounded currently
diff --git a/code/_onclick/hud/soulscythe.dm b/code/_onclick/hud/soulscythe.dm
index e290d960e56..53b2d850011 100644
--- a/code/_onclick/hud/soulscythe.dm
+++ b/code/_onclick/hud/soulscythe.dm
@@ -1,3 +1,7 @@
+/datum/hud/soulscythe
+ needs_health_indicator = FALSE //we use blood level instead.
+
/datum/hud/soulscythe/initialize_screen_objects()
. = ..()
add_screen_object(/atom/movable/screen/blood_level, HUD_MOB_BLOOD_LEVEL, HUD_GROUP_INFO)
+ add_screen_object(/atom/movable/screen/combattoggle/flashy, HUD_MOB_INTENTS, HUD_GROUP_STATIC, ui_style, ui_loc = ui_zonesel)
diff --git a/code/_onclick/hud/voidwalker.dm b/code/_onclick/hud/voidwalker.dm
index c6da1e0bf10..5460ee90a5b 100644
--- a/code/_onclick/hud/voidwalker.dm
+++ b/code/_onclick/hud/voidwalker.dm
@@ -1,5 +1,6 @@
/datum/hud/dextrous/voidwalker
ui_style = 'icons/hud/screen_voidwalker.dmi'
+ give_generic_combat = FALSE //we give our own version below, here.
/datum/hud/dextrous/voidwalker/initialize_screen_objects()
. = ..()
diff --git a/code/datums/actions/mobs/guardians.dm b/code/datums/actions/mobs/guardians.dm
new file mode 100644
index 00000000000..ff912c5300e
--- /dev/null
+++ b/code/datums/actions/mobs/guardians.dm
@@ -0,0 +1,77 @@
+/datum/action/cooldown/guardian
+ button_icon = 'icons/hud/guardian.dmi'
+
+/datum/action/cooldown/guardian/IsAvailable(feedback)
+ . = ..()
+ if(!.)
+ return .
+ return !!isguardian(owner)
+
+/datum/action/cooldown/guardian/check_type
+ name = "Check Type"
+ desc = "A reminder on what your abilities are."
+ //this is based off of the antag ui icon, if that changes then change this too please.
+ button_icon_state = /datum/action/antag_info::button_icon_state
+ default_button_position = SCRN_OBJ_INSERT_FIRST
+
+/datum/action/cooldown/guardian/check_type/Activate(atom/target)
+ . = ..()
+ to_chat(owner, astype(owner, /mob/living/basic/guardian)?.playstyle_string)
+
+/datum/action/cooldown/guardian/communicate
+ name = "Communicate"
+ desc = "Communicate telepathically with your user."
+ button_icon_state = "communicate"
+ default_button_position = ui_guardian_communication
+
+/datum/action/cooldown/guardian/communicate/Activate()
+ astype(owner, /mob/living/basic/guardian)?.communicate()
+
+/datum/action/cooldown/guardian/manifest
+ name = "Manifest"
+ desc = "Spring forth into battle!"
+ button_icon_state = "manifest"
+ default_button_position = ui_guardian_manifest
+
+/datum/action/cooldown/guardian/manifest/Activate()
+ astype(owner, /mob/living/basic/guardian)?.manifest()
+
+/datum/action/cooldown/guardian/recall
+ name = "Recall"
+ desc = "Return to your user."
+ button_icon_state = "recall"
+ default_button_position = ui_guardian_recall
+
+/datum/action/cooldown/guardian/recall/Activate()
+ astype(owner, /mob/living/basic/guardian)?.recall()
+
+/datum/action/cooldown/guardian/toggle_light
+ name = "Toggle Light"
+ desc = "Glow like star dust."
+ button_icon_state = "light"
+
+/datum/action/cooldown/guardian/toggle_light/Activate()
+ astype(owner, /mob/living/basic/guardian)?.toggle_light()
+
+/datum/action/cooldown/guardian/toggle_mode
+ name = "Toggle Mode"
+ desc = "Switch between ability modes."
+ button_icon_state = "toggle"
+ default_button_position = ui_guardian_special
+
+/datum/action/cooldown/guardian/toggle_mode/Activate()
+ astype(owner, /mob/living/basic/guardian)?.toggle_modes()
+
+/datum/action/cooldown/guardian/toggle_mode/assassin
+ name = "Toggle Stealth"
+ desc = "Enter or exit stealth."
+ button_icon_state = "stealth"
+ transparent_when_unavailable = TRUE
+
+/datum/action/cooldown/guardian/toggle_mode/assassin/is_action_active(atom/movable/screen/movable/action_button/current_button)
+ return owner.has_status_effect(/datum/status_effect/guardian_stealth)
+
+/datum/action/cooldown/guardian/toggle_mode/gases
+ name = "Toggle Gas"
+ desc = "Switch between possible gases."
+ button_icon_state = "gases"
diff --git a/code/datums/components/life_link.dm b/code/datums/components/life_link.dm
index d1371467682..026826e4fea 100644
--- a/code/datums/components/life_link.dm
+++ b/code/datums/components/life_link.dm
@@ -25,14 +25,13 @@
RegisterSignal(parent, COMSIG_CARBON_LIMB_DAMAGED, PROC_REF(on_limb_damage))
RegisterSignals(parent, COMSIG_LIVING_ADJUST_STANDARD_DAMAGE_TYPES, PROC_REF(on_damage_adjusted))
RegisterSignal(parent, COMSIG_LIVING_HEALTH_UPDATE, PROC_REF(on_health_updated))
- RegisterSignal(parent, COMSIG_MOB_GET_STATUS_TAB_ITEMS, PROC_REF(on_status_tab_updated))
if (!isnull(host))
var/mob/living/living_parent = parent
living_parent.updatehealth()
/datum/component/life_link/UnregisterFromParent()
unregister_host()
- UnregisterSignal(parent, list(COMSIG_CARBON_LIMB_DAMAGED, COMSIG_LIVING_HEALTH_UPDATE, COMSIG_MOB_GET_STATUS_TAB_ITEMS) + COMSIG_LIVING_ADJUST_STANDARD_DAMAGE_TYPES)
+ UnregisterSignal(parent, list(COMSIG_CARBON_LIMB_DAMAGED, COMSIG_LIVING_HEALTH_UPDATE) + COMSIG_LIVING_ADJUST_STANDARD_DAMAGE_TYPES)
/datum/component/life_link/InheritComponent(datum/component/new_comp, i_am_original, mob/living/host, datum/callback/on_passed_damage, datum/callback/on_linked_death)
register_host(host)
@@ -133,12 +132,6 @@
else
mob_parent.set_hud_image_state(STATUS_HUD, "hudhealthy")
-/// When our status tab updates, draw how much HP our host has in there
-/datum/component/life_link/proc/on_status_tab_updated(mob/living/source, list/items)
- SIGNAL_HANDLER
- var/healthpercent = health_percentage(host)
- items += "Host Health: [round(healthpercent, 0.5)]%"
-
/// Called when our host dies, we should die too
/datum/component/life_link/proc/on_host_died(mob/living/source, gibbed)
SIGNAL_HANDLER
diff --git a/code/modules/mob/living/basic/basic.dm b/code/modules/mob/living/basic/basic.dm
index bb89e69b42c..0392cfcc6bc 100644
--- a/code/modules/mob/living/basic/basic.dm
+++ b/code/modules/mob/living/basic/basic.dm
@@ -293,11 +293,6 @@
return
return relaydrive(user, direction)
-/mob/living/basic/get_status_tab_items()
- . = ..()
- . += "Health: [round((health / maxHealth) * 100)]%"
- . += "Combat Mode: [combat_mode ? "On" : "Off"]"
-
/mob/living/basic/compare_sentience_type(compare_type)
return sentience_type == compare_type
diff --git a/code/modules/mob/living/basic/boss/boss.dm b/code/modules/mob/living/basic/boss/boss.dm
index 31a7d2379a9..4ffd7961de3 100644
--- a/code/modules/mob/living/basic/boss/boss.dm
+++ b/code/modules/mob/living/basic/boss/boss.dm
@@ -4,6 +4,7 @@
/mob/living/basic/boss
combat_mode = TRUE
status_flags = NONE
+ abstract_type = /mob/living/basic/boss
sentience_type = SENTIENCE_BOSS
mob_biotypes = MOB_ORGANIC|MOB_SPECIAL
faction = list(FACTION_MINING, FACTION_BOSS)
diff --git a/code/modules/mob/living/basic/guardian/guardian.dm b/code/modules/mob/living/basic/guardian/guardian.dm
index fd84556c99d..9c2592f9748 100644
--- a/code/modules/mob/living/basic/guardian/guardian.dm
+++ b/code/modules/mob/living/basic/guardian/guardian.dm
@@ -34,7 +34,6 @@
attack_sound = 'sound/items/weapons/punch1.ogg'
attack_verb_continuous = "punches"
attack_verb_simple = "punch"
- combat_mode = TRUE
obj_damage = 40
melee_damage_lower = 15
melee_damage_upper = 15
@@ -53,8 +52,8 @@
/// Coloured overlay we apply
var/mutable_appearance/overlay
- /// Which toggle button the HUD uses.
- var/toggle_button_type = /atom/movable/screen/guardian/toggle_mode/inactive
+ /// Which toggle button the guardian has. Won't get one if it's null.
+ var/toggle_button_type = null
/// Name used by the guardian creator.
var/creator_name = "Error"
/// Description used by the guardian creator.
@@ -76,12 +75,20 @@
/// Cooldown between the summoner resetting the guardian's client.
COOLDOWN_DECLARE(resetting_cooldown)
- /// List of actions we give to our summoner
+ /// List of actions we give to our summoner.
var/static/list/control_actions = list(
/datum/action/cooldown/mob_cooldown/guardian_comms,
/datum/action/cooldown/mob_cooldown/recall_guardian,
/datum/action/cooldown/mob_cooldown/replace_guardian,
)
+ /// List of actions we give to ourselves.
+ var/static/list/self_actions = list(
+ /datum/action/cooldown/guardian/check_type,
+ /datum/action/cooldown/guardian/toggle_light,
+ /datum/action/cooldown/guardian/communicate,
+ /datum/action/cooldown/guardian/manifest,
+ /datum/action/cooldown/guardian/recall,
+ )
/mob/living/basic/guardian/Initialize(mapload, datum/guardian_fluff/theme)
. = ..()
@@ -90,10 +97,10 @@
theme?.apply(src)
AddElement(/datum/element/death_drops, /obj/effect/temp_visual/guardian/phase/out)
AddElement(/datum/element/simple_flying)
- AddComponent(/datum/component/basic_inhands)
// life link
update_appearance(UPDATE_ICON)
manifest_effects()
+ create_actions()
/mob/living/basic/guardian/Destroy()
GLOB.parasites -= src
@@ -102,6 +109,18 @@
cut_summoner(different_person = TRUE)
return ..()
+///Creates the guardian's default action buttons and sets them to go in their proper location.
+///Subtypes overwrite this for special ability types and whatnot.
+/mob/living/basic/guardian/proc/create_actions()
+ for (var/action_type in self_actions + toggle_button_type)
+ if(isnull(action_type)) //no toggle button type
+ continue
+ if (locate(action_type) in actions)
+ continue
+ var/datum/action/new_action = new action_type(src)
+ new_action.Grant(src)
+ update_action_buttons()
+
/mob/living/basic/guardian/update_overlays()
. = ..()
. += overlay
diff --git a/code/modules/mob/living/basic/guardian/guardian_types/assassin.dm b/code/modules/mob/living/basic/guardian/guardian_types/assassin.dm
index 19f98a70f40..377c3fec0b7 100644
--- a/code/modules/mob/living/basic/guardian/guardian_types/assassin.dm
+++ b/code/modules/mob/living/basic/guardian/guardian_types/assassin.dm
@@ -1,5 +1,3 @@
-#define CAN_STEALTH_ALERT "can_stealth"
-
/**
* Can enter stealth mode to become invisible and deal bonus damage on their next attack, an ambush predator.
*/
@@ -17,57 +15,44 @@
creator_name = "Assassin"
creator_desc = "Does medium damage and takes full damage, but can enter stealth, causing its next attack to do massive damage and ignore armor. However, it becomes briefly unable to recall after attacking from stealth."
creator_icon = "assassin"
- toggle_button_type = /atom/movable/screen/guardian/toggle_mode/assassin
+ toggle_button_type = /datum/action/cooldown/guardian/toggle_mode/assassin
/// How long to put stealth on cooldown if we are forced out?
var/stealth_cooldown_time = 16 SECONDS
- /// Cooldown for the stealth toggle.
- COOLDOWN_DECLARE(stealth_cooldown)
/mob/living/basic/guardian/assassin/Initialize(mapload, datum/guardian_fluff/theme)
. = ..()
- show_can_stealth()
RegisterSignal(src, COMSIG_GUARDIAN_ASSASSIN_REVEALED, PROC_REF(on_forced_unstealth))
// Toggle stealth
/mob/living/basic/guardian/assassin/toggle_modes()
var/stealthed = has_status_effect(/datum/status_effect/guardian_stealth)
+ var/datum/action/cooldown/guardian/toggle_mode/assassin/stealth_ability = locate() in actions
if (stealthed)
to_chat(src, span_bolddanger("You exit stealth."))
remove_status_effect(/datum/status_effect/guardian_stealth)
- show_can_stealth()
+ if(stealth_ability)
+ stealth_ability.build_all_button_icons()
return
- if (COOLDOWN_FINISHED(src, stealth_cooldown))
- if (!is_deployed())
- to_chat(src, span_bolddanger("You have to be manifested to enter stealth!"))
- return
- apply_status_effect(/datum/status_effect/guardian_stealth)
- clear_alert(CAN_STEALTH_ALERT)
+ if (!is_deployed())
+ to_chat(src, span_bolddanger("You have to be manifested to enter stealth!"))
return
- to_chat(src, span_bolddanger("You cannot yet enter stealth, wait another [DisplayTimeText(COOLDOWN_TIMELEFT(src, stealth_cooldown))]!"))
-
-/mob/living/basic/guardian/assassin/get_status_tab_items()
- . = ..()
- if(!COOLDOWN_FINISHED(src, stealth_cooldown))
- . += "Stealth Cooldown Remaining: [DisplayTimeText(COOLDOWN_TIMELEFT(src, stealth_cooldown))]"
+ apply_status_effect(/datum/status_effect/guardian_stealth)
+ if(stealth_ability)
+ stealth_ability.build_all_button_icons()
/// Called when we are removed from stealth involuntarily
/mob/living/basic/guardian/assassin/proc/on_forced_unstealth(mob/living/source)
SIGNAL_HANDLER
visible_message(span_danger("\The [src] suddenly appears!"))
COOLDOWN_START(src, manifest_cooldown, 4 SECONDS)
- COOLDOWN_START(src, stealth_cooldown, stealth_cooldown_time)
- addtimer(CALLBACK(src, PROC_REF(show_can_stealth)), stealth_cooldown_time)
-
-/// Displays an alert letting us know that we can enter stealth
-/mob/living/basic/guardian/assassin/proc/show_can_stealth()
- if(!COOLDOWN_FINISHED(src, stealth_cooldown))
- return
- throw_alert(CAN_STEALTH_ALERT, /atom/movable/screen/alert/canstealth)
+ var/datum/action/cooldown/guardian/toggle_mode/assassin/stealth_ability = locate() in actions
+ if(stealth_ability)
+ stealth_ability.StartCooldownSelf(stealth_cooldown_time)
/// Status effect which makes us sneakier and do bonus damage
/datum/status_effect/guardian_stealth
id = "guardian_stealth"
- alert_type = /atom/movable/screen/alert/status_effect/instealth
+ alert_type = null
/// Damage added in stealth mode.
var/damage_bonus = 35
/// Our wound bonus when in stealth mode. Allows you to actually cause wounds, unlike normal.
@@ -112,5 +97,3 @@
SIGNAL_HANDLER
SEND_SIGNAL(owner, COMSIG_GUARDIAN_ASSASSIN_REVEALED)
qdel(src)
-
-#undef CAN_STEALTH_ALERT
diff --git a/code/modules/mob/living/basic/guardian/guardian_types/charger.dm b/code/modules/mob/living/basic/guardian/guardian_types/charger.dm
index 10ef9c34d53..2d21803c25f 100644
--- a/code/modules/mob/living/basic/guardian/guardian_types/charger.dm
+++ b/code/modules/mob/living/basic/guardian/guardian_types/charger.dm
@@ -11,13 +11,11 @@
creator_name = "Charger"
creator_desc = "Moves very fast, does medium damage on attack, can be ridden and can charge at targets, damaging the first target hit and forcing them to drop any items they are holding."
creator_icon = "charger"
+ toggle_button_type = /datum/action/cooldown/mob_cooldown/charge/basic_charge/guardian
/mob/living/basic/guardian/charger/Initialize(mapload, datum/guardian_fluff/theme)
. = ..()
AddElement(/datum/element/ridable, /datum/component/riding/creature/guardian)
- var/datum/action/cooldown/mob_cooldown/charge/basic_charge/guardian/charge = new(src)
- charge.Grant(src)
- charge.set_click_ability(src)
/// Guardian charger's charging attack, it knocks items out of people's hands
/datum/action/cooldown/mob_cooldown/charge/basic_charge/guardian
@@ -28,6 +26,7 @@
button_icon_state = "speed"
background_icon = 'icons/hud/guardian.dmi'
background_icon_state = "base"
+ default_button_position = ui_guardian_special
charge_delay = 0
recoil_duration = 0
charge_damage = 20
diff --git a/code/modules/mob/living/basic/guardian/guardian_types/dextrous.dm b/code/modules/mob/living/basic/guardian/guardian_types/dextrous.dm
index 206b7b79e12..fc4ec678837 100644
--- a/code/modules/mob/living/basic/guardian/guardian_types/dextrous.dm
+++ b/code/modules/mob/living/basic/guardian/guardian_types/dextrous.dm
@@ -15,6 +15,7 @@
/mob/living/basic/guardian/dextrous/Initialize(mapload, datum/guardian_fluff/theme)
. = ..()
+ AddComponent(/datum/component/basic_inhands)
add_traits(list(TRAIT_ADVANCEDTOOLUSER, TRAIT_CAN_STRIP), ROUNDSTART_TRAIT)
AddElement(/datum/element/dextrous, hud_type = hud_type, can_throw = TRUE)
AddComponent(/datum/component/personal_crafting)
@@ -24,6 +25,18 @@
dropItemToGround(internal_storage)
return ..()
+/mob/living/basic/guardian/dextrous/create_actions()
+ for (var/action_type in self_actions)
+ if(isnull(action_type)) //no toggle button type
+ continue
+ if (locate(action_type) in actions)
+ continue
+ var/datum/action/new_action = new action_type(src)
+ //Show up at the top left like usual.
+ new_action.default_button_position = /datum/action::default_button_position
+ new_action.Grant(src)
+ update_action_buttons()
+
/mob/living/basic/guardian/dextrous/examine(mob/user)
. = ..()
if(isnull(internal_storage) || (internal_storage.item_flags & ABSTRACT))
@@ -95,7 +108,7 @@
/mob/living/basic/guardian/dextrous/proc/update_inv_internal_storage()
if(isnull(internal_storage) || isnull(client) || !hud_used?.hud_shown)
return
- internal_storage.screen_loc = ui_id
+ internal_storage.screen_loc = ui_back
client.screen += internal_storage
/mob/living/basic/guardian/dextrous/regenerate_icons()
diff --git a/code/modules/mob/living/basic/guardian/guardian_types/explosive.dm b/code/modules/mob/living/basic/guardian/guardian_types/explosive.dm
index b3c0684571d..49c15f62f40 100644
--- a/code/modules/mob/living/basic/guardian/guardian_types/explosive.dm
+++ b/code/modules/mob/living/basic/guardian/guardian_types/explosive.dm
@@ -37,6 +37,7 @@
cooldown_time = 20 SECONDS
background_icon = 'icons/hud/guardian.dmi'
background_icon_state = "base"
+ default_button_position = ui_guardian_special
/// After this amount of time passses, bomb deactivates.
var/decay_time = 1 MINUTES
/// Static list of signals that activate the bomb.
diff --git a/code/modules/mob/living/basic/guardian/guardian_types/gaseous.dm b/code/modules/mob/living/basic/guardian/guardian_types/gaseous.dm
index 8bf00ef4362..a70bd01f43b 100644
--- a/code/modules/mob/living/basic/guardian/guardian_types/gaseous.dm
+++ b/code/modules/mob/living/basic/guardian/guardian_types/gaseous.dm
@@ -9,7 +9,7 @@
creator_name = "Gaseous"
creator_desc = "Creates sparks on touch and continuously expels a gas of its choice. Automatically extinguishes the user if they catch on fire."
creator_icon = "gaseous"
- toggle_button_type = /atom/movable/screen/guardian/toggle_mode/gases
+ toggle_button_type = /datum/action/cooldown/guardian/toggle_mode/gases
/// Ability we use to select gases
var/datum/action/cooldown/mob_cooldown/expel_gas/gas
/// Rate of temperature stabilization per second.
diff --git a/code/modules/mob/living/basic/guardian/guardian_types/protector.dm b/code/modules/mob/living/basic/guardian/guardian_types/protector.dm
index 45d746b2335..229732a30f8 100644
--- a/code/modules/mob/living/basic/guardian/guardian_types/protector.dm
+++ b/code/modules/mob/living/basic/guardian/guardian_types/protector.dm
@@ -9,7 +9,7 @@
creator_name = "Protector"
creator_desc = "Causes you to teleport to it when out of range, unlike other parasites. Has two modes; Combat, where it does and takes medium damage, and Protection, where it does and takes almost no damage but moves slightly slower."
creator_icon = "protector"
- toggle_button_type = /atom/movable/screen/guardian/toggle_mode
+ toggle_button_type = /datum/action/cooldown/guardian/toggle_mode
/// Action which toggles our shield
var/datum/action/cooldown/mob_cooldown/protector_shield/shield
diff --git a/code/modules/mob/living/basic/guardian/guardian_types/ranged.dm b/code/modules/mob/living/basic/guardian/guardian_types/ranged.dm
index 6752c52a5af..126ca95da2c 100644
--- a/code/modules/mob/living/basic/guardian/guardian_types/ranged.dm
+++ b/code/modules/mob/living/basic/guardian/guardian_types/ranged.dm
@@ -13,7 +13,7 @@
creator_desc = "Has two modes. Ranged; which fires a constant stream of weak, armor-ignoring projectiles. Scout; where it cannot attack, but can move through walls and is quite hard to see. Can lay surveillance snares, which alert it when crossed, in either mode."
creator_icon = "ranged"
see_invisible = SEE_INVISIBLE_LIVING
- toggle_button_type = /atom/movable/screen/guardian/toggle_mode
+ toggle_button_type = /datum/action/cooldown/guardian/toggle_mode
/mob/living/basic/guardian/ranged/Initialize(mapload, datum/guardian_fluff/theme)
. = ..()
@@ -120,6 +120,7 @@
button_icon_state = "eye"
background_icon = 'icons/hud/guardian.dmi'
background_icon_state = "base"
+ default_button_position = ui_guardian_special
cooldown_time = 2 SECONDS
melee_cooldown_time = 0
click_to_activate = FALSE
diff --git a/code/modules/mob/living/basic/guardian/guardian_verbs.dm b/code/modules/mob/living/basic/guardian/guardian_verbs.dm
index c63dffd4316..dc95097953c 100644
--- a/code/modules/mob/living/basic/guardian/guardian_verbs.dm
+++ b/code/modules/mob/living/basic/guardian/guardian_verbs.dm
@@ -43,15 +43,6 @@
to_chat(src, span_notice("You deactivate your light."))
set_light_on(FALSE)
-
-/// Prints what type of guardian we are and what we can do.
-/mob/living/basic/guardian/verb/check_type()
- set name = "Check Guardian Type"
- set category = "Guardian"
- set desc = "Check what type you are."
- to_chat(src, playstyle_string)
-
-
/// Speak with our boss at a distance
/mob/living/basic/guardian/proc/communicate()
if (isnull(summoner))
diff --git a/code/modules/mob/living/basic/space_fauna/revenant/_revenant.dm b/code/modules/mob/living/basic/space_fauna/revenant/_revenant.dm
index ea32e7e5d6d..3bd92b48950 100644
--- a/code/modules/mob/living/basic/space_fauna/revenant/_revenant.dm
+++ b/code/modules/mob/living/basic/space_fauna/revenant/_revenant.dm
@@ -95,7 +95,7 @@
/mob/living/basic/revenant/Initialize(mapload)
. = ..()
AddElement(/datum/element/simple_flying)
- add_traits(list(TRAIT_SPACEWALK, TRAIT_SIXTHSENSE, TRAIT_FREE_HYPERSPACE_MOVEMENT, TRAIT_SEE_BLESSED_TILES, TRAIT_IGNORE_ELEVATION), INNATE_TRAIT)
+ add_traits(list(TRAIT_COMBAT_MODE_LOCK, TRAIT_SPACEWALK, TRAIT_SIXTHSENSE, TRAIT_FREE_HYPERSPACE_MOVEMENT, TRAIT_SEE_BLESSED_TILES, TRAIT_IGNORE_ELEVATION), INNATE_TRAIT)
grant_actions_by_list(abilities)
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index fb7af94d3c4..5ee30cec038 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -861,6 +861,7 @@
mob_mask = icon('icons/hud/screen_gen.dmi', health_doll_icon_state) //swap to something generic if they have no special doll
livingdoll.add_filter("mob_shape_mask", 1, alpha_mask_filter(icon = mob_mask))
livingdoll.add_filter("inset_drop_shadow", 2, drop_shadow_filter(size = -1))
+ livingdoll.health_overlay.maptext = MAPTEXT("
Ew#qRzZl&MPxu`yh}{6)68V8Q}TsOJ~U)KweB!T0R+)WxOY*sX{Y6{DZC5+Q45r zY7|Pk#vw^eHKPLK!d4x%9zWLp@H4cfy&yRpXbCMd=dahaEL3DA>516F6sgZ!zKKSv zdMs<#bGu~}8Z}15YmJJ10>N5i)}#@Z*`ZNac2Woe1ak8%f&sz@aiGhS{S&FvIkkxi zrD)tqVbKMy-UQMANOfJUk!*oF8Bk!eyi3}%HfN102hUh2Xyl5*3;jk@bF8cZ`X8Ia z-fs3ZK-9q?*EJQ;H;zi1ZYIFwAwb}Yr1cxaj8K(hs59)oVjn@8m zP{9BoHNq+kucceGT26GVMq4Lerz3O&U!aR@XLqDU)HoYHpRptfXx2a0mUVRI5cOB) zFC)Ey(+#_@s79^8;iEtW@r*?c2sVdhkvHw@_P{ZN&;l)3>cT>jrdfvab=}TIu#`gw zDX9yYy`Yy(RsNgborw_PciT$#nLtAP!AU`mGlzpuV8GH)Ss1y28SCE;m6S9nvlOT8 z_>Zw87CK7Xy1xcCadD7j(M7kmDt0agj?iyMc(uQ5kUflflM{aT?p=Af7+1!Y9UO$l zt<~?^y~)VLf@Hbqcb0l&r2qbzmS}M5U jqX0u75LVU*t8ONwD0*&-+R0m)Hhq?A z4>N{~t_cZvmYvtMGQIHa-Q@aT>ZB;2SN2&&MVD269{NeiI8l{PP7>oZ;G?6q?*sdu z^9jb<%T5>n40Y~1NmGrK4?Ix&^169(GrU1*9ri=Ji4SE7Iiif|sba;h|L*s1*X1d4 zxUqM7R`(gCFb4X#Gi6wgpi5Vekc|1AiVMH}0Rt#0@h^v}swPvUhq%BbeSMYd^si4t zEV| bH$~|LsI?<8qr{o$G*~OTy) z{Stu DY`&v>|@}P;+O`MAkY$?@s=wq-%S_h(nU>XLWj!$VXRpY zK=Zq~g8n0Sa3{@~-f#w#uq+xZ4Sko0Yf5K1m%si@T9Dppy|ez_k2v&xm;1H#;D=O& zbLhR8x43Xwyq7srnk^EJUDXuc4mk{_rs7$NDY;oFuu(l*RZL6(@+IX{U3izjw91Ix zmy~~@=5mR4n+AQs$A~^X>lvCCE4wS>lCl9IM06qBV63@x!z1H^xlLMs{q%)^kA&M| zG-T@QbZH`P(-@9j6$Sm{4&1mR4Kn0yVIR`yL#OeVG>LoY!$Yu1I{WH`%Z;gpIK3Y^ z;spm=bA&T1Z?7ZpyU6d5UyHjxnYI_&bUw0)mmiszzK@m6V0m*2Vu_&W8p}3Wx)E|8 zAe*M*4GncR0PI@mql?U^`cbRdeN!G_mFRuE0tBcWy_pwUpvUzMADA-lY~t<7IpV_M zz$3K7J^^m+TZGv; 9BTRdPll7RNP#;o=y+Y?>hOY zoL()TW)6IL?S;{h(6}j6OL*Ch>oPuyUbj&*nXQUq`uh5E%E}Tdt}U(*er`?Ac#$7% zrPt$T$_1@+1O5FOR#sMc1Z%Kg90 @5+1aFU0xcc!+F z$Mb0LJF!|PXWaZTQA*Q?A6M1XR@H157Z%zDc4o)ZaQn@-x?w^bdLlgO_6#zVe_>FC z0(sfTc%_5ko$D6efscj-pn;S~CtR{q9fMe8At}cnp)ogEr$^?kDU&PojzM_2PuIcv z*ZdbIxCnXY8M_m(O$ zqZ27hXFvRv_vGdb)7BqR>(RRUPJi!{is%_JmfPC8?Hat#w_e$nfX(V8C$Ps_wq9I2 z8JM(QgY|oHtMl6cI=4B&FejPi9}PbIgX*N|@8jh-w+KX)9luwA0oH9vAC{;%>!x3& zP!62CA77Tt=EnLV!I_V$*BMn (Xu{ZeZEB~Qu8x0bcSJV!NM>)=mV{WTrD_Qn9 zK)u-^Qj};G*J_lDz{9fv$P(uS?Z&>z-oc4GY=VPler~Mc&FN)hPPKe8#u6x1 <8{>-0W zYo+EhQ+k~VH_a;u090r)|Js4e%`Cr<;?^@b k7M?b>)!5cAtQkpXG{FF7066z`X!qL9)KowEbENaLz|FCaQ8HMiyKtxp zRuX>{DfKCPxWTF<;kx)IkXbp2<)sj f+dO4Z3u8; 6PGXaQsyd*|Igq?$87LqX5800V{$&y1A0S1=o3PS zwS85hPA$2QG{v2X0Hvybmn!-1YML!okZ5?i+0zm@UP6wHMg`BKL*FNylbJC+4N<+= zVdFWY>|iDqpQE(0deiGxKi$F~kt^IICHt|D5@IHAju8a;`t33{@Pp$aB&`E8=p77I zWDw^2&K0i)>%Ck&{fPrP%QeVeNgBNUe$FkCad%wHBZs(`0nXJ$8KWA<(vlYZJ-llM zwhpmdUV);XyFFJnyvc{Y+=sLtTY#^J>?=sc?#2KisJnCB@}o_6;Bx^|3+Lg|-o>sV zuN`?3sk{D-i~)E(X|XMvAG&^a~Y8@- wsR!<; 3wKoCDMj4G*NQ3sUCdiD83p2To36 z6qS{$+S)knnw;NHo5L|=%`DL?O}~YUMTSB^J&L8)y!<190A&(VmzrnGYq*o?&<_!S z#=}^{o&7aZZpI!GN(Y8+kxqgnua~N*k|vf{zP|BhhAEe`&kDv9h9EPMgR?fh=l_kI z No09`e`MYa8F6l;6nQst|c1ii~{bGlO?P4W`w%U 0^wvlxo~K zyN1c5lm_$rJi741Lr2NWhyaRj3xYF!&G6jt&2%2ZvCU4c$T#hWB$jUHY+!0Wy4WXS ziqeF?iQXG%mtK<_BN@L=zv;lClptc*dNr(4m8UKPVkCDG4}Z^F^oGMLc_PD@U2A70 zO_qeOVtO%3m+H1ddPO#uI8t|%NWuUht{Y*s&557rcAj1Wqk ucP|2?mmAe`kEZ{ zR*n6%b_cn&xFB8nA}Hc3kbbQ2_-dh)cd_Kv2}$_XvXt7Z*@o^{4t=x;Mr6Qa4iV2Dhk4u?b!jEajCE%J9vB++dM OQ zRNchH#H!-`XDWs ;#8BDywo#T_bYn^3{r>=4
7_9*bOx zj+nYZo-(mQFP$+PX{NO|U*0X-@q|CFV9tF%t`T EjGm9Jg zssJ;3{HLidV>~QBs~ZsPnAR|`RaC1Znn&oYChhhwEvcyj?^;!m$lq~!Zf*OKs|WZH z*Qw(`s93laZ1y4_?`XoFq!4)c$!;Gi^`)~1P@;x+iMF&%H1dVXY0i%Mpx0kU^J4z! zFI^{Au8#RMeCfKxGt< zcKRnH*Cf7w|A@&+&B1m^jvvUV(AO?_n_zTCGieU>6G&Sd*|G~D^J)tjo58k$ z0CJsK6aaR)?~1t%?*1(LbtK%%FE<@}Zv?WUBby-TdhBwwXXFZ&hV;1k5rV6}P_4wM zzw$F@pz~IjNzH1bx1F5(sudyknUuOH=G`cBUKE5;V; COa zl^=FLYWG7VGzVwMCY5Y|8gW~6FLF+;%u%UqD> HtzTd}p{z qtWmOkjO5>%gwyck%r!|SsqO1 znwZ%{#Bc!qxv155dWed~dNWu(K2WVLWtu+h;lL**=sfJQTOSWdKb^N<7*vEHsme zHQQWd=@9_UYjFw(b8I=BT)~;dE@@8b ~)@CbS5C7=g%K9h4E %j%(Rt#?TIbphv4H#|N;88n6UQwr+pLbI!>R36Zw z>N#b3cxE+LmuZ7Pr8E>20K=;@oi3JOEk-JxyC#IyT5+^jX<|X0tlhJ!`R*`Q{S9i+ zw&gRap%&)8tZL6FbukbHQfFf0$tRShp3bA|aA-f!@RG~r1b>ct7R0Jw>;D;RwgNvu z@?YlelfIvt-gap>BNQ_D?xBFO#ZfakwcNz+uUGAeX)G;q-9P~W%L?LAR1>8kCH99S zDFm{EvJ?6%;F@19KU6V0+<0W6hW2c3Tv>LUxNH6>u_Q_CeX50D?(i;3m24ky7w>7m zzHy4$WBSH4{zKF3xG>q8Ek8zu7p2_}H7#} Y@3c8kCZXc{F9q5;imQ8+an8pmg-%IXgXC z<|*=rB+&4-qWzSnj|#LZE8N)nIzdw2sXlH%IXk=rmOQ_BTT44uUP)jy@XJvFL7|;E zS5FY&8X@C;#HD*tD0h?sB$Xm_USetENb= w5Qic`KbGy^R2)$#&{RiU3Mpf}Y zoJT8>LrI4 HVymf7Ik*mVkl6fydnzWjf%? zVAF=xYmx4JOvIc-U^=(Dc=N-CZ;mxHajYtI{L&WmuF5~UUeIb1UU7pXjIj1eC5vo~ zS#93ff0FzOQLF|n>&FPcV<(i0b|e*j;zf9%sy^|u^0((Yu_ff#?)c3NE}rQ%7$VV` zbipI#*?#9V8W+#7M;n H!b!ZciS!%xd?KeqR^c35I zKX-8mRA=e1fc EotFNel&be+EA^!CBQS!by9O#O(Jkk7)ghdc|6E{elRLvtOu%ks4^w#E94Xv8kZ2 zd}lh>KI_*>h0~`Ibb8lhAQ%)hAM_sBrRBU)O};&<@M1G1x@sQCx>#s4`?H^z8l_{t zesL9Z>=J8OmB7kt_arrZZa}-C#uus37Q!jtBRE25v0zTus+~WJV3P7|aeWyqnOU(B z7eMWSJ>wsw%~b!_^zYN&oaF9{?!jJ)44?F${Ycd8xuKw_tlt7zUY@UI&Sf%`PN0I^ z#6+@%F{U;{LEDbL6A-s w#c;kEj;G{GF&D`>vt zH$DAXr6(+~DTso{{|Yx~5lFKbc>iU>f~@ACE+^)106H664h7|E0;kh>^ty=8rthdF zMEZY)N~3_ZS}qD<4SM*?7g=!X>;eDU7$Jfn;$O(wb71iQC&NKY2wz5RpEm2nvS_RY zY^lc#D9S&=W`cf#+wA`hJRE)qB3{MKrKGrLoud!MlwOM%e%it+c^3Q{um8 yf$4 zeRaQ8ON$-{wpHRamygEy(eL3cUkghG{6%~(3~`^e #4zMp80yaME z^?ssP0}1-h0A4WMyZFBML1<#EL+^T{nLwk9o~Uw!-Ru2Bt51sh0B-kA0a|8p&}f<< zm5;!*rb7_st^*IEuMKQv(T2gu1@kwZm&DX|vPuw`h?y~fvsG3baP1mO&n|d;dh{VW zQV5Fi9oEVS+KbBJJgX !^dvmh$Q~qSVD7i9?e6@GwR1Z554M+kK@lK7o7) zu76Qq+!-k8ssnbo4s2yD1tQLR+Q6$LkU#-$jd6*Fk(0f3`QpS_$=|4=xA-)zr=(3d u W7RL|%R7QFxSgH>G_WuBJs$-4- diff --git a/icons/hud/guardian.dmi b/icons/hud/guardian.dmi index 6b6c03912dd7d66d9df8a6df3e0ac27a2e1e2c2e..e39b6681f69c269d8a542970a5ddfa18533f3980 100644 GIT binary patch literal 13719 zcmZv@WmFtZ*9F?RI|O%!V8MgCyN2KpAh_G$?#_d|L$KiP?g4_k2Ztbo-pTv@xp%G0 zs_E`3s%E-QAKCkynMhS-88l=fWB>rr OH@}$2n!Hwrq;+59@9*tCfFU*I_t&A;epHt6)C>zwO5{nRAmwg5OjhaT z*l3-dSNDqJU9Ess!4f&&>L&{O6hpJs08o;i{yQbgZo-Y8Axf1iOCMT{qrw4m&G}s5 zEgRIjGV #IFSkpJBj_R=pjVs+q)sTinZM2 zoSd9dE4p>n^qI?>7Q}Pg_X;Cy;b%n*48RQf_~kRD4Lzm#>BkK@@7gW$A(qOjDsP4G z-q}2tKgFlNtDn1C{%GWZE+1G6?k~46faSOSc`l$lIVD|oIqVz=_?4Dh(z>IQ<;$VZ zazKCoZSe8_TwwOsZ(x-=XBJge9plE?!t^;=Wu68{r|9+9FZ?SuVqO4vd)Vu0T^(0B z(~ye(uVL85`KOxpy~S)TmpbIFmwz5uTG? 10^I6C7C@ z0=uEYVeN$y|E}}KAUA6MsUlXoNa;-fOc-Eb25EGCo0x&zL2sDTIsONtXS(9Q_~)k* zO+A{|6Z ;y#5_2gNJIR&1hWJ|Uh@WskKZoAN-wNS=p$RJ2Y}XQ#f> zE*?I9(VCCw>y3t!ArP_jhU+>mlm86ZdjkoWc~;DjP5BPo@iv^JnQkR~ojoGBjU~4u za7KB8e857uY2JS@MX$Y$UcE`lJ&N!FKZ~+XL|*Q{gFDFm`-egG``^JmuOkhaEDBpi z0NtCF$nDGH0n$*n4ANvqwUnDu!MJfP9&N#h(sRj-RD<(>*3*hCl{WC(b@O89y#5P2 zcGBUjeoc}$!^9585RLFo`oK>vuzd&JTYK_+MYstc+Zy0S@%Su|_opRIILiOk9^nF7 z^lU;FcCC(75{#JZN$dajfIbs@`k@PMKv8-QFm`pt9U2;vRZ@~tQNfUwAxtcy5e>R1 zv$FR@(LhLlK5%-=sCRo-=(Jl#ml8Z6_kyO-970?XIrMgN{Qk_AEby)tOPh6=e@l}f zqDAe|-nHE7ME$d&!GtGk$F<|%SQ(9@ K@R0s94W&}bM=h- zUm68lB;LXaxo6UNK?ee*c_^hj2TDI_Du!<)wmihrGBQ~74kO3M43G|FXxEaau;PuS z_#{9kmp2BvWJE`jmBh@ocW=8-g0XKm1e=ZI`5?F?_$1Wj>J_w@E~G-ML2EthRD;r_ z 9+7-~fIBoWX~Egv(edRbW6A>P zg J?%@8hBw@`+?o$ zEewd(k`J@xodp?+paQB@M`jZ|RUw50wEJaZzx-Y+4q@vN@*~Qi$#CH`wY7?2qcpx~ zC5o#B&SMWCPwi#mWsY$Bxzh$nLU+EjAUG`<5JLgi*l^iL4Onby0C3T6Lv8rB7MviP zeseod@x69dum-8=MV)_^dv_=Ztk+08t={zSl}WttVAqYmA!Oj}yxsyfY=jKZOhab4 z#(GkwqKF`HsNx#yRi{Ay0Atz5>0d^5`^=1tf!~{wyhfmB9@ma~7850~R1AK&voYi) z_!2(Q7(QzN#%mzp>Q;T=n0kg-+GuSvTXZc)R#r(=M+YCk1LZAROIcep{qR*TKH0q* zy$w?f7`9nsONuQPT7CcT7-rj_bR HTA8wskynZygVYd<*mZ)1A>*$ z?Rv{+?4zZ>zCgg%j<3i;@TkBo<@Pclfu72Nb=*M=Ts>)^5|Tf6Y3z!UjZaJ@CMNEr zVJ7bg3cmS7@82153@XfW6bHXi$MCR!7rB;yW0) $m;P%f4K1o4=jp zoGC{955CvIui<|kSvkFMbW&414uWYNPA7F|sBfQens>R1bT4zj6`+-y63^1Vc-F5` zw4bEJKPMl-;$;gRT`Qh2UwoTL^WGG=)3D9#P=EnWZqvEWf_uT%haRcVsg!^>q9{Xr zXgTqBRs70! oLT#{+EHcfb-ad4**l;JX7GPRh0>dO4X8Vz})`@CBfvqz6= zrOpJV*?uFc$!6)vV5{AYna6fHpsVUZzMI7|;(>e_6?jB-*n8jg1$vKD)FR_=;Ob5! zM5Wst#o9Le!G67Uf>>XhztB$QIE{`1pFVw>U0Fe*fKhqZ3+1$whIGb~eztL<$G_v# zeCxpOQVQSdU%&-?W0F2;L$?IBZdb0<@8L08HxaRQsxq;7S(M3qjKw!(NUhYgCK2>x z_%^nS_gYX+CpI)YApz8NrmEGrlzyIkQ=@!)JmHBKuaGo3#QpY`f>$oIh8oKQm)QxA z+JstIT}>*|W*_=d8H>KELT!2L)uifZ?yH9!vq+^xdp#ylRNQyAG#4`wvUPjM02NP6 z@VGm(FvYtC-C>4HO wCCS}<&uYKGRAE@W(Mm_gIS%+2yK2xprj2FEdglkWTF>Bn_z-h>;hM@&_+ z5g(2id5*VEh;K ?vFTsX1=^`vq9KElBgOd7umI;Z8fu*I&wksB?oiDJRgBT18 z#D@~HP?5W@hrIZ5ItB(TnZt3UYb&1n!ZlQ3raj}YBb0!y;3>zH5!3s8!Q%H_d%Y$a zd-+u^Kveq;)u-`+bFw+Eu(TB3!=V+<5P#nDJ&jnKv4_ud5}Y<}Ny0n%6uaA+Olin) zk3YEt4NNZ>(o86NY#^$MRm22or-hW38kTD^-4n*f#2BwORwRrwkl#@Yivqgr(Zxa( z*8UsqZnGz@kmh+@5Pmf+a9OuR=6y_==egzg%%WIDS)ZnIx9QV|(RxI>wP{arKz&6? z(G&i(e3_GUIL)_zbOZyaYiK|L9~5W}-^~is20{CCJdw&HjTqkE-U)em@uj77g7=`Z zK^CNqTKeJu$!q02VH|a$bx+!vv%j5J;uR^S5*nh|G6gZoP`yWo@2(JRweIxV B8rNWa;`I}uRlH+RnP{3s>Zd1B9#BT&N@_w4%abo6gcafwnYRKUQ6D?)?+ z4Xy;bk~H?uqzuaXKSW`Y5L~K$do(k$6GeTq(5Pu{VIiLleB$J!rPJtoa2&z{XRqAq zmnpxdR%W?%AOnY!=CVt|$0qYU%QiB~63b47^C!#hn{lK9#)8I{Ti3Z??_~`=0}1&n ze*75B@z{(M0^I{c+L302v5u+nqN-3(7OoP0V$GSEnZ~1zyQ7J85Fts>nRN@YLL{>6 zIh8Z%3o$sywm-hoa?oP3P#$N?7Zo)%VUpP0@pYxmL;~)%7+;`pxRLL@T;1HpQm#L( z*IQKR3DBY$vc*>JrKWcnQ&v4T98O7|pTHBuO7m@yW%GMMH(2gV6v>YmEU{_%|9mg6 z-f}kNv0LTx$QGx>;r4+F#ofEKIcC&cyaUGWDN8pV7T;BoQ?WDmCB1^=BXe`fCet}c z!C$;9o0?KD&d }+SV;6J^grV4ehCzt$zl?>Qlx7DmXonP9h8^43*x{k7?Rw)UmLl z0tqNm-UnEdQU*EA*|n1NSuN*LmoQ}KC#`~(6rM>`1g}FrE;~5S8q&oVJof#NK=-f& z@h;k5BnAH0cMhH1EY^F{Yn6kATmgH|63d>U2n4LoPdX-znTvxIsBzViq)%f4=Ap{$ zFzxXHy)bu|v>y#!SwGSF*MC!nmt#Bo2Jru0P4ugPmn(&Fn!mLi#b?#0Nt@V9NXYN6 z)T*K}Gc$AK%O)Tu9{AToLSh;{aMEpcO!V=7L-k5J5!LU}94N(;2alk8c4=3os__JT zuSte69+TPqQmx%cb_%^UgMYT&e^g~_U84ho`W*=KseNIZo`_A(%tX#oijyHbw-~c& zD52zDgv*CXfjtu{MoybJaBS1JeTrlv4WTFw;BM;wL!YRc&hJtxdCZH?-L#0 cEn}0GHxU*sZWGp7* zLH{cm3Uq2(JjgO4#Oz)r!oSIfTNV*Kve%bxCQCLdJZ2^@kGx0A=b_H3Gn$x@fdsG< zpkf0ABqWk=KiY7C{h3UKrgZD$7oS5t7ncTJW&s>hQc`w4mEjW0QVjspc9Nh~w+asr zkCKrQX>0R_ kj>$g{iwn0r(Y2Y#?%iQ}r6yW57qPo*+N#g0Jw@h~dkrIe z(`nM!oht6 ah4Bs65)*(Zb%=xVRcq?DPb@A;c gCne-rAZ@8l+LRC@U)~>gC1%XxBw=I7VLW zz+Hb`tzC6IfDnSGN>u=hcXhS`&xUmLb~utMTb_V7i$X8jrpgC`Cn6?J6nd}$qL(|} zVmzJpudwu6{Df@X5r&6{^XI=8Xfs`H@NVUs4W63OgD#d5mQ>S)eLrU_(|0 ?! zY$pt98yVG3PfewcFcQ@NsH`*<{!xKaXO*e*Yj#!?Ml{!n=k9LD84y)a;6wuqYw@)V z8g-nzkpYe5A;$gVi<6|5=H_-jv*DlyWxQ+L-!%qnEpDgUufz_WedvAPEG?;7SYjU$ zo?DeI6x5SE1kE0Wk(VKmB -tR&4Pr&4~ZOItPZj>%B}xx_g_3 z72D&pGs*5g|Lts1St$RAekv!^CGnNL5-@$ dFrt59*IhPDk*;U5GxC769O4TIo+>;4=cJA1895;)t%%4tH4-F~S*Ywxc9 z+R|^!Q&e7#Xwg9UwZ(oY>e~`Hp;m-rtm^eT_HhVwc^Z;pzt!#QePL8^#I|GEZ{1W_ zR)zq9B+>Y6(i$#ZnF6J23;MOwqoV;E_A(ISd*&{%_ly(K;(2Wf2_1j`{;m5na{m36 zlItEc#f>5uj-eyl(J>QDB8eAFTBeehWau&ljp4tpj_M2t$CgddfH8lPQSleIi)`vV zN40W+qImVCLx;mn?{oLl8?1N7%wE-{it(RDSKGIZDuCc8la}?%)qtGh+-YKNhJ5@= z`1eA;z_VKYCX#=I$i4*z(td(l=8=NkVD|HAMBUv#5E0LK;~~SDe`3T%hWpoPXlO`Z zk 7e#2uJM01><5j&Sn&eGm;nGqtWLoI44BPa9NJ~H~Z zYg1Dyh=^92$$>Mk*GtTs+c_@d@0T!Y;y|kqwSlYfj*-BO*JU1mc+<%d0vAy%kNu+D zsvEwAkVLii-a>`O@ySWx#DOVj5`v_{rz~zWNLf;pDG-~W 7qIzTt!U(Y#rRcW!!64 zRf68?b!fT}nY>D12!))T*>?W@r2xsVgh2SRe-4^y*M<)7mZjI<*9W&Pz8j}kCEos< zgERnohJIh%ktU>ZJ~Q)lk(EBS^w66-gV3a5h28(nheX6LTWfMC8o$AAWPM#<8>#I( zoVqYHC7k|GPpO{Z+a@e2T!sH7RG77YTq$Pp#CE+eUq_`lN{gE(!SVtzaj~Ph&!^Yj zehRfz0`x*y0K_L>^}=9m4`7H$dV7C{WSThG*#jyonXI^oAnVcAw%&ea7G~`_ezy7| z-Z{>q$wTS6&Q+vNW;~YkZT7p{s)_ov_9S JOp9KVbYvBC$ySJ+rAj;tz zF{~xY;h37lKrWJ_dd|E{xF|m(>juHLwCx))5v2UiuzJ-WAPwT=a&mH(A)J YmZXTBG70_g3T4H`#judi zg|w=-zgSF5EC{`m^y{kXR69?BFmZ4=T--|yi)_6KG305QpvcHbVPpdIpbA(ctRdCL zi0_ @d~SbI z+Vk^!=~C4&_1Lig1*(#@cZTIdYRH`>On!y7qvK?8d8Y4h1L`QLg^Ix;TYd)9VWGtV zz%rB-)yYe%dk3j}Ns?Pj$gjgaYLcc*#E2CSek 2pDGIn*&xz{MGxzwY2qqPdM82^yIC5KKfcv*wm!e*rK57 zJwk^9yxjPEoIa_*XmO(cQ)A+fIoJi@kd7smhb)y*I0aF+Bz4WEM?2A8qa6qe)n`pp zAy!2dUlV~;2GVS`^jq)C25k%=sL#2>0HtLuHZc)PmIj+IXIdC|f?RX)@($Ryn7P^_ zYW!-1s@ifqUxG+br$!GwC$8d-D2s@l&%8d-txuh>gq3~T_$D(mh*~BNu_gt@B2S^) z*sP=0-eNT%zWcq~UZUL~DLtLw#z(xyHv j$08!}WhLuR$fIOmjLU04Ku nyeW;)4knwTpixp$*QE$(9!+e z8(as6fZPbrB>$TNrGrCyz*7!=O>8g$o!J>y-))TL7@E0ZPP!QO0&*`5-Rc~LAHQ;9 zUY(t?E&j$-t7EHc9{AY0Y1Vn)1Gdha0iVp5r5JzUW0b0uF@9$Sn&- lb7&TIL| za~h=@AiqF;>FF-}Jdk6sSjfhFyFsozDGa0(`xQv64v0RiF`TqTHeuQNi`PE~T-_sN zBMzQDuRg4htGeq1J$#(}ykaODrBf>g4t%xs$j f6}kNTngq4e`6bFj4Q;CcHfeac1`N7%<-RfIli#dN6&sz|i%;;D3K?KjZ`QHONgb zz7nmx`QSvR`x-q9Kf`Pic%U( jrKoi06|K`|t2h?2xo;pW?4AuK21u FE*d?Cc=yBP`{ImNJOI^4*BhV!cvAZbs=tsOYBn201$>85qpA{HgP8waTPI zn(HhcAuZWA&+sZ^6KB>sg}_mcgU>j01g=$Is4hOP-@2jyys*H{+tK0})|LqGCx*or z5~zD`C|0Jeztni;4B7az1FV1VUMtU~CmLFODr`Kfa5>f8u3G!1&+b~kLiiAB^bmAB zaefcN^ga9jv({Sdf1=N`A=c!;o85EK$CWqLrx9Ui;i`l$2M?n&{sr$6C*&grZU!}G zJ2*(>(Bu2KKk_DMCjP_kvuH4xG?5sYWGc>P3{X@yS-GJtf9X^&?2Nk^-+i%+Z~Vy9 zpy7HGXZiJU9N%{1_|m0&0qV-8CGqw6!igxG*uDqvLo}Sk0F18ZA&O6011cn{ptWp8 zfrMWdz+cC)>A7IqY3@*X9C-7T@f+ES0m&1@m47$sebdoAJs4K2-=N-8Y()t&YOQ3j zcvlZv-fFT*Q$cI8TWc0BaJ=BYa4TRhcm(1Df{~CC+N?$okO=BrDLK^8(xSuGqz0^; z#Hy4+*QCtYDFd}cZhyJo53#y`8ekro1Lm8iD4EHja>h}0lkdp@LA&lban0FV(tLT@ zkct{8Mn=Y~)(oeaw>LlYZ->2m@TFVMYOlFdZ|Wl|#2c5Qs6KF*)N6TLuYf|-2UG0= ztR^?QJkW4aR9Y}}_iGvN-^=dzYXaVvw`ZO|Pyyu1H9{}jzlAS+#ZA^9|CLRTgkd%P zl;v(L4tK70U`EHsgA|p;Sj*CToN&>}g#!pV(X7CoQqC9dVV)DciZIqvEXup$GfbP* zNHSo=@?4bta#+XH0Z7_j!{HRzzHkn9ncIbXJZ2;Bwc-l;atb7HW01cdz mvKJj#|+3s`=@&Iy)-FI4Y^L}4oyds@Rh$1_;8uTtSDmHRu zL6RPDQ;``2b$WAib8(ZCA6pF+1%1v^tav>;i-izn6MeZRu$8moF{Il9ETg*@c3#%_ zo-5!W>buNm?FezPp6k6aCvfEzJbhLldwB_$3VS**=rn|4hM_&z1N2LKbDmMB<8d oxz4Q3L(B1sS{RH9_Bro_Ww|X}H*@%a=hO8z>yEQ59g~*JWsH3Dcr(8^wb_cSB z@`SS8qF%OWSmJy2q{*QV55I|5XhN%sS7n8^w|~yI{J?2)(fLLA`t#?{#;@zNPFpoM z)2-VGg3m=)t3EynY>t*}^Y9 #h(9#EkLqV2?*jm?+`sPvK+Fz9Qt;+k_W+5Un}%Wu zD*whxYWX1VBf~DE?OJnnJOintT2rf6vOL@HQ8?1;Vbyoq5tQ9Eq(r9t#ZMrBjNgYK zlDA_8tY11qOgr%(r<;d^3a_)v&D`=bEJWaZrE?~C?nAvg0Rj&k<1NO*w@D43TmT@? z=LShQ#>Rpdt?j+M-)n@_12DF@V@>bD)Y8&wb;;}F7ZP!XqcY!P%2L&uq^D0SmQv6; z#yA(jRp<8MXQ1fWkk*XO;`Lh|z_34GgDA*-x6*@c48FR8-)D#!S`sT++1d2}J(;IW zhWRwz&Hjm>oqaZVcv#w9s7?`mbl-{nz1&TIT&DN6P?0WKuf&3+gkB{F!m3BcH0bNB z=BQ-9rOf (jvwcYGZ9$GR^9juOqCuHFHhZmw@SN##`)S9$V{UU3eQ>T< z+H(Wz-hF8Hmv-%c ry;FUv^%4qHvo;T}toK~)JBtvmjh-2^2wA{g5R5!B{ z6dSD%V!9vug!A-b&CK|x{I&`t#&)jz)#Y-Ouos_y_Uz~A(`CS+-{H#d?BY@n;=R53 zCzuNz+e^Hw*3-peUzyclfZddM0K%qKHSC~y-@>c97qGb38&3=yA=Sph-MVt$w>0@x zd*-Dd3ob|_^wern(AZ?wYbuj(CBwz>ArOV%C;a&g@p}12UEWPwWB~~1B%-;L9q|JF zJF==VHvW99@Zlc`2$lL?F>L!UHahAXmOMUs+>;cY7xnn$Z#I6%5r8e5KS@YQ3EAlI zFuNz&YTlgQ%=)OF5g9AOXCBDai>qJn?C9&IuSK(6MH5MW;nGHgH){#v`RV_)Qn=xA z&Eek6u@||T2QL^#+vj=8ulNt=v*HrZ=@D60@W}yQo!CXH@ S9(1SzW zE7-bHDci{~zjXD%Kc9ctYX1OtdGj@I X%6=!_!alTq|M79oUI|{6U zLq6(PffPe7jB+W7?c-r!V1yh&B%_?>&r{Y=0c~{2%0krm(QAL)EMugbpE?qx$$@|3 zgmBAHic}7! #QSG97RE(H#1{9PZk;M$AO;kv8P~L1 z)9JwtpKD{DjGi9Ruyh9ZZ>1rYpe}>7 viY7~k*B4AXhRd|c!&=~83Lax!wL=>5?UwgqJH+;xf#8~E#{j!7N zF5g0m4J;ug7fHOHw 8Ny6;>GS$($}=geg9B|41NL!#KnLcd?E8oUDR; z=$buFj>@sJJY3jh5JrFxWpU2$WzAZ;?mjq_4|R5JO-t1yWqE$^h3+kz-YDK|XGek_ z)6m(1Ug| 6@p^naHp#Ow@&OZqrp!Nq^>G^TqFzO}?_=6 zGFaEHg$ZD5v>uBQ+yaNFXT1CLcN^|Vxtb!29=@WXVbmQ7b8?t(>lXz<95CjX&^kI2 zA#ZmQs4t-B=9@x z5HUV&*Ph#CB`@^~{Sa^s<5zGayNk1%kU_ZW)9?5&LM>!g5%c{Bi7|h|4pK)TwIn_b zZhkFn6WIxE&d&vreavCD^B;_CoY^ABoFC~YUV8=U2T7tse0Tag<7AG?BXva- J;d9sL)a3l-0ywY-H_sA}pDFAx6jylzbw7z7RPAMw`6 z*)9Cl&l_N4D8t4Aj>{!cIrNbS5eWv0sib=e= GcEmax2~?k2jJUmkm1$c3&urm=#_G z8rfH m>h>qux ziTVu6?1=8-t)VmsOPCM5Em!;7Ve$Bo`z{FmwR@;^ToAp1AL$DSf7@H#7s<0qGeQhm zf5D#;iRYnggWW4tn5M2jDhm*IR*s1fn{?z;CqXndO4jY5)^l$=2~{s~+LOE;La6k5 ztfZC dOUt7hQ)opz4nrztPoz-SLZm03o4!4Orc}R8WyeHf(}6vQi>^Q=_xZN{ z!LKt4*BV5nO7`}pSBtD54yomPZ@h>hEGRy)^Qew=t~iH!0UlF5FSLj>o9(^!+16 zF%C8P19gnM48sBu14#r^{<6X$l`0h2F32iDd@@%RWWGKu9-=y8ONCj!L|pFS)Anox zhs2O_;)vqhhA*gpWq`K6^%Bp#Dv9gthLosMZibE4lAy}pw*O(`D+A(j#38=VPdU8G z2VW{oJMMTc4AXu3nIM(^>%+8}Kv8l7K5m-8a_Y|s!7iVMiGtnO>3%*@V^;ksI=|lu ze(xL_9hsuf3)zz@7dmwWZ57&y)`txGguGBv3J-sUySn`#-)SXLuEagZib0ulJHd8; zR+P#{iMLOUeFr0nD2vQ^UkHXnaV3il$DHo (3sr3Z5GN{NzVNw{=bD1ME3g=7$V*x5_^xl&l zJ;X-f3>*-M>Owv&`BxEa_$KO9h*r do2X+^8>1#i5kQ%xYySV+T}%LnB9kd>3}osWDYK&Du O+Mc??wWtGN;kK2$gCSP`vg zvZZGzq;r732E|*U%SD?i0WaHLM%L&|IA-BD<^{nkyU0)@B*YFh0$V3}E<}cA8j58q zM|&SuBx-|VQd_-FT~DsxyEl~P(Z+?pi($nnlEO7EB5)H##F7YNq<4b5Tq%e4-VRkF z4syebP{qL%2dIsF^sDkT|G~GMt#`t8un~c=)D8XGB$`B6d1DCXsb6nG4cpUyCG@Os z!M=c~XbUjGk2L!u2mY{gm2cp0G)EAqdG&=Dn`KSh3u)nFRO5-u3K$AT%j4zL2X21^ zOQYYBvhnKc#~D*tH2jzNL>1c`kGnsMTt Q@u=zXgt}_C2v;mQ9fd<9W#teGzFy#K|pMl>+M!2^cso28h@w!Gl=O?L%j` zmywNjOvN;&Y?2JhjTDl{qR6-`DzJgNSt6L?Q! A&FG{X0W2 zt<6!|B8E}k8Zf= G+-X{$$s2pb!@E0bs z+3UUhE!rU5_F#Yfj $mF &Al;zDc2{z!EFEI8*6A~lH#3R1#; zPl1{aR5$(am0-kum>6k8@rrTTx5ATXGz)5?1Ck}5-myP+O7J1l#Dm@^bAGI*q|A`C zRI@`Pmi-+OGL^HW3LW@SNVGsui3Xa#j9xrc?(@qEtN0?t*onL53z``!5WM&~>;J6~@2?`%5rS&lpBNkamw5dlFGc)^hPK%jOsKa? zROkDQUf8a~ja2Im4ShvvWKvM?KxLPj+EqbM6GJI23d!{63#q51b|FdFi{+V3`qPcs z%%mPu%RL{x8}7 O%WO?{V>$dPh?0T89cU4|-QXQVO~Isq0=p@~zFF!*PH10jnhK+M4k5sq#r^3OhW! zPA55gCZ{Owb;?ZN(3Y?#zW?*K0ni(MJ*KAcU_H``UwS)0XU1sUNU`un{W#Y3(9m;9 zNF1Zrt|K5$XPgfw2aAihBAu`!ZtHyLX@{UrU+4!b()QrTb4LHLd07 6k-5(J2q@o$%{p^Usb#O7gS@1{Xv;5 zh>=3)4pExi5BDJkZFk_&Tn&2|SCs@}5HYrCK_TKAv*0Kat4LD@L@B7y6wC-l<6^{& zfR`b@WHIqx|6pn8f;vYm*@_VF?gDpdQ)C8oF=+U&2LAks2^|DJovaz6@_6<$ybG?i z?h#K=L-$5IOiFw`MWM!$WDabeR4;BEBKdrhNTUWmlOnB7A&5L!gB`ezF>}HQ`1&$` zl|c6YlY-=0Kp-MbBOCJjW~5#b(GM^7+$k^U3Y?bP>!BPYX_k#D(n45NX$n6FuH{QB ziiN*aT3e!j20eNJRK`dmc&cxTcY~C&qV?`6vxfo&FLC!DzKeTdN0GCNYl*Uos|}<> zM^T>@w2o1bx0EShM$NG4ukA2U_%pC3{GTu|h77E4ocfe>Y^h+cwWNa_@z@vKO%$Pq zu -$FpBSDa+AzeC(`jxP$lpkP zK4cCPm2Wz@6M+K8$-EL?S;BtGkfHKJ_Oh3m@Hs<%#Nkqknk_ITN`XnZZ#em4F^<_= zNw!f0=vIGy*;05i1l369U0Z*VJaPM-gRM`9KOm()2OC2N`KgFliMR97boX?-1{TYN z59Cs~fXi%xgKf8xKL7tycY>6b0`p9zG=?(2p5A?JenGXfJ6yg|97IF}Mkg{N|7(W- zF9fHHTjpyPA;c2t2ZvL`meDKHv!^2E6^ukr6lT=xH|kCQcahvAw6+-cjzJ`4`B;}D T_XF}vD?m<4S+YjlIOzWYmEURT literal 13153 zcmZvDbx>SS(Cx+D-95OwEd-aK0fKvQhv4q+1a}P*AV7fN9^8Yw2X_{Io8SB6z542_ zn!VC>YwzsL^y$;5XQNb=Wzmp{kpTcelb4fHhnx%keGuUx$Cyb=R> a(kv zi?x%RwW9+7c;>`S3p@02pu%r13Be_uNE=n9Q@`J&YK38*#m3U%l3O0X6ox(2n#xA> zrIdb^eGoDVC&~FPxhR*a7e)>;GL*dUEB<`AwIk}5De&0`-^L17loYw#E@CQ<1zEH` z%mF*+2>kl7e*9WjuqesavRWkRQ7Mf2>o%7yBVK@=y>KD1N&U&MP=&vhjv4{GKh73i zb$8a@o`10@J+D-nkg3Ut!B$84{*>d6{?nfp_VMQkFBk!Tb#XbDnP|wst8rc>lw8qz zB%5MX4kJaB)l5cy_dLF`V&qoLGxYitw)_~=AL^GNro-HfnLhwf0`gMtH9T`p{k+_8 zH9OzRy;XjtD0^hV{%}l0w+)3gM?n;bKknPXA&|;{y!PrQO6L!G9o+Ge*$_EkoDlgU z<9n!LkvDSq`x=$o!Brm 0&N?>QLWSH8F#+R)$-Gi1ah%#-^IpCa062NPRmA0gwrOAwuPS}+?~Enf zXuY;>%yWc2O;fgkXZS|2lzCluZ8 uoH%SgLl`HMz1X_w2h>?ku4KtlyjVi|VBXhqhk_jIm!keSdWTlHY*hH{ zC1FD~rGrN5(J3U?tCA0@@jH!r+S`2|Uf6JD*ZE=2u;^E~?3jvI0cD(5zD{1j5)~Dd z_4?|sS0M1*D8c&H6M}$7!e?ik5BK&QGvjzOX+q*3b?^M~=$&GL2 JFHEhs60m6w-4JUZ(6jY#8?3L7~u7W{S4 zgTp7V)#y86Hj&=Fc2qN(a6xS0piCYtq9&)rol1)lnf~ 2)z zTLOmOPrLUrGVo&--1_AF|7@wSd2 -Pa&c6UX4t!+b&ITjEDokrz1yO}#M~Sf*-KbPM#i{dN&FjbWF|?(ez-?s zH3GShprsUpXeYJH7HKIAxokYC5-L7@s^``sJIN|fm9`C1gyEw*hYpA%p>P<-qIV_l3}>Y8r&meFZ_FX$F!K)d(dpKhA->OmI`#1pcVx8cBcH995DlxR=yX?uv{%BF)Gb-Li0Ykx$N)b-goRP{a zsc7V!uY_8*`E%d@fWDELeS(&w?Y0f@!t_{cf&(yV)Ox>g!f;~K0h{03er`5(i6BOW zGK&5CLYvc+Wz|vkG#CSS3gq-dCy+zuqwlKkm+V$G*NvY((`&PI^h16tXVMUZ Gx^vvEWmih2e?Qv5Tr@y$l< SfnBni$hLf=! z7WsG`BMK&xHQtt=#+JS1LlLW-3SsTd%>+WMIAM2>Q?^Ia$}&t@?C7ohHQI7%XlKN* zftt=LR$yz7T&(6v_D}Erp0L_q&l?_KB7e0gEOQ4MBL)LM6Dro~z~>r9K#c akzC1qvt z@{z+%e0jdDnpgYmgxdpuiDr5(uw;lc8}q$IJzx)~W90$D>o1rCdJPszVuAr%VFc}y zVsE}h#@0al!#2wLL4JUt!i Yi#x`3R{SjiS4EZZNBt}2mQ3@8q9 zK*EbfyrV w|$*WBg4f*^OMB; zF`+2)>;3V?PCsEjyG4%u$Gg*&dar8>Qf&|MD|;fz_J9FCpxe@u;4KIP0B9OyX#GbB zy2~h_i1vEv_Ph}Yo`P~Toju(mG-qbMiQ6zGW@SZBOeh22JnsZ~C-Rz#8yZsRJ}Z_( ztGp7>`nV5)vl2Q&mZE@1Lb}h@unsWJJ(>+T^rJYu#At?IpVJ#}zy$54*6mj#Y~OTi zdXi{lancED&M>5Tkwzj6NuUEY?PFaGIOffI5|A$j%Z1w&(vab-8#G!Qw2II4Q5t_q zSv8Pw&Iv_cAFNzrEYy5uOhwkQubH`A$5`n|*!ZQV3sw_VkA(vW>Ch~?@+|b LeCe~|&;_+B>R@Ew{+ z$u^zYf^HHDC^?uIkVOFXK_4U9*xEYZ@9S;4a>v~Vw42oYjiI5}52*BA_v(8lNTWAE zy_BdoYLP+!1oS*IS*}HH-HU?NiQsZU } zMg*x-$JG`r?+$WE!w|i}ygOSPHS{?wjCkJmdpd3As0ry;<6H5#rW4zI?Rf226CaV? zloj{KxQ#MurDe@U-re7a29lGL0RUf-Zrzt=LUvp9?!ha{aIz7@+uJ)aJ3D57-$LY) zIlZ3-X|0yNBv9&dB1e!!op{x=bh2yHZ!gV2Jquk4N}jY-feI#Ya{O&Sb=bUR=g}6A zxCXt!f_wg~?FrP2b1#MfEH<9FpMW1UMcQv2_;Q86v#a@fAC?@uUUvzmq*#su-A7Jd z!ArHE@kGgN;)EMm3%TmDuT)rmkCSuBbc#;Z?GkyZIiZb>JW(j(y1H5Y<~A2(%(aQ^ z`gMzbk2m?>9>L93P{vy#;cllPhJ2@_vbis)p=9*l9eMT#qAxeI9OUkG=bmq@Pjt2I zy|FnOT3Xu^!sq?3FHb?(RsF5WGA$#rlof#h_b;k0TD|e{@!#@a3X6(}T3cHahcnm{ zV)F9H`3x25U5y|v<=_#r!5~kG$hbMHa(?q?ZcdyUX+u_9?^8&5{yNbQ=t1kWlk3C3 zf0MtNnzxv}AjdgqaruIXHR+k_E1Vds9%1sy3l6AyVjo`aK?=n8T1H{*eEChzlxe7a)kQBbb z(%i~)?}d)?AtsOjtdec5ihq{Ym2@I<$d400Y9O_Oxq`Ndm%kUJyvKUXk zT2*Oke1X>AQ(%mTWw#+Qw=wq+dSjB{WV83Y%Fe-h3P806!hLJsB(`=2 Mr~glmhe}xq8^>o=eM`1K*246S)MYdiS!B$!&@p!&o-I3iVBP%xk8QZ<6F}?L0Sy+{9R5?&ZJ9h{fe)nX)YzD zrBHy2iwiBlAs`UB3XWj_e&=>Y+VIZLw6=~lef^4W j%_QmP7I+Kmym z=vUzp5YT`? D}wpRjo9 zD?j($E)-f#L;pMX?6^=f3!?x|1=cD?dG*lQ4h>Wjca+&$GTv-ANb*j?1E=&>w^^_? zhC8=YhbJwR>GFHp?Vj~gwF`>a*x0loAt7=K3PnE}Tp55Ce@!HSQdl?w(#;}x1cao- zM9S&o+vI^50!4FmK_Owb-yP&xO2Y4}2;738x(6-!bb-x(uyJw0@sH4$d3t8lWbuO< zrhDm(Dn 72;asQZ=0anojbO9~ z_iOsjBnRq|^_#76?9l0DWMvB%jtkTnFW2}t3i{5j8&c{IZGYP`?(XgN?78$H5bP>k z`l6!i*rB1JWkJYTtHf~RXH8AKYm;%d{vU!Mc{4K_G+=2EZf;>{1ORGkSb2a4Uy#O^ zY0&Th6YxQ)Om*ZR^>wthb#)z#g|p0MGGl-Q-$KWyyVLOIb?+Fm;L+c|#auE-~($ zbH~0ucy34yUcBJeH8kMxt$apzUa{Z(JwDu=mX_9I(O^&+Z_mKYEa{-!8Aq{T&Q))e zJ#HasX-V(mI*6Ww1A$ZwF%3m9)5EdR+aS&fzgicCf5q4E%D|2_7)W-w=`!OaY~6Uz z5kl`RiJbR%$pr(5IPG|AXpn~VSx5(Kp+t;FM@O4^ZVui8f#v?~V+H&i9ea0q{w=vY z`pU#VO%S}>5HO49ehr)~%xCc!V#LMAvw7H7E!kH(y7{D_Y$>t9D#4Uj`d?&@pMpx& z!?ZrKq8%{kDm68#e+yn(JrmZv4M`}2a!L5sIlZ=Q V*$ihgr*)4k=y(J2<>DJ?C{K^zB3f=%WV zR%Z7ltxoQ _*L;?oq{+Sr3hrSL+?EGKfl8oDYKri(c+!nY;|W3a^vg&(Ch(t3aG z3H*AeTro$Csc!$Y=g8@!jNJM7itF9RzFl>$Vse**YX>nyahPj<<9*nQuo>ebOicbN zl^_&uUF08hQmfO3d~e@IK%RgDX+P+iXX`_5VRj2>#bsoKva%+?sS0%FT#S(8zZ)*D znam}*oQHqU(bhcuT#Mng{q&v*<@I@#xs&@Jfy0l1gRF`=ZI;D4lfI1gGsosNOQMIB zbh-8;nUiPp{Jf`F_R?utji&Z(Vacib&D9)V5-LJKfOM>pEM>TaYGKz!@E=o2O@(dF z250zqdoQlDMIiuwetveOMgBeBJ^E8TPP@O=j;@O4U;bspb5 +9YEeR+9VVPhBe;a#6)1arZ> z&GgC&isA;G0K!f|WYoZ+lh}#YAc-+W{cJs_u8KI^*--?aVFIhidK`w>GiIyStM+%( zP4mxb4og2it1_h>o}84VDbUTR&pQA3fsBg_vwFj=X6bl0mF08RiU9M~ +Fbn-&7p-hVk0|@kBy8btlPIuAreBA&eVxXdVSNJ&gRt9#+ZdkUFWD^Zec%A#lp6 z&qk1ym6e#162fgcAznOf?B<5syyi{ EDICEHQbE}a$ z@=;SqJ5*_E)UGe7Fy;OgGoLLjpZ*0bR#w)|KYz3;OjFIm1&E1>c_94vTWs%C9h}m5 zTt-*7Rh5V#>moc$?Zd>ylq3cf4Gm1!>uoJWSwX6rkAC$g>Gy8yT653eyTkxZ1?-Fs z-14s>j;0$yBZ}lFqVyzT&M4bL!g-4UPnI4rkGVzYxJBPTUU{`Euf-V?9liL|OiK&D zDs;6Gnvo(X5t@x%ckO)F*Io*1U`D`Y*J}Ikd{u|*{+P+RnDY-2&YUF7Oxiy%08O#` zQot+N+^DPcQ)W^oHUdywT igh3syM%;_dqiwj_3FYi%uk?|M3d=OmEh)T$3TX7Dm2 zZG0l7z&YQ~b`1L59lXEKr~UX8GEuPJo~c9onJ@dYA^!!nw6xTJ7l&kP@yn3b=;WJ6 z{ws5q%yh45_sp>J*7hWQKjczyWSv +v$9I{u9LE3d?Bs z(@jA^Q4s>LkXC $B6;OVKF_caN=H2ItFM6Pf|XecZyDk>!v6%=Hid#ZIB5;HTA zO4Xy#ucf_weS@tW`4eBNW4-tsRMJF-e(9!I>{V(`9p60cuQ;wYVq9It4EegWlG-1P zpDB^>_i!1%AE-AwX%N%YJWW@wvwUA^B;GPEI~({qNCFjTe-71M_0}>kp@I30@%;gg z3zjMrc=MOlgLCVGguEhR&$4wPlTM3s$Wpp+=EdTow!Z5)@6?eSAsN}g=H?!pqjEWp zGX3ml#6K%&7WoXCl9C}ZM3RMth3^~Obf`+yjja}gNgNhKmzQ-*%1T?<^;;;rw!)Pl zNSmk-R62_6{CH!n gXt7)L zzk>kywzYT&ABF_i*jRKEtsiX0w g?oxH~IDd ziVF}uz9-i8C9qpNjK(3;xU(}!ttz}ao_-WY@D2?k$*26{=qRn};UItFRH$i#kR}5I zgA1@PB=2{MpW( YlA<>0HFG-?ujD3wGQ>cuB{)27symoaTRvxR9qb_g`GV%S zli!Kr2-?_B#g*6BClyv6%T@6d&mU1XU;3G!sq(NL^M?N2j|ecgoRB;Q%X|$r)#FZF zk5PcSal5w(4!iEz$O;Oy+;A%W86Fwv7t};%(Q`|V)ATm}3E^d8GDolmx}jU1&fAal z?i|`!*j2X?)wloKZ6L @pyx>A;f|BC1mi4+r}ylS%Tom#zL27;) 43pnmtE;Z{p-UqE#? zE8^W;4~(^(;oF~MU9>QI{2l>sR7jO1F7fW580vY?VDo3hg-FLI3_!1Q)Y*Q`oBi(e ziRSo>>VU#%p$Gtkj;QuK@pe}79l5ZY&K)-(? (QKi`ZE{NPumh@<}PZS!TaESogzo zeVbG+cruXt9O%~{{Y0@CJvR0sM=XH6udgpLxoKn=V`uekC9JjiuiCO}iZo+lv+6wp zYUq&v)yJQxj<09UCf{UePgG!MhdYhfAMDN<4;z_KTS^H@>w1sjSI@`=Aa#T$oh|3t zsn&J@VK-#H8e$^Z8P*BFrvpe&W3MeD-GhsP@m>t;>@>>hn!cK0HTp}ku@u%S@9imS zY g?Sw zs`%SHjDP2Ur~gH1q5fhxlmhCr3-X`I&&g?3(IyQ`9Df@N%?$CdC-)`amDjn 0(qcHiQnpY7O%2jP^GeK6YI zcPPH;t=Q^BVdKpk(LSJ;x!dzpX(}F=Upz-Be2)D2@>q@RC4kfs;?loP!e6z0U+)jE z)#)0nYxiXIF>0w~uy|7lUfk&LX*NP@G8>8q6*`^qo_#6gD0~1C0z>NS6I-o+@6{95 zxlyqx!!&1y4=F)Jl=tO|!9z-B9DH9j#jc~>?*{N&Gq%!FtU`~Lzb2+71S*@tSIhfg z0C~I{R#Z%fFX*a6gFPA>k^TKro}yzdmH`1`GqYS *e>Pw%%D>-#c<*%4~;n-$nrComo9 zGOWezD x=39*T~P(VJ!!U`V?vU)P`Is@E|_|?THeDWuFu{!WDS9P`pUYSVg`fx6sr8&+`O- z=ax!suXYi0Y-IwtRE40Ldpi@oNvS48tb4zQONQ1?$f$R&wRw=Vn56rYJXoJTIk5!2 zAj-W*Paw(2%?ba5&pk6UQz*)d0i(q%B($9L^(%Tpc2q=y0rr|jZ9*dg6eCxBxn8gJ z^<@tO!G-!|y0^YB!2zhr*ddu*PsT-`DGl2YgM*))qKWq%VI273-L3A8$9<2vP2h9} zMlC|(Xll!~as2VlB0iioMiHUso%(X&naXd+1LvsUqV&5@ CiHXf>+lBNr-@ zQtiaOyaXqBIq%b|^~THUjZL5+n$el_ZVTua8uCmY?q9T+rGOK9G2RDV89e~NCi%A) z0G65@>{oP^noo?KcnqjQ2L9wq1uvBo*ZpL1S~eBErCN8jUA{DZ=ejS{|9ZYLc?a(D zJX9`i>L^1LV2&q~TpcHO2c;ifzZ)LW{IIsRG8 9J-DJr0zh-iHG*~F&=W&@8^X9U1P%W*5Yw4$=IHy6QG->Y@!6Qu;- z_a8`_1HLXU^1AJ&O WesTiB6do>H? z2`jQ-F0lf(fQTLM-yxXi_?eiy7#kNLC@CqOcpGPuCJy6qyj9psjL3Gs6n%J?B2!~R zS~_2@(zE4M@OZ<>qW2S3ooKK5ORk1QVaJY0Wo6}JDHJ60Xp#y0bG>!0;#qWsOQQA3 zk=S*Do~SFNw BH3Hlq)zfcw^uC!jwT5DfFZ8T!r~KL*|==qmNEXLudhLj z>8OX`cbp*=XuxVhL$)?yFlvW>%Sm9#lNPP@L)0>{MVgMG!zP^2?s0pGHvHy~5iD#r zcEgdo;Gp`--)J AJg21U z^M``LG7z=|k!w|P7k&OAz&8!13SK6N4YG9tGq(oqfmwC$@~U$iuL@0nJGVk)09#EC z4{0lKG&f~rXU~sY396R%88O3!cFm<{%|T9O^1Y%fH}>uDNz*hIzl)3O^s=eUNK(|T z`+(DFwC3-Tk={ (yIPw^11?sgy<`0;sERnH8X|24w4YYvBZ z_1CRoV^dRM`*TKx-)p+UvV-lPT23dVA$l4$X=rS6n-!I@*R;XZgir=E2J-{+8!}<{ z#X5(zUz|PwImnlANs!2I6${<6+C}22&zV!eJjjn0>t3u552AAQp>({OwW8n?+f%$8 zC1lm;HUE%wg4A3fy1-(yBLzOojpK0#BxXx9ao1lWM6e{nX9P2Ap?_yjsEUU5O{2Z+ z^JDu|4E<<7DRbwj$W?Od_cTt0imqKaOK0NL9qrg97)mRtn}4*7-&cf#lJrRnon#ku zl!Hn*IfrtFv9N5)=kx}@l3)9Cu%GAv&c^on4I#@lRmR<-^R(k_DPo=6;- N$YT|*JPwBZSPzeiBK|$o6?aGiLi_M&e24X(E>#%UZ zkDlN^oFtC3yY*m<0|CD$h7Wfp>2ZTK1}ltx5W HMq)fR}mRrv>XUa8^*9@FnunF!c-UM}aeKxQXV4b9= ;Dj16!LMaBmsV)9Q-Y+NoY-kBi?}bY@>Rx;3#Ua}M1)~i$=J}{ z>BLQkzP%*&?nb4*VSZ1HHP8Ra;E|!>Zs!* HS!S>aBp1YB39P3BVUH0Jv2gEOd}oH zry>#Fh`UHlw;+5#)Q>D&I_5yKc)H-%FXET44v>0)z}c;Mb+fImzOjxu*HIe->&$^g zkJqbjH#pP<4lb4m%N(*-rOvqU?KQN-z>+JIM+&d&_0d-5MF7-wT-!wsp)!z+n%HG> zDeEui5v+s&veYV@6ckONAp{wrEN+5pgI8@~pRuqCv699Ab>hf+Y0NGiiW#4kp+9N_ zhYAc Jsfo?OPmh zKrc7km`!cBfApq&ti=wbQBc$j3~Gi)$D6%G)BOSpD- Fvc>{A{d@8skOh&P0RV6SA4ol-!NFpFVcqCAjNb+;e3vo zZ%79-mJN{1va*`Aft?rX4TY+*$+&RZ{b!l3 $;by%^CZbLOHIf|@MXAahC1Dj$WIzMIgWRS}wPo-uUUGF!bthWr(2 z$+Y2z4LJzqQl8}1jYRh5vFQSb8cr^PLrpP12A1u^kN=%d=Rf#X!wF7M@(#>75dp-5 zwGytb%(9G&$+s3UV7V+41&ZmpguNl)O0=zJGYb?NA2Mbg?pt zf6IQgadtxEJs=LU 8yzy%mcLPy2PiRJ!;*iIg+*1bg~Joi`o=KemR zm7Hm?O8gmp*mE`$9oe&Vt69u=Wsq-rosFVw01iL!62`yqPQla^PfiiV9%Rz;w3C!q zuQAwo9f~`3>TK-vJIGZD?fr^>(rW&Ny53Z`D8|=`4=WVTT&LIf2vX}-o@Q+Un*9p9 zi8Rb9;QZcIaHv>v $Z@Jn61OX9GI1`>vAAgAz z%scc1yxj+U{B-;;dt_JpFMlkb11WYh6lEYs#w$S7yEO6CK(!ByMX<4^3RrZ;xF4e# zpo%lpr96i7O|-lGJ2p5b3ne24WAiU}A_ub3Gc=%GDEi&}0B)pRuNj_eZN~L3iUW`% zwk*TCryX|UJ)uJj;UK2!;V}{~C)E@WT69sJ|BJUbH7#l?JJkpHEy>|Nb3ZHnD>d8! z>{yXcoGva=0)|erxYS++7si+x;)Nfs<1n32CNU1m_>*cA^WzsK=@zI>Vo*3gWBpLs zR))uF{k-!vO=V&jSjZzB4%>zeF{TgIlXG!Ga}IDtQ9*ZjkgA8gQI~<$VLg=m*P`D} zJw|t}oqqQ70nX7CN>F0oG1rY4QtB#Om=5x~C5l%P5ky27(Ll+O^{F?88}P)9ahl1noO zkExz7_f4&iM=fSs}ghlb*wCe}@sVUC!AG?J-cQE{IdB7NBh%Oy&T<*E9Z_YO*g zst(z4VOA`VRCtK2z0?N7;*Pkrz-6AnVG#I!g1P5^+ll7E3ez``*v0vqA=S%DtD(%+ zI&g)L3@uayhRe565Buwvk1C}*K9r5Xd6i<>L%$_;J$fKskieEhoGd 7plK-E? N9R*G zZ+x5}RW#aN+=B(JRbQB-s@z~dyB)^1%_7?R$}nG~9lygJFU)7>MPvKKVL~`e@7BON zV(Gu7F}wl6U%Usaq;Q6D#8^nPi>kICq;@c-qZmmA58N>yOm?97bHz2CXzikw5TG%H zWz?O6{SJeKj8m4#F$RO2>?1@eI1)|H`Z8kk7&k^K7?ew>_+;2{+12^L=oW?PzNMl# zLEcL{!-}fV;oAq>#ONBVO0XYKp{XGn7a>(XIZ_uj5hCEQ-eR&N&rAs=d2|XpN_f94 zaK&H4k!Hh +%V1o{qh?G-?h3hrC#u}FYCXr$~FhL&^ z8T1pfAuT^v `?aTR2!_? zmGZ3*5KuMNE^Dvx5-DUqAoYb!^*Yvz#9;C0Ux>+o>W4SJ9RHd2g^T7v8i+*D{|?o< zhhBbyMP*#FXBcZIflP_}PG;mX*a%d=E@(tYA8p)^|B=$aJxcsgk`j#d$kAty94g%{ z9_38&M+#|}K7Mh5)gnJ&(sQLuLV@~DB6M2{St1m@L_FzA3Nx|^3_~^N8*3XNUY|}R z&mXIL5WI+(%3tU+C4 zE!?q5vh8kd#thuAfTB=L8*`M_$al!E4Vd2brXz~qoo6!{9`^R$@Tn~satrH_8152j z=FhOMnw*V-RaaCQVrvUl8~daSCdBLFd!_PXR40?)F0cE*WMP-f5I5NILyQSDh1+iS zd8g}CpUzU|FR{@78!O7!d3L*;;%EZs3h7bNt8kChi0f}2kfp5zBPE1>kSQj?e0z*y zEe!Fo=Smf?PA3^tAw&wzvY@p`u-S-dl9l)EWQw7pcF2%pMhjY8pcrv{eZhHO@Drc^ z!-)tsBJcRH3)E#c4+K(%Fa~4l%FJpooJZ@11E*pLdd+vGfB#gSOkKf=n{&nby9EEF z$U)?gDcALe6c?(`cy&38QR1DFMDY4)T$Yl;nDz==K~v_6K;FoXgCvRJAaox_S<}&$ ziIQiT@{eM|jVso%wsS2?lOIi-Q`Leh2b=7TMsmUi4DQIRId!6|H O i>Gd@X( zu4OKxW+lPGmYwa%V(E-&L(5#=2U+ve2t`++{9ix*=kf!ZUHoH@x5wo|D4%$XkpG9L z|Mx`fY3Q>knykTiMm;QSzei-W>AvycryjNKak~$mCPHF%OkW|e;EHu+9x9HKyx9MJ zs`7zni${u`O68>$J1!Ws)d=rGJnRMm_4pci%-pi*|qK%G!mW&CQx@v1I*B|PO% zxfQI!RDX1@ze3Bh%$>K6s0h`{L@;tLSD7@W4ERdp>#<`G+(`e1#a(vUR!B+A=KJ&o zriL)a)LXI+8C{0B-sWCGV@Urg@Xhps0c=4og{NxwmgY34Vs*4Fg%$gInr~w)*ovMO zmlsR7n3zE%n&APH&X{r!dzm0C;M_ckUHh8yZ+NB-VKelVPjQdGEOcQR!70=vDI&IN zH5pwaSec=Vrb9YQH7|5qmh%Pc2Z;sKFnucg#sR%li&cdABh5)+3$qf4Ex2@aL-<|v zQ9@nB_QO*>WLbn|8EV{G;P+A&Wc>JW`|iEkn11L7aVqsBzpLPZY!<1PIBp7VZ`UHZ zG4H4egdE+mLtd)sO8