From e784e2a22bd68a6ee103869104c227ddb2453c2b Mon Sep 17 00:00:00 2001 From: Nord1cWarr1or <47604048+Nord1cWarr1or@users.noreply.github.com> Date: Sat, 25 Apr 2020 10:27:31 +0400 Subject: [PATCH] Add files via upload --- addons/amxmodx/data/afk_protection.txt | 22 + addons/amxmodx/scripting/AFK-Protection.sma | 548 ++++ .../scripting/include/afk_protection.inc | 44 + .../amxmodx/scripting/include/msgstocks.inc | 2895 +++++++++++++++++ sprites/afk/afk.spr | Bin 0 -> 263274 bytes 5 files changed, 3509 insertions(+) create mode 100644 addons/amxmodx/data/afk_protection.txt create mode 100644 addons/amxmodx/scripting/AFK-Protection.sma create mode 100644 addons/amxmodx/scripting/include/afk_protection.inc create mode 100644 addons/amxmodx/scripting/include/msgstocks.inc create mode 100644 sprites/afk/afk.spr diff --git a/addons/amxmodx/data/afk_protection.txt b/addons/amxmodx/data/afk_protection.txt new file mode 100644 index 0000000..03d6625 --- /dev/null +++ b/addons/amxmodx/data/afk_protection.txt @@ -0,0 +1,22 @@ +[en] +AFKPROTECTION_CVAR_EFFECTS = Effects for afk player^na - transparency^nb - screenfade^nc - icon on a top +AFKPROTECTION_CVAR_TIME = Time (in seconds) before a player turns on his defense +AFKPROTECTION_CVAR_SCREENFADE_AMOUNT = Screenfade amount +AFKPROTECTION_CVAR_RANDOM_SCREENFADE_COLOR = Random screenfade color^n0 - off^n1 - on +AFKPROTECTION_CVAR_MESSAGE = Messages about enter/exit afk mode^n0 - off^n1 - chat^n2 - hud^n3 - DHUD^n4 - center +AFKPROTECTION_CHAT_AFK_ON = You went into AFK mode +AFKPROTECTION_CHAT_AFK_OFF = You're out of AFK mode +AFKPROTECTION_CHAT_COLOR_AFK_ON = ^4* ^1You ^3went ^1into AFK mode. +AFKPROTECTION_CHAT_COLOR_AFK_OFF = ^4* ^1You ^3are out ^1of AFK mode. + + +[ru] +AFKPROTECTION_CVAR_EFFECTS = Эффекты игрока в афк^na - прозрачность^nb - затемнение экрана^nc - иконка над головой +AFKPROTECTION_CVAR_TIME = Время (в секундах) до того, как игроку будет включена защита +AFKPROTECTION_CVAR_SCREENFADE_AMOUNT = Глубина затемнения экрана +AFKPROTECTION_CVAR_RANDOM_SCREENFADE_COLOR = Случайный цвет затемнения экрана^n0 - выключено^n1 - включено +AFKPROTECTION_CVAR_MESSAGE = Сообщения о входе/выходе в режим афк^n0 - выключено^n1 - чат^n2 - hud^n3 - DHUD^n4 - центр +AFKPROTECTION_CHAT_AFK_ON = Вы перешли в режим AFK +AFKPROTECTION_CHAT_AFK_OFF = Вы вышли из режима AFK +AFKPROTECTION_CHAT_COLOR_AFK_ON = ^4* ^1Вы ^3перешли ^1в режим афк. +AFKPROTECTION_CHAT_COLOR_AFK_OFF = ^4* ^1Вы ^3вышли ^1из режима афк. \ No newline at end of file diff --git a/addons/amxmodx/scripting/AFK-Protection.sma b/addons/amxmodx/scripting/AFK-Protection.sma new file mode 100644 index 0000000..9805831 --- /dev/null +++ b/addons/amxmodx/scripting/AFK-Protection.sma @@ -0,0 +1,548 @@ +#include +#include +#include +#include +#include +#include + +new const PLUGIN_VERSION[] = "3.0.0"; + +#define GetCvarDesc(%0) fmt("%L", LANG_SERVER, %0) + +enum _:XYZ { Float:X, Float:Y, Float:Z }; + +enum _:AFKEffectsFlags (<<=1) +{ + Effects_Transparency = 1, + Effects_ScreenFade, + Effects_Icon +}; + +enum _:Cvars +{ + EFFECTS[3], + AFK_TIME, + SCREENFADE_AMOUNT, + RANDOM_SCREENFADE_COLOR, + MESSAGE +}; + +const TASKID__AFK_CHECK = 1500; + +const Float:CHECK_FREQUENCY = 0.5; +const Float:ICON_HIGHER = 55.0; + +new const g_szIconClassname[] = "afk_icon"; + +new Float:g_flPlayerOrigin[MAX_PLAYERS + 1][XYZ]; +new Float:g_flPlayerViewAngle[MAX_PLAYERS + 1][XYZ]; +new bool:g_bIsPlayerAFK[MAX_PLAYERS + 1]; +new bool:g_bIsPlayerBot[MAX_PLAYERS + 1]; +new bool:g_bIsPlayerOffProtect[MAX_PLAYERS + 1]; +new g_iPlayerTime[MAX_PLAYERS + 1]; +new g_iPlayerIcon[MAX_PLAYERS + 1] = { NULLENT, ... }; +new g_pCvarValue[Cvars]; +new g_pCvarEffects; +new g_iSycnHudObj; + +new const g_szAFKIconPath[] = "sprites/afk/afk.spr"; // Path to sprite or model of AFK icon + +#define AUTO_CONFIG // Comment out if you don't want the plugin config to be created automatically in "configs/plugins" + +public plugin_init() +{ + register_plugin("AFK Protection", PLUGIN_VERSION, "Nordic Warrior"); + + RegisterHookChain(RG_CBasePlayer_Spawn, "RG_OnPlayerSpawn_Post", true); + RegisterHookChain(RG_CBasePlayer_Killed, "RG_OnPlayerKilled_Post", true); + + register_dictionary("afk_protection.txt"); + + CreateCvars(); + + #if defined AUTO_CONFIG + AutoExecConfig(true, "AFKProtection"); + #endif + + g_iSycnHudObj = CreateHudSyncObj(); + + hook_cvar_change(g_pCvarEffects, "OnChangeCvarEffects"); +} + +public plugin_precache() +{ + if(file_exists(g_szAFKIconPath)) + { + precache_model(g_szAFKIconPath); + } + else + { + set_fail_state("File '%s' not found!", g_szAFKIconPath); + } +} + +public plugin_natives() +{ + register_native("apr_get_player_afk", "native_apr_get_player_afk"); + register_native("apr_set_player_afk", "native_apr_set_player_afk"); + register_native("apr_get_player_status", "native_apr_get_player_status"); + register_native("apr_set_player_status", "native_apr_set_player_status"); +} + +public client_putinserver(id) +{ + if(is_user_bot(id)) + { + g_bIsPlayerBot[id] = true; + } +} + +public client_disconnected(id) +{ + ResetCounters(id, true, true); +} + +public RG_OnPlayerSpawn_Post(const id) +{ + if(!is_user_alive(id) || g_bIsPlayerBot[id] || g_bIsPlayerOffProtect[id]) + return; + + remove_task(id + TASKID__AFK_CHECK); + + if(g_bIsPlayerAFK[id]) + { + SetScreenFade(id); + rg_set_rendering(id, kRenderFxNone, 0, 0, 0, kRenderTransAlpha, 120); + + if(g_iPlayerIcon[id] != NULLENT) + { + RemoveIcon(id); + } + } + + RequestFrame("OnNextFrame", id); +} + +public RG_OnPlayerKilled_Post(const id, const iAttacker, iGib) +{ + if(!g_bIsPlayerAFK[id] || !is_user_connected(id)) + return; + + ResetCounters(id); +} + +public OnNextFrame(const id) +{ + if(get_entvar(id, var_flags) & FL_ONGROUND) + { + StartCheck(id); + } + else + { + RequestFrame("OnNextFrame", id); + } +} + +public StartCheck(const id) +{ + if(!is_user_alive(id)) + return; + + if(g_bIsPlayerAFK[id]) + { + set_entvar(id, var_takedamage, DAMAGE_NO); + set_entvar(id, var_solid, SOLID_NOT); + set_member(id, m_bIsDefusing, true); + + CreateIcon(id); + } + + get_entvar(id, var_origin, g_flPlayerOrigin[id]); + get_entvar(id, var_angles, g_flPlayerViewAngle[id]); + + AFKCheck(id); + + set_task_ex(CHECK_FREQUENCY, "AFKCheck", id + TASKID__AFK_CHECK, .flags = SetTask_Repeat); +} + +public AFKCheck(id) +{ + id -= TASKID__AFK_CHECK; + + if(!is_user_alive(id)) + return; + + static Float:flPlayerOrigin[XYZ], Float:flPlayerViewAngle[XYZ]; + + get_entvar(id, var_origin, flPlayerOrigin); + get_entvar(id, var_angles, flPlayerViewAngle); + + if(xs_vec_equal(flPlayerOrigin, g_flPlayerOrigin[id]) && xs_vec_equal(flPlayerViewAngle, g_flPlayerViewAngle[id]) \ + && !get_entvar(id, var_button)) + { + if(!g_bIsPlayerAFK[id] && get_entvar(id, var_waterlevel) <= 2 && get_entvar(id, var_takedamage) > DAMAGE_NO) + { + g_iPlayerTime[id]++; + } + + if(g_iPlayerTime[id] >= g_pCvarValue[AFK_TIME] / CHECK_FREQUENCY) + { + g_bIsPlayerAFK[id] = true; + g_iPlayerTime[id] = 0; + + ToggleAFKProtection(id); + SendMessage(id); + } + } + else + { + if(g_bIsPlayerAFK[id]) + { + g_bIsPlayerAFK[id] = false; + + ToggleAFKProtection(id); + SendMessage(id); + } + g_iPlayerTime[id] = 0; + } + + xs_vec_copy(flPlayerOrigin, g_flPlayerOrigin[id]); + xs_vec_copy(flPlayerViewAngle, g_flPlayerViewAngle[id]); +} + +ToggleAFKProtection(const id) +{ + set_entvar(id, var_takedamage, g_bIsPlayerAFK[id] ? DAMAGE_NO : DAMAGE_AIM); + set_entvar(id, var_solid, g_bIsPlayerAFK[id] ? SOLID_NOT : SOLID_SLIDEBOX); + set_member(id, m_bIsDefusing, g_bIsPlayerAFK[id] ? true : false); + + ToggleEffects(id); +} + +ToggleEffects(const id) +{ + new iFlagsEffects = read_flags(g_pCvarValue[EFFECTS]); + + if(iFlagsEffects & Effects_Transparency) + { + if(g_bIsPlayerAFK[id]) + { + rg_set_rendering(id, kRenderFxNone, 0, 0, 0, kRenderTransAlpha, 120); + } + else + { + rg_set_rendering(id, kRenderFxNone, 0, 0, 0, kRenderNormal, 0); + } + } + if(iFlagsEffects & Effects_ScreenFade) + { + if(g_bIsPlayerAFK[id]) + { + SetScreenFade(id); + } + else + { + UnsetScreenFade(id); + } + } + if(iFlagsEffects & Effects_Icon) + { + if(g_bIsPlayerAFK[id] && g_iPlayerIcon[id] == NULLENT) + { + CreateIcon(id); + } + else if(!g_bIsPlayerAFK[id] && g_iPlayerIcon[id] != NULLENT) + { + RemoveIcon(id); + } + } +} + +SendMessage(const id) +{ + SetGlobalTransTarget(id); + + switch(g_pCvarValue[MESSAGE]) + { + case 1: client_print_color(id, g_bIsPlayerAFK[id] ? print_team_blue : print_team_red, "%l", g_bIsPlayerAFK[id] ? "AFKPROTECTION_CHAT_COLOR_AFK_ON" : "AFKPROTECTION_CHAT_COLOR_AFK_OFF"); + case 2: + { + set_hudmessage(0, 200, 200, -1.0, 0.1, 0, 1.0, 3.0, 0.1, 0.2); + ShowSyncHudMsg(id, g_iSycnHudObj, "%l", g_bIsPlayerAFK[id] ? "AFKPROTECTION_CHAT_AFK_ON" : "AFKPROTECTION_CHAT_AFK_OFF"); + } + case 3: + { + set_dhudmessage(0, 200, 200, -1.0, 0.2, 0, 1.0, 3.0, 0.1, 0.2) + clear_dhudmessage(); + show_dhudmessage(id, "%l", g_bIsPlayerAFK[id] ? "AFKPROTECTION_CHAT_AFK_ON" : "AFKPROTECTION_CHAT_AFK_OFF"); + } + case 4: client_print(id, print_center, "%l", g_bIsPlayerAFK[id] ? "AFKPROTECTION_CHAT_AFK_ON" : "AFKPROTECTION_CHAT_AFK_OFF"); + } +} + +CreateIcon(const id) +{ + new iEnt = rg_create_entity("env_sprite"); + + new Float:flPlayerOrigin[XYZ]; + get_entvar(id, var_origin, flPlayerOrigin); + + flPlayerOrigin[2] += ICON_HIGHER; + + set_entvar(iEnt, var_classname, g_szIconClassname); + engfunc(EngFunc_SetModel, iEnt, g_szAFKIconPath); + set_entvar(iEnt, var_scale, 0.5); + set_entvar(iEnt, var_rendermode, kRenderTransAdd); + set_entvar(iEnt, var_renderamt, 100.0); + set_entvar(iEnt, var_framerate, 10.0); + set_entvar(iEnt, var_origin, flPlayerOrigin); + set_entvar(iEnt, var_spawnflags, SF_SPRITE_STARTON); + + g_iPlayerIcon[id] = iEnt; + + dllfunc(DLLFunc_Spawn, iEnt); +} + +RemoveIcon(const id) +{ + set_entvar(g_iPlayerIcon[id], var_flags, FL_KILLME); + g_iPlayerIcon[id] = NULLENT; +} + +ResetCounters(const id, bool:bDisconnected = false, bStopTask = false) +{ + new bool:bOldState = g_bIsPlayerAFK[id]; + + g_bIsPlayerAFK[id] = false; + + g_iPlayerTime[id] = 0; + + for(new i; i < XYZ; i++) + { + g_flPlayerOrigin[id][i] = 0.0; + g_flPlayerViewAngle[id][i] = 0.0; + } + + if(bStopTask) + { + remove_task(id + TASKID__AFK_CHECK); + } + + if(!bDisconnected) + { + if(bOldState) + { + ToggleAFKProtection(id); + } + } + else + { + g_bIsPlayerBot[id] = false; + + if(g_iPlayerIcon[id] != NULLENT) + { + RemoveIcon(id); + } + } +} + +SetScreenFade(const id) +{ + fade_user_screen(id, + .duration = 0.0, + .fadetime = 0.0, + .flags = ScreenFade_StayOut, + .r = g_pCvarValue[RANDOM_SCREENFADE_COLOR] ? random(255) : 0, + .g = g_pCvarValue[RANDOM_SCREENFADE_COLOR] ? random(255) : 0, + .b = g_pCvarValue[RANDOM_SCREENFADE_COLOR] ? random(255) : 0, + .a = g_pCvarValue[SCREENFADE_AMOUNT]); +} + +UnsetScreenFade(const id) +{ + fade_user_screen(id, + .duration = 0.0, + .fadetime = g_pCvarValue[RANDOM_SCREENFADE_COLOR] ? 0.0 : 1.0, + .flags = ScreenFade_FadeIn, + .r = 0, + .g = 0, + .b = 0, + .a = g_pCvarValue[SCREENFADE_AMOUNT]); +} + +public OnChangeCvarEffects(pCvar, const szOldValue[], const szNewValue[]) +{ + new iOldFlagsEffects = read_flags(szOldValue); + new iNewFlagsEffects = read_flags(szNewValue); + + new bool:bAddTransparency, bool:bDelTransparency; + new bool:bAddScreenFade, bool:bDelScreenFade; + new bool:bAddIcon, bool:bDelIcon; + + if(iOldFlagsEffects & Effects_Transparency && !(iNewFlagsEffects & Effects_Transparency)) + { + bDelTransparency = true; + } + else if(!(iOldFlagsEffects & Effects_Transparency) && iNewFlagsEffects & Effects_Transparency) + { + bAddTransparency = true; + } + + if(iOldFlagsEffects & Effects_ScreenFade && !(iNewFlagsEffects & Effects_ScreenFade)) + { + bDelScreenFade = true; + } + else if(!(iOldFlagsEffects & Effects_ScreenFade) && iNewFlagsEffects & Effects_ScreenFade) + { + bAddScreenFade = true; + } + + if(iOldFlagsEffects & Effects_Icon && !(iNewFlagsEffects & Effects_Icon)) + { + bDelIcon = true; + } + else if(!(iOldFlagsEffects & Effects_Icon) && iNewFlagsEffects & Effects_Icon) + { + bAddIcon = true; + } + + for(new id = 1; id <= MaxClients; id++) + { + if(!g_bIsPlayerAFK[id]) + continue; + + if(bDelTransparency) + rg_set_rendering(id, kRenderFxNone, 0, 0, 0, kRenderNormal, 0); + else if(bAddTransparency) + rg_set_rendering(id, kRenderFxNone, 0, 0, 0, kRenderTransAlpha, 120); + + if(bDelScreenFade) + UnsetScreenFade(id); + else if(bAddScreenFade) + SetScreenFade(id); + + if(bDelIcon) + RemoveIcon(id); + else if(bAddIcon) + CreateIcon(id); + } +} + +public bool:native_apr_get_player_afk(iPluginID, iParams) +{ + enum { id = 1 }; + + return bool:g_bIsPlayerAFK[get_param(id)]; +} + +public native_apr_set_player_afk(iPluginID, iParams) +{ + enum { iPlayer = 1, _bSet }; + + new id = get_param(iPlayer); + new bool:bSet = bool:get_param(_bSet); + + if(bSet && !g_bIsPlayerAFK[id] && !g_bIsPlayerOffProtect[id]) + { + g_bIsPlayerAFK[id] = true; + ToggleAFKProtection(id); + + return true; + } + else if(!bSet && g_bIsPlayerAFK[id]) + { + ResetCounters(id); + ToggleAFKProtection(id); + + return true; + } + + return false; +} + +public bool:native_apr_get_player_status(iPluginID, iParams) +{ + enum { id = 1 }; + + return bool:g_bIsPlayerOffProtect[get_param(id)]; +} + +public native_apr_set_player_status(iPluginID, iParams) +{ + enum { iPlayer = 1, _bSet }; + + new id = get_param(iPlayer); + new bool:bSet = bool:get_param(_bSet); + + if(bSet) + { + g_bIsPlayerOffProtect[id] = true; + + ResetCounters(id, false, true); + + if(g_bIsPlayerAFK[id]) + { + g_bIsPlayerAFK[id] = false; + ToggleAFKProtection(id); + } + } + else + { + g_bIsPlayerOffProtect[id] = false; + + RG_OnPlayerSpawn_Post(id); + } + + return bSet; +} + +public CreateCvars() +{ + bind_pcvar_string(g_pCvarEffects = create_cvar("afk_effects", + .string = "abc", + .description = GetCvarDesc("AFKPROTECTION_CVAR_EFFECTS")), + g_pCvarValue[EFFECTS], charsmax(g_pCvarValue[EFFECTS])); + + bind_pcvar_num(create_cvar("afk_time", "15", + .description = GetCvarDesc("AFKPROTECTION_CVAR_TIME")), + g_pCvarValue[AFK_TIME]); + + bind_pcvar_num(create_cvar("afk_screenfade_amount", "110", + .description = GetCvarDesc("AFKPROTECTION_CVAR_SCREENFADE_AMOUNT")), + g_pCvarValue[SCREENFADE_AMOUNT]); + + bind_pcvar_num(create_cvar("afk_random_screenfade_color", "0", + .description = GetCvarDesc("AFKPROTECTION_CVAR_RANDOM_SCREENFADE_COLOR")), + g_pCvarValue[RANDOM_SCREENFADE_COLOR]); + + bind_pcvar_num(create_cvar("afk_message", "0", + .description = GetCvarDesc("AFKPROTECTION_CVAR_MESSAGE")), + g_pCvarValue[MESSAGE]); +} + +public OnConfigsExecuted() +{ + register_cvar("AFKProtection_version", PLUGIN_VERSION, FCVAR_SERVER|FCVAR_SPONLY|FCVAR_UNLOGGED); +} + +stock clear_dhudmessage() +{ + for(new i = 1; i < 8; i++) + { + show_dhudmessage(0, ""); + } +} + +stock rg_set_rendering(const id, const iRenderFx, const R, const G, const B, const iRenderMode, const iRenderAmount) +{ + new Float:flRenderColor[3]; + + flRenderColor[0] = float(R); + flRenderColor[1] = float(G); + flRenderColor[2] = float(B); + + set_entvar(id, var_renderfx, iRenderFx); + set_entvar(id, var_rendercolor, flRenderColor); + set_entvar(id, var_rendermode, iRenderMode); + set_entvar(id, var_renderamt, float(iRenderAmount)); +} \ No newline at end of file diff --git a/addons/amxmodx/scripting/include/afk_protection.inc b/addons/amxmodx/scripting/include/afk_protection.inc new file mode 100644 index 0000000..bdf78a4 --- /dev/null +++ b/addons/amxmodx/scripting/include/afk_protection.inc @@ -0,0 +1,44 @@ +#if defined _afk_protection_included + #endinput +#endif + +#define _afk_protection_included + +/** + * Checks if player is has AFK protection active or not. + * + * @param id Player index + * + * @return True, if player is AFK, false otherwise + */ +native booL:apr_get_player_afk(id); + +/** + * Activate or deactivate player's AFK protection. + * + * @param id Player index + * @param bSet True - enable protection. false - disable + * + * @return True if AFK protection has sucsessfuly activateed or deactivated, + * false otherwise. + */ +native apr_set_player_afk(id, bool:bSet); + +/** + * Checks if player is has OFF AFK protection or not. + * + * @param id Player index + * + * @return True, if player is OFF AFK protection, false otherwise + */ +native booL:apr_get_player_status(id); + +/** + * Turn ON or OFF checks for afk for player. + * + * @param id Player index + * @param bSet True - disable checks. false - enable + * + * @return Player's status + */ +native apr_set_player_status(id, bool:bSet); \ No newline at end of file diff --git a/addons/amxmodx/scripting/include/msgstocks.inc b/addons/amxmodx/scripting/include/msgstocks.inc new file mode 100644 index 0000000..2ad2df9 --- /dev/null +++ b/addons/amxmodx/scripting/include/msgstocks.inc @@ -0,0 +1,2895 @@ +// vim: set ts=4 sw=4 tw=99 noet: +// +// AMX Mod X, based on AMX Mod by Aleksander Naszko ("OLO"). +// Copyright (C) The AMX Mod X Development Team. +// +// This software is licensed under the GNU General Public License, version 3 or higher. +// Additional exceptions apply. For full license details, see LICENSE.txt or visit: +// https://alliedmods.net/amxmodx-license + +// +// Message Stocks +// + +#if defined _msgnatives_included + #endinput +#endif + +#if defined _msgstocks_included + #endinput +#endif + +#define _msgstocks_included + +#define MSGSTOCKS_VERSION 1.1 + +/** + * @section Normal message stocks + */ + +/** + * Temporarily draws HUD numerical ammo amount and corresponding ammo + * HUD icon in the middle of the right side of the screen. + * + * @note Draw time depends on the hud_drawhistory_time client cvar value. + * + * @param id Client index or 0 for all clients + * @param ammoid Ammunition id + * @param amount Ammunition amount + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "id" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock draw_ammo_pickup_icon(id, ammoid, amount, bool:reliable = true) +{ + if(id && !is_user_connected(id)) + return 0; + + static MSG_AmmoPickup; + + if(!MSG_AmmoPickup) + MSG_AmmoPickup = get_user_msgid("AmmoPickup"); + + message_begin(get_msg_destination(id, reliable), MSG_AmmoPickup, .player = id); + write_byte(ammoid); + write_byte(amount); + message_end(); + + return 1; +} + +/** + * Temporarily draws a corresponding item HUD icon in the middle of the + * right side of the screen. + * + * @note This stock isn't available in Day of Defeat. + * @note Draw time depends on the hud_drawhistory_time client cvar value. + * @note A list of all icons and screenshots of them can be found here: + * http://doktor.haze.free.fr/counter-strike/sprites_screens/index.php + * + * @param id Client index or 0 for all clients + * @param itemname Item name + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "id" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock draw_item_pickup_icon(id, itemname[], bool:reliable = true) +{ + if(id && !is_user_connected(id)) + return 0; + + static MSG_ItemPickup; + + if(!MSG_ItemPickup) + MSG_ItemPickup = get_user_msgid("ItemPickup"); + + message_begin(get_msg_destination(id, reliable), MSG_ItemPickup, .player = id); + write_string(itemname); + message_end(); + + return 1; +} + +/** + * Temporarily draws the corresponding weapon HUD icon in the middle of the + * right side of the screen. + * + * @note Draw time depends on the hud_drawhistory_time client cvar value. + * + * @param id Client index or 0 for all clients + * @param weaponid Weapon id + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "id" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock draw_weapon_pickup_icon(id, weaponid, bool:reliable = true) +{ + if(id && !is_user_connected(id)) + return 0; + + static MSG_WeapPickup; + + if(!MSG_WeapPickup) + MSG_WeapPickup = get_user_msgid("WeapPickup"); + + message_begin(get_msg_destination(id, reliable), MSG_WeapPickup, .player = id); + write_byte(weaponid); + message_end(); + + return 1; +} + +/** + * Flags used in draw_status_icon() + */ +enum StatusIconFlags +{ + StatusIcon_Hide = 0, + StatusIcon_Show, + StatusIcon_Flash +} + +/** + * Draws a specified status HUD icon. + * + * @note This stock is available only in the following games: + * Counter-Strike + * Counter-Strike: Condition Zero + * Half-Life: Opposing Force + * Team Fortress Classic + * @note A list of all icons and screenshots of them can be found here: + * http://doktor.haze.free.fr/counter-strike/sprites_screens/index.php + * + * @param id Client index or 0 for all clients + * @param sprite Sprite name (valid names are listed in sprites/hud.txt) + * @param status Valid status values: + * StatusIcon_Hide - hides the status icon + * StatusIcon_Show - shows the status icon + * StatusIcon_Flash - flashes the status icon + * @param r Red color amount (0 - 255) + * @param g Green color amount (0 - 255) + * @param b Blue color amount (0 - 255) + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "id" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock draw_status_icon(id, sprite[] = "", StatusIconFlags:status = StatusIcon_Hide, r = 0, g = 0, b = 0, bool:reliable = true) +{ + if(id && !is_user_connected(id)) + return 0; + + static MSG_StatusIcon; + + if(!MSG_StatusIcon) + MSG_StatusIcon = get_user_msgid("StatusIcon"); + + message_begin(get_msg_destination(id, reliable), MSG_StatusIcon, .player = id); + write_byte(_:status); + write_string(sprite); + + if(status) + { + write_byte(r); + write_byte(g); + write_byte(b); + } + + message_end(); + return 1; +} + +/** + * Train controls used in draw_train_controls() + */ +enum TrainControlFlags +{ + TrainControls_None = 0, + TrainControls_Neutral, + TrainControls_Slow, + TrainControls_Medium, + TrainControls_Maximum, + TrainControls_Reverse +} + +/** + * Displays the speed bar used for controlling a train. + * + * @note This stock isn't available in Day of Defeat. + * + * @param id Client index or 0 for all clients + * @param speed Train speed: + * TrainControls_None + * TrainControls_Neutral + * TrainControls_Slow + * TrainControls_Medium + * TrainControls_Maximum + * TrainControls_Reverse + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "id" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock draw_train_controls(id, TrainControlFlags:speed = TrainControls_None, bool:reliable = true) +{ + if(id && !is_user_connected(id)) + return 0; + + static MSG_Train; + + if(!MSG_Train) + MSG_Train = get_user_msgid("Train"); + + message_begin(get_msg_destination(id, reliable), MSG_Train, .player = id); + write_byte(_:speed); + message_end(); + + return 1; +} + +/** + * Sends the geiger signal that notifies the player of nearby radiation level. + * + * @note This stock isn't available in Day of Defeat. + * + * @param id Client index or 0 for all clients + * @param distance Signal distance + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "id" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock send_geiger_signal(id, distance, bool:reliable = true) +{ + if(id && !is_user_connected(id)) + return 0; + + static MSG_Geiger; + + if(!MSG_Geiger) + MSG_Geiger = get_user_msgid("Geiger"); + + message_begin(get_msg_destination(id, reliable), MSG_Geiger, .player = id); + write_byte(distance); + message_end(); + + return 1; +} + +/** + * Flags used in hide_hud_elements() + */ +enum HideElemenentFlags (<<= 1) +{ + HideElement_None = 0, + HideElement_Cross_Ammo_WPNList = 1, + HideElement_Flashlight, + HideElement_All, + HideElement_Radar_Health_Armor, + HideElement_Timer, + HideElement_Money, + HideElement_Crosshair +} + +/** + * Hides specific elements from the HUD. + * + * @note The symbol + means that an additional crosshair will be drawn. + * This crosshair looks not like the regular one, but like the one that + * is drawn in spectator mode. You can remove this crosshair by setting + * the "noadd" argument to "true". + * + * @param id Client index or 0 for all clients + * @param elements HUD elements to hide. The names are self-explanatory: + * HideElement_Cross_Ammo_WPNList + * HideElement_Flashlight (+) + * HideElement_All + * HideElement_Radar_Health_Armor (+) + * HideElement_Timer (+) + * HideElement_Money (+) + * HideElement_Crosshair + * @param noadd If set to false and the chosen element names have + * a "+" sign, an additional crosshair will be drawn. + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "id" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock hide_hud_elements(id, HideElemenentFlags:elements, bool:noadd = true, bool:reliable = true) +{ + if(id && !is_user_connected(id)) + return 0; + + static MSG_HideWeapon; + + if(!MSG_HideWeapon) + MSG_HideWeapon = get_user_msgid("HideWeapon"); + + new iDest = get_msg_destination(id, reliable); + + message_begin(iDest, MSG_HideWeapon, .player = id); + write_byte(_:elements); + message_end(); + + if(noadd) + { + static MSG_Crosshair; + + if(!MSG_Crosshair) + MSG_Crosshair = get_user_msgid("Crosshair"); + + message_begin(iDest, MSG_Crosshair, .player = id); + write_byte(0); + message_end(); + } + + return 1; +} + +/** + * Flags used in fade_user_screen() + */ +enum ScreenFadeFlags +{ + ScreenFade_FadeIn = 0x0000, + ScreenFade_FadeOut = 0x0001, + ScreenFade_Modulate = 0x0002, + ScreenFade_StayOut = 0x0004 +} + +/** + * Fades the client's screen. + * + * @param id Client index or 0 for all clients + * @param duration How long (in seconds) the fade is going to stay + * on the screen (0 - 16) + * @param fadetime How many seconds is the fade going to fade in (0 - 16) + * @param flags Screen fade flags: + * ScreenFade_FadeIn - default + * ScreenFade_FadeOut - fade out (not in) + * ScreenFade_Modulate - modulate (don't blend) + * ScreenFade_StayOut - ignores the duration and stays faded out until a new ScreenFade messages is received + * @param r Red color amount (0 - 255) + * @param g Green color amount (0 - 255) + * @param b Blue color amount (0 - 255) + * @param a Color alpha (brightness) (0 - 255) + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "id" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock fade_user_screen(id, Float:duration = 1.0, Float:fadetime = 1.0, ScreenFadeFlags:flags = ScreenFade_FadeIn, r = 0, g = 0, b = 255, a = 75, bool:reliable = true) +{ + if(id && !is_user_connected(id)) + return 0; + + static MSG_ScreenFade; + + if(!MSG_ScreenFade) + MSG_ScreenFade = get_user_msgid("ScreenFade"); + + message_begin(get_msg_destination(id, reliable), MSG_ScreenFade, .player = id); + write_short(float_to_short(fadetime)); + write_short(float_to_short(duration)); + write_short(_:flags); + write_byte(r); + write_byte(g); + write_byte(b); + write_byte(a); + message_end(); + + return 1; +} + +/** + * Shakes the client's screen. + * + * @param id Client index or 0 for all clients + * @param amplitude Shake amplitude (0 - 16) + * @param duration Shake duration (in seconds) (0 - 16) + * @param frequency Delay between each shake (0 - 16) + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "id" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock shake_user_screen(id, Float:amplitude = 3.0, Float:duration = 3.0, Float:frequency = 1.0, bool:reliable = true) +{ + if(id && !is_user_connected(id)) + return 0; + + static MSG_ScreenShake; + + if(!MSG_ScreenShake) + MSG_ScreenShake = get_user_msgid("ScreenShake"); + + message_begin(get_msg_destination(id, reliable), MSG_ScreenShake, .player = id); + write_short(float_to_short(amplitude)); + write_short(float_to_short(duration)); + write_short(float_to_short(frequency)); + message_end(); + + return 1; +} + +/** + * Changes the client's field of view (FOV). + * + * @note Setting the "fov" argument below 45 will also draw a sniper scope. + * + * @param id Client index or 0 for all clients + * @param fov Field of view degrees (0 - 255) + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "id" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock set_user_fov(id, fov = 0, bool:reliable = true) +{ + if(id && !is_user_connected(id)) + return 0; + + static MSG_SetFOV; + + if(!MSG_SetFOV) + MSG_SetFOV = get_user_msgid("SetFOV"); + + message_begin(get_msg_destination(id, reliable), MSG_SetFOV, .player = id); + write_byte(fov); + message_end(); + + return 1; +} + +/** + * @endsection + */ + +/** + * @section Counter-Strike message stocks + */ + +/** + * Draws a HUD progress bar which is filled from 0% to 100% for the given + * amount of seconds. Once the bar is fully filled it will be removed from + * the screen automatically. + * + * @note If the "startpercent" argument is greater than 0, the bar will be + * filled from that amount of percentage instead of starting from 0%. + * + * @param id Client index or 0 for all clients + * @param duration How long (in seconds) until the bar is fully filled + * @param startpercent Bar starting percentage (0-100) + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "id" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock cs_draw_progress_bar(id, duration, startpercent = 0, bool:reliable = true) +{ + if(id && !is_user_connected(id)) + return 0; + + if(startpercent) + { + static MSG_BarTime2; + + if(!MSG_BarTime2) + MSG_BarTime2 = get_user_msgid("BarTime2"); + + message_begin(get_msg_destination(id, reliable), MSG_BarTime2, .player = id); + } + else + { + static MSG_BarTime; + + if(!MSG_BarTime) + MSG_BarTime = get_user_msgid("BarTime"); + + message_begin(get_msg_destination(id, reliable), MSG_BarTime, .player = id); + } + + write_short(duration); + + if(startpercent) + write_short(startpercent); + + message_end(); + return 1; +} + +/** + * Plays a generic reload sound. + * + * @param id Client index or 0 for all clients + * @param shotgun If set to true, it will play "weapons/generic_shot_reload.wav", + * otherwise it will play "weapons/generic_reload.wav". + * @param volume Volume amount (0 - 255) + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "id" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock cs_play_reload_sound(id, bool:shotgun = false, volume = 100, bool:reliable = true) +{ + if(id && !is_user_connected(id)) + return 0; + + static MSG_ReloadSound; + + if(!MSG_ReloadSound) + MSG_ReloadSound = get_user_msgid("ReloadSound"); + + message_begin(get_msg_destination(id, reliable), MSG_ReloadSound, .player = id); + write_byte(volume); + write_byte(!shotgun); + message_end(); + + return 1; +} + +/** + * Displays a sprite to the right side of the round timer. + * + * @note A list of all icons and screenshots of them can be found here: + * http://doktor.haze.free.fr/counter-strike/sprites_screens/index.php + * + * @param id Client index or 0 for all clients + * @param active If set to 0, it will remove the scenario icon and + * ignore all other arguments. Always set this to 1 + * if you want to use any of the other arguments + * @param sprite Sprite name (valid names are listed in sprites.hud.txt) + * @param alpha Sprite alpha (100-255) + * @param flashrate If nonzero, the sprite will flash from the given alpha + * in the "alpha" argument to an alpha of 100, at a rate + * set in this argument + * @param flashdelay Delay (in seconds) between each flash + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "id" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock cs_set_hud_icon(id, active = 0, sprite[] = "", alpha = 100, flashrate = 0, flashdelay = 0, bool:reliable = true) +{ + if(id && !is_user_connected(id)) + return 0; + + static MSG_Scenario; + + if(!MSG_Scenario) + MSG_Scenario = get_user_msgid("Scenario"); + + message_begin(get_msg_destination(id, reliable), MSG_Scenario, .player = id); + write_byte(active); + + if(active) + { + write_string(sprite); + write_byte(alpha); + } + + if(flashrate) + { + write_short(flashrate); + write_short(flashdelay); + } + + message_end(); + return 1; +} + +/** + * Creates/Hides the shadow beneath players. + * + * @note This stock can't be used to set shadow to a specific player. It can + * only set the shadow that a specific player sees for all other players. + * + * @param id Client index or 0 for all clients + * @param shadowid Sprite index or 0 to disable the shadow + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "id" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock cs_set_user_shadow(id, shadowid = 0, bool:reliable = true) +{ + if(id && !is_user_connected(id)) + return 0; + + static MSG_ShadowIdx; + + if(!MSG_ShadowIdx) + MSG_ShadowIdx = get_user_msgid("ShadowIdx"); + + message_begin(get_msg_destination(id, reliable), MSG_ShadowIdx, .player = id); + write_long(shadowid); + message_end(); + + return 1; +} + +/** + * @endsection + */ + +/** + * @section Stocks using temporary entities (SVC_TEMPENTITY) + */ + +/** + * Creates a beam between two points. + * + * @note A common sprite to use is "sprites/laserbeam.spr" + * @note Video preview of this and all other te_ stocks can be found here: + * https://youtu.be/szW-bSMPuyQ?t=3s + * + * @param startpos Starting coordinates of the beam + * @param endpos Ending coordinates of the beam + * @param sprite The sprite index to use in the beam + * @param startframe The frame to start with in the sprite (0 - 255) + * @param framerate The frame rate to show the sprite at (0 - 255) + * @param life The length of time the beam shall remain (0 - 255) + * @param width The width of the beam (0 - 255) + * @param noise The noise amplitude of the beam, this controls + * the distorsion of the beam (0 - 255) + * @param r Red color amount (0 - 255) + * @param g Green color amount (0 - 255) + * @param b Blue color amount (0 - 255) + * @param a Beam brightness (alpha) (0 - 255) + * @param speed The scroll speed of the beam (0 - 255) + * @param receiver Client index that will be able to see the beam + * or 0 for all clients + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "receiver" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock te_create_beam_between_points(startpos[3], endpos[3], sprite, startframe = 0, framerate = 30, life = 10, width = 10, noise = 0, r = 0, g = 0, b = 255, a = 75, speed = 0, receiver = 0, bool:reliable = true) +{ + if(receiver && !is_user_connected(receiver)) + return 0; + + message_begin(get_msg_destination(receiver, reliable), SVC_TEMPENTITY, .player = receiver); + write_byte(TE_BEAMPOINTS); + write_coord(startpos[0]); + write_coord(startpos[1]); + write_coord(startpos[2]); + write_coord(endpos[0]); + write_coord(endpos[1]); + write_coord(endpos[2]); + write_short(sprite); + write_byte(startframe); + write_byte(framerate); + write_byte(life); + write_byte(width); + write_byte(noise); + write_byte(r); + write_byte(g); + write_byte(b); + write_byte(a); + write_byte(speed); + message_end(); + + return 1; +} + +/** + * Creates a beam between an entity and a point. + * + * @note A common sprite to use is "sprites/laserbeam.spr" + * @note Video preview of this and all other te_ stocks can be found here: + * https://youtu.be/szW-bSMPuyQ?t=20s + * + * @param startent Primary entity id + * @param endpos Ending coordinates of the beam + * @param sprite The sprite index to use in the beam + * @param startframe The frame to start with in the sprite (0 - 255) + * @param framerate The frame rate to show the sprite at (0 - 255) + * @param life The length of time the beam shall remain (0 - 255) + * @param width The width of the beam (0 - 255) + * @param noise The noise amplitude of the beam, this controls + * the distorsion of the beam (0 - 255) + * @param r Red color amount (0 - 255) + * @param g Green color amount (0 - 255) + * @param b Blue color amount (0 - 255) + * @param a Beam brightness (alpha) (0 - 255) + * @param speed The scroll speed of the beam (0 - 255) + * @param receiver Client index that will be able to see the beam + * or 0 for all clients + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "receiver" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock te_create_beam_from_entity(startent, endpos[3], sprite, startframe = 0, framerate = 30, life = 10, width = 10, noise = 0, r = 0, g = 0, b = 255, a = 75, speed = 0, receiver = 0, bool:reliable = true) +{ + if(receiver && !is_user_connected(receiver)) + return 0; + + message_begin(get_msg_destination(receiver, reliable), SVC_TEMPENTITY, .player = receiver); + write_byte(TE_BEAMENTPOINT); + write_short(startent); + write_coord(endpos[0]); + write_coord(endpos[1]); + write_coord(endpos[2]); + write_short(sprite); + write_byte(startframe); + write_byte(framerate); + write_byte(life); + write_byte(width); + write_byte(noise); + write_byte(r); + write_byte(g); + write_byte(b); + write_byte(a); + write_byte(speed); + message_end(); + + return 1; +} + +/** + * Creates a gunshot that consists of a particle effect and a ricochet sound. + * + * @note Video preview of this and all other te_ stocks can be found here: + * https://youtu.be/szW-bSMPuyQ?t=36s + * + * @param position Gunshot coordinates + * @param receiver Client index that will be able to see the gunshot + * or 0 for all clients + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "receiver" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock te_create_gunshot(position[3], receiver = 0, bool:reliable = true) +{ + if(receiver && !is_user_connected(receiver)) + return 0; + + message_begin(get_msg_destination(receiver, reliable), SVC_TEMPENTITY, .player = receiver); + write_byte(TE_GUNSHOT); + write_coord(position[0]); + write_coord(position[1]); + write_coord(position[2]); + message_end(); + + return 1; +} + +/** + * Creates an explosion. + * + * @note A common sprite to use is "sprites/zerogxplode.spr" + * @note Video preview of this and all other te_ stocks can be found here: + * https://youtu.be/szW-bSMPuyQ?t=43s + * + * @param position Position of the explosion + * @param sprite The additive sprite index to use in the explosion + * @param scale The scale of the sprite in the explosion (0 - 255) + * @param framerate The frame rate to show the sprite at (0 - 255) + * @param flags Explosion flags: + * TE_EXPLFLAG_NONE - default Half-Life explosion + * TE_EXPLFLAG_NOADDITIVE - sprite will be drawn opaque + * TE_EXPLFLAG_NODLIGHTS - don't render the dynamic lights + * TE_EXPLFLAG_NOSOUND - don't play the explosion sound + * TE_EXPLFLAG_NOPARTICLES - don't draw the particles + * @param receiver Client index that will be able to see the explosion + * or 0 for all clients + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "receiver" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock te_create_explosion(position[3], sprite, scale = 10, framerate = 30, flags = TE_EXPLFLAG_NONE, receiver = 0, bool:reliable = true) +{ + if(receiver && !is_user_connected(receiver)) + return 0; + + message_begin(get_msg_destination(receiver, reliable), SVC_TEMPENTITY, .player = receiver); + write_byte(TE_EXPLOSION); + write_coord(position[0]); + write_coord(position[1]); + write_coord(position[2]); + write_short(sprite); + write_byte(scale); + write_byte(framerate); + write_byte(flags); + message_end(); + + return 1; +} + +/** + * Creates the Quake "tarbaby" explosion with sound. + * + * @note Video preview of this and all other te_ stocks can be found here: + * https://youtu.be/szW-bSMPuyQ?t=55s + * + * @param position Position of the explosion + * @param receiver Client index that will be able to see the explosion + * or 0 for all clients + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "receiver" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock te_create_tar_explosion(position[3], receiver = 0, bool:reliable = true) +{ + if(receiver && !is_user_connected(receiver)) + return 0; + + message_begin(get_msg_destination(receiver, reliable), SVC_TEMPENTITY, .player = receiver); + write_byte(TE_TAREXPLOSION); + write_coord(position[0]); + write_coord(position[1]); + write_coord(position[2]); + message_end(); + + return 1; +} + +/** + * Creates smoke (a rising alphablend sprite at 30 pps). + * + * @note A common sprite to use is "sprites/steam1.spr" + * @note Video preview of this and all other te_ stocks can be found here: + * https://youtu.be/szW-bSMPuyQ?t=1m2s + * + * @param position Position of the smoke effect + * @param sprite The alphablend sprite index to use for the smoke + * @param scale The scale of the smoke (0 - 255) + * @param framerate The frame rate to show the sprite at (0 - 255) + * @param receiver Client index that will be able to see the smoke + * or 0 for all clients + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "receiver" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock te_create_smoke(position[3], sprite, scale = 10, framerate = 30, receiver = 0, bool:reliable = true) +{ + if(receiver && !is_user_connected(receiver)) + return 0; + + message_begin(get_msg_destination(receiver, reliable), SVC_TEMPENTITY, .player = receiver); + write_byte(TE_SMOKE); + write_coord(position[0]); + write_coord(position[1]); + write_coord(position[2]); + write_short(sprite); + write_byte(scale); + write_byte(framerate); + message_end(); + + return 1; +} + +/** + * Creates a tracer effect from one point to another. + * + * @note Video preview of this and all other te_ stocks can be found here: + * https://youtu.be/szW-bSMPuyQ?t=1m12s + * + * @param startpos Starting position of the tracer + * @param endpos Ending position of the tracer + * @param receiver Client index that will be able to see the tracer + * or 0 for all clients + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "receiver" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock te_create_tracer(startpos[3], endpos[3], receiver = 0, bool:reliable = true) +{ + if(receiver && !is_user_connected(receiver)) + return 0; + + message_begin(get_msg_destination(receiver, reliable), SVC_TEMPENTITY, .player = receiver); + write_byte(TE_TRACER); + write_coord(startpos[0]); + write_coord(startpos[1]); + write_coord(startpos[2]); + write_coord(endpos[0]); + write_coord(endpos[1]); + write_coord(endpos[2]); + message_end(); + + return 1; +} + +/** + * Creates a beam between two entities. + * + * @note A common sprite to use is "sprites/laserbeam.spr" + * @note Video preview of this and all other te_ stocks can be found here: + * https://youtu.be/szW-bSMPuyQ?t=1m26s + * + * @param startent Primary entity id + * @param endent Secondary entity id + * @param sprite The sprite index to use in the beam + * @param startframe The frame to start with in the sprite (0 - 255) + * @param framerate The frame rate to show the sprite at (0 - 255) + * @param life The length of time the beam shall remain (0 - 255) + * @param width The width of the beam (0 - 255) + * @param noise The noise amplitude of the beam, this controls + * the distorsion of the beam (0 - 255) + * @param r Red color amount (0 - 255) + * @param g Green color amount (0 - 255) + * @param b Blue color amount (0 - 255) + * @param a Beam brightness (alpha) (0 - 255) + * @param speed The scroll speed of the beam (0 - 255) + * @param receiver Client index that will be able to see the beam + * or 0 for all clients + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "receiver" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock te_create_beam_between_entities(startent, endent, sprite, startframe = 0, framerate = 30, life = 10, width = 10, noise = 0, r = 0, g = 0, b = 255, a = 75, speed = 0, receiver = 0, bool:reliable = true) +{ + if(receiver && !is_user_connected(receiver)) + return 0; + + message_begin(get_msg_destination(receiver, reliable), SVC_TEMPENTITY, .player = receiver); + write_byte(TE_BEAMENTS); + write_short(startent); + write_short(endent); + write_short(sprite); + write_byte(startframe); + write_byte(framerate); + write_byte(life); + write_byte(width); + write_byte(noise); + write_byte(r); + write_byte(g); + write_byte(b); + write_byte(a); + write_byte(speed); + message_end(); + + return 1; +} + +/** + * Creates 8 random tracers with gravity and a ricochet sprite. + * + * @note Video preview of this and all other te_ stocks can be found here: + * https://youtu.be/szW-bSMPuyQ?t=1m41s + * + * @param position Position of the effect + * @param receiver Client index that will be able to see the effect + * or 0 for all clients + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "receiver" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock te_create_sparks(position[3], receiver = 0, bool:reliable = true) +{ + if(receiver && !is_user_connected(receiver)) + return 0; + + message_begin(get_msg_destination(receiver, reliable), SVC_TEMPENTITY, .player = receiver); + write_byte(TE_SPARKS); + write_coord(position[0]); + write_coord(position[1]); + write_coord(position[2]); + message_end(); + + return 1; +} + +/** + * Creates a Quake-style lava splash. + * + * @note Video preview of this and all other te_ stocks can be found here: + * https://youtu.be/szW-bSMPuyQ?t=1m49s + * + * @param position Position of the effect + * @param receiver Client index that will be able to see the effect + * or 0 for all clients + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "receiver" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock te_create_lava_splash(position[3], receiver = 0, bool:reliable = true) +{ + if(receiver && !is_user_connected(receiver)) + return 0; + + message_begin(get_msg_destination(receiver, reliable), SVC_TEMPENTITY, .player = receiver); + write_byte(TE_LAVASPLASH); + write_coord(position[0]); + write_coord(position[1]); + write_coord(position[2]); + message_end(); + + return 1; +} + +/** + * Creates a Quake-style teleport splash. + * + * @note Video preview of this and all other te_ stocks can be found here: + * https://youtu.be/szW-bSMPuyQ?t=2m6s + * + * @param position Position of the effect + * @param receiver Client index that will be able to see the effect + * or 0 for all clients + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "receiver" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock te_create_teleport_splash(position[3], receiver = 0, bool:reliable = true) +{ + if(receiver && !is_user_connected(receiver)) + return 0; + + message_begin(get_msg_destination(receiver, reliable), SVC_TEMPENTITY, .player = receiver); + write_byte(TE_TELEPORT); + write_coord(position[0]); + write_coord(position[1]); + write_coord(position[2]); + message_end(); + + return 1; +} + +/** + * Creates a Quake colormapped (base palette) particle explosion with sound. + * + * @note Video preview of this and all other te_ stocks can be found here: + * https://youtu.be/szW-bSMPuyQ?t=2m19s + * + * @param position Position of the explosion + * @param startcolor Starting color (0 - 255) + * @param numcolors Number of colors (1 - 255) + * @param receiver Client index that will be able to see the explosion + * or 0 for all clients + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "receiver" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock te_create_colored_explosion(position[3], startcolor = 0, numcolors = 255, receiver = 0, bool:reliable = true) +{ + if(receiver && !is_user_connected(receiver)) + return 0; + + message_begin(get_msg_destination(receiver, reliable), SVC_TEMPENTITY, .player = receiver); + write_byte(TE_EXPLOSION2); + write_coord(position[0]); + write_coord(position[1]); + write_coord(position[2]); + write_byte(startcolor); + write_byte(clamp(numcolors, 1)); // 0 will crash the game + message_end(); + + return 1; +} + +/** + * Places a decal from the .BSP file. + * + * @note Using a decal index that doesn't exist will crash the client. + * @note Video preview of this and all other te_ stocks can be found here: + * https://youtu.be/szW-bSMPuyQ?t=2m30s + * + * @param position Position of the decal (center of texture in world) + * @param texture Texture index of precached decal texture name + * @param entity Entity index or 0 for world + * @param entabove Model index of the entity above (only available if + * the "entity" argument is non-zero) + * @param receiver Client index that will be able to see the effect + * or 0 for all clients + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "receiver" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock te_place_decal_from_bsp_file(position[3], texture, entity = 0, entabove = 0, receiver = 0, bool:reliable = true) +{ + if(receiver && !is_user_connected(receiver)) + return 0; + + message_begin(get_msg_destination(receiver, reliable), SVC_TEMPENTITY, .player = receiver); + write_byte(TE_BSPDECAL); + write_coord(position[0]); + write_coord(position[1]); + write_coord(position[2]); + write_short(texture); + write_short(entity); + + if(entity) + write_short(entabove); + + message_end(); + + return 1; +} + +/** + * Creates tracers moving towards a point. + * + * @note Video preview of this and all other te_ stocks can be found here: + * https://youtu.be/szW-bSMPuyQ?t=2m44s + * + * @param position Position of the implosion effect + * @param radius Implosion radius + * @param count Number of tracers to generate + * @param life The length of time the effect shall remain + * @param receiver Client index that will be able to see the effect + * or 0 for all clients + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "receiver" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock te_create_implosion(position[3], radius = 64, count = 10, life = 3, receiver = 0, bool:reliable = true) +{ + if(receiver && !is_user_connected(receiver)) + return 0; + + message_begin(get_msg_destination(receiver, reliable), SVC_TEMPENTITY, .player = receiver); + write_byte(TE_IMPLOSION); + write_coord(position[0]); + write_coord(position[1]); + write_coord(position[2]); + write_byte(radius); + write_byte(count); + write_byte(life); + message_end(); + + return 1; +} + +/** + * Creates a line of moving glow sprites or models with gravity, fadeout, + * and collisions. + * + * @note Video preview of this and all other te_ stocks can be found here: + * https://youtu.be/szW-bSMPuyQ?t=2m58s + * + * @param startpos Starting position of the effect + * @param endpos Ending position of the effect + * @param sprite Sprite index + * @param count Number of models/sprites to generate + * @param life The length of time the effect shall remain + * @param scale Scale of the effect + * @param velocity Velocity along vector + * @param randomness Randomness of the velocity + * @param receiver Client index that will be able to see the effect + * or 0 for all clients + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "receiver" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock te_create_model_trail(startpos[3], endpos[3], sprite, count = 1, life = 10, scale = 10, velocity = 10, randomness = 10, receiver = 0, bool:reliable = true) +{ + if(receiver && !is_user_connected(receiver)) + return 0; + + message_begin(get_msg_destination(receiver, reliable), SVC_TEMPENTITY, .player = receiver); + write_byte(TE_SPRITETRAIL); + write_coord(startpos[0]); + write_coord(startpos[1]); + write_coord(startpos[2]); + write_coord(endpos[0]); + write_coord(endpos[1]); + write_coord(endpos[2]); + write_short(sprite); + write_byte(count); + write_byte(life); + write_byte(scale); + write_byte(velocity); + write_byte(randomness); + message_end(); + + return 1; +} + +/** + * Displays an additive sprite that plays one cycle. + * + * @note Video preview of this and all other te_ stocks can be found here: + * https://youtu.be/szW-bSMPuyQ?t=3m7s + * + * @param position Sprite position + * @param sprite Sprite index + * @param scale Scale of the sprite + * @param brightness Brightness of the sprite + * @param receiver Client index that will be able to see the sprite + * or 0 for all clients + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "receiver" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock te_display_additive_sprite(position[3], sprite, scale = 5, brightness = 255, receiver = 0, bool:reliable = true) +{ + if(receiver && !is_user_connected(receiver)) + return 0; + + message_begin(get_msg_destination(receiver, reliable), SVC_TEMPENTITY, .player = receiver); + write_byte(TE_SPRITE); + write_coord(position[0]); + write_coord(position[1]); + write_coord(position[2]); + write_short(sprite); + write_byte(scale); + write_byte(brightness); + message_end(); + + return 1; +} + +/** + * Creates a beam with a sprite at the end of the beam. + * + * @note Video preview of this and all other te_ stocks can be found here: + * https://youtu.be/szW-bSMPuyQ?t=3m29s + * + * @param receiver Client index that will be able to see the beam + * or 0 for all clients + * @param startpos Starting position of the beam + * @param endpos Ending position of the beam + * @param beamid Sprite index for the beam body + * @param endid Sprite index for the end of the beam + * @param receiver Client index that will be able to see the beam + * or 0 for all clients + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "receiver" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock te_create_beam_sprite(startpos[3], endpos[3], beamid, endid, receiver = 0, bool:reliable = true) +{ + if(receiver && !is_user_connected(receiver)) + return 0; + + message_begin(get_msg_destination(receiver, reliable), SVC_TEMPENTITY, .player = receiver); + write_byte(TE_BEAMSPRITE); + write_coord(startpos[0]); + write_coord(startpos[1]); + write_coord(startpos[2]); + write_coord(endpos[0]); + write_coord(endpos[1]); + write_coord(endpos[2]); + write_short(beamid); + write_short(endid); + message_end(); + + return 1; +} + +/** + * Creates a screen aligned beam ring that expands to the maximum radius + * over lifetime. + * + * @note A common sprite to use is "sprites/laserbeam.spr" + * @note Video preview of this and all other te_ stocks can be found here: + * https://youtu.be/szW-bSMPuyQ?t=3m40s + * + * @param position Starting coordinates of the beam + * @param sprite The sprite index to use in the beam + * @param axis Beam axis + * @param startframe The frame to start with in the sprite + * @param framerate The frame rate to show the sprite at + * @param life The length of time the beam shall remain + * @param width The width of the beam + * @param noise The noise amplitude of the beam, this controls + * the distorsion of the beam + * @param r Red color amount (0 - 255) + * @param g Green color amount (0 - 255) + * @param b Blue color amount (0 - 255) + * @param a Beam brightness (alpha) (0 - 255) + * @param speed The scroll speed of the beam (0 - 255) + * @param receiver Client index that will be able to see the beam + * or 0 for all clients + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "receiver" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock te_create_beam_ring(position[3], sprite, axis[3] = {0, 0, 0}, startframe = 0, framerate = 30, life = 10, width = 10, noise = 0, r = 0, g = 0, b = 255, a = 75, speed = 0, receiver = 0, bool:reliable = true) +{ + if(receiver && !is_user_connected(receiver)) + return 0; + + message_begin(get_msg_destination(receiver, reliable), SVC_TEMPENTITY, .player = receiver); + write_byte(TE_BEAMTORUS); + write_coord(position[0]); + write_coord(position[1]); + write_coord(position[2]); + write_coord(axis[0]); + write_coord(axis[1]); + write_coord(axis[2]); + write_short(sprite); + write_byte(startframe); + write_byte(framerate); + write_byte(life); + write_byte(width); + write_byte(noise); + write_byte(r); + write_byte(g); + write_byte(b); + write_byte(a); + write_byte(speed); + message_end(); + + return 1; +} + +/** + * Creates a beam disk that expands to the maximum radius over lifetime. + * + * @note A common sprite to use is "sprites/laserbeam.spr" + * @note Video preview of this and all other te_ stocks can be found here: + * https://youtu.be/szW-bSMPuyQ?t=3m58s + * + * @param position Starting coordinates of the beam + * @param sprite The sprite index to use in the beam + * @param axis Beam axis + * @param startframe The frame to start with in the sprite (0 - 255) + * @param framerate The frame rate to show the sprite at (0 - 255) + * @param life The length of time the beam shall remain (0 - 255) + * @param width The width of the beam (0 - 255) + * @param noise The noise amplitude of the beam, this controls + * the distorsion of the beam (0 - 255) + * @param r Red color amount (0 - 255) + * @param g Green color amount (0 - 255) + * @param b Blue color amount (0 - 255) + * @param a Beam brightness (alpha) (0 - 255) + * @param speed The scroll speed of the beam (0 - 255) + * @param receiver Client index that will be able to see the beam + * or 0 for all clients + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "receiver" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock te_create_beam_disk(position[3], sprite, axis[3] = {0, 0, 0}, startframe = 0, framerate = 30, life = 10, width = 10, noise = 0, r = 0, g = 0, b = 255, a = 75, speed = 0, receiver = 0, bool:reliable = true) +{ + if(receiver && !is_user_connected(receiver)) + return 0; + + message_begin(get_msg_destination(receiver, reliable), SVC_TEMPENTITY, .player = receiver); + write_byte(TE_BEAMDISK); + write_coord(position[0]); + write_coord(position[1]); + write_coord(position[2]); + write_coord(axis[0]); + write_coord(axis[1]); + write_coord(axis[2]); + write_short(sprite); + write_byte(startframe); + write_byte(framerate); + write_byte(life); + write_byte(width); + write_byte(noise); + write_byte(r); + write_byte(g); + write_byte(b); + write_byte(a); + write_byte(speed); + message_end(); + + return 1; +} + +/** + * Creates a beam cylinder that expands to the maximum radius over lifetime. + * + * @note A common sprite to use is "sprites/laserbeam.spr" + * @note Video preview of this and all other te_ stocks can be found here: + * https://youtu.be/szW-bSMPuyQ?t=4m17s + * + * @param position Starting coordinates of the beam + * @param sprite The sprite index to use in the beam + * @param axis Beam axis + * @param startframe The frame to start with in the sprite (0 - 255) + * @param framerate The frame rate to show the sprite at (0 - 255) + * @param life The length of time the beam shall remain (0 - 255) + * @param width The width of the beam (0 - 255) + * @param noise The noise amplitude of the beam, this controls + * the distorsion of the beam (0 - 255) + * @param r Red color amount (0 - 255) + * @param g Green color amount (0 - 255) + * @param b Blue color amount (0 - 255) + * @param a Beam brightness (alpha) (0 - 255) + * @param speed The scroll speed of the beam (0 - 255) + * @param receiver Client index that will be able to see the beam + * or 0 for all clients + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "receiver" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock te_create_beam_cylinder(position[3], sprite, axis[3] = {0, 0, 0}, startframe = 0, framerate = 30, life = 10, width = 10, noise = 0, r = 0, g = 0, b = 255, a = 75, speed = 0, receiver = 0, bool:reliable = true) +{ + if(receiver && !is_user_connected(receiver)) + return 0; + + message_begin(get_msg_destination(receiver, reliable), SVC_TEMPENTITY, .player = receiver); + write_byte(TE_BEAMCYLINDER); + write_coord(position[0]); + write_coord(position[1]); + write_coord(position[2]); + write_coord(axis[0]); + write_coord(axis[1]); + write_coord(axis[2]); + write_short(sprite); + write_byte(startframe); + write_byte(framerate); + write_byte(life); + write_byte(width); + write_byte(noise); + write_byte(r); + write_byte(g); + write_byte(b); + write_byte(a); + write_byte(speed); + message_end(); + + return 1; +} + +/** + * Creates a decaying beam that follows the entity until it stops moving. + * + * @note A common sprite to use is "sprites/laserbeam.spr" + * @note When the entity stops moving, the beam will become visible again + * once the entity starts moving. + * @note Video preview of this and all other te_ stocks can be found here: + * https://youtu.be/szW-bSMPuyQ?t=4m31s + * + * @param entity Entity that the beam will follow + * @param sprite The sprite index to use in the beam + * @param life The length of time the beam shall remain (0 - 255) + * @param width The width of the beam (0 - 255) + * @param r Red color amount (0 - 255) + * @param g Green color amount (0 - 255) + * @param b Blue color amount (0 - 255) + * @param a Beam brightness (alpha) (0 - 255) + * @param receiver Client index that will be able to see the beam + * or 0 for all clients + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "receiver" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock te_create_following_beam(entity, sprite, life = 10, width = 10, r = 0, g = 0, b = 255, a = 75, receiver = 0, bool:reliable = true) +{ + if(receiver && !is_user_connected(receiver)) + return 0; + + message_begin(get_msg_destination(receiver, reliable), SVC_TEMPENTITY, .player = receiver); + write_byte(TE_BEAMFOLLOW); + write_short(entity); + write_short(sprite); + write_byte(life); + write_byte(width); + write_byte(r); + write_byte(g); + write_byte(b); + write_byte(a); + message_end(); + + return 1; +} + +/** + * Displays a glowing sprite. + * + * @note Video preview of this and all other te_ stocks can be found here: + * https://youtu.be/szW-bSMPuyQ?t=4m43s + * + * @param position Sprite position + * @param sprite Sprite index + * @param scale Sprite scale (0 - 255) + * @param size Sprite size (0 - 255) + * @param brightness Sprite brightness (0 - 255) + * @param receiver Client index that will be able to see the sprite + * or 0 for all clients + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "receiver" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock te_display_glow_sprite(position[3], sprite, scale = 10, size = 10, brightness = 150, receiver = 0, bool:reliable = true) +{ + if(receiver && !is_user_connected(receiver)) + return 0; + + message_begin(get_msg_destination(receiver, reliable), SVC_TEMPENTITY, .player = receiver); + write_byte(TE_GLOWSPRITE); + write_coord(position[0]); + write_coord(position[1]); + write_coord(position[2]); + write_short(sprite); + write_byte(scale); + write_byte(size); + write_byte(brightness); + message_end(); + + return 1; +} + +/** + * Creates a beam ring between two entities. + * + * @note A common sprite to use is "sprites/laserbeam.spr" + * @note Video preview of this and all other te_ stocks can be found here: + * https://youtu.be/szW-bSMPuyQ?t=5m10s + * + * @param startent Primary entity id + * @param endent Secondary entity id + * @param sprite The sprite index to use in the beam + * @param startframe The frame to start with in the sprite (0 - 255) + * @param framerate The frame rate to show the sprite at (0 - 255) + * @param life The length of time the beam shall remain (0 - 255) + * @param width The width of the beam (0 - 255) + * @param noise The noise amplitude of the beam, this controls + * the distorsion of the beam (0 - 255) + * @param r Red color amount (0 - 255) + * @param g Green color amount (0 - 255) + * @param b Blue color amount (0 - 255) + * @param a Beam brightness (alpha) (0 - 255) + * @param speed The scroll speed of the beam (0 - 255) + * @param receiver Client index that will be able to see the beam + * or 0 for all clients + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "receiver" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock te_create_beam_ring_between_ent(startent, endent, sprite, startframe = 0, framerate = 30, life = 10, width = 10, noise = 0, r = 0, g = 0, b = 255, a = 75, speed = 0, receiver = 0, bool:reliable = true) +{ + if(receiver && !is_user_connected(receiver)) + return 0; + + message_begin(get_msg_destination(receiver, reliable), SVC_TEMPENTITY, .player = receiver); + write_byte(TE_BEAMRING); + write_short(startent); + write_short(endent); + write_short(sprite); + write_byte(startframe); + write_byte(framerate); + write_byte(life); + write_byte(width); + write_byte(noise); + write_byte(r); + write_byte(g); + write_byte(b); + write_byte(a); + write_byte(speed); + message_end(); + + return 1; +} + +/** + * Creates an oriented shower of tracers. + * + * @note Video preview of this and all other te_ stocks can be found here: + * https://youtu.be/szW-bSMPuyQ?t=5m34s + * + * @param position Position of the effect + * @param direction Effect direction + * @param color Effect color (https://wiki.alliedmods.net/images/Palette.png) + * @param count Number of tracers to create + * @param speed The scroll speed of the effect + * @param velocity Random velocity + * @param receiver Client index that will be able to see the tracers + * or 0 for all clients + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "receiver" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock te_create_tracer_shower(position[3], direction[3] = {0, 0, 0}, color = 12, count = 1, speed = 0, velocity = 10, receiver = 0, bool:reliable = true) +{ + if(receiver && !is_user_connected(receiver)) + return 0; + + message_begin(get_msg_destination(receiver, reliable), SVC_TEMPENTITY, .player = receiver); + write_byte(TE_STREAK_SPLASH); + write_coord(position[0]); + write_coord(position[1]); + write_coord(position[2]); + write_coord(direction[0]); + write_coord(direction[1]); + write_coord(direction[2]); + write_byte(color); + write_short(count); + write_short(speed); + write_short(velocity); + message_end(); + + return 1; +} + +/** + * Creates a dynamic light with a world effect. + * + * @note Video preview of this and all other te_ stocks can be found here: + * https://youtu.be/szW-bSMPuyQ?t=5m47s + * + * @param position Position of the light + * @param radius Light radius (0 - 255) + * @param r Red color amount (0 - 255) + * @param g Green color amount (0 - 255) + * @param b Blue color amount (0 - 255) + * @param life The length of time the light shall remain (0 - 255) + * @param decay Light decay rate (0 - 255) + * @param receiver Client index that will be able to see the light + * or 0 for all clients + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "receiver" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock te_create_dynamic_light(position[3], radius = 10, r = 255, g = 255, b = 255, life = 10, decay = 10, receiver = 0, bool:reliable = true) +{ + if(receiver && !is_user_connected(receiver)) + return 0; + + message_begin(get_msg_destination(receiver, reliable), SVC_TEMPENTITY, .player = receiver); + write_byte(TE_DLIGHT); + write_coord(position[0]); + write_coord(position[1]); + write_coord(position[2]); + write_byte(radius); + write_byte(r); + write_byte(g); + write_byte(b); + write_byte(life); + write_byte(decay); + message_end(); + + return 1; +} + +/** + * Creates a point entity light with no world effect. + * + * @note Video preview of this and all other te_ stocks can be found here: + * https://youtu.be/szW-bSMPuyQ?t=6m7s + * + * @param entity Entity or client to apply the light on + * @param position Position of the light + * @param radius Light radius + * @param r Red color amount (0 - 255) + * @param g Green color amount (0 - 255) + * @param b Blue color amount (0 - 255) + * @param life The length of time the light shall remain (0 - 255) + * @param decay Light decay rate + * @param receiver Client index that will be able to see the light + * or 0 for all clients + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "receiver" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock te_create_entity_light(entity, position[3] = {0, 0, 0}, radius = 50, r = 255, g = 255, b = 255, life = 10, decay = 10, receiver = 0, bool:reliable = true) +{ + if(receiver && !is_user_connected(receiver)) + return 0; + + message_begin(get_msg_destination(receiver, reliable), SVC_TEMPENTITY, .player = receiver); + write_byte(TE_ELIGHT); + write_short(entity); + write_coord(position[0]); + write_coord(position[1]); + write_coord(position[2]); + write_coord(radius); + write_byte(r); + write_byte(g); + write_byte(b); + write_byte(life); + write_coord(decay); + message_end(); + + return 1; +} + +/** + * Draws a simple line. + * + * @note Video preview of this and all other te_ stocks can be found here: + * https://youtu.be/szW-bSMPuyQ?t=6m32s + * + * @param startpos Starting position of the line + * @param endpos Ending position of the line + * @param life Line life + * @param r Red color amount (0 - 255) + * @param g Green color amount (0 - 255) + * @param b Blue color amount (0 - 255) + * @param receiver Client index that will be able to see the line + * or 0 for all clients + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "receiver" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock te_draw_line(startpos[3], endpos[3], life = 10, r = 0, g = 0, b = 255, receiver = 0, bool:reliable = true) +{ + if(receiver && !is_user_connected(receiver)) + return 0; + + message_begin(get_msg_destination(receiver, reliable), SVC_TEMPENTITY, .player = receiver); + write_byte(TE_LINE); + write_coord(startpos[0]); + write_coord(startpos[1]); + write_coord(startpos[2]); + write_coord(endpos[0]); + write_coord(endpos[1]); + write_coord(endpos[2]); + write_short(life); + write_byte(r); + write_byte(g); + write_byte(b); + message_end(); + + return 1; +} + +/** + * Creates a simple box. + * + * @note Video preview of this and all other te_ stocks can be found here: + * https://youtu.be/szW-bSMPuyQ?t=6m45s + * + * @param startpos Starting position of the box + * @param endpos Ending position of the box + * @param life Box life + * @param r Red color amount (0 - 255) + * @param g Green color amount (0 - 255) + * @param b Blue color amount (0 - 255) + * @param receiver Client index that will be able to see the box + * or 0 for all clients + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "receiver" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock te_create_box(startpos[3], endpos[3], life = 10, r = 0, g = 0, b = 255, receiver = 0, bool:reliable = true) +{ + if(receiver && !is_user_connected(receiver)) + return 0; + + message_begin(get_msg_destination(receiver, reliable), SVC_TEMPENTITY, .player = receiver); + write_byte(TE_BOX); + write_coord(startpos[0]); + write_coord(startpos[1]); + write_coord(startpos[2]); + write_coord(endpos[0]); + write_coord(endpos[1]); + write_coord(endpos[2]); + write_short(life); + write_byte(r); + write_byte(g); + write_byte(b); + message_end(); + + return 1; +} + +/** + * Removes all beams attached to an entity. + * + * @note Video preview of this and all other te_ stocks can be found here: + * https://youtu.be/szW-bSMPuyQ?t=7m7s + * + * @param entity Entity id to remove attached beams from + * @param receiver Client index that will be able to see the changes + * or 0 for all clients + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "receiver" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock te_remove_all_beams_from_entity(entity, receiver = 0, bool:reliable = true) +{ + if(receiver && !is_user_connected(receiver)) + return 0; + + message_begin(get_msg_destination(receiver, reliable), SVC_TEMPENTITY, .player = receiver); + write_byte(TE_KILLBEAM); + write_short(entity); + message_end(); + + return 1; +} + +/** + * Flags used in te_create_large_funnel() + */ +#define LF_FLOAT_DOWN 0 +#define LF_FLOAT_UP 1 + +/** + * Creates a large group of sprites or models accompanied by green dots + * that float up or down until they reach the point set in the "position" argument. + * + * @note Video preview of this and all other te_ stocks can be found here: + * https://youtu.be/szW-bSMPuyQ?t=7m10s + * + * @param position Effect position + * @param sprite Sprite index to use + * @param flag List of valid flags: + * LF_FLOAT_DOWN - float downwards and end in the point set in the "position" argument + * LF_FLOAT_UP - start from the point set in the "position" argument and float upwards + * @param receiver Client index that will be able to see the effect + * or 0 for all clients + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "receiver" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock te_create_large_funnel(position[3], sprite, flag = LF_FLOAT_DOWN, receiver = 0, bool:reliable = true) +{ + if(receiver && !is_user_connected(receiver)) + return 0; + + message_begin(get_msg_destination(receiver, reliable), SVC_TEMPENTITY, .player = receiver); + write_byte(TE_LARGEFUNNEL); + write_coord(position[0]); + write_coord(position[1]); + write_coord(position[2]); + write_short(sprite); + write_short(flag); + message_end(); + + return 1; +} + +/** + * Creates dripping blood particles. + * + * @note Video preview of this and all other te_ stocks can be found here: + * https://youtu.be/szW-bSMPuyQ?t=7m35s + * + * @param position Starting position of the blood + * @param direction Blood direction + * @param color Blood color (https://wiki.alliedmods.net/images/Palette.png) + * @param count Number of blood particles to generate (0 - 255) + * @param receiver Client index that will be able to see the blood + * or 0 for all clients + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "receiver" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock te_create_bloodstream(position[3], direction[3] = {0, 0, 0}, color = 78, count = 1, receiver = 0, bool:reliable = true) +{ + if(receiver && !is_user_connected(receiver)) + return 0; + + message_begin(get_msg_destination(receiver, reliable), SVC_TEMPENTITY, .player = receiver); + write_byte(TE_BLOODSTREAM); + write_coord(position[0]); + write_coord(position[1]); + write_coord(position[2]); + write_coord(direction[0]); + write_coord(direction[1]); + write_coord(direction[2]); + write_byte(color); + write_byte(count); + message_end(); + + return 1; +} + +/** + * Draws a line of blood particles spread 5 units from each other that + * disappears after 30 seconds. + * + * @note Video preview of this and all other te_ stocks can be found here: + * https://youtu.be/szW-bSMPuyQ?t=7m53s + * + * @param startpos Starting position of the line + * @param endpos Ending position of the line + * @param receiver Client index that will be able to see the line + * or 0 for all clients + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "receiver" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock te_draw_blood_line(startpos[3], endpos[3], receiver = 0, bool:reliable = true) +{ + if(receiver && !is_user_connected(receiver)) + return 0; + + message_begin(get_msg_destination(receiver, reliable), SVC_TEMPENTITY, .player = receiver); + write_byte(TE_SHOWLINE); + write_coord(startpos[0]); + write_coord(startpos[1]); + write_coord(startpos[2]); + write_coord(endpos[0]); + write_coord(endpos[1]); + write_coord(endpos[2]); + message_end(); + + return 1; +} + +/** + * Sprays blood particles from a given point. + * + * @note Video preview of this and all other te_ stocks can be found here: + * https://youtu.be/szW-bSMPuyQ?t=7m59s + * + * @param position Position from where the blood will be sprayed + * @param direction Blood spraying direction + * @param color Blood color (https://wiki.alliedmods.net/images/Palette.png) + * @param speed Speed at which the blood particles will be sprayed (0 - 255) + * @param receiver Client index that will be able to see the particles + * or 0 for all clients + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "receiver" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock te_spray_blood(position[3], direction[3] = {0, 0, 0}, color = 78, speed = 30, receiver = 0, bool:reliable = true) +{ + if(receiver && !is_user_connected(receiver)) + return 0; + + message_begin(get_msg_destination(receiver, reliable), SVC_TEMPENTITY, .player = receiver); + write_byte(TE_BLOOD); + write_coord(position[0]); + write_coord(position[1]); + write_coord(position[2]); + write_coord(direction[0]); + write_coord(direction[1]); + write_coord(direction[2]); + write_byte(color); + write_byte(speed); + message_end(); + + return 1; +} + +/** + * Applies a decal to a brush entity (not the world). + * + * @note Video preview of this and all other te_ stocks can be found here: + * https://youtu.be/szW-bSMPuyQ?t=8m12s + * + * @param position Position of the decal (center of texture in world) + * @param texture Texture index of precached decal texture name (0 - 511) + * @param entity Entity index to apply the decal to + * @param receiver Client index that will be able to see the effect + * or 0 for all clients + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "receiver" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock te_place_brush_decal(position[3], texture, entity = 0, receiver = 0, bool:reliable = true) +{ + if(receiver && !is_user_connected(receiver)) + return 0; + + message_begin(get_msg_destination(receiver, reliable), SVC_TEMPENTITY, .player = receiver); + write_byte(texture > 256 ? TE_DECALHIGH : TE_DECAL); + write_coord(position[0]); + write_coord(position[1]); + write_coord(position[2]); + write_byte(texture > 256 ? texture - 256 : texture); + write_short(entity); + message_end(); + + return 1; +} + +/** + * Bounce sound types used in te_create_bouncing_model() + */ +enum BounceSounds +{ + BounceSound_Null = 0, + BounceSound_Shell, + BounceSound_ShotShell +} + +/** + * Creates a moving model or sprite that bounces and makes a sound when it hits. + * + * @note Video preview of this and all other te_ stocks can be found here: + * https://youtu.be/szW-bSMPuyQ?t=8m16s + * + * @param position Position of the model + * @param modelid Model index + * @param velocity Model velocity + * @param yaw Initial yaw + * @param bouncesound Bounce sound type: + * BounceSound_Null + * BounceSound_Shell + * BounceSound_ShotShell + * @param life The length of time the model shall remain (0 - 255) + * @param receiver Client index that will be able to see the model + * or 0 for all clients + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "receiver" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock te_create_bouncing_model(position[3], modelid, velocity[3] = {0, 0, 0}, yaw = 0, BounceSounds:bouncesound = BounceSound_Null, life = 10, receiver = 0, bool:reliable = true) +{ + if(receiver && !is_user_connected(receiver)) + return 0; + + message_begin(get_msg_destination(receiver, reliable), SVC_TEMPENTITY, .player = receiver); + write_byte(TE_MODEL); + write_coord(position[0]); + write_coord(position[1]); + write_coord(position[2]); + write_coord(velocity[0]); + write_coord(velocity[1]); + write_coord(velocity[2]); + write_angle(yaw); + write_short(modelid); + write_byte(_:bouncesound); + write_byte(life); + message_end(); + + return 1; +} + +/** + * Creates model or sprite with a blinking orange aura effect. + * + * @note Video preview of this and all other te_ stocks can be found here: + * https://youtu.be/szW-bSMPuyQ?t=8m28s + * + * @param position Position of the model + * @param modelid Model index + * @param speed Model speed + * @param count Number of models to generate + * @param life The length of time the model shall remain (0 - 255) + * @param receiver Client index that will be able to see the model + * or 0 for all clients + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "receiver" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock te_create_explode_model(position[3], modelid, speed = 0, count = 1, life = 10, receiver = 0, bool:reliable = true) +{ + if(receiver && !is_user_connected(receiver)) + return 0; + + message_begin(get_msg_destination(receiver, reliable), SVC_TEMPENTITY, .player = receiver); + write_byte(TE_EXPLODEMODEL); + write_coord(position[0]); + write_coord(position[1]); + write_coord(position[2]); + write_coord(speed); + write_short(modelid); + write_short(count); + write_byte(life); + message_end(); + + return 1; +} + +/** + * Flags used in te_create_break_model() + */ +#define BreakModel_TypeMask 0x4F +#define BreakModel_Glass 0x01 +#define BreakModel_Metal 0x02 +#define BreakModel_Flesh 0x04 +#define BreakModel_Wood 0x08 +#define BreakModel_Smoke 0x10 +#define BreakModel_Trans 0x20 +#define BreakModel_Concrete 0x40 +#define BreakModel_2 0x80 + +/** + * Creates a model or sprite entity that slowly disappears until it's gone. + * + * @note Video preview of this and all other te_ stocks can be found here: + * https://youtu.be/szW-bSMPuyQ + * + * @param position Position of the model + * @param size Size of the model + * @param velocity Model velocity + * @param modelid Model index + * @param random Random velocity (0 - 255) + * @param count Number of model pieces to generate (0 - 255) + * @param life The length of time the model shall remain (0 - 255) + * @param flags Break model flags: + * BreakModel_TypeMask + * BreakModel_Glass + * BreakModel_Metal + * BreakModel_Flesh + * BreakModel_Wood + * BreakModel_Smoke + * BreakModel_Trans + * BreakModel_Concrete + * BreakModel_2 + * @param receiver Client index that will be able to see the model + * or 0 for all clients + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "receiver" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock te_create_break_model(position[3], modelid, size[3] = {50, 50, 50}, velocity[3] = {0, 0, 0}, random = 0, count = 1, life = 10, flags = 0, receiver = 0, bool:reliable = true) +{ + if(receiver && !is_user_connected(receiver)) + return 0; + + message_begin(get_msg_destination(receiver, reliable), SVC_TEMPENTITY, .player = receiver); + write_byte(TE_BREAKMODEL); + write_coord(position[0]); + write_coord(position[1]); + write_coord(position[2]); + write_coord(size[0]); + write_coord(size[1]); + write_coord(size[2]); + write_coord(velocity[0]); + write_coord(velocity[1]); + write_coord(velocity[2]); + write_byte(random); + write_short(modelid); + write_byte(count); + write_byte(life); + write_byte(flags); + message_end(); + + return 1; +} + +/** + * Places a gunshot decal on an entity or the world and plays a ricochet sound. + * + * @note Video preview of this and all other te_ stocks can be found here: + * https://youtu.be/szW-bSMPuyQ?t=8m41s + * + * @param position Position of the decal + * @param decal Decal index (0 - 255) + * @param entity Entity to apply the decal to or 0 for world + * @param receiver Client index that will be able to see the model + * or 0 for all clients + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @noreturn + * @error If "receiver" is non-zero and the client isn't + * connected, an error will be thrown. + */ +stock te_place_gunshot_decal(position[3], decal = 41, entity = 0, receiver = 0, bool:reliable = true) +{ + if(receiver && !is_user_connected(receiver)) + return 0; + + message_begin(get_msg_destination(receiver, reliable), SVC_TEMPENTITY, .player = receiver); + write_byte(TE_GUNSHOTDECAL); + write_coord(position[0]); + write_coord(position[1]); + write_coord(position[2]); + write_short(entity); + write_byte(decal); + message_end(); + + return 1; +} + +/** + * Creates a spray of alpha sprites or models. + * + * @note Video preview of this and all other te_ stocks can be found here: + * https://youtu.be/szW-bSMPuyQ?t=8m52s + * + * @param position Position of the effect + * @param sprite Sprite index + * @param velocity Spray velocity + * @param count Number of sprays to generate (0 - 255) + * @param speed The scroll speed of the effect (0 - 255) + * @param noise The noise amplitude of the effect - this + * controls the distorsion of the effect (0 - 255) + * @param receiver Client index that will be able to see the effect + * or 0 for all clients + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "receiver" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock te_create_sprite_spray(position[3], sprite, velocity[3] = {0, 0, 0}, count = 1, speed = 0, noise = 0, receiver = 0, bool:reliable = true) +{ + if(receiver && !is_user_connected(receiver)) + return 0; + + message_begin(get_msg_destination(receiver, reliable), SVC_TEMPENTITY, .player = receiver); + write_byte(TE_SPRITE_SPRAY); + write_coord(position[0]); + write_coord(position[1]); + write_coord(position[2]); + write_coord(velocity[0]); + write_coord(velocity[1]); + write_coord(velocity[2]); + write_short(sprite); + write_byte(count); + write_byte(speed); + write_byte(noise); + message_end(); + + return 1; +} + +/** + * Creates a quick spray sprite with a ricochet sound. + * + * @note Video preview of this and all other te_ stocks can be found here: + * https://youtu.be/szW-bSMPuyQ?t=9m3s + * + * @param position Position of the effect + * @param scale Scale of the effect (0 - 255) + * @param receiver Client index that will be able to see the effect + * or 0 for all clients + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "receiver" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock te_create_armor_ricochet(position[3], scale = 10, receiver = 0, bool:reliable = true) +{ + if(receiver && !is_user_connected(receiver)) + return 0; + + message_begin(get_msg_destination(receiver, reliable), SVC_TEMPENTITY, .player = receiver); + write_byte(TE_ARMOR_RICOCHET); + write_coord(position[0]); + write_coord(position[1]); + write_coord(position[2]); + write_byte(scale); + message_end(); + + return 1; +} + +/** + * Places a player spray on an entity or the world. + * + * @note Video preview of this and all other te_ stocks can be found here: + * https://youtu.be/szW-bSMPuyQ?t=9m16s + * + * @param position Position of the decal + * @param decal Decal index (0 - 255) + * @param entity Entity to apply the decal to or 0 for world + * @param receiver Client index that will be able to see the model + * or 0 for all clients + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @noreturn + * @error If "receiver" is non-zero and the client isn't + * connected, an error will be thrown. + */ +stock te_place_player_spray(position[3], player, spray = 0, entity = 0, receiver = 0, bool:reliable = true) +{ + if(receiver && !is_user_connected(receiver)) + return 0; + + message_begin(get_msg_destination(receiver, reliable), SVC_TEMPENTITY, .player = receiver); + write_byte(TE_PLAYERDECAL); + write_byte(player); + write_coord(position[0]); + write_coord(position[1]); + write_coord(position[2]); + write_short(entity); + write_byte(spray); + message_end(); + + return 1; +} + +/** + * Creates alpha sprites or models inside of a box that float upwards. + * + * @note A common sprite to use is "sprites/bubble.spr" + * @note Video preview of this and all other te_ stocks can be found here: + * https://youtu.be/szW-bSMPuyQ?t=9m22s + * + * @param startpos Start position + * @param endpos End position + * @param sprite Sprite index + * @param count Number of sprites to generate (0 - 255) + * @param randomness Randoness of the floating direction + * @param height Float height + * @param receiver Client index that will be able to see the effect + * or 0 for all clients + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "receiver" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock te_create_bubble_box(startpos[3], endpos[3], sprite, count = 3, randomness = 0, height = 50, receiver = 0, bool:reliable = true) +{ + if(receiver && !is_user_connected(receiver)) + return 0; + + message_begin(get_msg_destination(receiver, reliable), SVC_TEMPENTITY, .player = receiver); + write_byte(TE_BUBBLES); + write_coord(startpos[0]); + write_coord(startpos[1]); + write_coord(startpos[2]); + write_coord(endpos[0]); + write_coord(endpos[1]); + write_coord(endpos[2]); + write_coord(height); + write_short(sprite); + write_byte(count); + write_coord(randomness); + message_end(); + + return 1; +} + +/** + * Creates alpha sprites or models along a line that float upwards. + * + * @note A common sprite to use is "sprites/bubble.spr" + * @note Video preview of this and all other te_ stocks can be found here: + * https://youtu.be/szW-bSMPuyQ?t=9m37s + * + * @param startpos Start position + * @param endpos End position + * @param sprite Sprite index + * @param count Number of sprites to generate (0 - 255) + * @param randomness Randoness of the floating direction + * @param height Float height + * @param receiver Client index that will be able to see the effect + * or 0 for all clients + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "receiver" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock te_create_bubble_line(startpos[3], endpos[3], sprite, count = 3, randomness = 0, height = 50, receiver = 0, bool:reliable = true) +{ + if(receiver && !is_user_connected(receiver)) + return 0; + + message_begin(get_msg_destination(receiver, reliable), SVC_TEMPENTITY, .player = receiver); + write_byte(TE_BUBBLETRAIL); + write_coord(startpos[0]); + write_coord(startpos[1]); + write_coord(startpos[2]); + write_coord(endpos[0]); + write_coord(endpos[1]); + write_coord(endpos[2]); + write_coord(height); + write_short(sprite); + write_byte(count); + write_coord(randomness); + message_end(); + + return 1; +} + +/** + * Creates an spray of opaque sprites or models that fall to another sprite or model. + * + * @note Video preview of this and all other te_ stocks can be found here: + * https://youtu.be/szW-bSMPuyQ?t=9m44s + * + * @param position Effect position + * @param sprite1id Primary sprite index + * @param sprite2id Secondary sprite index + * @param color Sprite color (https://wiki.alliedmods.net/images/Palette.png) + * @param scale Sprite scale (0 - 255) + * @param receiver Client index that will be able to see the sprite + * or 0 for all clients + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "receiver" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock te_display_falling_sprite(position[3], sprite1id, sprite2id, color = 78, scale = 10, receiver = 0, bool:reliable = true) +{ + if(receiver && !is_user_connected(receiver)) + return 0; + + message_begin(get_msg_destination(receiver, reliable), SVC_TEMPENTITY, .player = receiver); + write_byte(TE_BLOODSPRITE); + write_coord(position[0]); + write_coord(position[1]); + write_coord(position[2]); + write_short(sprite1id); + write_short(sprite2id); + write_byte(color); + write_byte(scale); + message_end(); + + return 1; +} + +/** + * Applies a decal to the world brush. + * + * @note Using a decal index that doesn't exist will crash the client. + * @note Video preview of this and all other te_ stocks can be found here: + * https://youtu.be/szW-bSMPuyQ?t=9m56s + * + * @param position Decal position (center of texture in world) + * @param texture Texture index of precached decal texture name (0 - 511) + * @param receiver Client index that will be able to see the decal + * or 0 for all clients + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "receiver" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock te_place_world_decal(position[3], texture, receiver = 0, bool:reliable = true) +{ + if(receiver && !is_user_connected(receiver)) + return 0; + + message_begin(get_msg_destination(receiver, reliable), SVC_TEMPENTITY, .player = receiver); + write_byte(texture > 256 ? TE_WORLDDECALHIGH : TE_WORLDDECAL); + write_coord(position[0]); + write_coord(position[1]); + write_coord(position[2]); + write_byte(texture > 256 ? texture - 256 : texture); + message_end(); + + return 1; +} + +/** + * Creates a nail-like projectile. + * + * @note Video preview of this and all other te_ stocks can be found here: + * https://youtu.be/szW-bSMPuyQ?t=10m12s + * + * @param position Projectile position + * @param velocity Projectile velocity + * @param model Model index that will be used for the projectile + * @param life The length of time the projectile shall remain (0 - 255) + * @param owner The projectile won't collide with the owner, if set to 0, + * the projectile will hit any client + * @param receiver Client index that will be able to see the projectile + * or 0 for all clients + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "receiver" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock te_create_projectile(position[3], velocity[3], model, life = 10, owner = 0, receiver = 0, bool:reliable = true) +{ + if(receiver && !is_user_connected(receiver)) + return 0; + + message_begin(get_msg_destination(receiver, reliable), SVC_TEMPENTITY, .player = receiver); + write_byte(TE_PROJECTILE); + write_coord(position[0]); + write_coord(position[1]); + write_coord(position[2]); + write_coord(velocity[0]); + write_coord(velocity[1]); + write_coord(velocity[2]); + write_short(model); + write_byte(life); + write_byte(owner); + message_end(); + + return 1; +} + +/** + * Creates a shower of sprites or models. + * + * @note Video preview of this and all other te_ stocks can be found here: + * https://youtu.be/szW-bSMPuyQ?t=10m27s + * + * @param position Effect position + * @param model Model index that will be used for the effect + * @param direction Effect direction + * @param count Number of sprites/models to generate (0 - 255) + * @param speed The scroll speed of the effect (0 - 255) + * @param noise The noise amplitude of the effect - this + * controls the distorsion of the effect (0 - 255) + * @param rendermode Render mode - one of kRender* constants + * @param receiver Client index that will be able to see the effect + * or 0 for all clients + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "receiver" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock te_create_sprite_shower(position[3], model, direction[3] = {0, 0, 0}, count = 1, speed = 0, noise = 0, rendermode = kRenderNormal, receiver = 0, bool:reliable = true) +{ + if(receiver && !is_user_connected(receiver)) + return 0; + + message_begin(get_msg_destination(receiver, reliable), SVC_TEMPENTITY, .player = receiver); + write_byte(TE_SPRAY); + write_coord(position[0]); + write_coord(position[1]); + write_coord(position[2]); + write_coord(direction[0]); + write_coord(direction[1]); + write_coord(direction[2]); + write_short(model); + write_byte(count); + write_byte(speed); + write_byte(noise); + write_byte(rendermode); + message_end(); + + return 1; +} + +/** + * Emits sprites or models from a player's bounding box. + * + * @note Video preview of this and all other te_ stocks can be found here: + * https://youtu.be/szW-bSMPuyQ?t=10m39s + * + * @param player Client index to emit the sprites from (can't be 0) + * @param sprite Sprite index + * @param count Number of sprites to generate (0 - 255) + * @param variance Variance in size (0 = no variance; 10 = 10% variance) (0 - 255) + * @param receiver Client index that will be able to see the effect + * or 0 for all clients + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "receiver" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock te_emit_sprite_from_player(player, sprite, count = 1, variance = 0, receiver = 0, bool:reliable = true) +{ + if(receiver && !is_user_connected(receiver)) + return 0; + + message_begin(get_msg_destination(receiver, reliable), SVC_TEMPENTITY, .player = receiver); + write_byte(TE_PLAYERSPRITES); + write_short(player); + write_short(sprite); + write_byte(count); + write_byte(variance); + message_end(); + + return 1; +} + +/** + * Creates a particle burst similar to te_create_lava_splash. + * + * @note Video preview of this and all other te_ stocks can be found here: + * https://youtu.be/szW-bSMPuyQ?t=10m55s + * + * @param position Effect position + * @param radius Effect radius + * @param color Particle color (https://wiki.alliedmods.net/images/Palette.png) + * @param duration Duration of the effect (will be randomized a bit) (0 - 255) + * @param receiver Client index that will be able to see the effect + * or 0 for all clients + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "receiver" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock te_create_particle_burst(position[3], radius = 30, color = 106, duration = 5, receiver = 0, bool:reliable = true) +{ + if(receiver && !is_user_connected(receiver)) + return 0; + + message_begin(get_msg_destination(receiver, reliable), SVC_TEMPENTITY, .player = receiver); + write_byte(TE_PARTICLEBURST); + write_coord(position[0]); + write_coord(position[1]); + write_coord(position[2]); + write_short(radius); + write_byte(color); + write_byte(duration); + message_end(); + + return 1; +} + +/** + * Creates a field of fire. + * + * @note Video preview of this and all other te_ stocks can be found here: + * https://youtu.be/szW-bSMPuyQ?t=11m7s + * + * @param position Effect position + * @param sprite Sprite or model index to use for the fire + * @param radius Effect radius + * @param count Number of fields to generate (0 - 255) + * @param duration Duration of the effect (will be randomized a bit) (0 - 255) + * @param flags Available flags: + * TEFIRE_FLAG_ALLFLOAT - all sprites will drift upwards as they animate + * TEFIRE_FLAG_SOMEFLOAT - some of the sprites will drift upwards (50% chance) + * TEFIRE_FLAG_LOOP - if set, sprite plays at 15 fps, otherwise plays at whatever rate stretches the animation over the sprite's duration + * TEFIRE_FLAG_ALPHA - if set, sprite is rendered alpha blended at 50% else, opaque + * TEFIRE_FLAG_PLANAR - if set, all fire sprites have same initial Z instead of randomly filling a cube + * @param receiver Client index that will be able to see the effect + * or 0 for all clients + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "receiver" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock te_create_fire_field(position[3], sprite, radius = 5, count = 1, duration = 10, flags = TEFIRE_FLAG_ALLFLOAT, receiver = 0, bool:reliable = true) +{ + if(receiver && !is_user_connected(receiver)) + return 0; + + message_begin(get_msg_destination(receiver, reliable), SVC_TEMPENTITY, .player = receiver); + write_byte(TE_FIREFIELD); + write_coord(position[0]); + write_coord(position[1]); + write_coord(position[2]); + write_short(radius); + write_short(sprite); + write_byte(count); + write_byte(flags); + write_byte(duration); + message_end(); + + return 1; +} + +/** + * Attaches a temporary entity model to a client. + * + * @note Video preview of this and all other te_ stocks can be found here: + * https://youtu.be/szW-bSMPuyQ?t=11m16s + * + * @param player Client index to attach the model to + * @param model Model index + * @param offset Vertical offset (attachment origin.z = player origin.z + vertical offset) + * @param life The length of time the model shall remain + * @param receiver Client index that will be able to see the model + * or 0 for all clients + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "receiver" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock te_attach_model_to_player(player, model, offset = 0, life = 5, receiver = 0, bool:reliable = true) +{ + if(receiver && !is_user_connected(receiver)) + return 0; + + message_begin(get_msg_destination(receiver, reliable), SVC_TEMPENTITY, .player = receiver); + write_byte(TE_PLAYERATTACHMENT); + write_byte(player); + write_coord(offset); + write_short(model); + write_short(life); + message_end(); + + return 1; +} + +/** + * Kills all temporary entity models attached to a client. + * + * @note Video preview of this and all other te_ stocks can be found here: + * https://youtu.be/szW-bSMPuyQ?t=11m24s + * + * @param player Client index to remove the attachments from + * @param receiver Client index that will be able to see the effect + * or 0 for all clients + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @noreturn + * @error If "receiver" is non-zero and the client isn't + * + * @return 0 if "receiver" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock te_remove_player_attachments(player, receiver = 0, bool:reliable = true) +{ + if(receiver && !is_user_connected(receiver)) + return 0; + + message_begin(get_msg_destination(receiver, reliable), SVC_TEMPENTITY, .player = receiver); + write_byte(TE_KILLPLAYERATTACHMENTS); + write_byte(player); + message_end(); + + return 1; +} + +/** + * Much more compact shotgun shot stock. + * + * @note This stock is used to make a client approximate a 'spray' of gunfire. + * Any weapon that fires more than one bullet per frame and fires in a bit + * of a spread is a good candidate for MULTIGUNSHOT use. (shotguns) + * @note This effect makes the client do traces for each bullet, these client + * traces ignore entities that have studio models. Traces are 4096 long. + * @note Video preview of this and all other te_ stocks can be found here: + * https://youtu.be/szW-bSMPuyQ?t=11m27s + * + * @param position Gunshot position + * @param direction Gunshot direction + * @param decal Bullethole decal texture index (0 - 255) + * @param count Number of bulletholes to generate (0 - 255) + * @param noise_x X noise multiplied by 100 + * @param noise_y Y noise multiplied by 100 + * @param receiver Client index that will be able to see the Gunshot + * or 0 for all clients + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "receiver" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock te_create_multi_gunshot(position[3], direction[3], decal = 105, count = 1, noise_x = 0, noise_y = 0, receiver = 0, bool:reliable = true) +{ + if(receiver && !is_user_connected(receiver)) + return 0; + + message_begin(get_msg_destination(receiver, reliable), SVC_TEMPENTITY, .player = receiver); + write_byte(TE_MULTIGUNSHOT); + write_coord(position[0]); + write_coord(position[1]); + write_coord(position[2]); + write_coord(direction[0]); + write_coord(direction[1]); + write_coord(direction[2]); + write_coord(noise_x); + write_coord(noise_y); + write_byte(count); + write_byte(decal); + message_end(); + + return 1; +} + +/** + * Creates a tracer effect and allows more customization than te_create_tracer. + * + * @note Video preview of this and all other te_ stocks can be found here: + * https://youtu.be/szW-bSMPuyQ?t=11m36s + * + * @param position Effect position + * @param velocity Effect velocity + * @param life The length of time the effect shall remain, multiplied by 10 (0 - 255) + * @param color Tracer color (0 - 12) + * @param length Length of the tracer (0 - 255) + * @param receiver Client index that will be able to see the effect + * or 0 for all clients + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return 0 if "receiver" is non-zero and the client isn't connected, + * 1 otherwise + */ +stock te_create_user_tracer(position[3], velocity[3], life = 1, color = 106, length = 1, receiver = 0, bool:reliable = true) +{ + if(receiver && !is_user_connected(receiver)) + return 0; + + message_begin(get_msg_destination(receiver, reliable), SVC_TEMPENTITY, .player = receiver); + write_byte(TE_USERTRACER); + write_coord(position[0]); + write_coord(position[1]); + write_coord(position[2]); + write_coord(velocity[0]); + write_coord(velocity[1]); + write_coord(velocity[2]); + write_byte(life); + write_byte(clamp(color, 0, 12)); + write_byte(length); + message_end(); + + return 1; +} + +/** + * @endsection + */ + +/** + * Used with message stocks. Returns whether or not to use the reliable or + * unreliable channel when sending a message according to the params used. + * + * @param id Client index or 0 for all clients + * @param reliable If true, the message will be sent via the reliable + * channel, otherwise it will use the unreliable one + * + * @return MSG_ONE if "id" is non-zero and "reliable" is true, + * MSG_ONE_UNRELIABLE if "id" is non-zero and "reliable" is false, + * MSG_ALL if "id" is zero and "reliable" is true, + * MSG_BROADCAST if "id" is zero and "reliable" is false. + */ +stock get_msg_destination(id, bool:reliable) +{ + if(id) + return reliable ? MSG_ONE : MSG_ONE_UNRELIABLE; + + return reliable ? MSG_ALL : MSG_BROADCAST; +} + +/** + * Converts a float value into a short. + * + * @param value Float value to convert + * + * @return Value converted to short + */ +stock float_to_short(Float:value) + return clamp(floatround(value * (1<<12)), 0, 0xFFFF); \ No newline at end of file diff --git a/sprites/afk/afk.spr b/sprites/afk/afk.spr new file mode 100644 index 0000000000000000000000000000000000000000..6c6853907bd46e99d234475c2dca6930d0103751 GIT binary patch literal 263274 zcmeEv4O|q}`hO)FWi4JUbqK>`BY$!gY>6o}Ss?|jFkyFLh|)yJ6xmH)Oi&lT611@9x&*c zQR8v!)xSUata5_4+s8v@vmh^8$Fg}+Kd=I=xOVL0|(l2U!5tA z{`%~-fBkan%TtYl=grSD#{0*={Kf~*4SVTt9Gme@PF}(QVs+Be+`?}w zudKb^R&4w;`GWD2Eu~Xe zebv=%;*9sEg)aDT^}jyfxu@`A)!jR{FW>%4sW+zRjmg)3Q~bL*N8cJ(_>0$t_a7SxpZ7a8bth@kdVl^XH4ItNOHh zgT{C({pO$PH}9;4jpmz;f8M!$`*y~4gR;(``n6ecrCGA?g3szb)BmyOo%r4S*xa|H zcT9@h=^nYuZDH0}pNMB|hH;*L+U2#^o*6R4FLq_-?Yrv?t=~2Np4MPYtv94zZ%)xS zk=Gh`HvM+@?%l%X7P7V}xz_OQ`T7sji)O4Yc<0M}ulU_l0fgAXx0mjj6jk6JRXBOs zVSG{6h}R~$JGHf*7j#v z%Pm=L6M4Dm+w+afbv1J`OQ!#$a7t|c2sFFe_eV`e&w2~_J-=$2H7t)%L)&DQE*W5ea?zKKao{6X@)`>E3>6LGP@e?`;4g!9Bc#k*zVQgX%U=d&uU=d&u zU=d&uU=d&uU=d&uU=d&uU=d&uU=d&uU=jH5BJkv(|E~R~p8ngYk^fB>tcSilwiouF z=|$ciWqoEC_CF8LSTp5ndxpfJ2N$+~u*k--sMC!ZTp4O>qwVm?~tb-;5Y#?UqW>xW~% z)?m)!Xql=b$#RlvYJb>jGG+hb$kCTSIQpbzESqY1-hB3HkJnz~m&73Bxn>XQmC<6| zv8E=GgDLmu5knbwE$RbZ*|rmPQ>Rt@yhEu{HNqcC!MTl!-}QBQ(J^J?%m&Twnm=3U zeQ{DYbxo3zva?mGYVcA8gZ0R`mX_%$DaNE6m1>RHLUtZhO~jgJuY);ALWhHWzN#u#g5XZdS$b>(IAcuiVZSyV}pV!#YRIt$>rw408qtu*QjsCBQH^K;#FZ zM7S36lj>mrBrDQ9x-V;qy@5+r$}%H=hm@ilj~ob!t&EMWESIYJ5``)+Ib~NWWeH2& z)-i?nB3V)X8=qTfM?j-1E0GtKlwNO;;CB4&!K##-sj16|$2J9c1T9O+`}udV&@o;@ z7$`k*0*lnS$e%ggI&XoU{10POcU80mi)_^ff`StekcYD{C^pLu zPvoSu#6brntH=NgnCiBQsljn+`IR^G=ZbL+7)OS)vY->FDH9^FZNb6IKmNG2we_)0 z0TVqxTK?Vc?^@$pB5^$81W^gtXJruv4{W4uIJPY=5{$RDe)N&-F`T2YBMU;`M0jT`^F^rSadTzyv6>C?nc&DWOPPkhb`?{0&&YYF&3LwpC5j(p( zOqt?<2`RDGRGskSmFUnpZ^wdnlKN`mVdciTPMa%L?>Ya+ALr*7urbd=-e(QvgfSfR z(;GyXu;9Y^J$uf#Y4EgnTpz7T@F3NPHcb-_{XA~H}On1h(0sI60oRG4&Z zrQYa}cLFYvo_h=caR2V+Jue}B@5MH^J5{)gF*TKNDH8GcC$v-GPM`+k{W4E_(XCLE zpuy)|avS(CB>QsA_SNyYPso?+_g%XEr`kv3P-GNqU4&X&TdmLodjh6BUe)~gJ8j-R zA@kIGwv5}%54!DQR55@0P z`ONUy@a1RjcOo8KS09d8+1S12{MO9Se`NerbqAm2US)+U5fC@a#YDacP56u5H~b?s zv?}AL(9oF~&WY}SS@IlwV&D)Ab8&w+?CZ<}nSafAZDAGt^?EBsh^+WxQ4M@IcGz-d zvh}+gGs6yKzUv;2JvnI-IzcR&CcXFRs*M{r-gS4mYP}k2=IFQ9dK7J~)r;YZGxptT zY|(ogH*VRu@x4jNtn-k?7PXFHliy$P&8C9~H^bN4v8$oULeHcCTaK+*oRkO$XI;fy z1|L4O{WiYiK|1-B*0p!o)3y|NRZL7RDQT(GhSPOidIyWA^mJ7Z-PH>%*H--#nJ|!6NMY zBbyg=Jm<0J==FSOY~n<-xuXj|+wA+I`IE)p0raC+(9;cbau(^)^{+koxr}|!+S2{r zUOT-}&5SPCUOaG{P$%Npj>8t4A5SiZv(%ywUb@;wpRS^jhmuh3B)!B|2YC9Klo3rG3_3RVIzh=-M$L9`z#OIYZ=EU zTTdR{Y02w@jNQL~B8Z)we21(9DWcj&9+}S;KB9w?8x&&hd7(}B}-7i+R~*S;MRKmz|=rD{blbgGx-1n91vNQwaJ%;QaU$AlD-rl^Nj z=hh<*FiOhY9f}z7HGNEUqu7#Ep!=HQEDkuvZ%k|1(U_NcN?6~we@71M~%D=N~`DyB`FmOqV{+Y%LsQ~?xGkByOv zVN=(rWPw1vU$QeL1)Kmc(u`?oz(pmOOjjs(oteGHAXYV!=hO!-J z?Fv5!%f+QMEB~8^l_bp z+hj_mBsW*Ny=+~8SV{pYn2_24H(26mW8jv`Th+8Gfhy)PQF1Zc7*#__sf4@{C^dNE zM&Kj|8RHQrn$Q@j!l=ftY*c7cBtL&lbHLOX)%LR`o}|hNCkPGVDj?#$yo!(RZ2?&(AL2= zu;VF;Q17+nk*egpmi*MzRO92YuS=a4nVh?QC!Z&sXGBT>lu4GsU@*XV!2OeAS}JbF z#@?JZx3m*S%wn$SQ-fmjTOxn=6lm09S_uJ2@l1*(D77udOGA@!WL|QfBFSP_J1P=G z>z2jt%1`sOqa^_VdJu#FZ3^guZx`Z;m?#Hb3zwr)u*C9nkn`!>?~onfV$`$8U(&-Da^OwvBbEc?{>%Az7IlNNpx{|c?BrIGzt<}|g z&v}&Q24c?7(2Wz7dlDY7<*(JcV7zzeqXmT;eC|8vY1X#I5U_H6BdrZjxOD!)g$sKe zo$RM*wdh8e0#Yu|ej-(wN;qKLOH%rzh88WPe@Q-baT5{SY`7p zFEzDNk2&xt{fQHPQwSmzi1FONG=&%4E?!DVz@6eRyF?N8@eW(RS?Wkc|Cr z&fLGj@lMsOe=w2&SP_w5E;ZaFfD;bs1D}~2X8!b7RcL5NXvV&UShb^tuESOw_!hhH zN@f^{4y?kxw~VZ2BmuA*L%vZYG#Z684|nX$nMd7cW@cu7of(?((+3!~DE+m*H~QX^ zV~!kf-{|YRF(afJd(xfeW&77@McSewt&S3*u3iXi?a}W-mM~x6cdb$RkuN-dZ#8}X z{Jiy%1sgA4UUl#=d>#G(NdjO=o+1%nAQ0&(G1z~00di{A=F4Fq9Pl3PV4sb3S8($C zFD%%6=%BAVdK&NydamHY36O|w^`4$QGzX5Px!_|C`G$pEzPzdbU;OX&Vc4h7JQL=7 zunXf~hi(EYPhjn0co_D|dkex2-d%8SX$yS*ehfC+_wZr#Sf@P+DT)H)4jte8#||F3 z;K-3Knc8#ra|2H2MVq&Dd89T`N7c^mQmy?n*yJnL7CQ60)J%U^*tu$lx8JUziiY^# zGt+k!@!U82d$!t@)h*d43zuMlE$KEW8+~<_g-~ z>XhU0Z;rK1vP(*`;Dzq-yUbc(5nvHu5nvHu5nvHu5nvHu5nvHu5nvHu5nvHu5nvHu z5nvHu5nvJc41&@ZWTzdid}W{RuoZa$%P>w7o`Wz|mm?hV{BsM}ec4pRVo~FMCYC z{C{B~Hu~Vx)%Psg?QrkWTLb#MzW2#R_Rm+N1>_3{_rpGx$gp1??J494_n6X=@96Ns zlj)`D3;WT5iPb|#byRuJ*1rV82%%s|N9+8L9qY(4Y}9j;v5_M&=!3qeQNxEH?Nk~< zlbVw=&-0WjDmo{-v{-E7f;$LK)S3@7?@vBGV$9M05EI4@eYvA~Sj};*Y4NjP(vFxY z5|P4{q%1nRbm}-TSW}yYh(eu`{iqSo^`ieemF#wNNLC%q$;To})&K#!Batz=yu~iH zb;s{3HqxT2wd=BKuhn3$8)9S~w&|^UV557~9y=zqJQ=TZlbo}3+H1TeF^nKVJ@W<* zDC_GLF~!2;da_h3=v=_U+y6RtTqwTzVcrrjt*oax*d`#nmIwb%{Ti^8jCovPf}tr9 zrvi@GmPfS&d+i4HW8p9d`M}Zr^J!s#z=r8<}tC-hx{f}$pWrtFOU3fE||?Hj33_okRb9a(o*8$RG-J? z$cP|-VPN>EKw@!(NO^4aZqA0 zOcbM%dx7wRa_3pnOBz*ZB+5y$Fw3}3rMeOLQOQ}k@1; z;_Nmf5o;`rve9cwNaYRhQ%IITm1F2y(juP*70W;qKvl0KC5=*EGb2h6Sct--8fr5r4DN1rnr_Npe$N4 z&k#!(ka=)`CZ!`^Jl7SZ>!xPY*QDgfFbBfvuTqtl>XTxw`xrrm0bmEKU>RP47a!#5 zDz)WHka^HW_%PPLnoev%W^s$hFj3SYUBAjrIM?g-pidJPzZjYf5G6 z&6d1m)zScg(_Rfh7$`m8NZXH%t*oq!t>mh02L+_0-Q2Y+zoI4b=iCmmd_Syq6fLTZ zO-;R-q6*%jo3s}vE7}*uDF^?9<%6lU=lwk*JJCst{lu z!v>*g%~S`MD6gQY+!3jat)&ayTZ$OCngPEiKandV=$VTR9qkd5&9 za>k4e``j0O`DgzL%YsYZlRh{al9BO`{TZS2FOA0+xQDnitnYB+O~NQORuU%rFU-i; zu;HhwUqbhXW@Kc9%)-We<=EdLm>9u!le zB7zVy5;P01Y?$RfGc+{w>#&T_&<&F@EYUr^pVwigrDG0chJ|GwIIyt_|7HNT;N4+# z2h?gQ%A=@AC(?V+{ak%zu>GR<5BMGk3p;S&z}+#B>DlTNPTys`pN?9 z!v`U4M%S6q04+QYkcjnqp@5?oQ&UklC%U8OeJ>ooyy=^;%Lg}GR2O6H`_(TVzI^E5 zrY-aXrC~IvLqw8tE~sJ{M6@i*GYD`DTX5vyH{j@D8Y6m-1zrYOSA*Wg!GlM-$X$RM zj`2inY!)W6>aa0-^A>C0gNLpA^W3kaHuKi#qu9v7cMok|Xx>4;3k?QPX7a$sb+SKl z%j(gG4{oNrs7vO4eXs|WmoZxo``&}979?@*)u1~%#@_u1(@*^}d4J*2N8s%1lKeze zQI{R?0S5eP5QupkX;GK%PaI;EsG}ULwmIBu>-#W^KKJaXzN1?E2p-Q)%H@bSZEajz zUe_<2&vYFo9px>zHNckJRwylWa&m&#LRy!mqjGzTOgbI)b-T5App`9{zEsE^h(v+@ z3(0<d7LK?)cy#~T{rq!7 zpXqZADELo5+rO}S=!m|rkNLjuzB7$Zd<7Qt!CxN}6aA=wC+lY?RxP3Pt5ws&in1L zqr+cV*ymH|<>62FVqyCrZEYt`vdIl#wZGE$1xhb;tikHsEN0um3OLEz{M$Wr79Rig z{#>K0A6Ccx`5(H+xr6AiOh{5ci9wU(pVu6ID)aqYFO<2>ocD|2bv z^vh0F&RLP}nBEZ49Re1!j}>LdpSE;x#!lxW=LQGgn4UH*|HEk%@XrY1!+b;p%Wagal&9$d5p7{MSi4gZIlzi6k*gGq zrHUOpvL(i|!Pyf1&%qG0UKK|G4Xgx$xT{pM^81$PwpY=wjihLm{BsCKt|+Z1%TES- z5|V8B^(LK&n!dy-i-;{JT|Eh+xxSuj7nrLc%LC~-QTBK^;fp0Q z)%H`ZOO&cI(ur5j1yUZ-whlPSgj2Q?rSZxp3)L_R;S7*JmMI{-97xfpRP~C6rgdEL z1!N!C*oYG?QSUWyi)Ew~|D5K8Kb{WoJ3}gWmYz9HZg(ma8@*AabO;d-k?J8{{5*rf zNhWjBoTfR+Gx~gn+p5?C|B%gY?8=woxBZ1yaDV39~N=5gJKO7Atq&9TaXNZ zq?A35DacBtfcBR)$>k8JzLE}94-w)`oNNOj&i>AhFQM%}7EU@Qlqr=zo+%Gdl1^Y; zY$60R#9)XRE)H(9)ipC>CD|qS--!0R3q(K)ZzwMll|=_~D}#ti=zi#c*j?~WcfoG& z2>o@`{^iMOu@ATt>5mghKnhnBmx_36q+lOR)0A9f8a68{4TTz^7%mX1hxNeA(B;TKphT(xY-s?6Nz1M$;usyaxJ%Q zo+oNMfn*WDK7shr1aPuBrHVLYeOdn8B^IB8YGPBDRjBfUv-Ltp5GA1aIvqvZ2lT-W zW4hYPe|km!&HS_$Wpduf7QYB{K1406h|4bFxT|p>r5lkd12muhPl)hzd*|sbO2i0< z89-TP=_yE*9anL4S!(Rfv|=8P8<6E7rs?oXXa}k}*pM^y^b4neO8Jqcr=Wlv%Xgn^ zjY~;Ot0+xZb3uzE2pk{?;DpCgLog0^A~xi7b~`6rX5kKSC~o+8EnBlCz_qlU&=mC!N6h9B09vEp`kr8_V z#7l<$XY#CAxpu`;nx<$m2Y4SB%sICb2;Xz&to*pxUsFA$rpCh$6Y43tqi3U=Zs*hI z=nQktc^9tuSYpX3z)uplq`<9kP64Djb4$Xl7_#kRv6Io*Zs&EcbLe=%99JB7E%?}y zocN?SrcHChz0dD~bpArw5R7@QRYMq!h><%5CLlg$b-|6!P~fQ15NU5%5P)raE}Wl^ zC*T(^+`4t^g16M!k5BR84ChD)gI*sVZiJ~ph;e|54;e1p!Zn(5$*ni~Pe?Wm9|xxk z7YlKkl3rFi-7v`?j06&tCr_`KkH4wD!6>o%V!Cu-JodfJZM8j_bd4bZc`{&r3)E zTDtV_76O3tXPY!080qUn_5msVPP`8;uon_QhOE(UwYB4T=uD4&Z1MT?tH$5H1dQ~M zkbM)r8t-Hg0Gu6Pa{P)RrGMo;e!TZjK2>maLnoZb2%L01WzaKE{%ose%-^s6^OvvI z&z~_P#Qn1>3sBNAYykcezPfrt#)db6l#buIROP-O*@t9L<%1%WA)lb&@e?H54L%z( zd>pGn_X8z;zV*bTxOe{nSZu2nzKt!KnGp&^^UMrK$FCQX>}eR0uQZT zggV6ez}?rbE_m11cU73LukYR0U>7!)W0|KRi>)_*vt`q&RjUpj0s8a8Z&0m5Pmxxq zE%MOm0*cXGyXbvr@}j$|Hid<4TIFjZCC{F+82QofRQ>*f1&9>??=5e`z?=0VROlbj z9AMzBwiP=C@DLu=tKrqf`tao~K#4yxsoy5MR513)tVOFX1J&JnBJ5`d1?FLthvLz=SX;%xPAb)i;}tEI>VC$>g$d5O#F) zrm!xLxczGRdYuO|`!aS|r_ zb(v=T+`IHrdl3t4ptFxjJgL;NP|D*bwcWlXm3Fz=bFs4Y=rbGb^zOXP#zrk|D=aK@ zvcU&-`H{)K%OL4g#9*Bs{Up0I;l)ht)R7*?9;g=l_!Vhq=ZcV-a8xU=d&u zU=d&uU=d&uU=d&uU=d&uU=d&uU=d&uU=ctFu$lnuIA9TA5nvHu5nvHu5nvHu5nvHu z5nvHu5wHvb&W~p)P*0s3!aqi@5btUJe&zEQ@&d%-sUnWQc>&IB0VnG*kYUVT&i3dO zl7u5}lt)EJN5|x-yaGi-=sZKTkCT->;MxzuqW@u>u``ci9AIO*zA;e14{!ll-jF#o!$7LP6_A595aiSUO7u|gN zrJ;2x$@BlU_IR!3&9>JVUY8}f_Nz0;E1E&RwZpz@r%E23q^mm~AdYx^r=TFKPH;@0 z5(V*sf%UQ-*pcR>tlyy|Rib0S%8n|wG#jQJ0IL(nBg8~%WN;&*gy%9rc}*^OsZ>h? zuhju>F(*37d_uODw8)0Yic@eA zOF+yT!>=b=($dnV$Hm1(Mm9oZahnl^!S$5V7 z*y`owbO$I}Egmg?T&`RN5vmmcLYe$ywbxPA+yh=~od7}{C^3zPD@W&7; z92l`c2H&0wVZuvft`kl}oNS^}BKt!Oq0*%Com`$8?30qfR(b?1ZL;*L)QD)6s-XkxfdS=t$)%d4r`p05NiZlqkS{W63%$wQesE zLV*iis0RD72FJY=kli2x$Kf5qWyc!` z&2pt&tzlT%AdJvuk#zr00uUrn>?l1QD3f1rb~F%p0OCXg8$F)(qf#6|Q0wFhJ9iT+ zTS;1&6bpg`V80}=Ro>{08)JbL3-*B%uAzy!L6sC?aFw~*+6FSLY)jL^QIvM&&a;w$ zQ{+w{+yxm-F`9u8%s4^-DLP6T!FMv*|6O9y4sd{eRo0iCP7+5i(EueI2)WRF03ep` zf4VEADz%VrVC*L=^DTNO?B9rPxr%q_BNQq;0OF(P2cdC??7|DY!cdR`E1WumR2hPk zTPiI}3*QzDavx;zNwJ4h4i4=HtIU7&4)KyJQJ`>dyIRksU_Mzn4T4%%T9TKq&(F() z=?%h!+XkyAFqHI4#EeJw^&&o>PZ)7^gswC@Z@01n2#Y`rr-N7a|IDLnpi*zfB?sr` z$|!-8W4r<4v=ao?9xEP*p_Q>>92fAjl`YeNIK3-BEpE5iLbg#gL~2lMMO!4xVYwZotYF5J{ZwdGtdt1xvZA7bl7i|S&A0!(7e30 zp*_jOc5302@F818=pKZim`4s)i2Z1ll5)kjfqoxN?XInxTM>)MrM|0$vL@Jssme8I{;{-6ox1uI)Tuda3n4qmvQ z3&s<3Jv)8p<*cAt>p)8{z}4#t))rgj%jmWXb8pVMpuSY_$NBT;|Cm0vDg1d`hJ!R) za@sTBh@J^d(dlYkFyY!i&eNF+3N`V~bI)6Z7a#8V#`OFP>h!(mQJC}#7o<%Nm_5_5 z8o2v3qT#0l9TH*)7V(Dng*_{GChtLNlti(Pt%w>5WtX&ZQ`$sgaBA zLLk?^OXI72AgntCbe~j>zhr01+^09rOLsKYK#0%Cc+)2%wCc|IUp}?oP-S|);b)wd z?l2Zk$mS_9ABW{sMac6p-c7dq5KK^|kb+*6Q8&KD)a5J;)li1qk%-y3^l+ zUz^lVeHHi~hh3eu z`5;Y;zkH;fzuiw>{)?N!CJ**S_8Cg}!td!05Q+oKY}{?Rl43D^0wzwPC%YFmUEbsl zwERtB$W2S6iPoF^j{+ecs-$O=|1q&phY&`C2xM_ic!*F>J2U+}+xqZ9cgSo(Uiw1c zx5M2*lHl+H=E2rgW@Ne;D`P3R3$Me(Xi7lWVU(=yezO|n11!i(4aybqg;J^;;yyO$4l;{Kyr{IoiXUu&NI z+v}aR@T&FU&8AtReQ$p@uEM~cz2LnqboX~uG|{70tP|Y#MH3j>)te8!*pbgNTZx0W zbh)3iUyL~m48r@GkAXwqzu%d?ZyEd8*je<1#?)s2gn+}ds}XZ-)%ZC3#rK@z!?v`a z{1!5fs&VM}M&)edWMd;Ow8bNw+}fOMobXPrK~9(IuAeRF1XI#KHWv5(^b91qfNqxS+K2GP@x>*ER1Xu)E z1Xu)E1Xu)E1Xu)E1Xu)E1Xu)E1Xu)E1Xu+A`v|a_0RR0yU_D?FU=d&uU=d&uU=jHL z6#@I|qoc?CH=TnB$;1C&{1gIy(GdZ-Z4I?RG)YKWq85k1}@u@kHy%BZfcMI}bj%XZa0Nt2V3d z-nbCq4$iOpca4*9uLq+hW8p_f3?JGn4;Br(w;K2?IDSl^?O0)kc-fwk&r45B3;_|Z zcg;VDUL|7xJcf<2Mn^`zGJI6m91s6A@~CM^UgvDiCywj1^g=!YKdrEMKO`f!t-kB&yC|H#gJnC)j_0MsG?wi(w% zF$7Fx+my0nN<~cPgnQK19?ueBiI;~De~zi=nZeK%Jx!Cr{wv*O_W$Ad*4m=0JaQ=_ zCf}FH=w?Km54WnlR+m*b1UAPk1k|fX4Z^H@Go6ln9{UZ%5X`0(ntU+%6sz1kNp6yNaTAFmY!ECuFMV;A$v`Wtk2 zC{?oPq@rJsZ53vnXqOOpVZ`v^hd$_)t!^?4ie)+Ea?$Z?5e;;(;x65-N0j6I%fSKswuI$SLk~`5%H?DOY?!Scao;VG&TgsrQUR! zD#$uv*_A^6r8M7KR$O!}t|d6{1*k_0UcJt;k;^s17NEwaGc2$BiY11R~l9%TgXnK51QvWT}HCz<~Cm5ydQ)P&C zn3f+5vBDAh+1HbnD_fPp6tzx~ck<`tJTG)20)G~f7;`)=WdHTECK(EOaU-h!^Eic^ zJ_ATEiV9Y$vdfGF@MX`G%Ck??v`CdF=q6Y$W;xF^*(-l+M&n#@J(rY}lL}I{+dvq0 zgMEk^E)JHTmXdNWnwCozp9Xq5>1CP4g5gcf=!cGP2JX8`ahfc2FW=r+QcPtLhGb>r z&xoVAj`UJDC~}KY2W6is2E^n`+AoOx>WFQTrn6n%=tSEum)b>??D+9IP|~5@ieMv< z1gXHNM!P~%)dc2SZ)|Ty{S;}LNeDv3Gl?w2k$t62x}F;>TL;8Af=~y`Bt#HIj7={o zw)K{iO)wL;Hf9&YRIG~XCnbhKEu5yhA`j$Fn(LrF@S{dU;ba>MmQ5JdUle*GW+K6L zEf;YMWX+%)peoIV$nh!*i312#Cis=PVhtcHKQ+NX;f@fao3`(YgCDTPmAV2oUgZS# z8@$LfjZnxkA=Aw#ze?VyP7fqiGN~P5z)|bLssYC(h?f~lP-}DYuuUOhpCiFaxZ+64cJ#hT=aM_kF1K#{Pb8uyqX|1uIiF(#m=eQz0QLDs3!A5 z{eJktk(=OGktKE}6w@Ao%&;u|f zvdpe_!Ugg>4MEUD4%tsP(c@9jb}Jm6fCUM-{{CT3PQu)d1Zwby-SY9`Zo`qe!Sx7s5D0l{rz`{JX1@|AvN11NnSx@ZLzwoKD9<598g;xFwH6Y*p%k=> zUyEXP6Cl!o7jivB^^rH-+D8>>6~>8Id1@Tk*l4gZ zPM|k};%jTS8bO&r?JcY|E>$Hb$02os)Kp!s%-x&Wp{d?H`O!DqOAWKJaiG3%f|&u3 zI0CTZksr_na5dK8>hv0YcCsoZ9}SzJ{EGhFf<~-GXHiF@FDN4K)tCqgQv}6kp+sK^ zzzLXva2&Tyx{<=jLVz?wX>ee_27p-EiRBM``zUll8>z3Lh~gR zA68a^GDC~9^}FxRH8%F=7SO+3-ihQ7o4?Z+R9i%J9i#(27TP{D^dV-fR-@M7U&OU8 zN8#+3FNgdel{T0dtoQb8k3Ng!tqrZMYt89gN*Zn7&z2!a>5K#ee&Y;UCGE1!0X3OU0PFQpfnVO33mubZiQ^R zg93jPEbns%@IVUz%xfIyAfW-!Blx3WB?tll1HH!d43erOK%C1DK?2FjZUDw>Nu%?^ zOTk{pIeX^juUu!v9PaJw>uqmbsEBon*Wj+__t5FQ^p?aAn<%baMxem(mHUKct2Q^sFGCXM&jUGx^|Tzqo%oQDeRt4w z7B1q$0CWaD1U^TgNrIn0y_<7YmvYOn_XnwrFXzwY^v7#;GoKIdwl%* z5FaQJ;D`Me|?*Yha~ z!MnHyrUnOmzE3EqBHS78I3KdV`Q`c<>wQAJZ~u9xcSB&J`cBn?DXaJSAZ-J1Vc#Xk z_4_k2Kxd&{XGMojJ+2xz5cx0NANp;t%8CXP%<<#1D?FQycof?>+v*n)wb#=8n6!T z?;gm^%naL-nR(zq=DXI;?(e?q&QPGQ79mwAU5!VLIG^CvnxA!B&78UV>cEX5m#S7l z!OXAS(W^<7Vxa%x9=3m*DbV-qN$(wi^ff3fz`u7VV+-%z{hH}VXDwe;L@P2B>8Sv| z`C<3MEAB(UZC^YC6+DnR`0E3Ad#epFd&odDoRjZvgtY1#^m^Al5u088-d*~4jBu`j zudC(5Wmllna`b$@=|R)#E1!WZ!s^Y3P>GEjeciYC-t8LO{m~FWq;+$04%>7Pq#!;8 ziGfu|pk^$5()+X`$70?&F`r*o3kc}yY6Akwn`xIPT3e$|w(?ztib0tLgMH1?5av32 z^X`I_2o7HU^bqI~xYKThPqJpFGU2+wGEcpbBh-tAF*@}bEK zj;u0ue{bxz=Uu(|;GsjC+_$VcwAu87sKaX0FS7!k!63Gqpn*W?BJ&S#Rtyt8eAZzo zcIePyYySnCkx)gS)At8KUE%UK*1rF4*8^}c-+R@-{6o~~4Mvb>V{UR6JDVnlqelR? zgO?9ao;~SGFMjsB-_39km^kQbeRPw#`H%&!woEd>HvpswK?t;>C(y3;UrZPM8{9s$ zdBMc1lYGtYnhN#u4QXKT0g;dRpL z|LLX0uGz;PT6O5i(W|o~yX7YV~18KP9|>=tHdo!;ZiR4)6Br74Bh0i3A?^ z7)P#r51o(3{lwnhcc8*u((DCSP}`?;!54N68shBiS5!oaifR%Q?>ohu4-M`o@a;}4 z>d=;H-v@UaiMF;PDYqucwuUQ}Mt~@V`4UWL@|)Ce;LXOuXLVB*&(TJ$wkecaacymH z!wh6&6R0*{G*H2CG!0uQbtCCBh{tt$^`cv0p-rF@=u#BAy&7m|OHTn7ve~(stKD9< zg-LdH+(MKt6>{y8`tvQnv$5W6i_}s&6>@u1%5r&M9QY!g{9nBHiu2(X#}|LePuZ2*e^ivWuNivWwj|5XI+Ul~=s z&_tvCue9+MAfyg|&Qd=q_Pz-No&!Seh;Avdy|1h(gyqjZB4Xqy0bCrki)dRYz z1AA6`oL}p4&ylOM!~OgmT)O#PzEj3QgGXbDqecuLyy(eJdmp?xn(l%7jtjE7Q1XF$ z%}){sN=nL$4FNpCLtGe5kLCf@J=U4%ekq0X@#CDWW|BepHlF9%$Q(qazNHP|a4fd~EFC@38@c$1rUf)$P)X``Y^A}!F;b>a3<+0%nf=km);fEy;q17E*K^I!K9u;BP{ZLJ_YJU|wG zzjfrr(&#{X^@vN6_L?s11R^DWZ;j9&{Q_(ae)fSzI~^DaLIT~w4~w8rWNEK?IE&XP zR5xyzTg|+ixD(1~2`mo?AE!O`Yh4!KyjmLrTK;Hk=u@4nJY>^;%&_i``ila^{4AYL zXF!qKO<}^@oyawB$>d_^*K3c}amgeGF3R{J#E1n{ z&X(puq}H4On#r5fbl-BZZY?}~C(o=%K$et)c~x9~OCF5$V4$jHuM-9SzFd`kJtVLdtI->a|K^Y3C$| zF#`EpTW=s$09BNsCzt$=wsx~6G><-&QldtR4`j2(PHz*Ha{;2%6GTAa7r{=IL15pm zxXe~lPo4o)24(IJvKh_Dva)_pLGAEEq;4b$pd!WbK)(N?&<3ps1}Ol!H_gr`(p}3$ zNzy2nl+bu$802QfDCn#^nbjGTt&>I#f13!}BI$o|bt7wD@K5$*8He^aMBLEWty1F#=Kk^qdx61W;i)L^hrsil-r zbEX)ArAL;Q%Sy_?zCzXID%g7`1_ef;p@)*Z6t`7ptK{nf2qGPsN6AQw6Tk-W!Eqp{ za0|=Ca#ePTIL8awSIYXiTGDC>I-BT3p5k&eDkYqQ&4PxCq%8r)4{$>EGc8!-%nWx z{)dr>i%ut*Btj=t*OT57Sd5QM2E_*Dn}DD{8sGqdr%On(R9GT8jmE!fX;ZgLYCARY zp_@kF<0t3Q=2hgW0G&`H{enK-!8+pu{ff*(2LLPt_p5SH1>pQ9DMP9Z{gj26f~bD^ zaSQ}XRS934u3iW22jgHD@xtK^68#>8f|e8MU%BR77x1^22hyqp^7?TPZQ#QX)~3b= z0oO21MF)RZ$a%H4YHyI<&?8nlBI485p(D)9@E~GBx@(l32QRxEP6J56WPeUTaRmYZ z(eWd9=OK-etsn^yZ;aLRYqcVs2n^GS(MLca1c@hT3JN(oadZiN{oCELO#kpEKJ2LT zSubF>FGKY9*!(zE^6$+x9GLIK05gh^ZJL5m&jTLF6Aclx9 zpOw5kWmiyasAI0t56xp!qm15PqJ$ zyd|Gjl1R-@+1V|hqbHz<&!JnGPKln(w(U)y?V^XKgMFHlpM`vZ>mT$9NRp`ScqJ`q zsOhQ8ZdSB3ocW#K6IUC(gLjb@#N+3$$k*>z=O69GfNwE7nMwOto zbw_dEzJs`kWep8$TN~EGEB$w_#Uu$JWTupfI%XC^rj3+H>t`>()n6H8rV>n{hL2Br z^=$^?to(SzijQ&|khTDw+9e76+M|*>Q^>N;!x_HZ`++C{jz^SzWXf)STkF-Q?*QS3 zcUG=k(dKOy7eMbONdnB@jHp%&(kSq}2Wb*)Eef~YYg<#kwv&bdU3i7qoV_Q#ZqCDB zJEveJNCFhDXjdfYkR&jj(#~SaPEYw^_EW-XrktJKM1QXpaUf+tr#XKV%t5jQfApaP z{F=}GQ7~Pt(d>m9kRAd26`X5Eck@$B5uqVc{7pjY*{%ryWK?I&YF*mg0y_5}=jTYh z!H=}L=RAA=C4hHs&xM<@Ht`xwp-E(5&-ua&AW4AfiOPHgN0R2+1 zuJ8gaU;r=Y)d}8v=A`D|I>$4k+S7N3Pu{rTMoa_y@!sbz&}mPbrm!5&d>w(NRiHsH zrl*# z4YBJXSU7)j>!M@AJi=*Se0;j&MUWV914#lfL2|$yeE+Bwk2ci&K zq)CA6b1o$$T!I2nq74W8@$>LP`1oq?&H?VLZr&jw3GgPLDIR0AEz=Kj~8FL8VJRU`t;`vJ3k0}><% z{RwmhHdOtz9~1^=hR&Q|ZbLX|A`tmhd6@)>613aDI$^`iu*qSdir|O}?+@JqvIZHU zi!g`D6C7V^7j$TMx0{WD-c_HWR$76a0J0B?1eqH{GiO>K&CI;}mias`66hp14FaCf z2zsdc8Z-CRVZysJtEViui{HUPl^`@T^V6R)Lo@z?y8i0h91*BzJSv6T&0v`2W5e!( z<;(-LBEo^pyOXC_znht98pTrte7=bCC@QKE81uy(zS%9mx2_EKgP8Uqju}W!;XvjV zD4wy!{A;#@x%(dI#cWQsDRa2>U0;;KHv0N*^u6oufcbB^`|f9S$srMNx9uSi2s{KH zT7E!4o%wgs7c;*G5B3<&PNp!I-Zvp>6QeH9%H7p*k#MYJYDZ5^L4X?iDs-jB`t1`W`w)ify|if{U6 z^~OybnGQt-dy~elx(s3no7_LWeDKf_=9kNf)muy_0ME79t2khiP^dSQC-IVm%RXm^~q{2TS)(N7P5+VK=~qInXtH^A2(iUMguY6_pZF4&uoVUuZ9 z1Yb~c@IO53>Z46{o8#&%P((Ov?Y!X1>h6wPiH!z|66@jQ7d75(Yd!nT{ocyy z&l49MId}vj3e5VTyTkT1f?5j10E=MEbvkY7th1pcBTL}ix53XCT(oHuQkL-Vz79Wu zhn^A$%yVyNA3>GjFfC9rsQaRw^FCxdd@!vkGNof(L6^)mMHE%k{R3{RBOoQw|8(^I zYBYN9{}IChI+;p(+Zp}iX9oLSVgkLNaByoqRFSday zfE^cZ{yHV+?s}!u@g8nowd$^(ZBprNxW5K90vns8!b>2Ea8c^S?P4FHW{K48il+hL z4r*zjlhY+y6XBB7DNx#nubBOE?_b0GI6PYYtnH$7o1fnk{i>}`g@qzpCW%ZJ|31~i z7Ge=#5nvHu5nvHu5nvHu5nvHu5nvHu5nvJcKaT*b3Gjcui`fRU2(SpS2(SqB5rM=- zA6S+P-Ag})0Ui8r)(@a0_p+`&Wq%nFLWd9QQ`tupdZs7MN*wXrsG~<;ctllwIy`Fl z&>s9aTnz+P?Eas)`ed<7p=X8;1*)%kaYmOzoj*L&kDpLG*K^-CtQHvk-0%_Aj~d^L zp1H56C3YOOhFS)FKXmxe`+r~TQvWdc9ow=g5!yWRkf~Xt9$7s-0v_N&cumKWl?Pv+4xxF==2G zGAGF(@yeBxkxNcDi6id)^}XXPPJ|XEK4*ly9wm=hscpQ|BzLy^`O^3j0-4@ zmbKHh(7Ju4ET%-*@l*5=t?>A<4hXPnXxY#Q^=yYPAACQcuymrk>ko7~?;3*HS{gDTu(K2OrDgXF29w>1@^G!TulLyKrUXie= zyiuLE=NlDI0^2n+aM&1oqzsuqL{lxs{&HG5#=VOa#F zrs+m;5{02xwmKn(SlYCFP$NhsfFl4g0;$;4*kxdP?(`OAa-OVAh$xwIrA3yjB$=A8 zBFoF6o0Ta?ua@BCW8qCvbY)<g0Z?9Xw{ zIw1UeeMJ!(sT#2&!Tw%XH7!p-7~5ETESm1Cf7D)w)97@f z6DiTyf&vLCh3Lrfv?u~?AHvo%_POc+LX0oxf*J`Ka9Tx+a`bxw6hzXe6LLUSY{&7A zRLS6^rx;BJurFqsj{u->L##304fm2Ol>x$?R%14($;4+e7$2 zOh`lY8#^V9jtZBhm4|~vKM#xtG8;@0mL#S0YiF6(+;oNQ09(d31?b#RPuxhQ%%k0V8t_Gr? zRX7KzY|i^ce=Dg9rda7Hn5!|J=%(Y)7)e1g0D!!{vI=ZZkn$@wpFvqP9|2E=7{Pgh z{2&-{n0Z3!*dbHfDrM72`Nv2K(gjfa`obA2-=hXNnth3GR~x85w3gOFbh*$;g=)tZ z%rLEW{iea-X)3ePc|he3#SjrT*y)Z?At59HCqiWvEU36_^r&25L9uj#5g}k?1pNSM z67{G9XcWrPIs;NxBnCLGg6aYqz5PNf4 z!4E;jvbMVDOo_+zY~?W+Jhy7yddnCl;rWiw>MO6EyiV}_&z)Sk>RD5U0kC%l{w`#B zD98rf&S(fWhDGH!CaHZ|LZmads$h5F`qnYbKunh~-q%;vJ6CQvd7aFw1EO5u-UGDi zQQ5rAu>d0G@pvqSQl+v;>

x$qF_+hwzyL$m%FX-pt?Tfqtv1zH%k$%@bWpF`=Lc zYljtxeSm{89dU!RLht*;QB}2a2JzaQ!d;^uf%50Ui;+TtIYqj6b_T;1o~?6Y3ATt8 z;Dm6Ay`TwO2hT$audf_EE!FZMne9Xh9Zd~cVv&{E1%-182`2>W3WOjiqN))cr7i1D zlAwKV*Y0&I=T3Jv(FaDOsDijp`j8^5qWZ1X5WT>6(0&UZ8 zE>lj1Q>$p&c_;ofO1y-wrTqCfF5h^AP%;pLh0AYj*g*Anh`C9v2UKWv#Qng91w2?z z6@(>{%K79{_J5M_#t8)NXvA0sT7?^{d2WU0pFg#71KXL76A)OSg$NQ@6hK2(e=Qhu zB&Cj1;S^-+jZ-XWexxSkm_f?$#+0m6VOEBQxolB#bR7OACtwTM(7x5aT8~GaoaS1Al`}ikCd+M9hQT5#NR6-+%K=YLX1<*SOByWW}}Swi!>feKXdt-?clG zF7hxw6AaMOMxn--5b{kD$%=|^ao693^=tM%guOjxp^o}g^8mY6*_oR~#ZUY@rB!G< zI~8&>bxn2AzoUpg3m*Ec-<>f@15ySoQy%caD5GT#@rwE$S=PeTo8p`dtB0x=gu|kT^i5x~d5&!$x--(*JZsoluJG?8I{m*Q@~##F{lPxCzC= zR9E(z1?P$;!^#e|9*u3hUav9w@JHkGEFTZ=uitfDBbtP(px(Vc!Cp0XP~! z5^-xJH{#;66O}3zPYSUy^)@IK7Cr%fhtzOOO4fMw>cnb^+T%4~Jg^#DEm$o+*R=p7 z4!0*xoOnAc8=Hg_V$(ikaBtG^Ye1fQ@3#*uQSAdC!@~qmA~*ax@8%TnYAuO{o*_+_`fu`{4!IAcfetU{iJ$NFn%U5?RmDwQOCn^^aPKfu<2@NTQ0Ut`xt#sSa0u{nd-sCkkn->4_9Mq>0Mv3g- zF2vu3@hWB8pC=Bt8MH6dyufd=goF$deNMRf-TO z(UoIb)xHF?J0kL}2f^y_=1VVsh`(>Xl{ZNg_u|1f!TSS=({vd-y&iBffE2>0)o6GJ zO#9<(EBHL#s@Y6QA>MowoD2s?086)qG2CEwpu7$$O71W#4joU)zr2Mv$ruAA_cL8S zjRss$dY{i@G#X3E*n?g`MRmo!`O-%;?Mt)b7r*&kJntQP&7glKafK%rwNp}vEh<6^ zaWI}#dc9CAt~iA0}@YVOUc$PVMYUTZuqin z3jy|TQEkN!DLy1QfolNrp2nu8pcu$(j6ez|)4;~%GB!S~fW#Bozh&`*s#!0wbvAs( z+?9kBV*mb^Knk({0BWB~ZaeE}Py(53GN~fX)!1m(FkH7ZK9T#xrv1QvDhFrlR20@e zV&xP0scj#C0E?-#;!l;Za&8B<)Cr zGAo?l+737Vvyj%xHz6PHdJ2!?naguNwUPD8q@Qz_$yrj4w`S*{E%HVQSqyh$5~0?Z zl@Pb}Euq_sNNUBHYhgkyL51~Io6s+_7f?PAuz@6_MZ{yU9;F<53$!97ug+#$UEfS} zcm%=(G(L5X$Y`PyQsIhpLdvn_CG5*!Qx10z)DmC5EXUXpwF3buMJ?|8^wH*)x~*H-E+a!2nue=1 z^15YP4(7qL@~HYn8G3I}q4xH6J)1lw{w>N$A?o9o$jpbaZH@nzL%1xZzY1$|?tkQ} zy`g~D|H>=yl5Em|w78KzOhQB3`7C+*oBuudz z8{1q(vLbL&G=dhRbS!~Bus!L$s4j%-^s*$EQU(hMB}P(Gl2kbJm)RJz_||K|?}O!Bty=3&4~#&qI; zQCRfAO2)VUU`+WBlK5@J^(z`-#{-orTc%8!27E=m~kG3^fyeNWN%4}hAs zqxOjm?1WeTUo5Eoy~q#ZVZi^*W<5~-{|y%NCE(fbM}G1k>h`Y_?i2k}!T<{B0?~gz zz{$IEc>Le~@Ne&F9|#$WIvNCzOAL5b?Thw?VA!_(UvTjM;#bY?mumcv|284|yBF@# z|G?tEp8jt~`eiim0dzh;9I_D%m^|fhUrhESd7L3%QL4yK)D6?FpZx29*$;Ul9XLxh zK7Hh5(l$k~<(+~R1Q`9!F|)DHt556QdMm=~!{@+thiiFEc1pf^XW5Rj?G@y+S?6}g zjvb$tMryQrG_}L@Nm#)UTV$PbkGF$drLmXoDDVBnuHzYd7?ZtRjdkKX2Mwnoltno$ z2PC+Yyn@u(96Nd|r(X^~>i{5`3f775JdAbXqhvCMLsrcZ--XV}BK`4a1fWdhC(D%; z&ot3*BPMwh`E}yQpss&X&ylX$i@L;5p02FC)Jw6jv*S*t}8Mg`e!!M zBPj-3>ER=B7Yv^fOf~@rMhFkdu5_#@wdy>FFK#FbX6dPm!* zI3wIm=|RLno;JO9v<&NzzuUs&^yp#ezd}}U#_y+pn7eMnil(^EI-l)sEfWu1AaL+R zcG&z)>#z>{@lOc?8|%Z*oy)FPUvc7-a%|VnJ@HxnwJPT|#f78!t9}=nFv4;UbUD9J zyu&W8sKi3`mg|6HuftOHD_0gg^|jLpm~QuP3b1!=odt-1-6vZv`hq(upZ?_TgkUnM zb0P&N$m*w6A8XfP;ZO>?z~W?NfqGyQ33>?vJi@wy`e#cGm*KK!6a$rLM8^$S@0p6D zg&>_B581a@Rb3*m@RPe|*jsn)+VxzBA;ks~;!j`Atp|LrC%6JBp6$LHZJ>j9e`Uq- zkJ0VaZ@6BMmAHYrsj9k~DSftn)%+@3UD5XXk1y5NU#3ghJKv$JB#(WWY~m*!UGkkc z;13j&UGeLcz^Bm;r|hevHb7<_Eg?(jYQ+^ai}Dt-K6z!Omi%#+-;G8nEY)3pqWcCi zuQ+zeaizN)-9g#!nYtvz#&&#~uC1!Llm!qlyH32Ln=Dg4Hbfd1BON>=0iwK_l&#{p zbDq@vbmgT#eT8*0vq(fjzimqS4dqwm+mBIiIa(+*eDr{zaDeJ~MuN)i-Obdi#~ZT5 zW-O7`#MD`W(C_$)d>vL)=5%K{utYh<0)9*}@neRh!VF=ddgs^LB2xZ>CYMCqxU+mN zz^O!kd4m>!AjW;AOj^CV{1Ry*H!fB7+`y$Pv^n8|jB=}#?R&{W=`tDZWnF6mf#0ua zPyz&H38p$KWI!cZEE2O_qMG8^d5kpHD~@g~R9sm$Mo215PU+@4A5a1$?JYp{zw36_ zN#AQw0t=05FM7I&F4k=c6kRSgn#;Z>v<;Of*f@0jnwyY~vg}Bf$TK2TI_xeN;=lZ} zG+Uj!O-UALNBN7UBmtI-O~%z=W2!&f*$f|Do(|#!1m<1n08G65D;+&b_s0dGL{I>e zU2J2u+FZpPCM;Oo$Y7oN<2}&(b+h9bX#f>B1o+Y@J&@AEyT8(5cBf4#uPn=AEKIS9 zV3AR3pzz2RHbZWlFr{8Wj5sgZ3O*x4g>y{HbQ6;e4ifTI95Tslf{Ay52tvSwE7{@` zQ>4m}#paq~b~?+iWPZ$YLyQ>{A9g;0L3Q`Fcn)0gGw3v z?`RI5VD&#!I!eED$*f`bSC%U^8fAmybzpM2<>}#c>26j%^xNF6(62O?0X=T#^pCXz z)H~S;4ygc#RO72|ENcKJcMh*KNC^o@`3vWSKvNKMyNQ0I_LCEYlc91)aBSrd?BZ6b zM=Uu_icU#Z!SCJp4wx#O0~|Wa&B+|%6^qmj!m1X%w)q&vgqJmqsRJBuS^wNR7Lbj? zG@Clb$|<~lD24%ode}njl2&(@JuR)ZH#eU^Uxhxa|M!|B@Q9jBs#riaGON&b<||XD z!2i&T*kgl`6rY#@XylwZt&;4f6|d*}jIWA@BtZvu3_v)d(((!AJ zLFr0$TNsLfj?hoE6C>tW(yAMu&hi*nwb)4Y14cfUIdHnYm77(rtg0u|8HF0KPq#(u z(|CMFz+zE!B5?gKc0-$%J!Q4nV|u2Abc2;u&VTcbti-*p)}K1Dj$QD*aQDipD%^ii zOnL~R#z1JtN7SP#I81u5*gYjn?>km@1xl2 zrLQI`UBxy4&=3IdH!E{?`S5LiFlZ@kl`36r;#%e^T1#bB{f5Fh>zR?MjJ!I%=>&X8 z=DE(5>*#$&fZ%T349ZI?T#z}IfY0ku8!0B-rS}mUm#V6Dt?TC$t`9}#II``y6U2#B z>d9og@^`qOFaVQYM;st%#|CO3qzzi;p!;(v{EEvJRX~N4+mXUT%jj^IIDp;<`V$RbZFi#VM4mhO)a#@ER(QFsKp6X23w8i{&|w57odd-a zoxCNO3xW|v>8dt8#RB4=1BZa~^-s$L7~9C458%YNuPJ6qBo9r1V)t3>w}5Eag{-J zemrW;P@{7e+kj*zSK|*!^ZXmnPaoY)csj+TPj7r90%PuAv&z+RW?D%vhyli{_SSZK z{E05N-UcLlFFCb(bi{D_$5ubKdUcj-^<#oG{E90I4}tVBOaOq;96aoWf*c1(`S7WQ;jiylz!KV2QryGE(Zj6Aq^O$(9_&GtlNg50YbtYDIHO#IE$smj$-VB!NX zV126^v=~7J7HPNG*=HPnj}L}So|?s7e`Zgk+g+@j0!;duJtKY$BEA3SO;@p&=y%U0yMD!a%yMT!gg7g-cbcIdP1?trd3*kW79kl9i zyQ>L?o}{3F`X`jP&fc2((-HOoil3fM1)}{4f=PcOi(ulXV!wKC68agD8Z-pH43QW5 zH3lDmX*!W-eIbV1R*xvLjmOa6n&>8}*KAZyB z&Z!>YG4a_16aNJe?h6(u!?}1AezjWcQmEBx`kp6XVen=<|BLK}Yh4r*ugqSsktWJM z*9J^H9kgKgFl1cOMCIZ`Yd2;u+{9zzixy-re0bv~3jlY5iQkvVC-LJJWOuNq5mwBw1cc8P#QSP$N){{c0FzE& z^baiFRP+AK7nhBTSKhf-I?P)^Md~8}vFGG*nD}4Te6VjJ!Nf0~xo8vr@_f85F$6HW zX|)}gc#CE^Z`QOw&Qwi^2PQx313=;zE!s*T@xawte>N@Y-r+UE$yqa(pej26frl)j zn0TPmXO_&Kx%rV2PEm$l&s?|o5{(R4SQ)}eL#0Ff$jp*g+Yc)50FzEc_1n#h9sx8J zl9DKyAlS)X9_??sTZv2NLSn;#(vNg{rO(HGQU-1joq?FLOP zdsNh+`XdUv?9G{}3*LnG4>xaJym|8@6wghrNa2Sn?(%3qiDC>RM07811{!|Wi%)(? zejb^fo}TyUcN{0cxI~Sy)34S8lkP^t`wB zlSGik2_L@s-5?*G^|i|y9w^8%^#oe~d_mlha_q#*X(g!I-6`SI#HWQ;r zRD+QqV6@5X3U-oxh{diin?)hv093~xdg;rpe^1kn_>X++7GUDR2>@*U%j|R9^pa^@ z2$cqZfBN@IRa(;Yxn`e&c7Q;F&Spbb{xVVmlE42z`-A(V0=kD|OnM%{5Y8iF}*0CV4fSQ@l3Ms5ls%8g?qErX^P__Pu5asetn@=N;G* z2KZWe{i36|39jqH4OpSZ#64t4=2~Y5i{}66V0*{U&T}*teKQ}%{(bui8$$e{^9S?z zMiH@Qy$|S~UDhxZ_PJzI0vvE)n(pPOn0TnusgB5G(9Px34$dOH2FrdP?XpSeeL@<&I@!qv%-n5y9mD zoFCr$T#>BTTROvhFp+0lyF}4_<8*SJ+G8=Ob#nPDk*evo zd~tlZC+~N5_y?ArAE5I#A0|X!)`z(KTLLR75fPGHF{<8;i-8xq9gzsh$C^ z&j|N?!Zr7#q~y01rNZ$Pliy}8YLf^vP~ocYb;Bx8jx)$WhtSw~yD?uLX7c%7wf4$< zn~RsyUdR7pJ3^xrHvVF&V~S!Ph{NYdTR(^x$^Y;Jj2TMHkqxeIAz4Uv-qxQ1r=O6v>hY5X( z`U-t++yBW{uY`ALXKBLH9|0iTJGVps*n9u`+Z+FPe=V|NIo#eFzPII}d#l0TgYo3h zeSLw!gRPF-FON|ku>KX;<)4i1>7VqekWs1_EZIN*==?u%#gB4X`zT)=MagP_Lx6?< zFVTRM3_lsci@O073~`vi(&PC~u1^E}`=$TSe(q)05V?&0^eYK4fcG+uLLskqfVF@0 zed`yAezNpmK?xB5W0B||{!Y-1jr&ON+v`Z=*}J^`V*>n7z#HDMQ2j&J|KIpM1H79E z=QND1{XhKS-!ARb{1F=QLp@Z^y@+?f!^nTAOWsCZ|L`CBT=my|5A->YU7$Smo&Da8 zb);L9b@Ji7>lbo-r9FXt!7LmZ*2d)jtTX6qBOm`-y#|FT*xk}%*V;-A-_I+7uxZIa z*{UNVKxecayMg7&pLICOR+KrM$4$cbGF&37x}Uqk*^PM13XrwOgZGbACYU~T?BI~9 zhNDoZ-3@^e)tUv zQ2B-CF-4KNVg( zk}o^=Tk(vY{c35sSAXHc(Yv}-I0=B-3vn4nhXV_8_fahD?s%7cA8?Off8ns9uFk-H zBrrD5)6~fZ&5^_Ei+*Dn)bC`0r-Igqjk0;A=_05GJnq7gTC!C5-RQ7U0J-Vi9c4RApoGY8UO`Zae-gBDMqEA- zapZTl3x{jRk@j+TqA#)KX%zZdEmnzFkY?vRPVk<+Iq^lLY4SXVH& z>2uHl@T#fbE1fOuzH{eSb62kWyuMs~q0Z3#yQliUtski+IRYa6S*_s@6Pks4uVC7HFIBC9k*a&c9+3;6K8o)4JGY<+aIAJTRtbg6{ zYXGqDT{Ko@zYZWizR5fZu@TJB_3OKyYi%vuHRGDI-dGD(f=b7jL8%&^5CHW~VSc~q z`KqGe8d)Wt;>E}p;;@FUp0>Vl*Y1-Ktz1=A5Bdf;3w1J9P-d7ApmKZDr^s>chT~6R z3DA!LQF5+axz4UVxdFwu)Y;cvySCCf7YoJjB%$DFAz*!=vU{R@)G&anqaBu$7DvVT zb@xsZY&UjosB&Ia1t=k@BEzTm!5G{C}r4dV!Of{loq0LY%6t_3R9hmE9M?j zAP_U`73X&!zfw7cERja^JGu!w08_NWA$6ZBC~qQT@r|91ZW@SVLM2=2g1f|>s81OR zhhMw9+9+9FRyIY-YIQiKP<8-DV&5qRDS@M#3=fyDIGV^x^_4r!WB4pg|1qsYs^6YO z=qD;2GPjg*ul^07xdaO;ZT!vaAO#?x#OmfIg}A8P(M0%hpr1!2k6{j`pnV8YPZ$AQ zRKKm5VU+V5*AQGd)t`mplTAtE)24v?(u!^}JYPPseL8IjWzD0X1WhuB^;ZCIS&53R zkOC8|EGh;pk|=dI7LldO=M(~ypEcK3x7O@16IPDP)61{0@p63h9nge#X;(su@BD*J z>AqA@S@3QeC<&Cn#j=G4M3#aQVGE<2VzNk6-?d?waDtlQzqF+O9aly_3o;7Pj~Tbk zE%`mVw<&3Gx{{|v2)UK)Lh*0_Q=AIZT=Q(`c%1LrD*m8_yDBUGK)#I}m2{91l#`05 zTxsH4XlsqY0ao*r2;cx9VMv6KGAM&!YnYM*I+F4$rSCesN!l^cGROrs6cCYo>=u_4 zl~+27z{A2(B0y)5Rs_{Q$KocW2*pJ%)W74H=~y|{U%6w{bD(@Ov~W^By;@_~d)ev8 zVhR}nk_(@6#fJmH2Y?>Iy;q9%=jiTk+Ro}9Juy*u>_NAGMWQjdrwz@nn9dlYwoV>CiM>>`KT%%OR_yAL_hSO5Ni^viyTfD+Wj1=5Gq>* zTskqphEPN+kiJ_{;WTtNzXRSLqTe=3{l4`l!_!>HCz(c%1Qh@(7Eb*f=oh?C^lQl} z=)de-(XDQ3K4z!(?-(sFjSVO_XB8;|q~b(#0E`Tc1xh=spZ?`dq5hadNg0@8>AZ?( z6&|QRPCM_i=F!c-GRVww*EK9pPsI84Jd-cqwf7RCqMc)ar8w{cj z1yJ{7vWYTB2*#d3XRS{iAfyn=R8_6<1e$(*)wS!mGlTw7%s}*EJ_y7Rxzn9@19$U@ z(BFmV@2wy1z*Hm@vdqyc2`hsd_g+<1*C;Cl4A?Mvk*w`(2V`Bk&wB zB3MYL2ch~~85Do5_T=tecsMWv41G7=d;QeB&z!*#Pr(&8`tm`nnsRA2wYdI=L@g-m5KK#Zi5JSAaY847G@6z;RBYhBW4LbT1|J2HYD^!23o2^YR z&q+ZHfwWozUJ$0ZBxc8{Q>UnAE{l1eUK#0gsBIrRpMM^t5ky@M-i6yPCm}Q z;K(ot$Wkv@0T@Qp=_kOE47CTO6bj?Ka2jrF{s~+7y#QzYpg+1}^H;AvwK}!oR3yDb z1Lwub0!&3?JIXM4Z>jdEJw9J;E=Vc7#(9xx*zM=FBO8Jh^T8_de385Hd4Z4OF%VR6 z`X}-Fa}|t&vH3;g)gHe;7q@w{_s$k6e#KEzAZY`5Ey&*UpN;4tNN&>`4GpJ2X^?e_ zqn98*kDcnC^c4O+&-#d{Sx4DfXOfSwq(?&Gzfz(akDBgl4YX-SEw6LQ8>U-zbY3zG;}T;q*5n zXaQF9V|(`O-VOckqJ}-3oSrh}6c|yK)5Uq&_n@G}u$zLrL&Ee<4hMCZ?hlhvoCc3W z(dmcQKX+!eOt^}eKB#E!-*aY9;d&VeIb3_raB_NY(R@5h&9SwTewEB9I>5q2hC+c8 zLqy`D!*+9TI8hPuXgj^(@tbE>5Bou^HF*EcJw@7oM^d-D@ytysXByXJttPG5W5J}b zbr&jK&G-VrI&dMeVc`Qj67M@YY>mZyqMK)2#qMJFt%s)Gyt$`wxVOQEn`dt}x}RuC zB9sY2EtCM6|Pq=SIq$)11cDJ1csm0B{%_q7oiQv<4ZCtZv(*nY1 zQC&o{y6s-D=804rDM5OuHROXzy#bUQ8bg;xV+2KuWxb`9l47LDl+_zkS^X#m$z#n6 z?zXA7Zl5h0PAAkMJv%ik`vsbA&6))ZT>!t`p87@hnl%f*;21HyB$Ppk;S2bH$~0_Lwgn*M*r;UnvpMKBUcFwgQW|PKUJnA_>a(mT^gz0-eYm&?iEiIc1trGAlosRR zeW|x_WEh=*^j^?$v@al37W7{>;g?WmV{hYvNZ6qwXz=^MK~?JUY8XGUNk_oBq6vE! zZe08Rx3}-yxpSK&Tex* z$(qrjU_QlNER?&UGoLTceq~?J|H6MKOEeJVk zK*&+EFkF8+-0)Z|rr%Eqk{*x=cdmwWi#Dm+7oEG)c1QUEI6Y?maxwB+v}tz6xY_60 z?oA!M4M`%2ssm0?rEPUE*GWbH%g5zNylAIIiJPksPm z3lMTVqFTBbj2HsET@Ff)8M_&|!Vm%{hgKc#Tc`c8X7RX;c(8JO%d&E8Rw0kgGY`?; z&#IRg1~wo^a;}{|EbeH31X`i@NtRgynlq+7viVV-k;AI)1SJRK1s9ecVPNq2FbQHM zZ|2MrYe&hW54W9r2{|B}Cl`~Pmhu;*3_KT3d|(;ZM}rRpGHdhJ7YQN9hnp9V6HRz? zGtbD;;rD=&!%HYRKnf9JY(5a8v62)2$E`pyFWvm6vgS>a$A{lNse*nmg$yb3M4@@! zw|Ev|)R^@o`}MF1Xr39{wMm$%^O%~`~Ix$%#_!~(SSjSXO8GJ=u= z`qBLwjYiW1HXHeiTS-Z+dEb%rM7AuBpY`T<(NX=JYWj1JP=(kfd?1kXTUA@|b07g7 zEIK$9$BodD-_T<8b#)Q_on2j>+F;8wbZ#aRE&GlJT1UxuU<9EuE1~4zOW%$3^Ufs) zN#gU1RV14Ohp2@eakJVvH|Nin*@KKYQLonoY$mX>7`a>gC9J6;mK1{IabWhLEn7Ip z(QJnGN4I#(e#l4h__u|pb;xN)9I#@vP1(~>^n}FS_^Yc$8YAB^ca$t+&)-K_L5RHc z(SwQS52&aEhozal$O=*iuzGA!Z9V_d!P#7?BN#zM{s4pj#44o?oFF0o{wjqd1reoy z6@hWbl!k6b~ab?08YqI6zv!!Pz;YIEzkW1 zBsclXvj`Q>_yIp*%+SX%j8`9SlD%xuZG9`DZ>99QV5ps(lDBBpX9!I$oZ_BW{`sF@ zN%5+gpjVx1weqb#d;u{ZgZ7x@XJ3-&jV}3Ov9w6+FO~YY$z(;*?rk&Thy0>Cde*{G zYhLu0zdYY)6pO{Kvq{jOA-&ajODQ%Q75TmWBy`0>ek0z93wOMcX(#;j7r39i1wIgi z)RhlTlD5WMw|@EyS?@2na|Q_8$ef1QPKh2`I)yQ5Dq#a@D=KPhq?{kM2jn$Q0$UQrAb6L5%9xEBWEwe$$QM#$PLo7#0ibJZ;6FrXUw?{KZ9+A7KfAn z7=E(Yl`#**JP`9h%mXnG#60kSxCdgK0RM*vK&<#N55znW^T7WvJ%Hy=V}Hgm>XQFW z?M00y`U8?t=Q)yua^NfVo~RGVa#B(Td~z}p6@y-z(pA@`7x3Whr8#mvAn`VHw>D@h z&DW3ax$B@>!zY&m-Z|XiV@7Wz#q<+PU9gfO(no7C1V&PPx4F3-z_QtY_ zRlj|;iNbqDy{V;QM_CvW@2uEf_ROD5-rg!QIyIf6d>-68BYXpi0I2n-*$9|m`qR^8 zeZSZQFzuNurIG3~JRVKm;pCt9&1*FK$;hd;Q%~NRT1($02;percsdk*YoFoKd%Eh5 z-W^ap@aRYM7xVzcd$j}L@u@*OcJeOB)$1?%fXXH&-v#j;txLSn8TYFG*faQ4m;G8f zstcY8($~{iN8|8C4HhfUxeLniJ{Yd_)n4=)u8?o7-|eqo_=bPK+_$c@8N^&m0O z^a;sP8IxkL{W|EYI~->;d_~k>x*}-fU2x;6@S$g&iVUyk$VGtCkKBc|;&bx5olo!h zwdOyM#3`BxM#(vy*Bbu)LnI{L@vN!#@Wr^e!|1d|Rp7`(x}al6MWu6|@o=45L0Wvp z6}kXtSU1_a%tGR^J~Hvc?&p}J`EiMLb(%4~lp$tJZh3~b^c^PO;ZC|{Yefrz-S?Fi z_E^Pn(f@+Gpwc+TJ;6yYCQ=)vJP=y;UV#rH(GFN!;BU7 z{J8(D^O^Y8I2zp~O@0N}&pA%$Yg_P4hKfQ^||M+pS*UJ zxnTGV{q&9#qxV2Z=~W@r9CjM^+go~m1C+@1=O`W?Um>!;93+1I`Z>?duxtP*epOjZ z9E;~21t5TTRBlfgly_N6npXXWmSfxN>p#B)Jp8qFD6e+Lb;!S2j#_rZAD}9z{Jgoo zo`h$4DMj#CuIP>&6#1-&^=r5!gu3Inod8lRo!55*oO9x9n1WirYEx`~9bf)m4c6J- ztFL=2n&+V^RN(DOeYLJG??6 z@c>LaipVnB$LIph=o8JWNRrAOiUBnYe!@^m3qtZJxY9#;IGi7MI~>x-z@?IHNzrf28c9)^qld&@#g(0oCfa3|zdNc9 zz;IdUd=P#~Zo>UgStfmg39T&xBA$cdWI3~VbULG4Rm3pv&sLa8RaH#iS=K~*pz_Px zqLpu`V-e9`>1cAf2_b@W9?;;yVzN>+TV~tdEEW?E2LKIT!~~0*-c2HE%a2`h*lADT zEFVn=l+5;?qykZFty1Dbp~|nM0d=laQY13*xl~!KWg%IGu&XGm&Qe`eAtj+wW6ijQB%?G@Br*Yk0fC6%BLZuHhl53~RZ3vu zE1xxKcYMP3L{E>V1B}Fjldwx%JDml@Tcj)?pQsGEi|wp>q90#~6YHi(kD=j~+k$1E zar#Hm0p_xUC+q%7hfCriU5f*x0~Q{T50zm=KCy-YJprO1RSHac!3ml9GOvFW9iV~q z>w-93MxQtfT?+vDApwdDjXWU%tpHmwP9ZuaR|>!!qV1l}GPhK&7zHRiGWyYlNDaVa zPcL`6f^!J}1}o4n*g^~lWg{*?j35DZ#M7qCPmg`dj)bECh38sMa#(Qc14pJ2cx?0l z&@ZTm$3yrh2sjB~8=^ou-|2MZD=yhtQjpPr!ZqvH&!_|rnv)8x&6ntQU8*F2bXHh1 z_&suLjwLt;_5c%KK`{BIx!o-YSxCXxBfbs8TDa?5SH8!>;nDA$==OOe$|9m)Z~%1k z>gg{f2$)kCsFs!&Ts793p6#|%4x>@9QY5#o$GoO6 z3QeJ`Nv$S;eDDBZVR9l|zY7z{K)^!s;Q^`Jow`b*_62v8e@ZwB=Dv4r*Lq9Dlf%Ij zbLR|>f~r*I(_C6F|O8Lh;}v2&&TY1RBFqGpG+w)|C4a&9Goht!`2f%sv$xy~}ost0JNdVHS4(l%rkvj2t zz*3+k`rT@Z$%pp(b-QRN0m3(Y(S5?+Ymj=!O-@z)4cyR%Fo{D8kdT$(X}AmOi8ZYu z#%Rx3gcX^YVXm0>R}10 zV-EQt?svKU>h5RjtDGAsE*-6C_lA*-fE~dwzoTHq4gxDrm+W;XTLa+{Ai@W9a}J8H zbcyx0tE;Zf;No}JjFq2W?H)k@PB^}Eo}icCU~eMyF6B6ph)3j;Qu7v&Hh>Aa1nR3Z zZ>*!r@f=_V?#17mJN>DV@DeF@_JzX(TfTyh;gb}5$y_oQjgM#s5k?_r0o88_R1-}6 zpH70N56@~=-T*HC6kzc?kChF73YZcs=mUqx?&Yf#4=I|UWan}o^nL^ePnsMI!8QzF zI`t@iwyo?G^nwgPz{NX1Aq(6OQxZ=&FJFEGcz6KX$q)XWTDfiotG`36VzU|F8H5i6 zX|)6c>c0`8i^k|bkEW+N(0nf6*!h|E)nTgdFqHvM|NOi+o@Zh8^yl>r|HkSU$;HCQ zuiik&(%K3ifTBcAZn1LJMg(7G8JCiS<&)gzPj4CS5bXVA{;5-^=Ka3mdHnFQ`i*Nr z_T57VeFwmn#T%%rV?6S7yn@O}@vA#M=%L+u6QLyNC&z|62QU2D8sEULAPw_* zOm+A>$!?e7Rokx~3xneM3|3P-^DwHw-|{@r@2j)iSwPcA z$b2*3g85%yq5~2Iqsb9<$dj$~G5*o+Syz(Z8#>dZ;qK0Ppk7Y>;u^KTDg=|5~?(ogkBt5>( zmfLR?ofc9y6aiO%^Yr!gD{rnQBghbCT+lLqPGan-4vNL-!9o2$tSI<>pPLlB!3t zn^UNq0kpmGCUKtz!1ML!^e~+W1bm7hQy0>jXaJ~TORELoWL;xwb=w&>;gp-;ByhXe zxE=z`e#)7~{%=To`$Grt{LQ^jxM#=!hc9NK^aPKuT(c(i4C+>-+1mwJVMLP~T~D}pO#aPO;Q9fISKhig_3YVS*oLTq(x2WsoAtz+H8LnH zUh_m2K|Zi}{A$-3I)dme>kC1@2}HaPi1@D3fDhoz@uGB81ZEjC01DUNR#xu=1fI%N z0*WtQv*roqZF1zN;aKTiaCUEU+tjnE`+#9zNa6Sk+_#bD_AP>JU*o>bc3^=JlsQjt7h!Y1C$-TFV z_C2sbkcFuPT7OGPQ0*JrdPNUeA710pixYi-grY?PoP(D>Aq1u&b>V_10Hh~!D~lw3 zfn=Cn+=k5Vl|}RxeeIY~bgS*$);u1Kk2K2L6DLw&J+{Ay^j$|l13YkIwM*hvd-Xo@ zWkxb%p+iJIbY^E~{dpo0V*0|hP>&4urQ+DVl7YYCkN}OJy=2AI^UGeHV%VJUqbp*$brM;JwEPM7$+bs#Lx} zfPukC=5eDE0RG>;4_$XAehW~1_QKx+kzcdv;k5}Ld`oPa+}H2y{&FeM_|sB4+80pu z)PzL~+EN#ByE9)1S6zA_q($#*O3g|FB%D?|pJ|8W+@hJk%$rFt@oncQDF1<90+e5q zJ@Zha>Rj8zKPyxCYkU1}Yy0*)0*7BZvxbG^|Mr2J_dodJ+y_AB<4DcS2hag>G6`%z zfWkAsUriDD7Gt<-IwYGGZHj;Jx9_Lkxs&?AB7*B*v~}kD0L3qQup{?D)wkd!2w%-- zh^e)dMdORcEoR~PHH!(Bp1|oB&CJ7Q%?FtIvhs7k*FcyEI%PIHiVr3VVNN8nrp*NY zU8e#j{*Lk`3hb|WlKj-XNB~yW`%08;Y)j^IV}A{)H6^ryb5)N3LJxs{;PJ6h^W=m) zK=f;b@hd|QFyd~D&u`Ehi5|83sf?W4+IW(^|Zzc=JU%Zvj0bu))l2_wi`tHL=cz_y3#CsUh0@Z#Pz!)^0f&-F& zS#xknj_ASf_J8}uequi|*!m=XABjMv3#>Z41(Rmyk>Q<4NBg4$hCl1W7oQ|Qvp$@) z_-&DO_M@{N<#ELm^gg3e?FS+s|M@imnJEm(7mfSykvs(IeNWC>aPFlKXORMYxHx|E ztXYrd2{y8dBK}VDzReAyIJoRX7EHfi#r_gJz9?Ds)_3u21I(?q8L>Kv4-3STUQq8h zDtuiYK7HJGFA+zkP9C9`+e{ab%;bQ4>ns*bpFn@!+!9BQj@$Yc z7OW?dD}AQP=;ILidX2`{$!M4+J~-O{IGdQ6(=K50VMpG6!1`%6G>5)_dSeOG^H?^w7WKLPVo*|PP} z;w=Zb<9&5U*>67x96W)eKS{EnbOg96eaQhHW0`K6(*0Powlv>h5HrD+QboWxfosz# zD()hA!Yo!hfWdijFK;=>(@8{8*yqqVn7)7i{w*)7w(RHW2yltDT>uBC7){+pjah5) zL~#3iznA&~!rXcsA!Hx|NHX#ua{l}h@5^5b#Adt<636~ay$WUW*HI5aup4L{Um;KRR>7tJ6y3+IQxNk-Ry%025L2Orp3~N z2cbce@jj7%djH#dD{V&mfvQJu@ML_y9(OQfNDJ715Z&&9h)%P2f*dcJpphW*vG9&H zVB_muxGEi(bjU%{?WCwiQhbnafRN&&ElWiiDuE3`$d})cV*+Tzv)E3;(Bvn$_&yRx zYLV?dlG`I{uFqxBcGIUF{Akw8a*PE_qn)P5tZEDcK_B{G6fhbZSoiXmA00p@kmPV! z4wzrB6LDM6YoJ_mp<(wrO?H+8k*^7P^!kDF&W%5?F*?G<<7#&eP9; z487WD@g|buN0s#1Z+&@app#KkL>zqZz!nlR_pn1=#0k2Y8#iHsP6s9oJEq^d`*g4L zy@2fJw7whwUz{cPRzT!~ zl^|b6G4Z!=ojqIB*I^@Ta}g@YX3juN5Ge+Ok=|RvfVMW^^4r?Tjiw=P!e8~tVr;wI zI2tXJ``~|tf=A>x$`q2)$eY7xN$&cwL~#@B>=bu zVw?b{PQ^F@28K68K6Qz40>n50Vw?amP5=U2>to{KBIsXFY{@}F>K3`uR$iIMIUPW%#5reljDsyFr)f$~l zluvs%eyzSEKCeE^hEDR#$@M1YD@si^ld05bi2GiR81FfJSnrLXgBK+m6gF*BGbi?@ z9-Fa0r)!FQOkAB2o>Lz_?0HQsM8E_^u&LQ@ZwiaOxw%Kt$AXkvpNCz-AR?#HZR)y? zbiStcvk@@4w5K^zH)n;tS!;|`m!ei1j$F(gDMxNp19N>xx?ZdG5>8&LF{*ZAguU6u z^QD6v88r63x-M@7cXZUOhjnmL;^D*UPPKozNN0*xcD^E-yNz5RW_Z;XIu9Q)M0#Xc zs-j<{?mD9H^o+B{1)HI(o7dOx*WPTRQ2_N9FBpy-)<>gIj;>;`qZxYN5zlKEblbE< zeb2!9o0^(~+pwa}WT=npI^yfyW(QL-@VS)4QnSf(q-(M-k(Rzk+ppM>9%*jM&(J}= zF7e1=!`Qop4ucKt+-x{}cwD}Xl)lLvMSY}6_GZOv7cY#P+*Rj`T)|`D0uFXYo@u8_ zHC>1O`Lxw(BXx16bn`a#kOLM=pvy2$fB5j&qfZxXp(>gcofkbpsy`U5_Jf=uT4DfM z!^Eubtm_K5#=(j>$hi~~Ej*&iKhO`>09d!jLgy@6& zxd^A3ay^jU)}=s+Axs@3!+jHOkG`_LT0zy(t5%H zXt%MBXwDp1#b9S5-EX%^X~o02GD)JsW(%5S3Mgfyr1-XwrLHcZgnn@ntRztYGk8Zd zn?|=Db(zJYolsI1!wA5LcYN$`bVp(-{N5w(Atc2KOgA*`G;RC?l ze-VwriY=UraDP*eNy3)jCQefrQBt#nD77%|CVP*RbO50`vD79_l$iORO54pj!fqZO z979mdZsc-dOv=(^&XmwyduE!V&gins(#Qf~aJt*xR84#2x;nATF7=5?Ezr2rc5@p| zJ)`OX5+mGC+|KHksF*r&l8dUR`kUNjtrL?OsLqFRCH4U`bN}m$< z-i>rW!Y_?9t)?c0qK-+cX4OM~soR}K2OQ{U(qu}8Nwf8^p&IPr8^EYKpj^&&qO{3w zl89+b*XA*nKw27CWHkDQ4(o!sdlQrT|zn? znHUXyt%5q7_*}A9!f#`zT7t9H-8591OHIvK$Bbk!styoyhp-^*;=~xu?JhKWg@W@q ziY!SJrUM9owWXoDzymS~t^d+YJJ%DArUOigbbpgwDpr%O#jXrk7;#u7Bh&=(g5m)a zsRgNm#J|~O>gM(LU&W_)s72Y^7U}*bjI*8+H*!U=GoO0Pj;Kh zX6E&eq66&Ze&|o^Osqz+sw0#`r=r)cO@)f7OIs`ML7kT>%t21SedIHcjL`9j=HFyj zXgaq^Tm_=v)cg=7HAIiQ;(nkPkUU-qV>%JN0SOo~E_E zHBz?=e?s)6A`LCI+2&U?VUS`&xO=DtO8ePCbFznBV77It#S&K&>GcN|+AfSLG84#u zt+d(34usgl9r1`Hm(|fCxWKOU)y}T2mO+1rZGGHNKVw2-=(pP@cuXxeZUTgRhY@Kf zD}i%j=Pj^nJc-p3DfDZ60lG+8q$gODXc|T=#uzO2`fSZ66W54ZMmhuH`&Z=1SEzzXkm=Ur}p|f{gL{4r{H=9%K`o>Y%ZL81x=?@p zsP=#lYbWBt$6ATR-L9s^hxNRrWM$=Hi-9YC*a#S4!oo%4s;gE0@SP@~dBkrBF}hG-7)*tG~lAjjgWnwY@qZbV?fU z--ysfOECHq-AEPw+if-ty9ZL>=?R~lY*A^ku=+*G;kDoV8fro)#9+Z{@|Ziro1gu{ zY(=>Ed}>5MkYC=tZ?yH@pDZJWqwf?F(~V{m`|hD*LU=Br(_pP^b#l(~6zg)U-0M-J zhfY(MQu}+S?(Pl_cL>D2bx%)sPjylge#6qlJ21Qy=6D}t)G!{rY4CL7U4u7yd9I{7 z@zqj$IF+!~-95|zK;uKAZrtt&Y3YWbUnI0-f50df2e3$XM{e#U`l3l!EuMt%?Fscx zOZJ*1FEK~Ln|5<5kXKJYh#!$!>V1kzL(DGMt=p%A%GM83J z+2cY%NRA;{ccxHty*wVdBgbPEvy9cB<`QzzN+o6)deHG2cJ%iljhxYxlE+TA0QZI` zJ;P7hc(N@?A|y1MNlB_@p^!`_>lykvn79Ymy&xfpNHSiM($bP-q~oRYLd-l-7aC2c zCNogSm=rWH{A3Cg#DclJqlYz$%uEe^#Z=36!U2&^R;>zKuA~{M)>8fEh^5vey)JAUahY4CQb{HF zgCClTJ@kT%cKm8Y025-YBCL>nxC`r5W7gprFUrwcNNCst$)dOd48EeD z4i_ouNP;%0@I=f)-BYBx!kgnvSA z#FgBe_xuEJ$ZZG}SNlC2tk)Z0AWg&mNl@|LC;Q<6AjgOm zk}W}n68*o$9%3TLR`HY2Si(Ah%_W|5z|y#BX|ANKh;l@FAHURF4sSZEpDT99&*I}b zC#NXvHUlZM-|r<=VK8Sl_i)`>M@b$#&m2co^0E{gob}Ny=yjAgJui=@=ax86k4xYi zKzgan)?+gn4T;+f3RBRiQRMUWXPw4fp38fW)co6d_`}ywFI~}g{*g1A)jylBoAf2Z zs@vB5QkyF%Rf*GF_HMJHQ^A%QnaP)MU4gYdTmf-9=;!Q;rm)X3D{ngaO?Xf^Yh4y@ zL9ZPR1dbl{8N`YJb5zsK_bB)1cxyX|HL&PdKn;HpK)Y_N?(oayZ(z0k4{)O;Hi ziC(48V2W3>_1>})x>$Sps#J5cJAqYbrINOcm zYx!^QA|jb@MkIby@)Bqx8m0kk1tk1fjyimMfHb**U@#a6*cgRIF7j*p-`xoTfbrIv zH~i=$`e+MCIF$aggaMa2&(Rq)22H?#o)FVNqbVF3oWVJ4GfH?6j!(%Oxba6TpPUBH zGNc>0+H%nY`j}3ip4@fFy?oq-v!emP_8zYgBSs+Ur12nPJ02Xk)mSm_(=a~tzsNfx zFa$O7Jd}bB`;>m(5w429fzFOvo+~u$e%FoH;VCqO+x~FK_r4~D^rLL}SV#H|r1i%M zwBb)0Sii{X#WQxldce<;i4&KO%EMteAd-_)^x#mA~I-OkZ_iKWFFE->+-HUR?Ug^v1}WzRnQPFS>fvNIifarKg^?2lKl+a%n^=;V2Vx$Gc_8M2mDv)cd_r z0qz}>tfPMN7e!O_L)O}h9-Y7U1JaHRU7W#?kH>Mwe1m>W58$FJjW{~qd!f^>;~??$ zc#1w>k!cbnGgD!RczePnwdRiLxm<(+x(gTZ3QliwRJop-0%rmHVp(7ooDj~68y2hvVV3A@0m^Vg~`T+~N>UM?6p>4&z!K-722!3z*c;}MzV2(~-)3PgLUzVm`SQ9+7s zDveh92&b4#`6#_yj+hhP-DaW5O_edtVXIG`W3p@eAJLkp{Qh+ z7okqb27@mZ_3{fB)%m?Tqye=Id}15l*iD%_e<|o^GBZmBRlIKU%O51(F)=t`kYDW7 zXWA6~M}>j4^*bXJADM33hKw1TEr597oDyLGzK-OilyuIFt@O1E>U;!FX}Cx1m;I0j zbm6vcGSaFrF#$lmY!DV0#1LyB`LK-&j+2w7OwDWmyS=O1O&ry87$&I0Xx1qs20gdf4uP_0}c@1*1d5+M6#|VtVV}J$9W!_+atA1=lAR+Y3(Uy)& z-LWyQ^{w^QTC1vz%WjBh{ecv~GD|z?Zpp#{qLD-3H+d9V2}7Hy*g`dEK__+wHscjK zhyP?^@pzZK3jEnXx*u#Ndqc7o_D*qo03icXxI(AH#F-uE;2`ALR={@#qJ;qp+oVd( zrm2hF@F`Ts;DN$!JTHlkb(#mepdgS7?kKl^mO{B`XUX`tP4{U9G!C8Oqow#s9d*Cb zyY9AeLbOgl7uKXvm$Gm$eZo+L+WN2WPjJr;nG8)iZnG&V>Fm4>a|3VlW1fD(g#w)> z+;2c55ENJ~@M(2E?R6Xz_&9}=!nL6~hdLm_R~0<=idzLY=nUpW`e5L&)zgy+ybkc6 zo?K*Vrv)Wad`U#-z#mK_#Ut6^DEz^o+G7JMF+e$f)0uq-J~1;tgU&J+DMdQrj-R(T z`QG@PqaQL&X}{Uh1Cz)%XS1j8E7;!|Jip9vgH(Ue8Pw=AZz|$WI6!A`SODg|zZpt= zr{9|5MzqeL%0XS?-<;h7|7jjNrdFj^z%l+$hHNvtmukbrw?5{R4_X+4sU5;<{1-dx z3|b+Q4oHW?nb3sxp_Vfu-FV=W3d&~>%D{R0I|H-Dy}A>(+^4?dv~X82_$Pc54T16< z`^~edi&o&SLP07r5W3E{?A-NT&if(BY*F{qY4+LEs%5rZSWNh_X|`tQ1c(5)I&fC2 zmeb@-Mff5BItL{nE9d=$-v`scpS$1PKmQc)usJrXAy51u;IEcr{snS6n4D2d!5sx> zokMOK(5Nd>1LmkcBJuM(9V!V?#SOLrJ zEe2!c1=SecgJZi*M~xFco`6D(DQ|ND*mN36-$ZJ0Xt24nP%2=3;5YRo?!W^C{~u03 zbvdd{Dd;pu6WufiCTIK&6>fnKM{zD2A^L1lztb7-Xy#pqhZsiFusWpxqggm0N;n&h zrf&F*l4Id1O+qivbIOz~!QkIXCvWPW;azx}$72DX(*RRyziJ}ezPODMF6=aHH{T9V zN|{@?KQ}wh(F9KDi12TAZl5;+-u`T12oF~x1{4QyD0>e3Df2(Ca3}mqA<~w(pmVW_ ztLTCHKIl(}skbk)H|}uTqKby92s+H-xDGU%YC83L0DMMpx0rzCtiPQ#utJO41o7WD ztB&)KV6q4aB!%pleQX30i>g8gz+tFy>qH9=4Zxnz>wYIC^5uCrOl({re0~XWj?=Pf z>d6bC<6mQol{*i4YOWzf5EC8Xmr95LHpNKm75)nz2{3|Vf_`#REzw2fi8e&jjCO); z`C^=!uN1&GL=)Pk*|(Q@!__` zBmco)D01L8d@c@wA8Av=;71G;*Xm+0(A<9r_C>hvnuN|wPU040Ihj44 zgd*b*(bOE_(!VJoMOWpFe62o4LVFJZROGG+nBB@roK;J2{WX@)!uW7HJ-427`U)09(Be86XrMyx_k9h=wzkSQner+vibq9(h=zX7|mOzg7R{VBaoK(ucl& zy-@s9iPEvmao}Joh|Cr>kopq8er{Dwt%Bsat?cOlo(MjZ20LpdR1GNgK%Ba`HQvQT ze~;@{g;;yQ9C0w-O zF|Sl`E@%%L?L`2Yf6;laR;d@|<>I2rCGat1eKJhfKN@g8$C>39#MZF%1=D6cssK`` z;ze^%H3!X$*-PhQFArp>hRfF>>^BG4mu28w5Pn1pfo9L*sx~^CXAFesp%Aj%(8@H+ z!O3Z9I;|E20e^6zJV>3sW$O{-^z&zs}}=I;?H%FR|(R4W@d=a_}P`e@U$a? zT*MljnJN6m1tdX%PKOT3)UgFu9by+4vzt}3Ma86xJX9{uTCFoq--vP!c*n1b%VlE} zx_>=8F?TE*%ams`EKm0aPXCO=h*IT}FcXKE!Fv}XJKP84UA!Fw z#@U%rSX63JB`RFRnYf5BeRhrVF)avMPB92>VAM0TN)Bd{O6?qo*aY9J zui>Kx7Y8A&+?wWNJnZ^;_ROl)K0OO8%*T~ZHe(J(1can5|!3r(wZxdN*1; zrv@W$Tv~RPFKSIW^tCq$r7hx`<95!3*1VM?yRP7p#YMhCI7J zS3CWFm+vA0i}HtOHwbou-jBA=b~d`k>h^yBbN!JBP`V32b84l^SIv}>tfYzU)xY{Z z-m^!KO6wGVZg=U}sj7kB_8UmI4NtR2gx^RqYAn=xv?>|`_Dl+rmdxczZCf*5-N_SG z`v3+E{#PAa&p~S$%Hy(~s0*rpY1|V;atdrt%O1r6!ipO-@ zwrOFhEZkPIUo}J*?PB3Wjkgb$`M^Z!8tFF{BOU{pG9HgsGulfxXj-m3J8BVYE0aKrLP0&{YL7R77tPg$$MC%<0Y<^PYQOU1&q6jDEXD6$0)PMI zv9_p44glU#w{7>*7L4#R8V4hVeieh%3)W!&Rt6b8>1E|^ia$RA8T}J=%DY=+0HFa9 zkVYM%<}!<*1ec&zt5LvQceT=+V=465R;MgJD|}c$E+v}fU2r;~C##a%%zw?QlvRvE zmnZ!CfEC#^=buenHL|QIc#H^A`i~GjzwJ-Is@k7lBIwrYWkFh6;sV&qYD(7~*>S?8 zYvw#zIY1x&3r2T)e`cTBEAs~EKYB=o>4RX@mvU>lxZLKtPUz~tV$7Q#oQN}!vWNks z1I!!dwatvTA#VL6j{x)smznpipMWT}8{_fFZQ#ONRI0GoovO?L{Ri}R(c?$VFO|Mh z@WS-yagF{p9W1QL2R_#1BR_b#r{buyxC0RTrP7^z-i-R{z3mOSBadA?qh zLS$hNjh<`w^h9(4TnG+WnOmk`zqw}__V1D%)sXar`+WSF0PuY3 zZYyuxz8U%U=-Ez;Tu`jp1QPq7(f9|I6VYEBQ|rAh5uO9!8Mwji+4c?ZZtama>Di0k zZz>t4$M)W_9^dLOjByZ{XS%1Gwh^B>XIr0mu{h~&*M1)*77sgz3qgzyhcV~Otm|ey zpmDA^vWaHw@{D~HxI5j^u4T-T2@^$U&X}G{M&;t{)dij%0`@^iexb11R?3>D3&^#< zn*F!E|4g9Desr4(cf`NWXE>xoNT0Ty_fH=4bv4HxI9uKCp9F_&>4n5ZJpPBV3h@O4 z1p@^G1p@^G1p@^Ge;)(IGXefSE(=Ko0|f&G0|f*BR}B1AuOE7S?Qc-=ypEfWe&iC< z59$!z4}A{{qPLVqrSit*n=KU%IaEo8iD$20AYDYBe--F-L1?V`2Cm@#bLH3`-s380 z?!tcLk6FxbK#j4%f2LWl@XOX#%3huK{s99GP|q$hdH^TTd@#)U|`0rUSl(?!`#{IqJ4~MVci11+z z7CvIljQ#t2?`l8z*bKb;#PeYOk9(h`3(BwVhxIGP@jKfv9Nqh#0rP)2`joqyL2_>+ z%HD-y#MQC`^6h4=|u*_=#?Rn_kJ0V>srAelgQhnyDvl{!I_JM7@0iJd}WM@mD>X2sNHO3Pb$%hi$&awV0f z3g0~RnFQPDC!tKaWw4sU?+F)+6KId={1g2_k!qUxTP8o^hU@f8Y0P9j!pFEbSgvHV zV{ybPAkDftT)_rK?ngkgbJyvYtOB-X2lPuM3vgG`Qs;nxUky1kq@~nU?X2C+n~8sS zZ=HT!NM(BW%IBau-~~QoA>NrbM7*)j^wkD_%ns`X^Yo)-CB9Z`@W8H3L*S1HPhW-D zUurtjPitH7Wmm5edaIP6Gd+1h__jtalBb^jHA= zu^IxbmNkTdDo{+vw>2j5b>#`>0XHqIB_H^>X7H$E!_`zvA%QQPkEF!3;a00oM1^X*iFZb$>X zPxdvqzqJ432{3^`g-u(gCw5nlj>I31l8NWx`IyuLsRA~X1|!_F7Bkz%z&PbUoW5i4#@7)*m1v~_^XeMxN9uL4 z7;A|4#AavUZL#VT+z&kf%+F?S5HrX>b7A_Lxx6T-OPM>!iNHY z=-(_M1BFMrt~GLPovE?HOKb7kL<|V7;iadZGGCn`mT|r^bo+taq(4(b2fnB4UF$yc zH6=aUq7SBXJf3;d!*2MI9`IPtP}4o$hb=U{7PYgfZVEsO4(bH)xSstn} zU*?G%zd<3Y3HW?{7VkdAsjmS-QAO-QXPrW_@@*iYlv-ZNPjvP)sX|o&D#4 zxoa+&3|Ed}7DsYr*0H_JkkRO{pNZZx_7P`yfVN2=%icK}uEwE250({Jc^*uUMXKBSY7W zt@_7o-!4$nr>A2FX@Vj!TlRvbD2)b#W0jKxH^_U@dAW9d+1`#H@96-Rz(pLV)QKI1 zUrHm{3mTdh;5~tVM9~dzl{;O#X>Tg7^xtn1D$HlKnw;;YTD+b_2Y4odKAPqx*EW{p zVc@=giAYIMOZwjQLNV)d0sji0^vBN->4UNBt_uZRH#fOFLN@~md3^LoP=KeQeLRqx zABK9jR=ZY;(-uQ%;8%F!lP@K1;QhdO3{9AIE$6g8Bg#g-ykeJzV;o;kTW%)>qV)y7 zobZy6cwUR?Lh|uM#C!q))^q~$k$?hu^Zt3cPB9LA0Hy_&kOI8Ce;tgQe_bQFZ9C0#c`h+_K)}-??1ilV~MMVhUg1Q*FlN{>9-zqd^0en{n zAZ>({c#i#RaTU`8_|#ptONQUTdL&K5yOQw}+xe7_{oPSiG8k#AiV%eA{6PG63|Mp$ zM;3oDkmH3u)hN-RG^T;oKF0gT?fb^WuP1m{HGX2enT9SgfN`!t5~SuiX;M}$SY8u> z>pHC46WILkoWlzn*qZlvo`)Zoy(8Pl%20S_eT3n-OFG)z0--o3Q_2$x=(%jMsQ{T@ z>z(BAIcvl|%443p<3?h6o}uYl-LnkNOf+&wlmvZ#z9azNmldv)w)-v)m|yGKd3@fE zQa~+`9T2HqXDsm=0j|C@?8zvoa8uem2On{|B;CAj$|zTA=SbLN@SMx&G*g(njq;#w zev#6IF?gI-t7$sIZtZOmS7dXq%bQNrRrsHU7oxScmE!>Lr#PNP8UDiKxVX-s z1KxGB6pRI}sQ>vJCtxmt<>qUt{Oz;O`guoE=%w@Vyn9N{c_+{ADzzc+gpTFj(rsBj z!D6&U=DSmQUjzxeA^Yv|v@)EAPE^*n##sWk`e$-KLLo;5Ydo@TiD(L4$Tb^Y$r~yXbQg3`7Xu1NX?l83Dg^d%wc43Ruj_Co<#roW1M2=aG;s zjz+4U#OLzJEoA_d1Cs%9!trrWNMetZARS)Y-JeO=;`coM35g`N_9<9PDKsFhq4y`D z+}ECRpbD<6`Ov_q*FD1bV_fTy&apU=TK+0zh`+znCT-yNlu)Wm`=wtl?5+xc#hAup zOgpvhFSr3rn*>*uY`>o#z6tS>Vvkz>7y6U6@H-0JDb=}%hl)J?=2AX21Fd^BrbMP` ze2^L>*{c_WvUGt?v3cL+c-8FY5XgKfGLEK|01VS^4+(zdDZSG>*sFommQU&fI8lQ z>A_W0s&5(Cr49h(O7ByeAa}@HJIo`Xd%5^EpETFbD4kpW@D&mC* z;AyAw@DcMdx8T&FzkK+4XVl;!dyPcv1Q14Wm;LZttDw6``UNSWd(7(Nusn-$utDxL| z;+CV8PhH+{H@opm70;VYE#tN4OL-UrAoLC_-(-J*w%t<7|GvAkEDQLaXIYW;KU>Zz zEiSvKySv&QP>Op89wV6DXGFw5?zT{cKJ7mHpZUf(N-r|(aKC>BS4s89WHm3r zkvdpx3kC`X3I+-W3I+-W3I_h`87Q6!@L%6Vg@OeG1p@^G1p@^G1p@^G1p@^G1p@^G z1p@^G1p@^G1p@^G1p@^G1p@^G1p@^G1p@^G1p@^G1p@^G1p@^G1p@^G1p@^G1p@^G z1p@^G1p@^G1p@^G1p@^G1p@^G1p@^G1p@^G1p@^G1p@^G1p@^G1p@^G1q1(28Tb!< CcwY$s literal 0 HcmV?d00001