Иконка ресурса

reapi [Fork] Snow WarnUp 1.0.1b

Нет прав для скачивания
Автор
bizon | Fork BiZaJe
Исходный код
warnup:
#include <amxmodx>
#include <fakemeta>
#include <reapi>
#include <hamsandwich>
#include <xs>

#pragma compress 1
#pragma semicolon 1

new const PLUGIN_NAME[] = "[Fork] Snow WarmUp";
new const PLUGIN_VERSION[] = "1.0.1b";
new const PLUGIN_AUTHOR[] = "bizon | BiZaJe";

new const SNOWBALL_MODEL_VIEW[] = "models/snow_warmup/v_snowball.mdl";
new const SNOWBALL_MODEL_PLAYER[] = "models/snow_warmup/p_snowball.mdl";
new const SNOWBALL_MODEL_WORLD[] = "models/snow_warmup/w_snowball.mdl";
//
new const ICE_CUBE_MODEL[] = "models/snow_warmup/ice_cube.mdl";
new const ICE_CUBE_CLASS[] = "ice_cube";
//
new const SNOWBALL_SOUND_FREEZE[] = "snow_warmup/freeze.wav";
new const SNOWBALL_SOUND_UNFREEZE[] = "snow_warmup/unfreeze.wav";
new const SNOWBALL_SOUND_SPLASH[] = "snow_warmup/splash.wav";
//
const TASK_USER_FREEZE = 0x134;
const TASK_AWARD_DELAY = 0x513;
//
const SNOWBALL_MEGA_THROW_COUNT = 8;
const Float: SNOWBALL_MEGA_THROW_DEGREES = 45.0;
const Float: SNOWBALL_MEGA_THROW_RADIUS = 300.0;
new const SNOWBALL_WEAPONLIST[] = "snow_warmup/weapon_snowball";

enum any: HookChainStruct
{
    HookChain: HC_ROUND_END,
    HookChain: HC_RESTART_ROUND,
    HookChain: HC_PLAYER_SPAWN,
    HookChain: HC_PLAYER_KILLED,
    HookChain: HC_PLAYER_DUCK,
    HookChain: HC_PLAYER_PRETHINK,
    HookChain: HC_CAN_HAVE_PLAYER_ITEM,
    HookChain: HC_THROW_SMOKE_GRENADE,
    HookChain: HC_WEAPON_DEFAULT_DEPLOY,
    HookChain: HC_PLAYER_RADIO,
};

enum any: CvarsStruct
{
    CVAR_SWU_TIME,
    CVAR_SWU_IS_FREEZE_USER,
    CVAR_SWU_FREEZE_TIME_USER,
    CVAR_SWU_DAMAGE_USER,
    CVAR_SWU_START_HEALTH_USER,
    CVAR_SWU_AWARD_WINNER_MONEY,
    CVAR_SWU_MEGA_THROW_COUNT,
    CVAR_SWU_AMBIENT_SOUND[MAX_RESOURCE_PATH_LENGTH]
};

enum any: StatesStruct
{
    STATE_PLUGINS_ON,
    STATE_PLUGINS_OFF,
    STATE_CVARS_SET,
    STATE_CVARS_UNSET,
}

new
    g_iHook[HookChainStruct],
    bool: bIsSnowWarmUp,
    g_iTimer,
    bool: g_bIsSoundPlayed[MAX_PLAYERS+1],
//
    g_iCvarRoundInfinite,
    g_iCvarForseRespawn,
    g_iCvarFreeArmor,
    g_member_bCTCantBuy,
    g_member_bTCantBuy,
    g_iIniParseState,
//
    g_iSpriteTrail,
//
    g_eCvar[CvarsStruct],
    g_aStateInfo[StatesStruct],
//
    g_iKillsCount[MAX_PLAYERS+1],
    g_iMegaThrowKillsCount[MAX_PLAYERS+1];

public plugin_precache()
{
    register_plugin(PLUGIN_NAME, PLUGIN_VERSION, PLUGIN_AUTHOR);
    @cvars_attach();

    precache_model(SNOWBALL_MODEL_VIEW);
    precache_model(SNOWBALL_MODEL_PLAYER);
    precache_model(SNOWBALL_MODEL_WORLD);

    precache_model(ICE_CUBE_MODEL);

    precache_sound(SNOWBALL_SOUND_FREEZE);
    precache_sound(SNOWBALL_SOUND_UNFREEZE);
    precache_sound(SNOWBALL_SOUND_SPLASH);

    if(g_eCvar[CVAR_SWU_AMBIENT_SOUND][0] != EOS)
        precache_sound(g_eCvar[CVAR_SWU_AMBIENT_SOUND]);

    precache_generic(fmt("sprites/%s.txt", SNOWBALL_WEAPONLIST));
    precache_generic("sprites/snow_warmup/hud_snowball.spr");

    g_iSpriteTrail = precache_model("sprites/zbeam3.spr");

    register_dictionary("reapi_snow_warmpup.txt");
}

