From ab781dcc45cdc2707fbae9219520c2728dd80a26 Mon Sep 17 00:00:00 2001 From: wraith-54321 <69217972+wraith-54321@users.noreply.github.com> Date: Fri, 22 Sep 2023 23:04:21 -0700 Subject: [PATCH 1/3] monk --- _maps/templates/lazy_templates/wizard_den.dmm | 2 +- code/__DEFINES/combat.dm | 15 ++ .../signals/signals_mob/signals_mob_living.dm | 4 + code/__DEFINES/dcs/signals/signals_wizard.dm | 2 +- code/__DEFINES/traits.dm | 8 +- code/_globalvars/traits.dm | 1 + code/datums/ai/monkey/monkey_behaviors.dm | 2 +- code/datums/ai/monkey/monkey_controller.dm | 2 + code/datums/components/twohanded.dm | 7 - code/datums/elements/haunted.dm | 10 + code/datums/materials/hauntium.dm | 6 +- code/datums/mood_events/drug_events.dm | 5 + .../mood_events/generic_negative_events.dm | 6 + .../mood_events/generic_positive_events.dm | 14 ++ code/datums/mood_events/morbid_events.dm | 4 + code/datums/mutations/hulk.dm | 15 +- code/datums/mutations/sight.dm | 4 +- code/datums/status_effects/buffs.dm | 110 +++++--- .../status_effects/buffs/stun_asorption.dm | 235 ++++++++++++++++++ code/game/objects/items/food/cheese.dm | 9 + .../items/granters/magic/summon_cheese.dm | 28 +++ .../items/stacks/sheets/sheet_types.dm | 1 + code/game/objects/items/weaponry.dm | 13 +- .../antagonists/cult/cult_bastard_sword.dm | 9 +- .../antagonists/highlander/highlander.dm | 2 +- .../antagonists/revenant/haunted_item.dm | 4 +- .../antagonists/wizard/equipment/soulstone.dm | 1 + .../equipment/spellbook_entries/offensive.dm | 8 + .../antagonists/wizard/grand_ritual/fluff.dm | 25 ++ .../wizard/grand_ritual/grand_ritual.dm | 66 ++++- .../grand_ritual/grand_ritual_finale.dm | 73 +++++- .../wizard/grand_ritual/grand_rune.dm | 72 +++++- code/modules/clothing/head/jobs.dm | 2 +- .../clothing/head/mind_monkey_helmet.dm | 4 +- code/modules/clothing/under/costume.dm | 2 +- code/modules/hallucination/stray_bullet.dm | 2 +- code/modules/library/random_books.dm | 13 + .../mob/living/carbon/human/examine.dm | 5 - .../modules/mob/living/carbon/status_procs.dm | 4 +- code/modules/mob/living/damage_procs.dm | 2 +- .../mob/living/silicon/robot/robot_model.dm | 2 +- .../simple_animal/hostile/gorilla/gorilla.dm | 17 ++ .../hostile/megafauna/blood_drunk_miner.dm | 5 +- code/modules/mob/living/status_procs.dm | 140 ++++------- code/modules/photography/photos/photo.dm | 1 + code/modules/projectiles/guns/magic/staff.dm | 47 +++- .../projectiles/projectile/energy/stun.dm | 2 +- .../chemistry/reagents/other_reagents.dm | 39 +++ .../reagents/chemistry/recipes/others.dm | 11 + .../reagents/reagent_containers/syringes.dm | 10 + code/modules/spells/spell.dm | 15 +- .../spells/spell_types/conjure/cheese.dm | 17 ++ .../spells/spell_types/conjure/simian.dm | 98 ++++++++ .../modules/spells/spell_types/self/mutate.dm | 17 +- code/modules/unit_tests/_unit_tests.dm | 1 + code/modules/unit_tests/stuns.dm | 72 ++++++ icons/effects/96x96.dmi | Bin 1902031 -> 2119369 bytes icons/hud/screen_gen.dmi | Bin 110566 -> 110965 bytes icons/mob/actions/actions_spells.dmi | Bin 34606 -> 36263 bytes icons/mob/clothing/back.dmi | Bin 108693 -> 112938 bytes icons/mob/inhands/weapons/staves_lefthand.dmi | Bin 21459 -> 21769 bytes .../mob/inhands/weapons/staves_righthand.dmi | Bin 19945 -> 21992 bytes icons/obj/library.dmi | Bin 22942 -> 22320 bytes icons/obj/weapons/guns/magic.dmi | Bin 18101 -> 19401 bytes icons/obj/wizard.dmi | Bin 16304 -> 17094 bytes .../antagonists/wizard/equipment/artefact.dm | 2 +- .../equipment/spellbook_entries/defensive.dm | 7 - .../spell_types/conjure/lesser_summon_apes.dm | 16 -- tgstation.dme | 7 +- 69 files changed, 1103 insertions(+), 220 deletions(-) create mode 100644 code/datums/mood_events/morbid_events.dm create mode 100644 code/datums/status_effects/buffs/stun_asorption.dm create mode 100644 code/game/objects/items/granters/magic/summon_cheese.dm create mode 100644 code/modules/antagonists/wizard/grand_ritual/fluff.dm create mode 100644 code/modules/spells/spell_types/conjure/cheese.dm create mode 100644 code/modules/spells/spell_types/conjure/simian.dm create mode 100644 code/modules/unit_tests/stuns.dm delete mode 100644 monkestation/code/modules/spells/spell_types/conjure/lesser_summon_apes.dm diff --git a/_maps/templates/lazy_templates/wizard_den.dmm b/_maps/templates/lazy_templates/wizard_den.dmm index 025f9e8cdd00..75ee8f52454b 100644 --- a/_maps/templates/lazy_templates/wizard_den.dmm +++ b/_maps/templates/lazy_templates/wizard_den.dmm @@ -427,7 +427,7 @@ /turf/open/floor/wood, /area/centcom/wizard_station) "SD" = ( -/obj/structure/bookcase/random/reference, +/obj/structure/bookcase/random/reference/wizard, /turf/open/floor/engine/cult, /area/centcom/wizard_station) "Tl" = ( diff --git a/code/__DEFINES/combat.dm b/code/__DEFINES/combat.dm index 040930e52056..03b8514e0cf1 100644 --- a/code/__DEFINES/combat.dm +++ b/code/__DEFINES/combat.dm @@ -67,12 +67,27 @@ #define EFFECT_PARALYZE "paralyze" #define EFFECT_IMMOBILIZE "immobilize" //Bitflags defining which status effects could be or are inflicted on a mob +/// If set, this mob can be stunned. #define CANSTUN (1<<0) +/// If set, this mob can be knocked down (or stamcrit) #define CANKNOCKDOWN (1<<1) +/// If set, this mob can be knocked unconscious via status effect. +/// NOTE, does not mean immune to sleep. Unconscious and sleep are two different things. +/// NOTE, does not relate to the unconscious stat either. Only the status effect. #define CANUNCONSCIOUS (1<<2) +/// If set, this mob can be grabbed or pushed when bumped into #define CANPUSH (1<<3) +/// Mob godmode. Prevents most statuses and damage from being taken, but is more often than not a crapshoot. Use with caution. #define GODMODE (1<<4) +DEFINE_BITFIELD(status_flags, list( + "CAN STUN" = CANSTUN, + "CAN KNOCKDOWN" = CANKNOCKDOWN, + "CAN UNCONSCIOUS" = CANUNCONSCIOUS, + "CAN PUSH" = CANPUSH, + "GOD MODE" = GODMODE, +)) + //Health Defines #define HEALTH_THRESHOLD_CRIT 0 #define HEALTH_THRESHOLD_FULLCRIT -30 diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm index d737e448ecb3..63fd640d77f9 100644 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm @@ -73,10 +73,14 @@ #define COMSIG_LIVING_STATUS_PARALYZE "living_paralyze" ///from base of mob/living/Immobilize() (amount, ignore_canstun) #define COMSIG_LIVING_STATUS_IMMOBILIZE "living_immobilize" +///from base of mob/living/incapacitate() (amount, ignore_canstun) +#define COMSIG_LIVING_STATUS_INCAPACITATE "living_incapacitate" ///from base of mob/living/Unconscious() (amount, ignore_canstun) #define COMSIG_LIVING_STATUS_UNCONSCIOUS "living_unconscious" ///from base of mob/living/Sleeping() (amount, ignore_canstun) #define COMSIG_LIVING_STATUS_SLEEP "living_sleeping" +/// from mob/living/check_stun_immunity(): (check_flags) +#define COMSIG_LIVING_GENERIC_STUN_CHECK "living_check_stun" #define COMPONENT_NO_STUN (1<<0) //For all of them ///from base of /mob/living/can_track(): (mob/user) #define COMSIG_LIVING_CAN_TRACK "mob_cantrack" diff --git a/code/__DEFINES/dcs/signals/signals_wizard.dm b/code/__DEFINES/dcs/signals/signals_wizard.dm index a4b8f0755c42..5cdebf4f0622 100644 --- a/code/__DEFINES/dcs/signals/signals_wizard.dm +++ b/code/__DEFINES/dcs/signals/signals_wizard.dm @@ -1,4 +1,4 @@ -/// Signal sent when we finish invoking a rune +/// Signal sent when we finish invoking a rune. Will also send the amount of cheese sacrificed on the rune : (cheese_sacrificed) #define COMSIG_GRAND_RUNE_COMPLETE "grand rune complete" /// Signal sent when we finish 7 grand rituals #define COMSIG_GRAND_RITUAL_FINAL_COMPLETE "grand ritual finale complete" diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index d18c8785b40d..91b5b6c2e323 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -191,6 +191,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_DISFIGURED "disfigured" /// Tracks whether we're gonna be a baby alien's mummy. #define TRAIT_XENO_HOST "xeno_host" +/// This mob is immune to stun causing status effects and stamcrit. +/// Prefer to use [/mob/living/proc/check_stun_immunity] over checking for this trait exactly. #define TRAIT_STUNIMMUNE "stun_immunity" #define TRAIT_BATON_RESISTANCE "baton_resistance" /// Anti Dual-baton cooldown bypass exploit. @@ -671,6 +673,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_CUSTOM_TAP_SOUND "no_tap_sound" /// Makes the feedback message when someone else is putting this item on you more noticeable #define TRAIT_DANGEROUS_OBJECT "dangerous_object" +/// determines whether or not objects are haunted and teleport/attack randomly +#define TRAIT_HAUNTED "haunted" //quirk traits #define TRAIT_ALCOHOL_TOLERANCE "alcohol_tolerance" @@ -911,7 +915,6 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define CHANGELING_DRAIN "drain" /// changelings with this trait can no longer talk over the hivemind #define CHANGELING_HIVEMIND_MUTE "ling_mute" -#define HIGHLANDER "highlander" #define TRAIT_HULK "hulk" #define STASIS_MUTE "stasis" #define GENETICS_SPELL "genetics_spell" @@ -921,6 +924,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define NANITES_TRAIT "nanites" #define FLASHLIGHT_EYES "flashlight_eyes" #define IMPURE_OCULINE "impure_oculine" +#define HAUNTIUM_REAGENT_TRAIT "hauntium_reagent_trait" #define TRAIT_SANTA "santa" #define SCRYING_ORB "scrying-orb" #define ABDUCTOR_ANTAGONIST "abductor-antagonist" @@ -1019,6 +1023,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define SPEED_TRAIT "speed_trait" /// Trait given to mobs that have been autopsied #define AUTOPSY_TRAIT "autopsy_trait" +/// Trait given by [/datum/status_effect/blessing_of_insanity] +#define MAD_WIZARD_TRAIT "mad_wizard_trait" /** diff --git a/code/_globalvars/traits.dm b/code/_globalvars/traits.dm index ee663ac6c6fe..55326d5633ef 100644 --- a/code/_globalvars/traits.dm +++ b/code/_globalvars/traits.dm @@ -219,6 +219,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_APC_SHOCKING" = TRAIT_APC_SHOCKING, "TRAIT_UNCATCHABLE" = TRAIT_UNCATCHABLE, "TRAIT_DANGEROUS_OBJECT" = TRAIT_DANGEROUS_OBJECT, + "TRAIT_HAUNTED" = TRAIT_HAUNTED, ), /atom = list( "TRAIT_KEEP_TOGETHER" = TRAIT_KEEP_TOGETHER, diff --git a/code/datums/ai/monkey/monkey_behaviors.dm b/code/datums/ai/monkey/monkey_behaviors.dm index bce880ced7e9..e2a2a4ae1f75 100644 --- a/code/datums/ai/monkey/monkey_behaviors.dm +++ b/code/datums/ai/monkey/monkey_behaviors.dm @@ -318,7 +318,7 @@ if(possible_enemy == controller.pawn) continue // don't target ourselves if(!enemies[possible_enemy]) //We don't hate this creature! But we might still attack it! - if(!controller.blackboard[BB_MONKEY_AGGRESSIVE]) //We are not aggressive either, so we won't attack! + if(faction_check(possible_enemy.faction, list(FACTION_MONKEY, FACTION_JUNGLE), exact_match = FALSE) && !controller.blackboard[BB_MONKEY_TARGET_MONKEYS]) // do not target your team. includes monkys gorillas etc. continue if(HAS_AI_CONTROLLER_TYPE(possible_enemy, /datum/ai_controller/monkey) && !controller.blackboard[BB_MONKEY_TARGET_MONKEYS]) //Do not target poor monkes continue diff --git a/code/datums/ai/monkey/monkey_controller.dm b/code/datums/ai/monkey/monkey_controller.dm index e365a2f3bcb1..fdd82c0d3bd7 100644 --- a/code/datums/ai/monkey/monkey_controller.dm +++ b/code/datums/ai/monkey/monkey_controller.dm @@ -52,7 +52,9 @@ have ways of interacting with a specific mob and control it. . = ..() if(. & AI_CONTROLLER_INCOMPATIBLE) return + pawn = new_pawn set_blackboard_key(BB_MONKEY_AGGRESSIVE, TRUE) //Angry + set_trip_mode(mode = FALSE) /datum/ai_controller/monkey/TryPossessPawn(atom/new_pawn) if(!isliving(new_pawn)) diff --git a/code/datums/components/twohanded.dm b/code/datums/components/twohanded.dm index a0c491a27a50..756f30bd644d 100644 --- a/code/datums/components/twohanded.dm +++ b/code/datums/components/twohanded.dm @@ -148,13 +148,6 @@ /datum/component/two_handed/proc/wield(mob/living/carbon/user) if(wielded) return - if(ismonkey(user)) - if(require_twohands) - to_chat(user, span_notice("[parent] is too heavy and cumbersome for you to carry!")) - user.dropItemToGround(parent, force=TRUE) - else - to_chat(user, span_notice("It's too heavy for you to wield fully.")) - return if(user.get_inactive_held_item()) if(require_twohands) to_chat(user, span_notice("[parent] is too cumbersome to carry in one hand!")) diff --git a/code/datums/elements/haunted.dm b/code/datums/elements/haunted.dm index 1ed7f325294b..d678083dd199 100644 --- a/code/datums/elements/haunted.dm +++ b/code/datums/elements/haunted.dm @@ -24,3 +24,13 @@ REMOVE_TRAIT(master, TRAIT_MOVE_FLYING, ELEMENT_TRAIT(type)) master.RemoveElement(/datum/element/movetype_handler) return ..() + +/atom/movable/proc/make_haunted(source, color) //if not haunted, make haunted + if(!HAS_TRAIT(src, TRAIT_HAUNTED)) + AddElement(/datum/element/haunted, color) + ADD_TRAIT(src, TRAIT_HAUNTED, source) + +/atom/movable/proc/remove_haunted(source) //if haunted, make not haunted + REMOVE_TRAIT(src, TRAIT_HAUNTED, source) + if(!HAS_TRAIT(src, TRAIT_HAUNTED)) + RemoveElement(/datum/element/haunted) diff --git a/code/datums/materials/hauntium.dm b/code/datums/materials/hauntium.dm index 9a4e09f90818..79e254417208 100644 --- a/code/datums/materials/hauntium.dm +++ b/code/datums/materials/hauntium.dm @@ -15,10 +15,8 @@ /datum/material/hauntium/on_applied_obj(obj/o, amount, material_flags) . = ..() - if(isitem(o)) - o.AddElement(/datum/element/haunted) + o.make_haunted(INNATE_TRAIT, "#f8f8ff") /datum/material/hauntium/on_removed_obj(obj/o, amount, material_flags) . = ..() - if(isitem(o)) - o.RemoveElement(/datum/element/haunted) + o.remove_haunted(INNATE_TRAIT) diff --git a/code/datums/mood_events/drug_events.dm b/code/datums/mood_events/drug_events.dm index 66518199122f..1ca2f5abbe3c 100644 --- a/code/datums/mood_events/drug_events.dm +++ b/code/datums/mood_events/drug_events.dm @@ -107,3 +107,8 @@ /datum/mood_event/nicotine_withdrawal_severe description = "Head pounding. Cold sweating. Feeling anxious. Need a smoke to calm down!" mood_change = -8 + +/datum/mood_event/hauntium_spirits + description = "I feel my soul degrading!" + mood_change = -8 + timeout = 8 MINUTES diff --git a/code/datums/mood_events/generic_negative_events.dm b/code/datums/mood_events/generic_negative_events.dm index d4d50d5a29a6..ef4cec4ea467 100644 --- a/code/datums/mood_events/generic_negative_events.dm +++ b/code/datums/mood_events/generic_negative_events.dm @@ -409,3 +409,9 @@ /datum/mood_event/unsatisfied_nomad description = "I've been here too long! I want to go out and explore space!" mood_change = -3 + +///Wizard cheesy grand finale - what everyone but the wizard gets +/datum/mood_event/madness_despair + description = "UNWORTHY, UNWORTHY, UNWORTHY!!!" + mood_change = -200 + special_screen_obj = "mood_despair" diff --git a/code/datums/mood_events/generic_positive_events.dm b/code/datums/mood_events/generic_positive_events.dm index ebac71a6d4cb..18432d12ef4d 100644 --- a/code/datums/mood_events/generic_positive_events.dm +++ b/code/datums/mood_events/generic_positive_events.dm @@ -359,3 +359,17 @@ mood_change = 2 special_screen_obj = "birthday" special_screen_replace = FALSE + + + + + + + + + + +///Wizard cheesy grand finale - what the wizard gets +/datum/mood_event/madness_elation + description = "Madness truly is the greatest of blessings..." + mood_change = 200 diff --git a/code/datums/mood_events/morbid_events.dm b/code/datums/mood_events/morbid_events.dm new file mode 100644 index 000000000000..cfb8771bff1a --- /dev/null +++ b/code/datums/mood_events/morbid_events.dm @@ -0,0 +1,4 @@ +/datum/mood_event/morbid_hauntium + description = "I feel a better connection with the spirits, I love this!" + mood_change = 3 + timeout = 6 MINUTES diff --git a/code/datums/mutations/hulk.dm b/code/datums/mutations/hulk.dm index 5344cdeaba11..e1784f009c8f 100644 --- a/code/datums/mutations/hulk.dm +++ b/code/datums/mutations/hulk.dm @@ -12,7 +12,7 @@ var/scream_delay = 50 var/last_scream = 0 /// List of traits to add/remove when someone gets this mutation. - var/static/list/mutation_traits = list( + var/list/mutation_traits = list( TRAIT_CHUNKYFINGERS, TRAIT_HULK, TRAIT_IGNOREDAMAGESLOWDOWN, @@ -256,4 +256,17 @@ yeeted_person.throw_at(T, 10, 6, the_hulk, TRUE, TRUE) log_combat(the_hulk, yeeted_person, "has thrown by tail") +/datum/mutation/human/hulk/wizardly + species_allowed = null //yes skeleton/lizard hulk - note that species that dont have skintone changing (like skellies) get custom handling + health_req = 0 + instability = 0 + scream_delay = 2.5 SECONDS // halved to be more annoying (spell doesn't last long anyways) + /// List of traits to add/remove when someone gets this mutation. + mutation_traits = list( + TRAIT_HULK, + TRAIT_IGNOREDAMAGESLOWDOWN, + TRAIT_PUSHIMMUNE, + TRAIT_STUNIMMUNE, + ) // no chunk + #undef HULK_TAILTHROW_STEPS diff --git a/code/datums/mutations/sight.dm b/code/datums/mutations/sight.dm index 233e9ca338d2..b71c6cdd6a14 100644 --- a/code/datums/mutations/sight.dm +++ b/code/datums/mutations/sight.dm @@ -166,7 +166,7 @@ to_chat(source, span_warning("You shoot with your laser eyes!")) source.changeNext_move(CLICK_CD_RANGE) source.newtonian_move(get_dir(target, source)) - var/obj/projectile/beam/laser_eyes/LE = new(source.loc) + var/obj/projectile/beam/laser/laser_eyes/LE = new(source.loc) LE.firer = source LE.def_zone = ran_zone(source.zone_selected) LE.preparePixelProjectile(target, source, modifiers) @@ -174,7 +174,7 @@ playsound(source, 'sound/weapons/taser2.ogg', 75, TRUE) ///Projectile type used by laser eyes -/obj/projectile/beam/laser_eyes +/obj/projectile/beam/laser/laser_eyes name = "beam" icon = 'icons/effects/genetics.dmi' icon_state = "eyelasers" diff --git a/code/datums/status_effects/buffs.dm b/code/datums/status_effects/buffs.dm index f0046785a94c..72dece18b8bd 100644 --- a/code/datums/status_effects/buffs.dm +++ b/code/datums/status_effects/buffs.dm @@ -22,10 +22,16 @@ return ..() /datum/status_effect/his_grace/on_apply() - owner.log_message("gained His Grace's stun immunity", LOG_ATTACK) - owner.add_stun_absorption("hisgrace", INFINITY, 3, null, "His Grace protects you from the stun!") + owner.add_stun_absorption( + source = id, + priority = 3, + self_message = span_boldwarning("His Grace protects you from the stun!"), + ) return ..() +/datum/status_effect/his_grace/on_remove() + owner.remove_stun_absorption(id) + /datum/status_effect/his_grace/tick() bloodlust = 0 var/graces = 0 @@ -45,11 +51,6 @@ owner.adjustOxyLoss(-(grace_heal * 2)) owner.adjustCloneLoss(-grace_heal) -/datum/status_effect/his_grace/on_remove() - owner.log_message("lost His Grace's stun immunity", LOG_ATTACK) - if(islist(owner.stun_absorption) && owner.stun_absorption["hisgrace"]) - owner.stun_absorption -= "hisgrace" - /datum/status_effect/wish_granters_gift //Fully revives after ten seconds. id = "wish_granters_gift" @@ -112,34 +113,30 @@ icon_state = "blooddrunk" /datum/status_effect/blooddrunk/on_apply() - . = ..() - if(.) - ADD_TRAIT(owner, TRAIT_IGNOREDAMAGESLOWDOWN, BLOODDRUNK_TRAIT) - if(ishuman(owner)) - var/mob/living/carbon/human/H = owner - H.physiology.brute_mod *= 0.1 - H.physiology.burn_mod *= 0.1 - H.physiology.tox_mod *= 0.1 - H.physiology.oxy_mod *= 0.1 - H.physiology.clone_mod *= 0.1 - H.physiology.stamina_mod *= 0.1 - owner.log_message("gained blood-drunk stun immunity", LOG_ATTACK) - owner.add_stun_absorption("blooddrunk", INFINITY, 4) - owner.playsound_local(get_turf(owner), 'sound/effects/singlebeat.ogg', 40, 1, use_reverb = FALSE) + ADD_TRAIT(owner, TRAIT_IGNOREDAMAGESLOWDOWN, BLOODDRUNK_TRAIT) + if(ishuman(owner)) + var/mob/living/carbon/human/human_owner = owner + human_owner.physiology.brute_mod *= 0.1 + human_owner.physiology.burn_mod *= 0.1 + human_owner.physiology.tox_mod *= 0.1 + human_owner.physiology.oxy_mod *= 0.1 + human_owner.physiology.clone_mod *= 0.1 + human_owner.physiology.stamina_mod *= 0.1 + owner.add_stun_absorption(source = id, priority = 4) + owner.playsound_local(get_turf(owner), 'sound/effects/singlebeat.ogg', 40, 1, use_reverb = FALSE) + return TRUE /datum/status_effect/blooddrunk/on_remove() if(ishuman(owner)) - var/mob/living/carbon/human/H = owner - H.physiology.brute_mod *= 10 - H.physiology.burn_mod *= 10 - H.physiology.tox_mod *= 10 - H.physiology.oxy_mod *= 10 - H.physiology.clone_mod *= 10 - H.physiology.stamina_mod *= 10 - owner.log_message("lost blood-drunk stun immunity", LOG_ATTACK) - REMOVE_TRAIT(owner, TRAIT_IGNOREDAMAGESLOWDOWN, BLOODDRUNK_TRAIT); - if(islist(owner.stun_absorption) && owner.stun_absorption["blooddrunk"]) - owner.stun_absorption -= "blooddrunk" + var/mob/living/carbon/human/human_owner = owner + human_owner.physiology.brute_mod *= 10 + human_owner.physiology.burn_mod *= 10 + human_owner.physiology.tox_mod *= 10 + human_owner.physiology.oxy_mod *= 10 + human_owner.physiology.clone_mod *= 10 + human_owner.physiology.stamina_mod *= 10 + REMOVE_TRAIT(owner, TRAIT_IGNOREDAMAGESLOWDOWN, BLOODDRUNK_TRAIT) + owner.remove_stun_absorption(id) //Used by changelings to rapidly heal //Heals 10 brute and oxygen damage every second, and 5 fire @@ -486,3 +483,52 @@ name = "Nest Vitalization" desc = "The resin seems to pulsate around you. It seems to be sustaining your vital functions. You feel ill..." icon_state = "nest_life" + +/** + * Granted to wizards upon satisfying the cheese sacrifice during grand rituals. + * Halves incoming damage and makes the owner stun immune, damage slow immune, levitating(even in space and hyperspace!) and glowing. + */ +/datum/status_effect/blessing_of_insanity + id = "blessing_of_insanity" + duration = -1 + tick_interval = -1 + alert_type = /atom/movable/screen/alert/status_effect/blessing_of_insanity + +/atom/movable/screen/alert/status_effect/blessing_of_insanity + name = "Blessing of Insanity" + desc = "Your devotion to madness has improved your resilience to all damage and you gain the power to levitate!" + //no screen alert - the gravity already throws one + +/datum/status_effect/blessing_of_insanity/on_apply() + if(ishuman(owner)) + var/mob/living/carbon/human/human_owner = owner + var/datum/physiology/owner_physiology = human_owner.physiology + owner_physiology.brute_mod *= 0.5 + owner_physiology.burn_mod *= 0.5 + owner_physiology.tox_mod *= 0.5 + owner_physiology.oxy_mod *= 0.5 + owner_physiology.clone_mod *= 0.5 + owner_physiology.stamina_mod *= 0.5 + owner.add_filter("mad_glow", 2, list("type" = "outline", "color" = "#eed811c9", "size" = 2)) + owner.AddElement(/datum/element/forced_gravity, 0) + owner.AddElement(/datum/element/simple_flying) + owner.add_stun_absorption(source = id, priority = 4) + add_traits(list(TRAIT_IGNOREDAMAGESLOWDOWN, TRAIT_FREE_HYPERSPACE_MOVEMENT), MAD_WIZARD_TRAIT) + owner.playsound_local(get_turf(owner), 'sound/chemistry/ahaha.ogg', vol = 100, vary = TRUE, use_reverb = TRUE) + return TRUE + +/datum/status_effect/blessing_of_insanity/on_remove() + if(ishuman(owner)) + var/mob/living/carbon/human/human_owner = owner + var/datum/physiology/owner_physiology = human_owner.physiology + owner_physiology.brute_mod *= 2 + owner_physiology.burn_mod *= 2 + owner_physiology.tox_mod *= 2 + owner_physiology.oxy_mod *= 2 + owner_physiology.clone_mod *= 2 + owner_physiology.stamina_mod *= 2 + owner.remove_filter("mad_glow") + owner.RemoveElement(/datum/element/forced_gravity, 0) + owner.RemoveElement(/datum/element/simple_flying) + owner.remove_stun_absorption(id) + remove_traits(list(TRAIT_IGNOREDAMAGESLOWDOWN, TRAIT_FREE_HYPERSPACE_MOVEMENT), MAD_WIZARD_TRAIT) diff --git a/code/datums/status_effects/buffs/stun_asorption.dm b/code/datums/status_effects/buffs/stun_asorption.dm new file mode 100644 index 000000000000..d68f2f7408cc --- /dev/null +++ b/code/datums/status_effects/buffs/stun_asorption.dm @@ -0,0 +1,235 @@ +/** + * # Stun absorption + * + * A status effect effectively functions as [TRAIT_STUNIMMUNE], but with additional effects tied to it, + * such as showing a message on trigger / examine, or only blocking a limited amount of stuns. + * + * Apply this via [/mob/living/proc/add_stun_absorption]. If you do not supply a duration, + * remove this via [/mob/living/proc/remove_stun_absorption]. + */ +/datum/status_effect/stun_absorption + id = "absorb_stun" + tick_interval = -1 + alert_type = null + status_type = STATUS_EFFECT_MULTIPLE + + /// The string key sourcer of the stun absorption, used for logging + var/source + /// The priority of the stun absorption. Used so that multiple sources will not trigger at once. + /// This number is arbitrary but try to keep in sane / in line with other sources that exist. + var/priority = -1 + /// How many total seconds of stuns that have been blocked. + var/seconds_of_stuns_absorbed = 0 SECONDS + /// The max number of seconds we can block before self-deleting. + var/max_seconds_of_stuns_blocked = INFINITY + /// The message shown via visible message to all nearby mobs when the effect triggers. + var/shown_message + /// The message shown to the owner when the effect triggers. + var/self_message + /// Message shown on anyone examining the owner. + var/examine_message + + /// Static list of all generic "stun received " signals that we will react to and block. + /// These all have the same arguments sent, so we can handle them all via the same signal handler. + /// Note though that we can register other signals to block effects outside of these if we want. + var/static/list/incapacitation_effect_signals = list( + COMSIG_LIVING_STATUS_IMMOBILIZE, + COMSIG_LIVING_STATUS_INCAPACITATE, + COMSIG_LIVING_STATUS_KNOCKDOWN, + COMSIG_LIVING_STATUS_PARALYZE, + COMSIG_LIVING_STATUS_STUN, + ) + +/datum/status_effect/stun_absorption/on_creation( + mob/living/new_owner, + source, + duration, + priority = -1, + shown_message, + self_message, + examine_message, + max_seconds_of_stuns_blocked = INFINITY, +) + + if(isnum(duration)) + src.duration = duration + + src.source = source + src.priority = priority + src.shown_message = shown_message + src.self_message = self_message + src.examine_message = examine_message + src.max_seconds_of_stuns_blocked = max_seconds_of_stuns_blocked + + return ..() + +/datum/status_effect/stun_absorption/on_apply() + if(owner.mind || owner.client) + owner.log_message("gained stun absorption (from: [source || "Unknown"])", LOG_ATTACK) + + RegisterSignals(owner, incapacitation_effect_signals, PROC_REF(try_absorb_incapacitating_effect)) + RegisterSignal(owner, COMSIG_LIVING_GENERIC_STUN_CHECK, PROC_REF(try_absorb_generic_effect)) + return TRUE + +/datum/status_effect/stun_absorption/on_remove() + if(owner.mind || owner.client) + owner.log_message("lost stun absorption (from: [source || "Unknown"])", LOG_ATTACK) + + UnregisterSignal(owner, incapacitation_effect_signals) + UnregisterSignal(owner, COMSIG_LIVING_GENERIC_STUN_CHECK) + +/datum/status_effect/stun_absorption/get_examine_text() + return replacetext(examine_message, "%EFFECT_OWNER_THEYRE", owner.p_theyre(TRUE)) + +/** + * Signal proc for generic stun signals being sent, such as [COMSIG_LIVING_STATUS_STUN] or [COMSIG_LIVING_STATUS_KNOCKDOWN]. + * + * When we get stunned, we will try to absorb a number of seconds from the stun, and return [COMPONENT_NO_STUN] if we succeed. + */ +/datum/status_effect/stun_absorption/proc/try_absorb_incapacitating_effect(mob/living/source, amount = 0, ignore_canstun = FALSE) + SIGNAL_HANDLER + + // we blocked a stun this tick that resulting is us qdeling, so stop + if(QDELING(src)) + return NONE + + // Amount less than (or equal to) zero is removing stuns, so we don't want to block that + if(amount <= 0 || ignore_canstun) + return NONE + + if(!absorb_stun(amount)) + return NONE + + return COMPONENT_NO_STUN + +/** + * Signal proc for [COMSIG_LIVING_GENERIC_STUN_CHECK]. (Note, this includes being stamcrit) + * + * Whenever a generic stun check is done against us, we'll just try to block it with "0 second" stun. + * This prevents spam us from showing feedback messages, and is for the generic "can be stunned" check. + */ +/datum/status_effect/stun_absorption/proc/try_absorb_generic_effect(mob/living/source, check_flags) + SIGNAL_HANDLER + + if(QDELING(src)) + return NONE + + // "0 amount" / "0 seconds of stun" is used so no feedback is sent on success + if(!absorb_stun(0)) + return NONE + + return COMPONENT_NO_STUN + +/** + * Absorb a number of seconds of stuns. + * If we hit the max amount of absorption, we will qdel ourself in this proc. + * + * * amount - this is the number of deciseconds being absorbed at once. + * + * Returns TRUE on successful absorption, or FALSE otherwise. + */ +/datum/status_effect/stun_absorption/proc/absorb_stun(amount) + if(owner.stat != CONSCIOUS) + return FALSE + + // Now we gotta check that no other stun absorption we have is blocking us + for(var/datum/status_effect/stun_absorption/similar_effect in owner.status_effects) + if(similar_effect == src) + continue + // they blocked a stun this tick that resulted in them qdeling, so disregard + if(QDELING(similar_effect)) + continue + // if we have another stun absorption with higher priority, + // don't do anything, let them handle it instead + if(similar_effect.priority > priority) + return FALSE + + // At this point, a stun was successfully absorbed + + // Only do effects if the amount was > 0 seconds + if(amount > 0 SECONDS) + // Show the message + if(shown_message) + // We do this replacement meme, instead of just setting it up in creation, + // so that we respect indentity changes done while active + var/really_shown_message = replacetext(shown_message, "%EFFECT_OWNER", "[owner]") + owner.visible_message(really_shown_message, ignored_mobs = owner) + + // Send the self message + if(self_message) + to_chat(owner, self_message) + + // Count seconds absorbed + seconds_of_stuns_absorbed += amount + if(seconds_of_stuns_absorbed >= max_seconds_of_stuns_blocked) + qdel(src) + + return TRUE + +/** + * [proc/apply_status_effect] wrapper specifically for [/datum/status_effect/stun_absorption], + * specifically so that it's easier to apply stun absorptions with named arguments. + * + * If the mob already has a stun absorption from the same source, will not re-apply the effect, + * unless the new effect's priority is higher than the old effect's priority. + * + * Arguments + * * source - the source of the stun absorption. + * * duration - how long does the stun absorption last before it ends? -1 or null = infinite duration + * * priority - what is this effect's priority to other stun absorptions? higher = more priority + * * message - optional, "other message" arg of visible message, shown on trigger. Use %EFFECT_OWNER if you want the owner's name to be inserted. + * * self_message - optional, "self message" arg of visible message, shown on trigger + * * examine_message - optional, what is shown on examine of the mob. + * * max_seconds_of_stuns_blocked - optional, how many seconds of stuns can it block before deleting? the stun that breaks over this number is still blocked, even if it is much higher. + * + * Returns an instance of a stun absorption effect, or NULL if failure + */ +/mob/living/proc/add_stun_absorption( + source, + duration, + priority = -1, + message, + self_message, + examine_message, + max_seconds_of_stuns_blocked = INFINITY, +) + + // Handle duplicate sources + for(var/datum/status_effect/stun_absorption/existing_effect in status_effects) + if(existing_effect.source != source) + continue + + // If an existing effect's priority is greater or equal to our passed priority... + if(existing_effect.priority >= priority) + // don't bother re-applying the effect, and return + return + + // otherwise, delete existing and replace with new + qdel(existing_effect) + + return apply_status_effect( + /datum/status_effect/stun_absorption, + source, + duration, + priority, + message, + self_message, + examine_message, + max_seconds_of_stuns_blocked, + ) + +/** + * Removes all stub absorptions with the passed source. + * + * Returns TRUE if an effect was deleted, FALSE otherwise + */ +/mob/living/proc/remove_stun_absorption(source) + . = FALSE + for(var/datum/status_effect/stun_absorption/effect in status_effects) + if(effect.source != source) + continue + + qdel(effect) + . = TRUE + + return . diff --git a/code/game/objects/items/food/cheese.dm b/code/game/objects/items/food/cheese.dm index 4652017c65b8..ed980bd2a57e 100644 --- a/code/game/objects/items/food/cheese.dm +++ b/code/game/objects/items/food/cheese.dm @@ -56,6 +56,15 @@ /obj/item/food/cheese/wheel/make_bakeable() AddComponent(/datum/component/bakeable, /obj/item/food/baked_cheese, rand(20 SECONDS, 25 SECONDS), TRUE, TRUE) +/** + * Whiffs away cheese that was touched by the chaos entity byond the realm. In layman's terms, deletes the cheese and throws sparks. + * Used in wizard grand rituals' optional cheesy alternative. + */ +/obj/item/food/cheese/wheel/proc/consume_cheese() + visible_message(span_revenwarning("...and is consumed in a vortex of chaos!")) + do_sparks(number = 1, cardinal_only = TRUE, source = get_turf(src)) + qdel(src) + /obj/item/food/cheese/royal name = "royal cheese" desc = "Ascend the throne. Consume the wheel. Feel the POWER." diff --git a/code/game/objects/items/granters/magic/summon_cheese.dm b/code/game/objects/items/granters/magic/summon_cheese.dm new file mode 100644 index 000000000000..668d3be8f9ac --- /dev/null +++ b/code/game/objects/items/granters/magic/summon_cheese.dm @@ -0,0 +1,28 @@ +/obj/item/book/granter/action/spell/summon_cheese + name = "Lusty Xenomorph Maid vol. III - Cheese Bakery" + desc = "Wonderful! Time for a celebration... Cheese for everyone!" + icon_state = "bookcheese" + action_name = "summon cheese" + granted_action = /datum/action/cooldown/spell/conjure/cheese + remarks = list( + "Always forward, never back...", + "Are these pages... cheese slices?..", + "Healthy snacks for unsuspecting victims...", + "I never knew so many types of cheese existed...", + "Madness reeks of goat cheese...", + "Madness tastes of gouda...", + "Madness tastes of parmesan...", + "Time is an artificial construct...", + "Was it order or biscuits?..", + "What's this about sacrificing cheese?!..", + "Who wouldn't like that?..", + "Why cheese, of all things?..", + "Why do I need a reason for everything?..", + ) + +/obj/item/book/granter/action/spell/summon_cheese/recoil(mob/living/user) + to_chat(user, span_warning("\The [src] turns into a wedge of cheese!")) + var/obj/item/food/cheese/wedge/book_cheese = new + user.temporarilyRemoveItemFromInventory(src, force = TRUE) + user.put_in_hands(book_cheese) + qdel(src) diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm index b983a4ab5746..5d7a3715850f 100644 --- a/code/game/objects/items/stacks/sheets/sheet_types.dm +++ b/code/game/objects/items/stacks/sheets/sheet_types.dm @@ -861,6 +861,7 @@ new /datum/stack_recipe("paper frame door", /obj/structure/mineral_door/paperfra merge_type = /obj/item/stack/sheet/hauntium material_type = /datum/material/hauntium material_modifier = 1 //None of that wussy stuff + grind_results = list(/datum/reagent/hauntium = 20) /obj/item/stack/sheet/hauntium/fifty amount = 50 diff --git a/code/game/objects/items/weaponry.dm b/code/game/objects/items/weaponry.dm index b2fdb93407c6..a5c22653266a 100644 --- a/code/game/objects/items/weaponry.dm +++ b/code/game/objects/items/weaponry.dm @@ -150,12 +150,18 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 /obj/item/claymore/highlander/pickup(mob/living/user) . = ..() to_chat(user, span_notice("The power of Scotland protects you! You are shielded from all stuns and knockdowns.")) - user.add_stun_absorption("highlander", INFINITY, 1, " is protected by the power of Scotland!", "The power of Scotland absorbs the stun!", " is protected by the power of Scotland!") - user.ignore_slowdown(HIGHLANDER) + user.ignore_slowdown(HIGHLANDER_TRAIT) + user.add_stun_absorption( + source = HIGHLANDER_TRAIT, + message = span_warning("%EFFECT_OWNER is protected by the power of Scotland!"), + self_message = span_boldwarning("The power of Scotland absorbs the stun!"), + examine_message = span_warning("%EFFECT_OWNER_THEYRE protected by the power of Scotland!"), + ) /obj/item/claymore/highlander/dropped(mob/living/user) . = ..() - user.unignore_slowdown(HIGHLANDER) + user.unignore_slowdown(HIGHLANDER_TRAIT) + user.remove_stun_absorption(HIGHLANDER_TRAIT) /obj/item/claymore/highlander/examine(mob/user) . = ..() @@ -573,6 +579,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 gender = PLURAL icon = 'icons/obj/wizard.dmi' icon_state = "ectoplasm" + grind_results = list(/datum/reagent/hauntium = 25) //can be ground into hauntium /obj/item/ectoplasm/suicide_act(mob/living/user) user.visible_message(span_suicide("[user] is inhaling [src]! It looks like [user.p_theyre()] trying to visit the astral plane!")) diff --git a/code/modules/antagonists/cult/cult_bastard_sword.dm b/code/modules/antagonists/cult/cult_bastard_sword.dm index 30fe655f69ba..5ae594207db7 100644 --- a/code/modules/antagonists/cult/cult_bastard_sword.dm +++ b/code/modules/antagonists/cult/cult_bastard_sword.dm @@ -45,7 +45,14 @@ /obj/item/cult_bastard/proc/on_spin(mob/living/user, duration) var/oldcolor = user.color user.color = "#ff0000" - user.add_stun_absorption("bloody bastard sword", duration, 2, "doesn't even flinch as the sword's power courses through them!", "You shrug off the stun!", " glowing with a blazing red aura!") + user.add_stun_absorption( + source = name, + duration = duration, + priority = 2, + message = span_warning("%EFFECT_OWNER doesn't even flinch as the sword's power courses through [user.p_them()]!"), + self_message = span_boldwarning("You shrug off the stun!"), + examine_message = span_warning("%EFFECT_OWNER_THEYRE glowing with a blazing red aura!"), + ) user.spin(duration, 1) animate(user, color = oldcolor, time = duration, easing = EASE_IN) addtimer(CALLBACK(user, TYPE_PROC_REF(/atom, update_atom_colour)), duration) diff --git a/code/modules/antagonists/highlander/highlander.dm b/code/modules/antagonists/highlander/highlander.dm index c740de9279fd..98659ef19419 100644 --- a/code/modules/antagonists/highlander/highlander.dm +++ b/code/modules/antagonists/highlander/highlander.dm @@ -66,7 +66,7 @@ P.attack_self(H) var/obj/item/card/id/advanced/highlander/W = new(H) W.registered_name = H.real_name - ADD_TRAIT(W, TRAIT_NODROP, HIGHLANDER) + ADD_TRAIT(W, TRAIT_NODROP, HIGHLANDER_TRAIT) W.update_label() W.update_icon() H.equip_to_slot_or_del(W, ITEM_SLOT_ID) diff --git a/code/modules/antagonists/revenant/haunted_item.dm b/code/modules/antagonists/revenant/haunted_item.dm index a4772912a61f..4bee2f6e8f12 100644 --- a/code/modules/antagonists/revenant/haunted_item.dm +++ b/code/modules/antagonists/revenant/haunted_item.dm @@ -34,7 +34,7 @@ if(istype(haunted_item.ai_controller, /datum/ai_controller/haunted)) // already spooky return COMPONENT_INCOMPATIBLE - haunted_item.AddElement(/datum/element/haunted, haunt_color) + haunted_item.make_haunted(MAGIC_TRAIT, haunt_color) if(isnull(haunted_item.ai_controller)) // failed to make spooky! don't go on return COMPONENT_INCOMPATIBLE @@ -71,7 +71,7 @@ // because we want to make sure they always get dealt with no matter how the component is removed if(!isnull(pre_haunt_throwforce)) haunted_item.throwforce = pre_haunt_throwforce - haunted_item.RemoveElement(/datum/element/haunted) + haunted_item.remove_haunted(MAGIC_TRAIT) return ..() /datum/component/haunted_item/RegisterWithParent() diff --git a/code/modules/antagonists/wizard/equipment/soulstone.dm b/code/modules/antagonists/wizard/equipment/soulstone.dm index f93ed8abcff2..0a0746e52992 100644 --- a/code/modules/antagonists/wizard/equipment/soulstone.dm +++ b/code/modules/antagonists/wizard/equipment/soulstone.dm @@ -24,6 +24,7 @@ var/theme = THEME_CULT /// Role check, if any needed var/required_role = /datum/antagonist/cult + grind_results = list(/datum/reagent/hauntium = 25, /datum/reagent/silicon = 10) //can be ground into hauntium /obj/item/soulstone/Initialize(mapload) . = ..() diff --git a/code/modules/antagonists/wizard/equipment/spellbook_entries/offensive.dm b/code/modules/antagonists/wizard/equipment/spellbook_entries/offensive.dm index b23a1461c49a..57aa2ad7af18 100644 --- a/code/modules/antagonists/wizard/equipment/spellbook_entries/offensive.dm +++ b/code/modules/antagonists/wizard/equipment/spellbook_entries/offensive.dm @@ -23,6 +23,14 @@ spell_type = /datum/action/cooldown/spell/touch/smite category = "Offensive"*/ +/datum/spellbook_entry/summon_simians + name = "Summon Simians" + desc = "This spell reaches deep into the elemental plane of bananas (the monkey one, not the clown one), and \ + summons primal monkeys and lesser gorillas that will promptly flip out and attack everything in sight. Fun! \ + Their lesser, easily manipulable minds will be convinced you are one of their allies, but only for a minute. Unless you also are a monkey." + spell_type = /datum/action/cooldown/spell/conjure/simian + category = "Offensive" + /datum/spellbook_entry/blind name = "Blind" desc = "Temporarily blinds a single target." diff --git a/code/modules/antagonists/wizard/grand_ritual/fluff.dm b/code/modules/antagonists/wizard/grand_ritual/fluff.dm new file mode 100644 index 000000000000..8a1e340a84bf --- /dev/null +++ b/code/modules/antagonists/wizard/grand_ritual/fluff.dm @@ -0,0 +1,25 @@ +/** + * Fluff book to hint at the cheesy grand ritual. + */ +/obj/item/book/manual/ancient_parchment + name = "ancient parchment" + icon = 'icons/obj/wizard.dmi' + icon_state = "scroll-ancient" + unique = TRUE + w_class = WEIGHT_CLASS_SMALL + starting_author = "Pelagius the Mad" + starting_title = "Worship and Reverence of the Divine Insanity" + starting_content = {" +
+ + + + Most of the scroll's contents are unintelligible, plagued with mold, milk stains and a stench of spolied goat cheese so potent,(h)JURWaJBFQ zyJ{!NvN3a1dU8^fU&>t&^i;?q*+sI_9axIY`8Tv4h9EA{Q~Yv8waxI(kRq?V*x3Qk zM}BZYPr}E00$qt-U|Vo9*Q!VTeZX1Kk@V&l>zU$Q3V> (FcAr5) z`?$llCE3jq1G7#ccY@39bW{Hlq3=(0jt0u$n0Xc;8cH9-75IabqHPJ|ieUi;O`aqp zPLiM4PUSf{Io&g4t$J~R$J*}_q9~ZU8$LGf0q7 B{`SPP9O-0vok(}vTNuFBA71X)zwnsl zQf|v;Q`{*|^xw~9m)6xXOF38|Kw3h~MJXj%$6^@2KPQzurnaOBtA`xV!2{gBlRHUU zTU&casQ (=a>)bYp2y@)mP>b{v68bL!7QVuv3_Pn61~R@_}Zf3h{Bs!O9$OsFO* zkW2jKo0Z %OpI``&XuG_j;f*RM zO9XvDbP$yZVYM?@K4?2*I_3exh (ljC+Oc2e z08LY#vTbc@j%Ep&{Kt7r-G@Jcp{$y)Vi>`CApEsfZye8o2%bOkzZq%_>|E#k#vbnw zh%Z2sI{Yfxvmdd_Sbh`tn>XD|U0$dzZ5YTw%1uNhUsBkPlcNyyfBW?p$l--q^5QP~ z#q@)jykmlsS2x>%fzs6|b7MJb)^$OlKwcgtyDRZYY>7H_d=>?&Xtl$^ZiQFxC$%Pg zl17yv)i*WovZk&!BxtoOfjf&Ejnbrj$0GDM+&vRhB1&3vX$lPFN*!xOVx$w(&W-E^ zG@?nTn~lPKob5u!zv{-=_Mo3-vRa%xr;R%&UsGkCz1we{=&To#($AJX6xOv2^)b4E zJc?SaSh%@=i%Y=zo<@xvYgk01(_3As>c2E8HQn)FpZt$3KK8lDMs+hE2vmM;J??GD zV87&rN`~fev8!9}#4BzOk8ANgz58i^s@0`LuO;)-oda_%t*!=h77beu2UV8{NP5}f zzkh9_@01TVE4Y&owV)e9t2x*~za7IH8TVRv?wLMK;kNxW%aI)#olrnECRb%n*VQ$$ zw)e!cR YY?hv<_rYcd;sWa!eX&Zz4D~#?#he+}`Tg57 zHzRfmhSz;l)m|QmC}zdP5!twVi6dW|HZ10q#k|TciPL=p9Vaf+%zs7O0WIv`T9Bdx zC2^WBI&B;fRogdcU;c9&=a9cUg#WSR`-r~3FG`TY^CjDO)!RRWb5w2j4?8oO@x90E zSTr+;q|*D2VY%Z6bC6u|bULoCNaw-JiCC(+joL}COg3U&Ikl`A&4$KRf1(&|#;a{N zhmJ(Dckkc5X5Sqk8mp@24JC3?1i!tvklT2%(N-SW;}p>8FyclX?<(?oBKjU|IeEmC zRzpyS&(U;gT7tW!cvq8}S=&p!T0n4wFHXI^qxSUhme58@P2|{<)9ojg#_&Ba*~GXX z612|Q &3%j+k$iWzia8cDLK?4OF8Do)aDcZOvVFfz~P5eI4~L^gzYkM0;+ zT3RY$WfA9nQ5euy3xks(k`!%&dylEu5#jAUoeFGNZ>+uDopdHmj{)T5YBb~T{2;Ze zZ4JxofT&{P*R0dsL6?jVRm>s<#QmnA%tbnz-Db#B_EX*`6iT{V<1NL{FqXt##DSD? zww=IG1M{OE7*JIelK#88=8@MP3DziI5Y$jE{fy^X-_}Tia~~8j{O*z86ag}a4Q0{% z>zX21fuq ;dIVhe ||1nslM^`bN}A$+Wy zUJ73|o?rV7T;U~4uO?H5^pJwhJ18|@aHy1p`yJO5S8Bf3AE+X8KG5lXXm7m#FrIn3 z7iW#Ogf^&>&!7m5^kz!`N|R`oJpPL|0DRuti%XJyV?#FfSbdH~H5<<12>-DfxEWl= zeidWK)jXFl5XMfX5M`;@3>%qOxi6if;o+|9G*YonlK`WdGbepA=^H6+1(@N+l^Z)4 z^AlRtPA;@|@!xs3>_jAU@x?4yn5)LT7o|^8E+2JLOH(#5PkWGy@!ZZBYRP8%ap%EP zV%wU&cpQ`YMuPM6cQ(u*88O-##I@KlN&$h_}&)x1MeCd z^zPg_k3AyOu&mOOIGXj{JHLXMySK VHz`2Y4c;G|7g@D9uu4{i_OzH~6Ze~a^G z)K9#x=u6`(Y@riZC9^9la;8&MQ+`(%DvQ{~?K+GKrT(JMo6n?!c0D!jbx8lRyZ<9I zJc~Irf6A*8LP(l;VwMuoq9RdsvO}>^{=(5g?w82SZ5pl;;t>)E5>mL={F_Cwr0(%d za^FC4_oD|W{yo?gtq;0VYy~uGeVKr $!{@kPvy~3P=Hhq4R+Zi`CM+`nBXHa47 zYP|}(C-vIgN#l51(V`Zg;A*=HZyHHI@ajea@O))S>yu2SyoM)6HRBD{l=}JZeg6d| z`zk<<_S%~4jC+v^O*Tziy4h-Q6(8HD!WV@1U#= -yTSD$rk(ASXR^2MTuB1mz5bI2$0+7UupiLz=KuDU=PR|3 zPvaI*P>QZbPg5@et#Kt}RM9vdc~#zjWc5+y^9GVPR5QmRGf6vNvq0$^ (|{kMK}g zy}6&G;+AYpgY}83sR~*kBp04lLP`M+fs>m>N4i=%>fE2I@-qN>rHH<>i%HzgsyJqb z#Dh7MOAvO1-WFSeB=rN&`^gm-j*{{{yDl&gY%l%5Yqw=?kJ#SBsWEb!p(!ReRF$3L zS60
X5gXN1 zdlyc(9J}gzy5j%h&nZ3Bd(9YMyKu5`fP6BTi)~=%5o~If;i$j31g^)TZz7bFFD{?0 zCX&j3MA4kSa180y3yr65QBTtF>ZLEMp}TJ+h>oX}n-o>MG)!J~b!E7wBtf`Y>@RxI zJyr+;bThzSAclt_p?l2~mXb@o2`Qv9IUBO;%s2 Ol1e%VIxn5U8L zb`Qu)0x^f5>$htgmCvzAzwjHx9l2VHAoZ(BrBT_W6l*xP-l?qmQMCNVeTB3^SATTe z&q@_ag(PaCtW2lqJ5ZphD&hlOYC*77l?O0s-D2nMvAzV!8|%syyYP8t6^X=<@EyFw z^X?NQN+e7w=h grc-=dg16Gv<} zpmZkG6~&2kjwmd}Zb}M!y{~~;Vy8LvikCi1hJH#wimcOP>f@ewxoXUn@t_mF00=!R zFR$IMs%&rvx_&Q8=K1LnM@jUs!0fE8dCh9W`$;)xS-m;@Zm2RxJf98sDgeNu93jag zVAqYV{SN30oy}cdcpICzTYvs4m&9=WYqaz6>Lt;z%5_DBTz;x|y6(z1>2KP4%q19h zaRbi3_IAo}r8(B?gG4C)Ep>-c$S+Jfso=)PHv{^DmjoQc@+&B&2WQ_Zmp2aw-$`$v z3>23s3))UM*D6t}q76({&*fJG0KBA`Zt@8xz9?`JFPB@gw$7ac{h+rVfNG)g%Jn;1 z*Ysf;2xWm_>)?y4jxhNruOwo2kWhT<`B*(v;=f}yYBA)dS1`X5f)46VAT0wqM&)?+ z&*uaLJBj8!QsTszo-}>ud>H6_-cL(<{m*0{w~Js<{JO$;L|)rxOMKbLlmOHIdyB8C zA1Hv|-be7`IhK5V_K| I+a9-O0_hQTHASiZ zf)uFRi5V&pwf=Dq`r*}+TyB68z*q|(DNE@}hVf8%>GN+jhN&0(2|$PJ1OlYc*iF9o zdmzR0pT_EZPiLrH;ni2MQB9tU8bZcWRPwUq=Kk6R)n=yWf0tW(y7?z(}-tnb2c%+?TUwUbtBhF?TeP=t+;a5aie^5=Q zOvm-Je7^eEmLnx#IBRA3&4{V~D@apUYb>+6dx>;ZTERbf-p}P-6CEo-clX)^L2o0# zkOTJ{S=-a4JzULwitOzK5h<-H0^pLrC+GYa9D5}=m9(QtokD!*({9tTbABd|XFY;1 zs#Sc^edWJq%=6JGV^pha1y#H4l)Sph(?{|8*W!H=*K!^3>ozsuE?c|GGOSpfJ#{TM zqVGzWfb#+E@2gL2cf8j7PWth`pD#Si1lm5jv#~Ig*lzqgw{3c;5>96|n?=PHWcq=& zrt8vR61-t{0QMMX?&AXZm8X|5-n;5hKvPEfrx^>n4vGt$E;+exW55u9)s^@}|6RD1 zz+>+M(nZ~q<19TJHi_2S#G-a4f!?@`64UK?Yhb0`!|UIea5ca6K<;R`Ho!4iihPnr z{(SQNPk7X)3&&rK*15}=XkIUkH?0sYgZIc)b|Tzj!&S99M5n&g8ywk0R(`1YM#{xa zY^e0dJ^~P~E7r4Cg#4r6^!;!>P*?1ek9b86JL;DopvpXxc#IA6{s;oY6u(E?KmF29 zHI-|#=E_Q=_7BwGBEDi*SFQD#Ni$9J5cg!wkosjTW$0}pV-sGHZE!R3knUSGWNS0$ z-0#>q({?mVZR|wOHlpbJW;NjZ*}ZtVdw=SJfVnkGqr_EC=2 tFN 6p1*vTmVQl89^?Vfd`3^vu)FMZIEFOHHkP93%8DL!o zJ_j&5D+if;%yo%DLUI0kU3>hm=^}^fUQ9r1BYj@VsXwciI-lDF!GBz?+io}fBrsrS zJH`|$g5SRObmK$zoghBHr H4Rz1Y++_SMQDzK8Y&CUzzGt=`ex!a>Hq@ z=z2C@@x@l h)v<7(T zzt2rdhLb|p9 8g!*ozkBkIpo zDHZECeQI3%NEFPksjdnN#HBEq+ji0L86{GJl=AY(OM9;x5FgN`KN#79`#A!_G=N1v z=skkF@4JL)?8>D3YedkfLZzNT=>NOzhwbxP?c?r{AhEFE6a82q9gISY9`@kGJC^Kr zk|uEi;yRaklCfocjm$9J?!Awbb^KVLoG<-jMJ665xt0+3;fqD(?+KH)F*W@_c9LCF zn)+WB&56YRxCWG_($@X1rM3OiDSGo*7>TtXmJGy{{daa`mK {D-TR~n z849bct(paU{!d}~vjfTc@rP=kQ{6JV{u;n<70@_*&Acu6En`Y^m1bPc=1S&Vklvb} z-F-=E11JYgw)xYVNiAL$b#IPm!Y5WNRToH%!H5Y~X3O9TM9MiNEAjLzBh=qqWR^wI zVB<5mYGNzvO-|Xf-bF5rs@Ag~mDw(niiNbIjUO{ZA}~r4;~D-e=6V)DX8pLNjLX>~ zb3`&TFe7=v_@`#WhqTPQk46m?Ry*bNLb{)o=(P*;OO4j@#Vv;187*~M&p9@bqA60m z1@6B0K0<}ZkHwXT&@LwnbB*S=ePd(UQYqmrE_QW-3QzImEv~G_@5!3j=9kBO^?j!S z@d5_#Fj*6tx9*?qyOk=&rTg$^YCpL7x|HTM)jvsor0BG6Z<%0T*3H* wG= zpOKV*Qkhuv*wkNXwC>7abt`VDC=? ;(VjU#kh-%rhKub)v zzcJhwdxZ^=%(ENuRmp|WJ`YiF=?hIeF>lDyI_1{ ewxpcTbe*5Y;cWwV{KDUtbQ62W5 zSAB?j%pkWB@=J%(GzU$K(PrIjuRUbT -{ZQ{}1T2DF} zc~u7TjX(ACXv;k!W6-dt-fW@#fz*5^Zv#Du&A>rYj?F|h x8ZNTkg6tA2EHaU6U{m1TiV0F`ZR0 znTw#&F45Rc9j#nvc1`N{JIVC2Ll9JmpC+}j=(HuTR4VqK#76=@%lD4CMvnSYIXlp& zntc6&ZBCbR+kSA{$)rv2Yp#34oA-}w$&%@JR(P$Juf5mYP}^FPpSJI&2Si_n@uVWY z egH$IK?KBcYot0g$Of8d%AXG6TB~VnDqC 1JtTt~D!WM+rw%`9}wnqEzG6nxL)TeS{Z{1u5OUvhvbBD~NP?d03|5Rf|m$OB+*O z zG)u4NI?vv(T5w>crNWOM2t8lypbIgS{S%lg9f6YrBXLHB2<8!=?&3>nuH z&;UEgCFP^)$L6$tjf`FMw>6Ok6-gJo5c(*Pn)h4{l%8tp^|pFp=!k2?ii#6M{^a$P z%K^7}=QZ3B&-7;rn*5yxQFWUu+La8`78M`I6c_aW0%ne>Qtm!hGKc+rew@(2%Y5BD zj9rrA{>_<}&@gQTFejv&HGYX>i4^A>rU@)!KFdrwWvF6~u0N@@W0|OME0l271*qTr z!143etyFq4J=t&We@q}KpD;?C5E#f`|ASw5Dw^+~3mo30Cr6x3M{ruKGWK5vd8!3t zx~l~-38O1OPLg#3dG0stl(i4m7mTHyf4_?1AStKh-5Cl>@Z6Pk?9xp9e63ve8K*!n zZGJ_J$}JdZ6`ALP54JgwS!Y%bIgwaR|8Y#SbT5bMJbel${I5HC1^6EQmVwNCaSu9t zfH^C@M7M+gbz0(oI&qFI(_4bxGEGtinpdc2(yxh8sb{k3yt;cjEn$6CA7H`qW}@bO zOm$HoOV@duV4m?ki>oGi;osp>N&IS*<$Q6^k_MjX4(OQ-7*z59XcgwfcDym!*AwZF z({)?>0Fd2MnGv7qVDUMVFPM4N;4dg$K$G%NaeoIy<_twV(q(&>$raBlyLX4Ci3Od1 zPU}174(<3e;~5 6` z7<1;iX6d0mJIjhm&Y@(LD=~=3O59Wuz6;xr<*gGQu@k5Wbr@Al&QOGy!CM1YAB@Fj zJg&0Qx$?pz$zUZr1N+dUa(gt+PA{pZ^aqA@)Oe$`(9BG@O7dk+n_%Rv`?du%jx5zW zH}l&J3N|Z4ggrlqZ-qK;=9HSHWKd1%&AyebG0f}HVTw{=Oz8KzQvbDk)y2rD^pld= zgCcg=-%X3B?sWX`ohxgM`46=%ffV~mHN6_T6Isv9b~18gcLty3_4gX5D=IdujxdFO zH=xQA%_~oDGBTr%ml4$^WSz?CPP4w@=cwG8u=|yu3jpi>eAL?o?_JtpL!1m6{%pCx zjy_3g*OtHZgdo(;zr|-6m7((dYDuk60i}r}BK(J{H?L5Qs>Nn|az!OeDff3VJ`qY4 ze_v$9YPBbM{o4m6)+342+5Nh0cs`A&NAewyOQ21*$yCVRQd2Y(9Cu?8pn1(y@?>p( z;T3Zbx`oqkmZi_>WfJ^0%qdAf2e3k2_Rx37Aoy>fso}zVCL &YS$4HynNgcz3R^XWBxY zb#}F{t=~W&Hk{b}BB6%F3Ee|1VsCtn6+Ku+3HQvZ2Fb-WJb|Vx$~D`3aZQg4_6oh= zQ4_J(b$o;m5-#}Roi7iN4KE?L8B(0zUB>u=Ov8@MzoqfTnSvL*EkAvjZ>=Gv)j%nJ z-^kuF6|ww&x#8;f^;G_#cSCOE8UKl3ZXHvImFqZ=e3|c-#rml})zgi>6C?1xiav8H zq6-9{|Iz+YaCuL1!z3fzV?Ck?Tl1!4GVZ7J=7a`Mh@IU|hoQC-x0G7?RM1N?qnd3t z#Z5xZ8I*gNF#Vu7aPp5r>c>P2Gbz{Vo#E%^L3LD~nMWXjn1*&l|2;`4F>-pAR~jrS zK*}c`>|QtB3YED(Po~#XiER0dxb9EK$8B1%r)m=wsGj6pq!uOnf=1{z^>a;OOWgeA z2D`wY9v7 I>SG(?a=;*}qK0b0 z {sb`c4b=*ervKZbXsmWF~lT(!hCbN`g7J7Fpt;P$92_!>J4X3L`qx}5p z{OZyf+2eAU&`uiqP9A^K5)6K&V;Up)zEfQ10}~xVbWKxy!3 U)eh|B>@wK(x&*E-Xo7pVw*&BOpGIaIlb658P0_`2*K z9s-?=?z0)tFm)BBTovXuru)NoblQ6J%3o3b&4!&xvtOd6kExOQx@Af3+cbY3;0V1v zLd)O@JUURB?Wq+}-&=NUpKaoP($pixovWom^VdI(onG!H{evL>AFAFusI51C7Dfxf zgS!TYA}v~q6?gaIl$IjJp%6kTrMPR+QZ!K9N^yc~DXzuc9U?d1-@W&}^G-68OwJ!? zawd89+5PP9IekR(_S63CV0`G{j!Kz;T|SNl%8!y1BgnGW g{1%ATZjy?Iyb z4|I-EM>&DvLakLnQ6e4AR`u_7e-YiZ&wH87cx&t@8+^Nv!FWUEJR2qECFfb`^ 0AAwN77%Jz4@dVKbPAbdcO zyo0F75$_E!2d@2K__#O8MgnACN6V3O`G_Ouzot G$iFS0OPJr$7yQEWQkpI7 z#{@>MZd4bB@`1GQ?ZU!w037!Ig897>s0h^D|CbSBf`5I22FkS;@R*00fOVf7;9p63 zL+3lyUb*LYmfY$Xz~^_)y>e`R85dGke~2j_)}tk@{;)iy^)u~7y+x~#kL~NI3#Nfi zGzCPHMSWXo{|Jb4)cyE$2G(=sqH jd8!mg)=;m@)3)g#jbSRGahK0WI!VCeCuM4^qf#EaCZ|9|rE5F$H^2GBQa zV(%%iZ#JkT8Fl}!7l0|#rX>Ym%@>ysG{d|1FO{?pKRlhXOr0+zqxhh-A^+wgUx^(< z45*3~*+O$9hUp%|9XyK=@Z6Z;eNPU2`tHr{sQWtQsSzzZ-MDVb%bv)5X^OFcb0&=` zS5Ki;6LNkx(e4z-autIVfe5;ZedFXz3@*BO0F|8EFEzG5Nsc|2!u!fS?wVM~N=1a1 z)8ohzuHKxXm3B@mwcs;#CEY#aPFkHD=yC>eiWGc8_mXG{^~5 5I9n#WJLn z-TRk9O|23N0}5_Uu
ALta`r1}FW@~(n$*o!6*p{fl)bg16Dn!hZd{U1uH>V> zdC{#M!=$JtU2%=+{>`;^|D}HLt?Tw)X+XMFYJ(a^`4MZyZx;X}x>oX{zB%pAyFN~c zU-K$?nHmjsP=bnkjv;oV(^!j=%_F;T3SgkYjIPmj5cEMsY1M+x;FGTY0cKI6o|%x@ z8wG-H1sE^H-sJc@U*TX*Dz~R25nCdTLSHRSCVN(7jsUMNRY?r}klwOU!$}U7s*2}! z2+c^V9R l17BK8Mj=Ql0{Ik``u7uXQiC9YaJG0-vg|vi|Z&R5a2`7w%Bg58v#<(ZM`j ziZ-?ad$nle1O?B**W5OvHez>Ux~VdUNI-d{5vSG!Ln($6$sZasvS|M-)jk=85s*+u zYPBB9WESveSVa}Iq4bAY2}lZP-E1C?IcbzfIkW(i!JorZ{~Q=iDHiPb8YO3>sn@wh z5u$AVbx@nORcpR7d#6s#ud*@rbXUu3qT7DhHo$=RDvnZgNkJojpS75DCi|2))A*G- z78DH1HD04W*dMztyF6xM9I_diE;UkN^eyjEy`E?v*YIW1$Src=S^A3$m|pbOjVL1L z#~WVe3>EkF)8}e1U0iDw#G~2Ql4r9^MEua04A N0qbLrh (pI8@ zG%diVMgb#7mO;SMOwQ1`&!cOj{oaJLw3~~hrX@-EcAf5-TKb!{D@Sms^CMV6{|Q*U z^R7K9%bMt${s^lmnApbS{ZeHgoefE>a>wym_KwPs2?5}##R`V2g(olK28_SX!=8^3 zP@%kkW;m*`XT-7EOMF)+8dtL`#1Wz+wac&3nG{`Nt~C9jlwf=2Oy)=8T9t6vFEES# zL$UKHc8Usy>3d7nN6-Rf%6#R8B}3(Vx1SO$a*F|w>Lb|(CWpknP3xG&OOgINfQFp2 zP{{)k$6Tv;81~Z}o?71F<&2-<(z)sr3cK&d9G-q|#3=RRsbY!$)!91_cRc=J%-S?R z(X9$P==h@umx lOm^dJjw<-s7+E*U1zmOHyzAV$lH~^2b;DPCx5PRD7s=b59wc zQbSaGy%Wd}CuTcNh$nI*tpurw{X+PnV`5fJvz#f+WtPYZksWhYi;Y#XsHXV`r!k)p zk1l8Z8{GqWj^3F3Kj=)SQl0>k5u T zH)Ejc zDB;{{gAB-w_TEl1<|?6}uPElfPF>e+y#cFiaV7N6iAw_J*>*A2y3c6jaR-^|de((V zAY5xBMmhLHXZftVfbX5G{rs)#(e4m2IO!fKH_=zjUMKXlE&@e3MfqL5 yuw0crK@yCiB@#;i1KG^`^8$Qw(pa16~J zJXS}XEHY{Nak}rik)DbYS9>>r-VmiumOm_2v?NRsnh8GbtgktyYG3Ja7wzL{-;u0$ zUdwgbJyOF^KM^Zukj(!i)(+e|55xo-R)zn|tAJ^K2C}^#3VsSyo{`~`oPIZ50}7p` zxy%H7*RmH;*iXAs U3b1p1=K17t1g%j|KuLebfL!#L)P(r OFT9b-6ray#26Xj`+5^7qgo^II{F=yQ#*rc#^#YKD5ql}8RoR^id6|VM zXZEW|PKlXe3@w67v!>U5bKC QdVe5xC?i0rU9*1%_AhBDu?Aw&9GtiD zN3TH^>_qVJBu^(3pLYH2_f@{W?GojT)f#89_J*GwOuk&5M|8X{Wu8tBSbLv!@n9&3 zGbzDSl*+9M6OB;j0*|e!H~qL^1_Xez5^)Y@0P04YSDPuCJMktg>U>4?3o+?RkA%_m z6vo-sJ|^R>W-G&f)mb7_Gkv(Bg8gpbw<#&dA+hz+{HH`bF79}j9whjaba~LdwhYCa z7g%@91VjG>H7;)PIdb;2N_Mzs)@Xl}#rOGzJ9X8at9zY}xXg3MP_@mf6PzFN)n9nZ ztCJZXr^&8a1}Aikj+LsN5ge4@xqHr-sulRd!L`tCst@7Lzgd#C{Gh{1kG26Ru7T5v z5%cE1jw_D~dm21C)f;x?F=|gikmOLdlRUb)b^> )X@h0fq zP!4R@%h&DcQjA7~_2oXbGx@vVweC}n5!tVjs6(Po%wm$n(SC8;E-j3M^(XjhYz!%7 z8;^SJGlKoBNxyWB@d#{ht``pnDl1 g|pF?v! zrWLJQ3lq7zL=6vn+f-K1TS6+$A1xEQ6)35z%e9!j$8%iTMx;(F5i8%d7=DjPnQpMf zf*hTO5M`_FBTmvs3O{Weee;i>nLBq6=35OsvWz&rA)i%i+r|jxC#c *XSi9|S?E3Gq2{5mS z-&}CxVHov1f0KNi5=q2c+->wo>+KR0voN YRX{+tzI-BQF7 zIbYvtkKZp;rC|RsV^J|K# wOI(d0Dmo*+dcO#R4PMJM!xvT @qN8#{nT7YOtg)U^&8YNO zx?+F>T $k!^_f(kLShT7Mqsn&J_m=u5;e;#?3 fCqhr3V7U( zbP(rLKqtPE$pYBgl*{?ivN+mQyOkq_QJ(Co44S|8tl?jynvu;!j4Q)KPFUs<$(bbP zvN5miV20_P={KnM$eelSKAGQxp;P%}bK?|0DlGClna&i6=FT?#Yyg $^odBpTBcyr08AbB5sREqB}GpbRn9*w!sd z6w{`tY2ZRFIaRd&rG;>BM&VrlOp+I|;<)@Nf7S%y{ kwGL>gGjV@AY%aQJW{R zrI>RW%o&%V=aeF^rQb%2&$!AnV?W2{1w6-=B79!aYeNkA`)5~^0F$-*j5HDB@rbN7 zmKFH@l q)%&%n$U@(s25e2Lqc-7ncSZq>MY8h znj6FndF4kg>{sT@ap8h5J}3-t*E*WaUk?AwvHz)K{C3DDf4$6%-rb04seAB!4eyc& zH`)8b)nr})8?H3-JJ3=xytfER_3Ts9oPmNjpkBGKLR)xM6K6@fwwzXd^(dCrtE _B@XIKlzD7ENiR2@jrB+YW8 z{F$ATkW;kR?24;wqU22BF$-h5QPc(OHQwgMMX(gOYtI?PcPg-;X+Q-C*D6YZ4S^gz zwiO#Int5Oo(D1iWvI^?Mgp8Q_ZwfzZxBiCNrz?Ie(@3#5jJL!Rt#Bb=LrdCruh`Qp z3@)M#B&>_dguqya%1UgX^Dx?)aS-OtPEyHv=C^#S%w1xg=>M7l3oLomc$@gkKko*| z2eePThf8?i246LrB1ytPjXMa#L*V{k$g}aKos>mk``4J?2GjW9 NIEw9hJF zWFjW{mzZtCnID%O;tWWEu0F@ z4HzF9TZi9$AT@||;HI2uuXhVd%PJecxYU5 ptim7p~$9J}^?yewn&dgZxWVI8N|4=0RtT zI|)?${MWoLuC5Lts=S;fgjX5&Y9!|pRZzy+Q80~n<7r()wy)ND^ZDcSS(PDfH7tpg zykIUCLF5ajJRF#;_P6J2=JDM9+4m6|N`8qQntL6SSD82c5vaK5J)V0X=yMRw7|<2+ z{`j^MrfY267!qQPn499_-wBB~eUqz*|01>JmEt5Fr@L%6sUGI+ZE?L_3+pHHXVx~F zRjpsWEyZP?jQrIGALE62hH4nUgfZ^EFnb}$K0wxUtF+}delHl>%oZ+ fzH zX&;LQ#t5?c-D}ad;HP$|ggdPGL> ?ct%s-=8_NkNdwwbMT0;s|b(Rwz91tww%uG>N^ocd$eqIlzPTHm2d>fGOXyO8n z$-;TytYmRH?ormZTP&}6h;E6lh~bm~7n-Oi#R#eF#vEN<{<;d?81cYBBfhMQ{=X7( z=_Lnp#De&(3D f-z^}{wA!*ncs685+6|a&74o0G9OQ8PtNYsz}GJ;QJ*igX0}By zmAl}sjVXmSM;Y80kEsTyc`RygcUdi}#V0;?`>{o~pAJcR`_ZCwxU*50_c1t=*3kry zxb97u7>_xZfJ= uB$V%qJ zlaFD?teXxgi^S^YUZ=3nM~7CAxP1_gQFr{Uuk~#YZk=OGu_Jl`z1z5d0~5|KV%LY? z{d-b0%@zkXh78jS&*M+b>qq^2= dG$np6JwV3E46 z{^tR>Glpx@wZ)_ExZ}~_iMDQ@dWMAbTsI6{--jNeHv(Srt;`yAFX(OzpQDqsd@iQE z1BF;d=gpKlPslVxTee0i6aSr=awuL!);9FnY2mLhv&BcQ&;`oawzU;>9tr2hc>S?G zMm_iQKg;moMdHPlj-Sa{usA1-JSKyl#;tZOI!>&E8*3bMzOTDduIkk=FqX z@__S-{wp`YQ5HvKP{Hl)@Hpi0?T=XXfhw#%KsLX~*NV&|zE>IH`)EpUC2aMAL!KN( z^A$DHO#7cO`??469wGt%@6ieV4_4)v|NB@H-u$07%WJ4A+@MSDRwlDC#F}TMTo-Q& zxx~pE=hT$ua`P!adZm~loW-vB<=MP=#W3|PwL7<_;+`TgrFS8e4`;tJbz>+$r~jpR z%XB#7_Xh8ZanRIiNCneeiY`@G82&WbmsF=8&(0G9^rcG3ReZQw1D(XG%euFK>d76! zFM+8_Livtt_w_o2`%S-ipM4bqe4)_r+H;Lk=7R@N(IuPIm4j>BEOP9&6)xCHU49S{ zAH7H^m_d)$Rx{v!S}jX{uy!t{#zblK>_~<1SKN@0j)yeuJ%~ODRsk{DHXGHDGon$@ z7)p_&!LiL(YRx#?glG-6hJU}kKRAVvJbRbnl16ih-u#GqecZtHoQYrJ6OA5qe4EU! zPF?|P7k@XqYMP?Pq43F2;-hjgTKfBU6`Du($BxTcgv~svwaFvSQktTj?l3b`AZs9t z_TSLBZ>#m?0CW8YQJN`tZ(^pN6jVpsJs%{PTf~Et>-yVy^lyqk&(@^vqw%$6Zj=S= zEFyAS#3O@B4jQc~t(ycF-whTP%l~25`Pq oSOQiAuuT)#Oeoc@cZofw2s(i zk;IINowtmu&nfRlVpwY{Aws`Y87R_n9m|be3?zoB3pdBfN4*EtS{Z2MmRl;ur7G`P zx*|@+wmIh_0( tq2t zN;&O~oe1gvtfpA2C6x=0K_`uK>z(pdbuWk5^TS_6?&So{!W(RFdeT`UyD#kM1mT$V zr E(mmV>_DVV3l!SN~%?1Q%ZB-En&fQ=U#l3|=9*OC|ET=&s>U^;} z-Ez+5rC>L7tM$DfGW5nkgV$pBYU8GIafnTYOhbjwz32@`qL8=_M3FNPiQ9z^sI3`Y z3qc=f%8MYr$WrT1riILtyR03z?=Rmj$)a-vsEO-}w}L@(wBuIz@}0==stY&~!<@K| zq+ANo@Eq6fE?#dE=(0&IR<^%UTaL{{^yEx-kUtcwi3i&^R;z3aR;dCKU+cv+lId7L zk<60FtqIH~xPaD3X+L`1uhre7UR-_Q{*K4--TP0EBjN*j5;q4+2-+V~7QW2yVt!GP zd-yZeOLXJCWu 4zd2(4Ahw#t$ivU; zv(a~(f|fxolZS=Ad0 yQ5^Swg`_tWu~wTiT~C-QukL6aVxiJoIj>?x=4C(; zVv%Awt!+sQbU$*9d _>bCcRa3{FVPW=jXt8OuY?-) z!K&tEY)Znd5B)ub`=>l3WBY#iAFyolQOrTgn-<*AH(zs>)_15_PCsBylX!dFB7Ofs z$}ko^WIe2Xf2`iwth$@6 kYQ8%e7 ?7}Lrt*P?QP=*)p((8K!kl4{2kpI12GlhoBH3MSi8$~#yNB5Q%y9L# zb=c1hW(+PHjZo^p%XcKm4NA$dBsMQCF-!_mSPOeB;l+nnTBniwVL4Cd( iD~kfK|Krm+tuQHt~8PJ>m%wDBO`Hz~LkA cX(=K;jH)~^hhAv6BsR-3M(m4 zgbMbYwUl^?JTYC*p;~Zu3QfdK-;zY24oM?X97uTkKUAa~WZ+J2BOecmN=Ls=prnuq zcb7I_(T9UwJAaRHn#m056lJil@G2BibYd|Ara7fEZ3|uYszC7b5?P2T6Cl-162t@J zJ`Zu*Ex(^r#Q(@cxEASIQT zh1# za9)n|=( B8_b~ldbBjxCB<23D#` VDx?xlsk#SN#MT$`1ASKU%lh#p<~u2CYVn`On)eu06pb^#*qr6>~F@D z2~UetEABIKyV_GlzmlaJ4AU!`xpthn{7hx$DAzd-mc% 8*QiygWzyQLvdb7lE zAfv;6ytiuU8Z1 I^>l8$yPqs|DJ#W4VoxGsH2( zYaG;`q@`TPmzG<7rFumA!a5E^dg0O8s8Oi@C$P(wU?nGCeRQQy1qxNc-~fbQwe(T{ zUoQa8By~e7G}Iy%F7<7!XJ;l1iZQGV{IM`LbC&xGAM_6?SH4vX=tALs8}=4wC`jg? zMC8~co_)GQwcpQm-q77F(qP7_6kbDnK>2dtlLxHtXxrOP`hvTY?xf1b+KV&p-D;C= zzR=9<`&+Wz2TGLwl63ZWl!3lP?#PxOyn(Siy(y?;ox%KpU~$U@Ni^P!84SfMC`EJI z)gH?*gOPvM7}s_??O3uOl?f=cUK;av$0E*HFhW!~xsaf=fBwoWFH$05IhP>zKa?xk zi}j6mHIl!|6=U3Hb)J$CVA$fAu{ABy^f(#6*5tLuec5efR!qMBl-*0Pxa~Xi(Z=|i zNd &b^8_2 zr+eli b(xQwZ=WxKhE$oVzF7IChxWoTeydT=1}$2Cc+V1aV4}??|(mjEkt9< zh?sJAP xe8`ColwW)#V0SZ9h +M{8=R*%L?aa}3K#3TXIGGs}}b!d$$o+P+^i6Kr{jkLw=~Dd2t+D0i&4 zLN6L$C+_e!{o=ApzvUM2m@r$-6X~4YB1{ki+DeqIX@mDe`la)e-tc!f>I}XY>>Sz( z8p7o4OUL=kj^L7M{>Xx@Kp7d$di|!82-j{f(j@wsPC1|OSR xjUGY$^o^fU^4)V<=@h|bxgAs+z5-#uSf+a^lO?1$B zI(%4cef)<3VtCzVuDvVyv}{O7Kin)9Uw=l=MSc2NPmP@#Vb6zJ*e l7&bQsSS7L^>y>V-4jhHVO|Z$Bx|X4C{mwAgTKl7?F*nNNIFkCLI#Z z4aYuIJ4!HTG!st2!*j;xXWwhLc~BU9E3lN;p@`=E^b7&k?`0_)Htjnj4ds>edAv0h zvA?UQEMkR)3KQXfwpYXM5iTqONNGnd0eYW*FEZ5B%AicDg!`$R5ExzK!64ABujs3L z>fHMfeec_I;pZ~2?WXvRdyBI6XL`U|Xezsp<{+;rZb@pQ_osB%yNr+1(Y}51#E{ef zV(05D#HhE9k!FCXS4y-hMC!mN1t0|-jty#IEg&ank( `44d+ME@Z!5Q4PZm>9T8SSS;Hn{A4XeG~o^BhF}6BY}mySVo+@>;#}Gn1!YK zd`q7RIJ4`M;P!_7a{|Q8fqghd?scFGSN~!hSkvSql@c`5Z4bbc>?I$ZY1I_2s!8_N zG)~W7N6`Gt9BY)5!D3@YcGp-`#~{i`))QQZU}vWRN@;Q*-;u|`pB7YPsrZI7zfetn z`L);Mncc#}0C( jGOuLm@etnZ*(} z^F0+ya*}JcX6nhRA42o-3f7c;?Ci6Fou;c6ycCDo=#{%1_m;g3z=KJqg*ku{uVEov z<4gsoS2~2;on^L6AsODmk{ykXE(v(eUGB#@!{rM>B2 @k`U(+%NR9H znL0UHP3xY8vNQtF`KA4qC0A(HeDMRr2$szs&90QT8A|T;;kZkYR)RQgOFoQz8RGO0 zMXwFs&Dm1Ol74U$=w0CEi9*>rd>%G%op`O(Z$JRv;|an-2&6sV)Rg@UK9)E_%taFhMnsHe}I|NfGXT>@jyV8qm`^i--l*ogNFCk^*uXNkQ_M;`^--UR)A%ISi4 zV~D{q4&@>nf>*t!;q*tH+jB^spyz0jI3SPsiR4A` qZkayS$X4^Xy{BxsoOwJsl|PRqrR{zpP7(|*S&m;<)hChzomoZ&Ms zwf9 MQ(PH10Y$E|`<6<6-#6V3%FN>Xtx1 zc4t{t#kY{{^WB}}9f>-64msXwI-^`e>5df1hI=VxdgAJw)roDI%CB$s^>IfYzi;L& zQIffJQ2NxBazozihuiV3h^nyNfcWw>1k2mfEeZqvY7nsBU%LOc88j?PmX}g}4te7c z>PZx@nyeq632Aa$noV7;G0g@65C^WvWbcl*abF~ FH+r0=8;2tmgszCvjaP3Rr=M8Dz7d*Qd{TcU3GNl zAIlN{WXQ-DSO)Ir66j(~ReCQ7{+VlEk3Fo@rNPy)s2?L__bSt5hH+^?X<}(&SBIfY zm^LqdnY&hP|ME2aDxzL+RBGQsc_n4)X4N3Ia5QHsnptbgy&YUv@0=|c7MCz~^uz3h zzhqNCb8zA*wr}ln_iaq3X#JJ4uiK~Gdn)KZB#0fA4@Clu0q1>3(Xb_ogLyoyZS&s; z2cEKLge(^O?;mY8Ta1sq$6+0-tWYI^c;W}T@!kdp6RLmqp$baWmNni<8dq(TC{1pI zyy9d9DgQPsd0u4=-oxkGfX+H5#GgMmU`WepF)6eDz_vE}hp3Bz#QBHYH39vYqG8)^ zZb=t((Hgqt)jt(?2PpM `^T4KV9G<5~mB?)v zzRjo^^iEcPrBM7BM~{3TCcLbO?{ `q!D6^S{yHjZkY6is)s}tTTvPB%ya9oI>{_l( zLP(ys2zbh~{#LCEol53_v~pDNX|drfB8}13Bb|>^9eNQWq}9FOrsNp+DOOPD%=+@z z+f&)41{#0(rdticJK%(!(?2ugfn(Hh|8y>19K&of0`z3=z3YEvR5u>lB%J>#`Gt6m zqvwBlAM5tZzI{#WdY$fY>Dfv3M5ax?NN0!b{Tn{UYB6Aahj}2h+2W~dpd3dvnvsS# zXbm1lPPuo@iQ0a{nx1A2SPRSuY7Xkjsa6bKxl+~c8i*w$?0LH_smn06AMRsOagm&c zf(}8_QKHv)hHN|w _-T0(e z*baq8mH^$=0E|U=CQE=v11r29MWko J`2Axy z3W$<9L){Lb&`9iX27%?HKK^%D4v0d7@{$^R=r)7kuYv5<;Fm480USAeZr19(84^y( zWxT4b98syqJF+QgJ4P=M`AgR-*!i&l`7Qxb3zSDZEm{5wHh+_kBMBvI+@k*&=C dIL%m5#P)-;er`H=QstVph$ Ckf~eS p^X2 zZGv<`bvOqA738!A{MRCFi{7=NakZ2)v>{nwCAobuYX7&vd{wnt(~pFU%}$`gQE+Bi z>4UR;voqKA40$`94#4QQM*2X0G y;!N^}e;Ah16;VkhlB7utzRpUBI%!YGP`NdJA*S^H z6b}-sGaP3yL;`FyautqUe-NPkgDz`b?^=hy>h$?*%^p-MI}s7cu^y5hEN4H~TuFMr z6f7tyvxgGe;|sFEXhTOj(G!Pf(h9lZKI85BIS<^euT?Q7s~R+NvKMnsMlkB1e=ro- z$@IIsyfm^H^9#}HSFNAxhToRu%6F=9ifN1VXTf9)pAh@W+HWP==i3wsG0$67P8}g6 z=R!8T ;J*pVueJYhzZXecQfO=af4Sthq%?b1Vo_M4_C- zsm&66Z^!heJM@4dIjHR&=PsJGd5>qCi0&2U3d?z})-lZvI0Mc949%e9wqE1fxVf@} zjrZ7Wi=B|1zXlqhNj=_6Kv#wVfhM|BxFyx#=`4*YN3C@ud4wb+B~&cUAUKv@J1rsF zHi_`rRl)QaR|fQ8?DGBQ>W 6t(0+%O2Y&-ckYUld zdDiM&y3Nk!(({OvfLV5Jm=V@cFDV+@l?G@Yy3Bxt?E?}_o>XCkyWu<^+$F+hd|gw% z+5>cTm5sC*YU t7GU;U*7zgMNBe2UY-i5}K@{$`10CwseK< zpSp@fT%M{nzU-%N6W`1s(^{B5wRa=Kus_ecZH$(dC5R=m)L@I~yN7E-A9x(bO6o`} z`0RG2c60EIP;xL@yv(WJkvZtfUvS4*HZLc-^$mizwAMg(pW@&-rD4mle#~u@d`yFZ z`VMWT !Us`9kFq zY_!ju^D{A+=-9LCt%I~Q1JCSj4KA1^_~FkfBmq7Yx8{btuY}IgZq^$WuUBL Kgr^) ^MX)^3$ zfvg=oF=M#VXLd0*v3enSTXF65hhF06Ui8(^gCXE0N7Zu3Gt8?Dn~-uQy(zkP?d)Tw zmEPJlXtJBx*=`#G?nYRG+uCH;k=MU?6)Q`0YC3Ex9cfe69NMMY<9PTfy7r=Mmi*@u z(*vrVBX>&cT5x12uz-=9k&;eZz7?GHXgT>8*UI0%VRXsc{kWsgQ0+>9Nt$0^Nf`9b zF^Dmm7YOHjL_z8hukVCBga(&rTt}YOadx`w|9&=QGLc_A=d%A(Z{(9xK~ePMQ_Oyx zw%-{8kIGsdnw5Y%GTgw(>-&O84v!;J{N8Z%?ScXwzUf^=ifTs&Vhu+I-D9ukS5Qnb z#s#nsis60k*?f{}54K0h!voh?i6S2HVVIFWSmS|q7$6tzk8VIIV*K+@C~Oo27nz}Z zMv4btKby1Z?#v77vtdMrN%Cyq!$fG2Ku?}QOSGKbdrE{F!9+3ac<4qz(3i-%w(TXG zhlJ}0abUYyR39LaA+ag6jfCgdDvw?|WHdU5{KA9?6;?;}pU){fk&{&o6GV>;6Mh0? z%S7OXv(X~M+IYPP@I~0;4bmVb& 5|H!i{JW9?0em{?_&Gu^)X<=CIbMHyH+NbD& zL%3k{_kYQ)QjF|%`OgF9vp1rAl!>`cWH8 g{Q>(ih!Orty*2)6d!QMLK&l9yLtE zD_~bIMc!{YH-6Ua`PS0T$^Kf7`0MV#1blHenbpr-n{8w~3rC8aLHssn`(2iRrn}9b zW3i=QtF}&CPSr>pp9}1iLIU}?y_v=Gpo>~=Ws!BU?_9nfdr^H1u>n}BO^V!EvBjz1 zQ>XA{wesi#x3Do&-Og@KT`^~8Pq{QPYl`w)2SBn7$PAt6w=n14Y>iZ{04N#?VlDDM zh=@kh@5JqK=wME#z7>B&>Ps)sp9INqVgfOCv*`h*O5;+__TW!RxiiCw+4S4I=-kO$ zer0#rpPaV=dFgv@F8T8m)9owXMCB(#VkeXhNd$H<=3N>Kb=OD41U#Z}QI=w|11`11 zOOoG>bWXKk_WESF*eGkP>G*)dTbVCA|7Z28C@ttYV|j4E-zwxXd5?j*d 20>2X2|meO`6;#)H$fo#q|i=|&cE)px6O)9 zpmFe Ona*9?n-^@IceV7|9EQG@DV`r|0I7J6XwCye5cf zHiWM@Sbv5)=1Ys*?*U!mH20s5Eb&oq*C?*_ZcHET32kn2FRk8#)V1TS7TguH5zU90 zvOW)Isw@n!A4xxcY7fC@JoT|OAt}ovvZVGdb7kQI>4G-Je7)#m54u&n-yYrxjS3CW ze(^rr-ZI|5Sz~#2;Y!m}XmRa~#X$YTMA;kwI~IRnBHD7f5d0LQb&ZWpB6DH|A@p#! zJeJ@$z5w?ZPxcv<`nvc uzMnc=59itt@8y@MWj zaD*b!_y5D}3Qs;9L-}^t|CX}@Lwb% 9J%lnlWgPw!gf}b9#t0~yrkJhe@AZ1X} zVTMVvX>!NCnOh~G04B(QtVq7_zcX)7K#-TEOlNWn$fxk;TOqYW!l{d}2ALnOa~2_P zFK0lb(zBx8@0C`u46uB#y_&*JPac!-yEQG&-Z~iJ-~%Ifo;lz+;zaNaIw&!+_n48D z#wN3;a-Ng`CxOMWlcKgfz#7neryz0(e+KiL%Z8_>y!odFtanudt`msN&=a?iubrHs zUxD}(!aDLY*qfk8Lzu9NS|xVH79Nrmj>@{TA-N-sfPA?7A1g6}3QiUFEnJ!GKfD!z zA4}pAIfTN#b)zCtS1)={_IEZSk6Vv(&dZ%EXe8~u33+9apOnr&g@)HA-{-{&3aff4 z73%s1-RT6w-x6nIpVJhHu~p-~6P$Dn>g`;sIl5tCLnAj~&vTRCa(J<5s~27`3r}F^ zj_aMO{Lkrk020(06MWky5@H-zd1r%Ob{^*lPu94WJLBe8xr@-#c&sUQo@{$d!V7{e zK@JZ96!6U?wZUGKVYrp;C*Yk<1VqImWxd)Y-jEcjx(MS}38n2171pLL#XM&e(W$u4 zrvU97yuWx`6a#RA{!15?kFn jNYArl5vscISvBvC9}?3wzHXMsLFyJfkd%8Cv( zyKzb%mIFyng6}NjFgR5nQmcet^{Lx ;0a %r8xS@?jMe;2?_RkCPLb;M}Ik^n_W>U#=9Sx{S5I|$JwR@HMp+~hkll0 zMUZio7s38$$Xa9OXbKU^VM=DzQI5=$7N`D6(lGOTX7-p}t zfP4x)P`=_|D#fTroul_V*G~EL$GTsINpyF)5w)faD?s}h&b~jpp-g}Ua0yU>=(5{R z+0uQ;pW)TQHLqKaQtFnq2Q;N2$siiN*bD2hg)^YmeEVYz zQU^fP`zWpssS!ySZ5$i_#@fa=4D8Lj+N7FN2eGf$_bH3#HzPeSy$&gYo!vw0b$eG* zhV15(V{?vPLTgF-r=yy99C(VK&v^f=)#` c=VqI;FApSIK(XFGA=Cac@hH(RX;q|P&}PcI8LVYM zcaRDa0BXs>?mS8{hQ|g-O2X)kuamt?Hu%z($8U0!SRX)8QX8fd0nTHZFZ#a8=e)=H zE#eG+bpFA bz!Cs|@AfKN!pyw6`ksvd#^$0WdD@up0 zJJ%Oc9`2WOGI7BP2rSSz-qkL}F3wLS80rTU1^DL-yjNGsvvXNl1bi^ETDeC|Y33}Y z@>mmRBNUh1!+97;Ye+MLrgn0CbTf%-yk?411yl+QXHvc0J4a5%S=P?j&DX5ohpR%h z3xyb$^bk6AQuA3|Ar347 5CBa(NrwXzV?%uH+S) zH0PoGfc3wKdJCX7+i+ GRZj zN_zjDjO37muOsRkRN&ljBkQ}R7a2TExii{4ZFZb;9Qs0GH2II=A&Zcbo6#1{Am)!T zq)P0RvhTjQUm?R^+?Io>;j7QM?fYz{H<*4w)i^Y(WPVlq3bW!&bwsxDS%gbxz+w*G z{WEr}i{Nb0Fe%ldC _vff4UUQ7;i6mhXJ{d@G*;qKi{5=7dVlLf~@ z#4ehPU}OKHO`$V=V_X `JeKqyMviX+%LLJ1pEfK|w>_prQ6T&lbNvYm+Dye?zpHYGDY+8{5(^ z?~Mi8#jJvm8he6-eTHuO=?|(Bs^ZEA@MY{X)<-}TNG1*~7Cp;DP69A`<#2D02aU0! z!AHd8<3eB1NWeT >TgBGMPzuUV )eyjdF@P>LQHqlae^2y$}p3YGd;VEknj2a~?64_utP! zkr5LF`~QvM(*6NRUR?dZ!F!YI|EbnB7f7xgd8j9ogQVIKeTn0Lvj8ong>1o(rB*%4 z^=9i4WBM=6IsJZQOFS2KqbRa$yLAn}0Kp7I;4ntOTH5!dd%#2Q(_505eww|ephAo} zsk5|kHLVe#yEMDe(j7+K$6_<2a4qUHE}`n=>&cYPK@lwiD6%*7TzdSm+sB-KUy933 zG%oeHhmf>7MECpdLzSNWTC1{J@1*tf3wh?zs?>_POnMPA<%YHK2%344Jg1tV=xT4` z!UAfNJQn*m#1TNYmS=rtOY!*+#D0#mx|BVHAXStCP32FDLTk*ZpR=EAJyQV+-@AZ4 z60I-CXb;9pt3anDnn~`LgYdHK)~WK}N-)K#+OpUms?mdb*#bVu+NXr8(BE BxjC@}P_ #*0o1R%XI_@>8ibJwXqeW*YC5m~Ok z^rOI=WqE*ije#*qCDvW|hZKh}SU#tj&p+@T{p`<_Z)vL~sr50aWSUj})G8b?{G%D# zTlwZH9E=h2a(22q<8t7S!{tnn9cQV3B&gkwY%pY=J7?yxSCiCMpgVt_-G|Rv_4!8= zacRGfpte&4vI%0ht=WT8Y2dz--;1*iZ-&ByHqse}AH#wS5`2{+^&X?`n5Q&IuRTZe zs_V-#bU1*k9)b|Buqqp612oKjH^f_F6>QX_?zqfCJF1<*CmaCS{uax{D(ZnfO%`c5 z^WxaI21_afa~qFgDPD9RFf)Q?cNmUsq=^|FsS8O@DI{gM9CP*%3a4*CKmERsC3Ci8 zGeo4Qa @q6Yy^EQ1D?vP`KPT#ICA17jn3PGmjO>66>9 wyfpoIcHPdzi^cyRa%3l5oK+g-{XO4yg`yE41@lPQi^vsERFtXmB#eG;FYQP z{gT-A(512I8huY=oxk6MFCy6n=%K3zt8E18(s!P{WO+97dW)3b4nv Oc)eF1WW=^K)$Ouqm>)3N;R4U6O}f7MA$G;qM|@BpG~AQXtgP2-Cby>!PSxhD zHZFIZ`Ig*t8>E6JbjhZNGkpL>DlA1c)l$xS8^P}kAU9I6)&F?li;}3HD~5vxEEk0f zA o1&m3%0&hMW}m9tY*13r3}?;;VW9vdj>8+rA Qw@AUXum^2yF}u3=`efm!Td-0;FREV~hM#pn z0CB-=;b6s#1x4MopSq`LwE*W1JtqKIgeRjE)||**;h-YZ1l&Hl(rj_$d~4pKRQ0v9 z2%DdI7%#Sr4rn8~|6dUq0$F2Sj`4`_g-zbOO=z@(-kBGsWEnrcu4CJ?t>&aLkuxr3 z-K1b}Z96tIs(UK9i8W@TQ%KM}De}6ycu$G)dMOE=;l1Q2s@hl9Psov<=sSmQt(W9s z7b|2`8w+zDxB-FZZ9()iv(vcXjxQEOEc?(`12mpg(5zpKq7~rqRoCs3Fklm|%iE62 z=reG{GsqmEl%nhzLInFzC%D|ZQFqC5UJtle-7DfN?S~?u_eX5^M;3z?boac{Rwm{z z?=@Z`EbqA%L`M7#zC$SCPWKf5jpolu&+*8JVdNL$ByeZ)to_LHKV8y3jcn5gTRtIw z1oxn$!r1fbCTc$qxS4J55}&G`C76~ JCl}rfPZ8% i-@0O8?8cKSak#)2||?Mp;n7kEKNEZZfKYSF8_3S#o3j`TzEk;2vB(E?`$D znwfM+4+bR(;c16S0Ais48mdk#UJXjCl>H*bx*1d@3VvD-+K^h*WpB%#a2*#s`AK{N zTYLDy&%c!%$PH7s&YDU8l!pVn#n9Z@RM~1W%aXf*D$h{+5M9)C|HdBdF95rq=I2;w z-{n&S9ORvrC$(xyC_(X@9IcqFQeR^(oRaKM;z|xz=*rT _ho(mBi$jWN+v0s;Fds@ zbQLNPA{5c6q9?^z#S(|DTEKc2gu?}OIpcSxC{24)Y3c34t4o$8hx?tcRXfmW@4f16 zp$f-ac~PO6Wc?koaT#vf;|cD7n`uj7ITIqfIy1GPwDVWNiM`0+loV*D8OUzVLmn-c z?LDcphIj0T{^? %;miNxRO0CLgrW&mrk0bd z+Jnk*M5YCiG0a%VjM*n;g?tqbiae}N_AToO4GlO=T|r%b(3GFSh91G;^nr8WvfBzK zo<((UleBldic+xPWfRJ8N@iuKEBwpmd+_wk5~`k70*O|9x-53yvvkm&!P|{ced|Kk zSEcERC387(EOTa?bYz5L3#~Q$UVkucCdwl|d7UBmom#p&Ql(vw6Dpm&X-Lcyr)%nP ze*g3nVPbF%Q4Cmm{62}xg4yOVkh}srEcBw=&zDqUGjF53|9$6V!tCxR?RF2<{)tD; zY)s+j!KlQ1)8x8v+y3`Qa6EsELFul93KM*!F&MxYh hr;jm 36F9{00k%zzon+@C;JNm+$btMEJQ{@fj z1w<)P-fw-RtCJ(vz=t}?>-BGns0SF)F*7}AMg;bd# Y=6%r!VngOz}YLio! zC=BK>1@pg&Q5?^;$3m_Yub=S)>}TIv*91k$1$15ktG-Sv|GZh09z6fXdnKn?o!oIR z1Cxx>lbhlnRX!?-X+NJJ_c-@=w#iEty}E(KB1@Vy%F K z`B*;alMMWO`S-;zhN-}HTFq)7-heII6f+Zzs5ii z`YH7uU8vBjaU?GAvFt&uu(#~S9=!??#nGj|H+Y)gZUArbV!y)&Jz#*o+)vPxB9Ll2 zJ<|O3hAYcw ~w$RbB+W9d~VkFxThv50i?BB{o&Fy z@C%;^#QZtL>fttGe-$}%yBR{+_PSU%J08M%3sVkq@yeyA9pC4YWZfm~n+!d+Gp&pK z%_7tp0us2-ow(pgx-?;s7RLG^^KEus&<67vz{MRqrLB{VI1rmOW{|>%I z-WepYD7hoWLnd_6r?eCK(ed|#8`p*N3rWf+A}(rUY(lGxNG(O@XK<@g 5XHTq5exlZ zx>4-vy4sFk&H0`0jkTr9KT=uIszb4|&+pVaMP&1l?-qe0DwxMW|0M>gdFkavh>G`8 zYW?3lQwWMoaavxVhOBF=j!QeMS!km0k_&B8X}CI*_UGoQBpN&s )r?SnFxwT^tomK%@feMEXcBryb@>^AFSR{%TS1ex?VJ@PhAQ P!`&+A{!RL^0Dc)veRD|!rrzNkZNCR2vDcq+*1r!{{2yGReu=M)cS8HzZ zSCXv+bktvW1K@MV8Mfo--0dw*V7zIxq73cfgKqt()d$*7EQxlXFQKK?TrQ#LAE@S@ zMx3tR>Cd~!nbL?POQQ5bAn7!vV)ku!%BPer{Vb>%KiAlpLFTTh16>)O?Fg|hfwON5 z#CHicl7pWV6|Qfg<~mT2&z|h}%yzuFt_T*=LN*GtR>L_dH~K|~ASP|qFIaPwn3Y~r z`YOt|efc^{Ea}=mWiP9icIfEYGqgWbzHsAeEhE6GO(Im(7N2)fzW%EDj8C>v`9npU z{25}f^$p>60l9I_b1nc;{QKFKfROlFMN42~@Q>>kd>dX7l##N8n<%#j4SxIB8SjNo zwoi3-9w2uZ_AR}7V-kx6WjSLmh(@(j((i-k)HA+U!%IPpW~4DLty=bhP4^P|AGE5N zS*eG(m=b)dziD!3ZZ}$WP;db!OH=M*uMOc*XVXxGsY`8+sBO?a7- QqV3ES7t0zz2z$Eu6duQcxr-68`(hhy(HuP-QzT-6w z0-q+e=Q-n_&p7q)ecP_wyufS=!3ww1pCs56)5;V5OAbDsl&|z|R!If^d2Zt$Lz(wl z6?zFZy1vJjP)R;}7CL)9#qxW~M+iK8q!|D%_~r43{N<9HOO!~%Jf+X&O0xs-)m2Mg z_ehN~MFddKHh-5Q+b^t?KKv~cKT7Qp4hm%y>Pvfz$AX_%tq+2?7ys0pOn(+!DKPJJ zU(AzJh=C@hLi0$LMi0_YOf!Oq3y^!%4|W`7?xB$#T#qy>!jQ^DjYr|{Ejh`c7B6um zMG-GT+ QmY0E!;*E$*GO_v zcpY0!W-4Tf=}>#LdO*wRvhVQi%|X+iK}^@iIX$uLhZsi2B pA3RIKyuyPMLgTw*{;d$F*dxDK zta#n?hk7hW-lewsfF%Gv_%kqz*m+ziuN5=k$xjOwFajwZ|JfH+eSh_04T836LW}DW zUPyAD5n6%j+mF&g;@*Q+0T5Rs>#>sKaXqY0j;o5_|ERo0)?7cZO6yxt+`x6-En`l? zM
Y2}+IjSnD|2lfa0-^BajF!-u!Hqokqad%~mssDC?Tp9|m{sEb`#kPM zO-o;XO?SF#i-W81#mH3|B^ Z^vw@rU8P7!2=iCkS;WXZuA z%pE>A*rVWo3g1pfhxdUIH}@J*h~@JJ*pv6jlmCc6gmIF0DT{hW!l>&9sw01ij>?Zb z>!8)fe%DUWdShQ5yR+4d16O+ortLZ& z0$;;V=&5Df!acWn88paO-GX?9`33R*DZJL%{a&&6b^12Au{@&HMM+gQSgg1-;lh8A zk0T@kBa#8_Rq+Wc(*>3+dlUk|Z%Q;4#%GF$xPtsbNbF40k0X%hKRw_-cU}O}od<&N z{%4*4pM5r||JK>UKfUHaJ&wibFU>*GtCR2Xe6Q*>$U(D1a!HL;^}UHXlnFktxBu95 zt@|1+EC^5{>sLUL%nJNGjxMi}o1XKn+W=9DrpPSaxffHyx{X_%O9UtaB%Q~i8@+G< zj``AYyTU@B+?AAst)o%5A@A4k1gn(VI%uipZlVpWZj||mc}!#zPFTEOckTC}j3wTB z2A&ef1l!Ey?}0zYT4vVc?8H_)eX>?so$!XI>wjsck+mG(9@&1O`qOu$&IUnj;)YoB z-9Uz^kaDW>AT~%n<}-HJc8fCv4)UY(TX<2=(g!|to*r+mPB1F(j}xH08gKbBxb2}+ zl4{;uU}%fNA0a~~nsucc0RHJF&ncE_SX=oKtakfRBdKk2HN#3He^o3FJIi)klpMtx zD1)UZxu0K=f3^Gr-~M_J7O7bGQ(8Bd@xh9-4DVKwr27QM;{IlXEtcqy%lBl!jw1bh z%=g=+Y-B*01r>k6N3}L7169@`;)uj89@tEHB7;m`W7B(L|3B3`rS BI%bBk~2Pc8UZnl z0DJoTi#56u*kb`F6J**P_tf>wIc`~|=^?h1PO3c3ygaVpR{M #XDOr5I-DJnMystSmPXMoL|O4!Gmw4t z#>M>otScI*zW(rgx{*dgc~ZBhL^5q)z{{d4xH3qcC2Hs)WYg_gaef*&D*A1T&6xw} z@#`R8sH{~d3|30t*%{&;l&WG~w6Z$cc()(a^*6HgKp{ne?QJ8k#Q2rq4qGh2#%-Qt z4fBYSLC>X++&>EdHJSNCFOk0snL;@ZxNl6V^s>&$pr7gAUTNDC%q5~#nX4+J6!KBZ zM$jT%w+-)m(Q5mNq0A@lotqo7qwby0;;9KE@SEyxnF2R4NFkC%cxEBGc1hL{gZ?=< za0qrj-!u7~b}EDSn}YRZZe`uq>IpMiWSRDwt*2}8(Mbjz{vi3WksU>dp2hv6SRR40 z9jl|kN#EcPpmp4`&voR7#B;UPDCT1HOw+?yqwjpjO7DcRIz+)zbYE!P;eE!-cO?15 zeYZ=|U^W0(mUdEna>%JcjK-T@O2JvT;GB;B7TWRI!q$ndh-c^o2G+^p%88)yxLvE_ zW5E7WivP*L$U6yx_HdS2o7JGTaj)Awma`5;lx$=Xl>z8=*%QVVlyFD`r9Y!uJ Q;2;sRB;IjC@=x%19IW zIjg~7>jZR7 ~jp(#eaaPm|u0a{1?6t6EfKL7yCgf8Ma!ER{>S42z~=N*_({3VHEcWN7UcM7)X@ z4wF2jypywzAapmy_&r%tc=zwK6N~AIoarO ?a49`RJnEkDkF{FKC$$l3*2ZetkD{0tuo@Orh224 zbKkRA+XMy4>$@&a&BTK1X2M!5&Ol2d^rPIji`K_%k6%CpvYLQ#*FSU+jkg{J?PV*< z;2rac%Egw+h2wmMs=alRTJ5NK3lltQ+51N9g9c(5(8GQ g- z!74=3rac1olnESsIeyobRm#cbU9CEWUj@PA?|_()Od_t{7nhIbeu)$VkfuFIIE2aV z5?O}c-(U6J0?u%6K@0zLZt% 3n(a3LQvLGp$o`5kH&Gf~+d-=`Pxc{}hsR;#mB z2Yr=2rQ9fa<#)uK^W(M~?2vgI^eKxBj^yhHs7C>FU+DJWQd=iM!;2kSh=7grY}>TO ze12#IPy^||-@uu&jW7@0ra{GzLTsH+r)c6Ks{3_)cEE`23kqZa&1LWi5>)uTwF;J; z--E$okhaR^X51A0ce!3_{cgA_{Wf_NwP#2Jf*|rS6D0g(5DgN5Y4~@2OvvVjw!DJ7 z-!@<&c B&*2v#}aRPpC6{g>`3cVSBlkeFP5pTpa^%d-D<0; z^DA+m2r(M^%@&y~_oB1^qJf^o`a}uOceoH`<%jm)acc+QMgAYar{1_v``WaugJ~8l za*e}QQmx6}_(fUIm;=pV#xgm~Aw!i|mRkoN5m =4b&}9Nf6j?XSW+o>8lj2x z>~Z| 9%&6L1<8ftIiR<+t@Kl8A6ebD<)twn}oHAYM9(CQmBOFr*g(l zD(CcYkemUnl(K=Z+QOnT7l*hBh@}Nlr0~IGn2V_5nzevNY3J2^y3(Oo><^<4Cpu0{ zxeef72(M2J99pGZwfZtWm*=UUU*8(BPWY&F3Y%L_Q)_Ly*dzDSkFS^xR{JzE>s92} z{%WKxlP8qo1cN2F?u&7lV7tn4!Yzxc*j7y*)1IU6xX#6=y|@Hb^;nZkM3Sl=z0=Ge z@5bqLzAW)}79|Fh{8Z;zhrRkNJMqaQ=8CIMus1Ot8!Dwiqq8FNNHeb8lGthO^+_09 zU6##0z2I}wbJ7wnzRy*M%We45yM5O#Xu+B=@2WB>x6+h@Y5%kMcr$m8rJ~-21>(j+ ziDUb-xRnuk!md)@j+jFg39bsqpTOUiA3NhG3D|sS)Ex85#<1%4w|strJsA{i=zC6L z{zPG-A{PMLiCTCcr^EVV!o1$t(A@IFlAuPSQ|GBa0&o}|IDoe43S?Df?W!EMG>RG8 zETe|nDt%k|#0W9}=)AF11=y7Kz5ditjkuk3|^)<;l V_t zrjkb({y<44->GuLTl$G$ijI41lvt0Q;N+jkh(`Xhxr|S!raCIfMKs(Hu-*+)Fd#~G z#@>!QY*EPLN-Arh9{jT`L{CDnV%|f}q%6@XU*WBOP7Ou>46ZwPTUkEg-0)7$&_mY6 zv||j;W!7UnIz}3Xtb9l1Gvr3q }Hhd{=>+FrN^ zmx3KWisac;3j1Y>BRuOJ7EPQM(Pk(H-IFQ^&`!QT3r{b1G&~SK;#eOc6G@1s#{Tw4 zKFiZ!oj4WJx%^QHq+2^e7ccHJ!^-RHFl38xSG+;}b710N;V@G_S>fn}lit2XfU;78 zcjml)+VCwex8<2mFNU|#8Lf){xBVUUN*L~HAPCmAxf*^a*gEnXd>g>3QlS_7t8V&O zygbowis%;ek5cU9=CTlLgHh-249F^{ZPBP&d`vH@ufe ~p5&-Z zVr0Grv7&YDolMUwNs3o(WB-Ntn7+r>MYW~*>D*X=(|z?Ycwk9?)M)V+Yqhh&3^X<^ zl3)r6> f7#AMatfZ%L9W?~k`MnuuK%&G4O%p=|EeRSm{( zq%%MsC4t>fZbe vj*-UHkeX@$LtST!5+ zN^~|!CJSh$KwYZCZ~SHm&)3xY;@HvO9sB2-nqak@^tUW@9+Wq-*BCn%>1T0-I4tB5 znuMbmRKz 99glom)I>Q262) 2_J-bja4@DBVV`W%S%i7pgeI3S%gP(gH^ z6G9o G6=>59o!C3Klz1AGhzwflT2%TxMIGzj&%3`I0(i7kw5*j zAVhGL{yQXlqPim4efr8DWHn6k4gXhkiU*X+Es3hbK>2)niIy0D5xE+2aGO%uW!)Ky ziRc~NjD04#R8rDNg0hu7{JFXw*}l&CcfaR;_4i_y1OS&yM&?l3pI0<&C4&Uu>n{)m zTNVdP4}KQd1haJfcuG3aqTblwNJ>a-=+F-;Lav}xv)M7exxb^n5?GBEfG-Y2w{M*e zcKNMAcuTZs_=~Bqqk$7fZLiGjD2$bsEpTi;*OYX?o=m>ROTW)b8ii0cjVqh)v)SYo zV_8WWJfG;^K3$XEk2Q@{G<_S(AhHp@x91}$D*kn;rEkh}kGuc|BBGpUI9dpPVLuAt zzbD9<#xI`@xo{k~Ub7DVL gMc27B&+Uggs<(}G{ENw7X$XWWnRZ_O@I zKTT+xPT|?1;rBKn+MjZcwy-I|fVq$Ntlu0-0@JrwBg&U?;rH^-(?Ix>&;vsC>A`sj zK@5UtokNDfAZd8^{S`6Dd}kW@g3mT+8GezcRi??52K=$aZLX$ZT` B#XAA zOe>T7qU4E!oH*v^Z<&o6Igt|CgsTmR3feqNobtz|nX?c^(9imxzW!>rr`DO*Y137Q z6(X?eh;C(0U4is1z6n2Pv>{f3_HkX9k#Wq&gve4$y^M^H+L^fyjFk%*3B48 g>ZKRku!6#4u`td4m9MCBfZbzmB_>$oM6x0y?amzVWw701?5o#HuvAd> zxD^%5C`O#rM)yP8UIS;)OLl;T9?Btbc}Wba8(C9ac3h;V7pNAR^O^fX7Q@ &^la^NN_rBT{&W(0Sv4T}7Q%BZX&uAeT+Il#87jI-fOSck~s zTuF+4zj*ry^zd{ gv9eI- zYG92{wG(l1Wqe>f?W|9;DA&Z }P4 r$SZ6-xMTVSv3Igk2 z^ovLgm7Sg(2acecMf<>%td_b`r zi71wp2QT j{R~~shWL2rg3bx)g745L%;Sn?rHQ?sntx*b;&AeSQnN-N)tZaXxQa*T&Twy zWnrk~ZCWz@ V ZLw*jm-ybil%mXawq%pBv*~cK|3EO(4$x?4RfayX`Hf=L|IjsW iYf~ zM{_54idLol<}jTM7g!v-xzPTvcj#cPI=J$qbRw{5SEUJ`(XdBB1%SMfk{f*i9ZvP@ z`~GAtuc5Wi)$u&74FTL`n_uvB=idulRNQa8n4tU};B*5`THv=eV_{kZtC`$L#&_J* z3A1L;F2Z;Vu#{pB`JRj5gaYc#OGFbwK+;u%Fc6A+xor0wj25U+<0J?eZ@O)1BdYmf zM(y+{YfVVbElEDJ&fuY;5t-8e&GubXAHs~oE&jRw$MeTR-kf$0{g8{d0tbD8qbnaD ziX@U#Y=Wi}gqDKGcCs@Am-coj_4+n%-FTnVe|@p=_=<&<@zC|BQ?I=mUX?Q;wqy!U z?5Vccw>@p}s<1q3$_S><_X>JFPvvcx;dz3l7jUK*l=?NVHaT!ox~@BF5>43e#YbqH zIP#6y9pteY(gtp@-C*2v5u=Eg ^+vye_~IYb?r zgVn|XL)l_E?SV(K`-YX2nU#OmN7z+nrF+IO?7DaCsh4;BPDi jIiljQZD9y0q zBv+qc?sYa~+)8;UU2Fk&_^=60Fpe{YWkdP0w={X`qnZQ$7gE^aZdI*tD%2kM?{yq{ zf2_N!+-y{{&*eD;%-<$xYCtSdjnO30dk_8udJFgHSI9| x3HL3} z{Y (FcWSNsM8FAxS&T9cO@Y0E!}x zx%G808ATHP3Ga7l?0tf