public client_disconnected(pPlayer)
{
    g_iKillsCount[pPlayer] = 0;
    @ice_cube_destroy_by_owner(pPlayer);

    g_bIsSoundPlayed[pPlayer] = false;

    remove_task(pPlayer + TASK_USER_FREEZE);
}

public plugin_init()
{
    register_clcmd(SNOWBALL_WEAPONLIST, "@SnowBall_Switch");

    g_iHook[HC_ROUND_END] = RegisterHookChain(RG_RoundEnd, "@RoundEnd_Pre");

    @read_ini();
}

@SnowBall_Switch(pPlayer)
{
    engclient_cmd(pPlayer, "weapon_smokegrenade");
    return PLUGIN_HANDLED;
}

@RoundEnd_Pre(WinStatus: status, ScenarioEventEndRound: event, Float: tmDelay)
{
    if(event != ROUND_GAME_COMMENCE)
        return;

    g_iHook[HC_RESTART_ROUND] = RegisterHookChain(RG_CSGameRules_RestartRound, "@CSGameRules_RestartRound_Pre");
    // избегаем блок вызова RG_CBasePlayer_OnSpawnEquip вышестоящими плагинами, RG_CSGameRules_PlayerSpawn - тоже не вариант
    g_iHook[HC_PLAYER_SPAWN] = RegisterHookChain(RG_CBasePlayer_Spawn, "@CBasePlayer_Spawn_Post", true);
    g_iHook[HC_PLAYER_KILLED] = RegisterHookChain(RG_CBasePlayer_Killed, "@CBasePlayer_Killed_Post", true);
    g_iHook[HC_PLAYER_DUCK] = RegisterHookChain(RG_CBasePlayer_Duck, "@CBasePlayer_Duck_Pre");

    if(g_eCvar[CVAR_SWU_MEGA_THROW_COUNT])
        g_iHook[HC_PLAYER_PRETHINK] = RegisterHookChain(RG_CBasePlayer_PreThink, "@CBasePlayer_PreThink");

    g_iHook[HC_CAN_HAVE_PLAYER_ITEM] = RegisterHookChain(RG_CSGameRules_CanHavePlayerItem, "@CSGameRules_CanHavePlayerItem_Pre");
    g_iHook[HC_THROW_SMOKE_GRENADE] = RegisterHookChain(RG_ThrowSmokeGrenade, "@ThrowSmokeGrenade_Post", true);
    g_iHook[HC_WEAPON_DEFAULT_DEPLOY] = RegisterHookChain(RG_CBasePlayerWeapon_DefaultDeploy, "@CBasePlayerWeapon_DefaultDeploy_Pre");
    g_iHook[HC_PLAYER_RADIO] = RegisterHookChain(RG_CBasePlayer_Radio, "@CBasePlayer_Radio_Pre");

    g_iCvarRoundInfinite = get_cvar_num("mp_round_infinite");
    g_iCvarForseRespawn = get_cvar_num("mp_forcerespawn");
    g_iCvarFreeArmor = get_cvar_num("mp_free_armor");
    set_cvar_num("mp_round_infinite", 1);
    set_cvar_num("mp_forcerespawn", 1);
    set_cvar_num("mp_free_armor", 0);

    g_member_bCTCantBuy = get_member_game(m_bCTCantBuy);
    g_member_bTCantBuy = get_member_game(m_bTCantBuy);
    set_member_game(m_bCTCantBuy, true);
    set_member_game(m_bTCantBuy, true);

    DisableHookChain(g_iHook[HC_ROUND_END]);
}

@CSGameRules_RestartRound_Pre()
{
    if(bIsSnowWarmUp)
    {
        DisableHookChain(g_iHook[HC_RESTART_ROUND]);
        DisableHookChain(g_iHook[HC_PLAYER_SPAWN]);
        DisableHookChain(g_iHook[HC_PLAYER_KILLED]);
        DisableHookChain(g_iHook[HC_PLAYER_DUCK]);

        if(g_eCvar[CVAR_SWU_MEGA_THROW_COUNT])
            DisableHookChain(g_iHook[HC_PLAYER_PRETHINK]);

        DisableHookChain(g_iHook[HC_CAN_HAVE_PLAYER_ITEM]);
        DisableHookChain(g_iHook[HC_THROW_SMOKE_GRENADE]);
        DisableHookChain(g_iHook[HC_WEAPON_DEFAULT_DEPLOY]);
        DisableHookChain(g_iHook[HC_PLAYER_RADIO]);

        new iEnt = NULLENT;

        while((iEnt = rg_find_ent_by_class(iEnt, "snowball"))){
            if(!is_nullent(iEnt)){
                rg_remove_entity(iEnt);
            }
        }

        set_cvar_num("mp_round_infinite", g_iCvarRoundInfinite);
        set_cvar_num("mp_forcerespawn", g_iCvarForseRespawn);
        set_cvar_num("mp_free_armor", g_iCvarFreeArmor);

        set_member_game(m_bCTCantBuy, g_member_bCTCantBuy);
        set_member_game(m_bTCantBuy, g_member_bTCantBuy);

        if(g_eCvar[CVAR_SWU_AMBIENT_SOUND][0] != EOS)
            client_cmd(0, "stopsound");

        new
            pBestPlayer,
            iMax,
            iArraySize,
            sData[64],
            iStartMoney;

        iStartMoney = get_cvar_num("mp_startmoney");

        for(new pPlayer = 1; pPlayer <= MaxClients; pPlayer++)
        {
            if(!is_user_connected(pPlayer))
                continue;

            set_msg_weaponlist(pPlayer, "weapon_smokegrenade", 13, 1, -1, -1, 3, 3, WEAPON_SMOKEGRENADE, (ITEM_FLAG_LIMITINWORLD|ITEM_FLAG_EXHAUSTIBLE));
   
            if(g_iKillsCount[pPlayer] > iMax)
            {
                pBestPlayer = pPlayer;
                iMax = g_iKillsCount[pPlayer];
            }

            rg_add_account(pPlayer, iStartMoney, AS_SET);
        }

        set_task(0.5, "@func_give_award", pBestPlayer + TASK_AWARD_DELAY);

        iArraySize = ArraySize(any: g_aStateInfo[STATE_PLUGINS_ON]);
        for(new i; i < iArraySize; i++)
        {
            ArrayGetString(any: g_aStateInfo[STATE_PLUGINS_ON], i, sData, charsmax(sData));
            unpause("ac", sData);
        }

        iArraySize = ArraySize(any: g_aStateInfo[STATE_CVARS_SET]);
        for(new i; i < iArraySize; i++)
        {
            ArrayGetString(any: g_aStateInfo[STATE_CVARS_SET], i, sData, charsmax(sData));
            server_cmd("%s", sData);
           
        }
        server_exec();

    }else{
        g_iTimer = g_eCvar[CVAR_SWU_TIME];
        set_task(1.0, "@func_hud_info", 0xC0DE, .flags = "b");

        new
            iFwd,
            iArraySize,
            sData[64];

        iFwd = CreateMultiForward("swu_start", ET_CONTINUE);
        ExecuteForward(iFwd);

        iArraySize = ArraySize(any: g_aStateInfo[STATE_PLUGINS_OFF]);
        for(new i; i < iArraySize; i++)
        {
            ArrayGetString(any: g_aStateInfo[STATE_PLUGINS_OFF], i, sData, charsmax(sData));
            pause("ac", sData);
        }

        iArraySize = ArraySize(any: g_aStateInfo[STATE_CVARS_UNSET]);
        for(new i; i < iArraySize; i++)
        {
            ArrayGetString(any: g_aStateInfo[STATE_CVARS_UNSET], i, sData, charsmax(sData));
            server_cmd("%s", sData);
        }
        server_exec();
    }

    bIsSnowWarmUp = true;
}

@CBasePlayer_Spawn_Post(pPlayer)
{
    if(!is_user_alive(pPlayer))
        return;

    rg_remove_all_items(pPlayer);

    DisableHookChain(g_iHook[HC_CAN_HAVE_PLAYER_ITEM]);

    new iItem;
    iItem = rg_give_item(pPlayer, "weapon_smokegrenade");

    if(!is_nullent(iItem))
    {
        rg_set_iteminfo(iItem, ItemInfo_iMaxAmmo1, 999);
        rg_set_user_bpammo(pPlayer, get_member(iItem, m_iId), 999);
    }

    EnableHookChain(g_iHook[HC_CAN_HAVE_PLAYER_ITEM]);

    set_entvar(pPlayer, var_health, Float: float(g_eCvar[CVAR_SWU_START_HEALTH_USER]));
    set_entvar(pPlayer, var_armortype, 0.0);
    set_entvar(pPlayer, var_armorvalue, 0.0);

    if(g_eCvar[CVAR_SWU_AMBIENT_SOUND][0] && !g_bIsSoundPlayed[pPlayer])
    {
        g_bIsSoundPlayed[pPlayer] = true;
        rg_send_audio(pPlayer, g_eCvar[CVAR_SWU_AMBIENT_SOUND], PITCH_NORM);
    }

    set_msg_weaponlist(pPlayer, SNOWBALL_WEAPONLIST, 13, 1, -1, -1, 3, 3, WEAPON_SMOKEGRENADE, (ITEM_FLAG_LIMITINWORLD|ITEM_FLAG_EXHAUSTIBLE));

    g_iMegaThrowKillsCount[pPlayer] = 0;

    new iEnt;
    iEnt = NULLENT;

    while((iEnt = rg_find_ent_by_class(iEnt, ICE_CUBE_CLASS)))
    {
        if(!is_nullent(iEnt) && get_entvar(iEnt, var_iuser3) == pPlayer)
        {
            rg_remove_entity(iEnt);
        }
    }
}

@CBasePlayer_Killed_Post(pVictim, pKiller, iGibs)
{
    rg_set_rendering(pVictim, kRenderFxNone, 255, 255, 255, kRenderNormal, 16);
    rg_reset_maxspeed(pVictim);
    set_entvar(pVictim, var_gravity, 1.0);

    @ice_cube_destroy_by_owner(pVictim);
    remove_task(pVictim + TASK_USER_FREEZE);

    if(is_user_connected(pKiller))
    {
        g_iKillsCount[pKiller]++;
        g_iMegaThrowKillsCount[pKiller]++;
    }
}

@CBasePlayer_Jump_Pre(pPlayer)
{
    if(Float: get_entvar(pPlayer, var_maxspeed) == -1.0)
    {
        set_entvar(pPlayer, var_button, get_entvar(pPlayer, var_button) & ~IN_JUMP);
        SetHookChainReturn(ATYPE_INTEGER, 0);
        return HC_SUPERCEDE;
    }

    return HC_CONTINUE;
}

@CBasePlayer_Duck_Pre(pPlayer)
{
    if(Float: get_entvar(pPlayer, var_maxspeed) == -1.0)
        set_entvar(pPlayer, var_oldbuttons, get_entvar(pPlayer, var_oldbuttons) | IN_DUCK);
}

@CBasePlayer_PreThink(pPlayer)
{
    if(!is_user_alive(pPlayer) || ~get_entvar(pPlayer, var_button) & IN_ATTACK2 || g_iMegaThrowKillsCount[pPlayer] < g_eCvar[CVAR_SWU_MEGA_THROW_COUNT])
        return;

    g_iMegaThrowKillsCount[pPlayer] = 0;

    new
        Float: fOriginStart[3],
        Float: fOriginEnd[3],
        Float: fDegrees;

    get_entvar(pPlayer, var_origin, fOriginStart);

    for(new i; i < SNOWBALL_MEGA_THROW_COUNT; i++)
    {
        fOriginEnd[0] = fOriginStart[0] + SNOWBALL_MEGA_THROW_RADIUS * floatcos(fDegrees, degrees);
        fOriginEnd[1] = fOriginStart[1] + SNOWBALL_MEGA_THROW_RADIUS * floatsin(fDegrees, degrees);
        fOriginEnd[2] = fOriginStart[2];

        @snowball_throw(pPlayer, fOriginStart, fOriginEnd, true);

        fDegrees += SNOWBALL_MEGA_THROW_DEGREES;
    }

    set_msg_svc_weaponanim(pPlayer, 2);
    set_msg_svc_weaponanim(pPlayer, 3);
    set_member(pPlayer, m_flNextAttack, 1.0);
}

@CSGameRules_CanHavePlayerItem_Pre(pPlayer, iItem)
{
    if(is_nullent(iItem))
        return HC_CONTINUE;

    rg_remove_entity(iItem);
    SetHookChainReturn(ATYPE_INTEGER, 0);
    return HC_SUPERCEDE;
}

@ThrowSmokeGrenade_Post(pPlayer, Float: fOrigin[3], Float: fVelocity[3], Float: flTime, const usEvent)
{
    new eEnt;
    eEnt = GetHookChainReturn(ATYPE_INTEGER);

    if(!is_nullent(eEnt))
        engfunc(EngFunc_RemoveEntity, eEnt);

    new Float: fOriginEnd[3];
    get_origin_aiming(pPlayer, fOriginEnd, 8192.0);

    @snowball_throw(pPlayer, fOrigin, fOriginEnd, false);
}

@CBasePlayerWeapon_DefaultDeploy_Pre(iItem, szViewModel[], szWeaponModel[], iAnim, szAnimExt[], skiplocal)
{
    if(!is_nullent(iItem) && get_member(iItem, m_iId) == WEAPON_SMOKEGRENADE)
    {
        SetHookChainArg(2, ATYPE_STRING, SNOWBALL_MODEL_VIEW);
        SetHookChainArg(3, ATYPE_STRING, SNOWBALL_MODEL_PLAYER);
    }
}

@CBasePlayer_Radio_Pre(pPlayer, iMsgIndex, sMsgVerbose[], iPitch, bool: bIsShowIcon)
{
    SetHookChainReturn(ATYPE_INTEGER, 0);
    return HC_SUPERCEDE;
}

@snowball_throw(pPlayer, Float: fOriginStart[3], Float: fOriginEnd[3], bool: bIsMegaThrow)
{
    new
        eEnt,
        Float: fVelocity[3];

    xs_vec_sub(fOriginEnd, fOriginStart, fVelocity);
    xs_vec_normalize(fVelocity, fVelocity);
    xs_vec_mul_scalar(fVelocity, 1999.0, fVelocity);

    eEnt = rg_create_entity("info_target");

    engfunc(EngFunc_SetModel, eEnt, SNOWBALL_MODEL_WORLD);
    engfunc(EngFunc_SetOrigin, eEnt, fOriginStart);
    engfunc(EngFunc_SetSize, eEnt, Float: { -3.0, -3.0, -3.0 }, Float: { 3.0, 3.0, 2.0 });

    set_entvar(eEnt, var_classname, "snowball");
    set_entvar(eEnt, var_owner, pPlayer);
    set_entvar(eEnt, var_iuser4, bIsMegaThrow);
    set_entvar(eEnt, var_movetype, MOVETYPE_TOSS);
    set_entvar(eEnt, var_solid, SOLID_BBOX);

    if(vector_length(fVelocity) != 0.0)
        set_entvar(eEnt, var_velocity, fVelocity);

    SetTouch(eEnt, "@touch_snowball");

    set_msg_beamfollow(eEnt, g_iSpriteTrail, 3, 5, 0, 255, 255, 150);
}

@touch_snowball(eEnt, pToucher)
{
    if(is_nullent(eEnt))
        return;

    new
        pOwner,
        Float: flGameTime;

    pOwner = get_entvar(eEnt, var_owner);
    flGameTime = get_gametime();

    if(is_user_connected(pToucher) && pOwner != pToucher && is_user_connected(pOwner) && rg_is_player_can_takedamage(pOwner, pToucher))
    {
        new Float: fOriginIceCube[3];
        get_entvar(pToucher, var_origin, fOriginIceCube);

        if(g_eCvar[CVAR_SWU_IS_FREEZE_USER])
        {
            if(task_exists(pToucher + TASK_USER_FREEZE))
                change_task(pToucher + TASK_USER_FREEZE, float(g_eCvar[CVAR_SWU_FREEZE_TIME_USER]));
            else
            {
                set_task(float(g_eCvar[CVAR_SWU_FREEZE_TIME_USER]), "@func_reset_user_freeze", pToucher + TASK_USER_FREEZE);
                set_entvar(pToucher, var_velocity, Float: { 0.0, 0.0, 0.0 });

                new eIceCube;
                eIceCube = rg_create_entity("info_target");

                engfunc(EngFunc_SetModel, eIceCube, ICE_CUBE_MODEL);
                engfunc(EngFunc_SetOrigin, eIceCube, fOriginIceCube);

                set_entvar(eIceCube, var_classname, ICE_CUBE_CLASS);
                set_entvar(eIceCube, var_iuser3, pToucher);
                set_entvar(eIceCube, var_ltime, flGameTime + float(g_eCvar[CVAR_SWU_FREEZE_TIME_USER]));
                set_entvar(eIceCube, var_nextthink, flGameTime + 0.3);
                set_entvar(eIceCube, var_movetype, MOVETYPE_TOSS);
                set_entvar(eIceCube, var_frame, 2.5);
                set_entvar(eIceCube, var_framerate, 1.0);
                set_entvar(eIceCube, var_animtime, get_gametime());

                if(get_entvar(eEnt, var_iuser4))
                    set_entvar(eIceCube, var_body, 1);

                SetThink(eIceCube, "@think_ice_cube");
            }

            rg_set_rendering(pToucher, kRenderFxGlowShell, 0, 255, 255, kRenderNormal, 16);
            set_entvar(pToucher, var_maxspeed, -1.0);
            set_entvar(pToucher, var_gravity, 99.0);
        }

        emit_sound(pToucher, CHAN_STATIC, SNOWBALL_SOUND_FREEZE, VOL_NORM, ATTN_NORM, 0, PITCH_NORM);

        static const Float: fDamageHitGroup[] =
        {
            1.0, // HIT_GENERIC
            1.5, // HIT_HEAD
            1.2, // HIT_CHEST
            1.1, // HIT_STOMACH
            1.1, // HIT_LEFTARM
            1.1, // HIT_RIGHTARM
            1.0, // HIT_LEFTLEG
            1.0, // HIT_RIGHTLEG
            1.0  // HIT_SHIELD
        };

        engfunc(EngFunc_TraceLine, fOriginIceCube, fOriginIceCube, DONT_IGNORE_MONSTERS, eEnt, 0);

        new iHitGroup;
        iHitGroup = get_tr2(0, TR_iHitgroup);
        set_member(pToucher, m_LastHitGroup, iHitGroup);

        ExecuteHamB(Ham_TakeDamage, pToucher, eEnt, pOwner, float(g_eCvar[CVAR_SWU_DAMAGE_USER]) * fDamageHitGroup[iHitGroup], DMG_FREEZE);
    }

    new
        Float: fOrigin[3],
        iVelocity[3];

    get_entvar(eEnt, var_origin, fOrigin);

    for(new i; i < sizeof(iVelocity); i++)
        iVelocity[i] = random_num(-500, 500);

    set_msg_bloodstream(fOrigin, iVelocity, 254, 70);
    emit_sound(eEnt, CHAN_STATIC, SNOWBALL_SOUND_SPLASH, VOL_NORM, ATTN_NORM, 0, PITCH_NORM);

    SetThink(eEnt, "@think_snowball_remove");
    SetTouch(eEnt, "");

    set_entvar(eEnt, var_nextthink, flGameTime + 0.1);
}

@think_snowball_remove(eEnt)
{
    rg_remove_entity(eEnt);
}

@think_ice_cube(eEnt)
{
    new
        Float: flGameTime,
        Float: flLifeTime,
        iState;

    flGameTime = get_gametime();
    flLifeTime = get_entvar(eEnt, var_ltime);

    if(flLifeTime < flGameTime)
    {
        iState = get_entvar(eEnt, var_impulse);

        if(iState)
            rg_remove_entity(eEnt);
        else
        {
            set_entvar(eEnt, var_impulse, ++iState);

            set_entvar(eEnt, var_nextthink, flGameTime + 3.0);
        }
    }
    else
    {
        new
            pOwner,
            Float: fOrigin[3];

        pOwner = get_entvar(eEnt, var_iuser3);
        get_entvar(pOwner, var_origin, fOrigin);

        static const Float: flCorrectOriginAxisDown = 40.0;
        fOrigin[2] -= flCorrectOriginAxisDown;

        set_entvar(eEnt, var_origin, fOrigin);
        set_entvar(eEnt, var_nextthink, flGameTime + 0.1);
    }
}

@func_hud_info(iTask)
{
    if(g_iTimer <= 0)
    {
        remove_task(iTask);
        server_cmd("sv_restart 1");
    }else{
        new
            pPlayers[32],
            iPlayersCount,
            sSeconds[16];

        get_players(pPlayers, iPlayersCount, "ach");

        for(new i, pPlayer; i < iPlayersCount; i++)
        {
            pPlayer = pPlayers[i];

            correct_word_seconds(g_iTimer, pPlayer, sSeconds, charsmax(sSeconds));

            set_dhudmessage(0, 255, 255, -1.0, 0.04, .holdtime = 0.8);
            show_dhudmessage(pPlayer, "%L", pPlayer, "SWU_TIMER_INFO", g_iTimer, sSeconds);

            if(g_eCvar[CVAR_SWU_MEGA_THROW_COUNT])
            {
                if(g_iMegaThrowKillsCount[pPlayer] >= g_eCvar[CVAR_SWU_MEGA_THROW_COUNT])
                {
                    set_dhudmessage(random(255), random(255), random(255), -1.0, 0.85, .holdtime = 0.8);
                    show_dhudmessage(pPlayer, "%L", pPlayer, "SWU_MEGA_THROW_ACTIVE");
                }else{
                    set_dhudmessage(255, 255, 255, -1.0, 0.85, .holdtime = 0.8);
                    show_dhudmessage(pPlayer, "%L", pPlayer, "SWU_MEGA_THROW_RELOAD", g_iMegaThrowKillsCount[pPlayer] * 100 / g_eCvar[CVAR_SWU_MEGA_THROW_COUNT]);
                }
            }
        }

        g_iTimer--;
    }
}

@func_reset_user_freeze(pPlayer)
{
    pPlayer -= TASK_USER_FREEZE;

    rg_set_rendering(pPlayer);
    rg_reset_maxspeed(pPlayer);
    set_entvar(pPlayer, var_gravity, 1.0);

    emit_sound(pPlayer, CHAN_STATIC, SNOWBALL_SOUND_UNFREEZE, VOL_NORM, ATTN_NORM, 0, PITCH_NORM);
}

@func_give_award(pBestPlayer)
{
    pBestPlayer -= TASK_AWARD_DELAY;

    set_dhudmessage(0, 255, 255, -1.0, 0.04, .holdtime = 5.0);

    new bool: bIsConnectedBestPlayer;
    bIsConnectedBestPlayer = bool: is_user_connected(pBestPlayer);

    for(new pPlayer = 1; pPlayer <= MaxClients; pPlayer++)
    {
        if(bIsConnectedBestPlayer)
            show_dhudmessage(pPlayer, "%L", pPlayer, "SWU_TIMER_END_ADD", pBestPlayer);
        else
            show_dhudmessage(pPlayer, "%L", pPlayer, "SWU_TIMER_END");
    }

    if(bIsConnectedBestPlayer)
        rg_add_account(pBestPlayer, g_eCvar[CVAR_SWU_AWARD_WINNER_MONEY]);

    new iFwd;
    iFwd = CreateMultiForward("swu_end", ET_CONTINUE, FP_CELL);
    ExecuteForward(iFwd, _, pBestPlayer);
}

@ice_cube_destroy_by_owner(pPlayer)
{
    new eEnt;
    eEnt = NULLENT;

    while((eEnt = rg_find_ent_by_class(eEnt, ICE_CUBE_CLASS)))
    {
        if(!is_nullent(eEnt) && get_entvar(eEnt, var_iuser3) == pPlayer)
        {
            set_entvar(eEnt, var_ltime, -1.0);
            return;
        }
    }
}

@cvars_attach()
{
    bind_pcvar_num(
        create_cvar(
            "swu_time", "100", FCVAR_SERVER,
            .description = "Время разминки (в секундах)",
            .has_min = false, .min_val = 0.0,
            .has_max = false, .max_val = 0.0
        ), g_eCvar[CVAR_SWU_TIME]
    );

    bind_pcvar_num(
        create_cvar(
            "swu_is_freeze_user", "1", FCVAR_SERVER,
            .description = "Замораживать ли игрока при попадании в него снежком?^n1 - да, 0 - нет",
            .has_min = true, .min_val = 0.0,
            .has_max = true, .max_val = 1.0
        ), g_eCvar[CVAR_SWU_IS_FREEZE_USER]
    );

    bind_pcvar_num(
        create_cvar(
            "swu_freeze_time_user", "3", FCVAR_SERVER,
            .description = "На сколько секунд замораживать игрока при попадании в него снежком?",
            .has_min = false, .min_val = 0.0,
            .has_max = false, .max_val = 0.0
        ), g_eCvar[CVAR_SWU_FREEZE_TIME_USER]
    );

    bind_pcvar_num(
        create_cvar(
            "swu_damage_user", "55", FCVAR_SERVER,
            .description = "Сколько урона получает игрок при попадании в него снежком?",
            .has_min = false, .min_val = 0.0,
            .has_max = false, .max_val = 0.0
        ), g_eCvar[CVAR_SWU_DAMAGE_USER]
    );

    bind_pcvar_num(
        create_cvar(
            "swu_start_health_user", "100", FCVAR_SERVER,
            .description = "Изначальное здоровье игрока на разминке",
            .has_min = false, .min_val = 0.0,
            .has_max = false, .max_val = 0.0
        ), g_eCvar[CVAR_SWU_START_HEALTH_USER]
    );

    bind_pcvar_num(
        create_cvar(
            "swu_award_winner_money", "2500", FCVAR_SERVER,
            .description = "Награда для победителя (сделавшего бОльшее количество фрагов) в разминке (в $)",
            .has_min = false, .min_val = 0.0,
            .has_max = false, .max_val = 0.0
        ), g_eCvar[CVAR_SWU_AWARD_WINNER_MONEY]
    );

    bind_pcvar_num(
        create_cvar(
            "swu_mega_throw_count", "5", FCVAR_SERVER,
            .description = "Количество убийств для доступа к мегаброску^n0 - отключает мегабросок",
            .has_min = false, .min_val = 0.0,
            .has_max = false, .max_val = 0.0
        ), g_eCvar[CVAR_SWU_MEGA_THROW_COUNT]
    );

    bind_pcvar_string(
        create_cvar(
            "swu_ambient_sound", "ambience/wind1.wav", FCVAR_SERVER,
            .description = "Звук, который будет воспроизводиться при старте разминки\
            ^nОставьте настройку пустой, чтобы звук не воспроизводился",
            .has_min = false, .min_val = 0.0,
            .has_max = false, .max_val = 0.0
        ), g_eCvar[CVAR_SWU_AMBIENT_SOUND], charsmax(g_eCvar[CVAR_SWU_AMBIENT_SOUND])
    );

    AutoExecConfig(true);
}

@read_ini()
{
    g_aStateInfo[STATE_PLUGINS_ON] = any: ArrayCreate(64);
    g_aStateInfo[STATE_PLUGINS_OFF] = any: ArrayCreate(64);
    g_aStateInfo[STATE_CVARS_SET] = any: ArrayCreate(64);
    g_aStateInfo[STATE_CVARS_UNSET] = any: ArrayCreate(64);

    new const INI_PATH_FILE[] = "/reapi_snow_warmup.ini";

    new sPathFile[128];
    get_localinfo("amxx_configsdir", sPathFile, charsmax(sPathFile));
    add(sPathFile, charsmax(sPathFile), INI_PATH_FILE);

    if(!file_exists(sPathFile))
    {
        log_amx("Предупреждение (некритичное): отсутствует файл `%s`", sPathFile);
        return;
    }

    new INIParser: iIniParserHandle;
    iIniParserHandle = INI_CreateParser();

    INI_SetReaders(iIniParserHandle, "@INI_ParseValueHandler", "@INI_ParseSectionHandler");
    INI_ParseFile(iIniParserHandle, sPathFile);
    INI_DestroyParser(iIniParserHandle);
}

bool: @INI_ParseValueHandler(INIParser: handle, const sKey[], const sValue[], bool: invalid_tokens, bool: equal_token, bool: quotes, curtok, any: data)
{
    if(sKey[0] == EOS || sKey[0] == '/')
        return true;

    switch(g_iIniParseState)
    {
        case STATE_PLUGINS_OFF: ArrayPushString(any: g_aStateInfo[STATE_PLUGINS_OFF], sValue);
        case STATE_PLUGINS_ON: ArrayPushString(any: g_aStateInfo[STATE_PLUGINS_ON], sValue);
        case STATE_CVARS_SET: ArrayPushString(any: g_aStateInfo[STATE_CVARS_SET], fmt("%s %s", sKey, sValue));
        case STATE_CVARS_UNSET: ArrayPushString(any: g_aStateInfo[STATE_CVARS_UNSET], fmt("%s %s", sKey, sValue));
    }

    return true;
}

bool: @INI_ParseSectionHandler(INIParser: handle, const sSection[], bool: invalid_tokens, bool: close_bracket, bool: extra_tokens, curtok, any: data)
{
    if(equal(sSection, "PLUGINS_OFF"))
        g_iIniParseState = STATE_PLUGINS_OFF;
    else if(equal(sSection, "PLUGINS_ON"))
        g_iIniParseState = STATE_PLUGINS_ON;
    else if(equal(sSection, "CVARS_ON"))
        g_iIniParseState = STATE_CVARS_SET;
    else if(equal(sSection, "CVARS_OFF"))
        g_iIniParseState = STATE_CVARS_UNSET;

    return true;
}

stock get_origin_aiming(pPlayer, Float: fOrigin[3], Float: fDist)
{
    static Float: fDest[3];

    get_entvar(pPlayer, var_origin, fOrigin);
    get_entvar(pPlayer, var_view_ofs, fDest);

    xs_vec_add(fOrigin, fDest, fOrigin);

    get_entvar(pPlayer, var_v_angle, fDest);
    engfunc(EngFunc_MakeVectors, fDest);
    global_get(glb_v_forward, fDest);

    xs_vec_mul_scalar(fDest, fDist, fDest);
    xs_vec_add(fOrigin, fDest, fDest);

    engfunc(EngFunc_TraceLine, fOrigin, fDest, DONT_IGNORE_MONSTERS, pPlayer, 0);
    get_tr2(0, TR_vecEndPos, fOrigin);
}

stock rg_set_rendering(eEnt, fx = kRenderFxNone, r = 255, g = 255, b = 255, render = kRenderNormal, amount = 16)
{
    new Float: fRenderColor[3];
    fRenderColor[0] = float(r);
    fRenderColor[1] = float(g);
    fRenderColor[2] = float(b);
 
    set_entvar(eEnt, var_renderfx, fx);
    set_entvar(eEnt, var_rendercolor, fRenderColor);
    set_entvar(eEnt, var_rendermode, render);
    set_entvar(eEnt, var_renderamt, float(amount));
}

stock set_msg_beamfollow(eEnt, iSpriteIndex, iLifeTime, iSize, iRed, iGreen, iBlue, iBrightness)
{
    message_begin(MSG_BROADCAST, SVC_TEMPENTITY);
    write_byte(TE_BEAMFOLLOW);
    write_short(eEnt);
    write_short(iSpriteIndex);
    write_byte(iLifeTime * 10);
    write_byte(iSize);
    write_byte(iRed);
    write_byte(iGreen);
    write_byte(iBlue);
    write_byte(iBrightness);
    message_end();
}

stock set_msg_bloodstream(Float: fOrigin[3], iVelVector[3], iColor, iSpeed)
{
    message_begin_f(MSG_BROADCAST, SVC_TEMPENTITY, fOrigin);
    write_byte(TE_BLOODSTREAM);
    write_coord_f(fOrigin[0]);
    write_coord_f(fOrigin[1]);
    write_coord_f(fOrigin[2]);
    write_short(iVelVector[0]);
    write_short(iVelVector[1]);
    write_short(iVelVector[2]);
    write_byte(iColor);
    write_byte(iSpeed);
    message_end();
}

// https://wiki.alliedmods.net/CS_WeaponList_Message_Dump
stock set_msg_weaponlist(pPlayer, const sWeaponName[], iPrimaryAmmoID, iPrimaryAmmoMax, iSecondaryAmmoID, iSecondaryAmmoMax, iSlotID, iNumberInSlotID, any: iWeaponID, iFlags)
{
    static iMsgWpnList;

    if(!iMsgWpnList)
        iMsgWpnList = get_user_msgid("WeaponList");

    message_begin(pPlayer ? MSG_ONE : MSG_INIT, iMsgWpnList, .player = pPlayer);
    write_string(sWeaponName);
    write_byte(iPrimaryAmmoID);
    write_byte(iPrimaryAmmoMax);
    write_byte(iSecondaryAmmoID);
    write_byte(iSecondaryAmmoMax);
    write_byte(iSlotID);
    write_byte(iNumberInSlotID);
    write_byte(iWeaponID);
    write_byte(iFlags);
    message_end();
}

stock set_msg_svc_weaponanim(pPlayer, iAnimation)
{
    set_entvar(pPlayer, var_weaponanim, iAnimation);

    message_begin(MSG_ONE_UNRELIABLE, SVC_WEAPONANIM, .player = pPlayer);
    write_byte(iAnimation);
    write_byte(get_entvar(pPlayer, var_body));
    message_end();
}

enum _:
{
    Plural,
    Singular,
    Nominative
};

stock correct_word_seconds(iSeconds, pPlayer, sWords[], iWordsLen)
{
    switch(get_numerical_noun_form(iSeconds))
    {
        case Plural: format(sWords, iWordsLen, "%L", pPlayer, "SWU_NOUN_PLURAL");
        case Singular: format(sWords, iWordsLen, "%L", pPlayer, "SWU_NOUN_SINGULAR");
        case Nominative: format(sWords, iWordsLen, "%L", pPlayer, "SWU_NOUN_NOMINATIVE");
    }
}

// https://dev-cs.ru/threads/222/#post-2364
// by hunter
stock get_numerical_noun_form(iNum)
{
    if(iNum > 10 && ((iNum % 100) / 10) == 1)
        return Plural;                  

    switch (iNum % 10)
    {
        case 1: return Nominative;      
        case 2, 3, 4: return Singular;  
    }

    return Plural;                      
}
Требования
Последняя версия ReAPI
Требование ReAPI
Да
Поддержка русского языка
Да
Совместимость
  1. REHLDS
Сверху Снизу