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

reapi Snow WarmUp 0.1

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

new const PLUGIN_NAME[] = "Snow WarmUp";
new const PLUGIN_VERSION[] = "0.1";
new const PLUGIN_AUTHOR[] = "bizon";

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 SNOWBALL_SOUND_FREEZE[] = "snow_warmup/freeze.wav";
new const SNOWBALL_SOUND_UNFREEZE[] = "snow_warmup/unfreeze.wav";
new const AMBIENCE_SOUND_FIND[] = "ambience/wind1.wav"; // valve/sound/...
//
const TASK_USER_FREEZE = 0xD134;

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,
}

new
    HookChain: g_hRoundEnd,
    HookChain: g_hRestartRound,
    HookChain: g_hPlayerSpawn,
    HookChain: g_hKilled,
    HookChain: g_hCanHavePlayerItem,
    HookChain: g_hThrowSmokeGrenade,
    HookChain: g_hDefaultDeploy,
    HookChain: g_hRadio,
    bool: bIsSnowWarmUp,
    g_iTimer,
//
    g_iCvarRoundInfinite,
    g_iCvarForseRespawn,
    g_member_bCTCantBuy,
    g_member_bTCantBuy,
//
    g_iSpriteTrail,
//
    g_eCvar[CvarsStruct];

public plugin_precache()
{
    precache_model(SNOWBALL_MODEL_VIEW);
    precache_model(SNOWBALL_MODEL_PLAYER);
    precache_model(SNOWBALL_MODEL_WORLD);

    precache_sound(SNOWBALL_SOUND_FREEZE);
    precache_sound(SNOWBALL_SOUND_UNFREEZE);
    precache_sound(AMBIENCE_SOUND_FIND);

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

public client_disconnected(pPlayer)
{
    remove_task(pPlayer + TASK_USER_FREEZE);
}

public plugin_init()
{
    register_plugin(PLUGIN_NAME, PLUGIN_VERSION, PLUGIN_AUTHOR);

    g_hRoundEnd = RegisterHookChain(RG_RoundEnd, "@RoundEnd_Pre");

    @cvars_attach();
}

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

    g_hRestartRound = RegisterHookChain(RG_CSGameRules_RestartRound, "@CSGameRules_RestartRound_Pre");
    g_hPlayerSpawn = RegisterHookChain(RG_CSGameRules_PlayerSpawn, "@CSGameRules_PlayerSpawn_Post", true); // избегаем блок вызова RG_CBasePlayer_OnSpawnEquip вышестоящими плагинами
    g_hKilled = RegisterHookChain(RG_CBasePlayer_Killed, "@CBasePlayer_Killed_Post", true);
    g_hCanHavePlayerItem = RegisterHookChain(RG_CSGameRules_CanHavePlayerItem, "@CSGameRules_CanHavePlayerItem_Pre");
    g_hThrowSmokeGrenade = RegisterHookChain(RG_ThrowSmokeGrenade, "@ThrowSmokeGrenade_Post", true);
    g_hDefaultDeploy = RegisterHookChain(RG_CBasePlayerWeapon_DefaultDeploy, "@CBasePlayerWeapon_DefaultDeploy_Pre");
    g_hRadio = RegisterHookChain(RG_CBasePlayer_Radio, "@CBasePlayer_Radio_Pre");

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

    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_hRoundEnd);
}

@CSGameRules_RestartRound_Pre()
{
    if(bIsSnowWarmUp)
    {
        DisableHookChain(g_hRestartRound);
        DisableHookChain(g_hPlayerSpawn);
        DisableHookChain(g_hKilled);
        DisableHookChain(g_hCanHavePlayerItem);
        DisableHookChain(g_hThrowSmokeGrenade);
        DisableHookChain(g_hDefaultDeploy);
        DisableHookChain(g_hRadio);

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

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

        set_dhudmessage(0, 255, 255, -1.0, 0.04, .holdtime = 5.0);
        show_dhudmessage(0, "Зимняя разминка окончена^nПриятной игры");

        new iFwd;
        iFwd = CreateMultiForward("swu_end", ET_CONTINUE);
        ExecuteForward(iFwd);
    }else{
        g_iTimer = g_eCvar[CVAR_SWU_TIME];
        set_task(1.0, "@func_hud_info", 0xC0DE, .flags = "b");

        rg_send_audio(0, AMBIENCE_SOUND_FIND, PITCH_NORM);

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

    bIsSnowWarmUp = true;
}

@CSGameRules_PlayerSpawn_Post(pPlayer)
{
    rg_remove_all_items(pPlayer);

    DisableHookChain(g_hCanHavePlayerItem);

    new iItem;
    iItem = rg_give_custom_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_hCanHavePlayerItem);

    set_entvar(pPlayer, var_health, Float: float(g_eCvar[CVAR_SWU_START_HEALTH_USER]));
}

@CBasePlayer_Killed_Post(pVictim, pAttacker, iGibs)
{
    rg_set_rendering(pVictim);
    rg_reset_maxspeed(pVictim);

    remove_task(pVictim + TASK_USER_FREEZE);
}

@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: vecStart[3], Float: vecVelocity[3], Float: flTime, const usEvent)
{
    new eEnt;
    eEnt = GetHookChainReturn(ATYPE_INTEGER);

    if(!is_nullent(eEnt))
        rg_remove_entity(eEnt);

    new
        Float: fOriginStart[3],
        Float: fDest[3],
        Float: fVelocity[3];

    // 28 - "Bip01 R Hand" - правая рука (кость скелета)
    // https://wiki.alliedmods.net/FakeMeta_Functions_Detailed_Descriptions#EngFunc_GetBonePosition
    static const iBoneRightHand = 28;
    engfunc(EngFunc_GetBonePosition, pPlayer, iBoneRightHand, fOriginStart, fDest);

    // получаем координаты перед рукой на N юнитов
    static const Float: fDistShiftFrontUnit = 5.0;

    fDest[0] = 0.0
    engfunc(EngFunc_MakeVectors, fDest);
    global_get(glb_v_forward, fDest);

    xs_vec_mul_scalar(fDest, fDistShiftFrontUnit, fDest);
    xs_vec_add(fOriginStart, fDest, fDest);

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

    // расчёт векторной скорости полёта снежка
    get_origin_aiming(pPlayer, fDest);
   
    xs_vec_sub(fDest, 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, 3.0});

    set_entvar(eEnt, var_classname, "snowball");
    set_entvar(eEnt, var_owner, pPlayer);
    set_entvar(eEnt, var_movetype, MOVETYPE_TOSS);
    set_entvar(eEnt, var_solid, SOLID_TRIGGER);
    set_entvar(eEnt, var_velocity, fVelocity);

    SetTouch(eEnt, "@touch_snowball");

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

@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;
}

@touch_snowball(eEnt, pPlayer)
{
    new pOwner;
    pOwner = get_entvar(eEnt, var_owner);

    if(is_user_connected(pPlayer) && pOwner != pPlayer)
    {
        if(is_user_connected(pOwner) && rg_is_player_can_takedamage(pOwner, pPlayer))
        {
            emit_sound(pPlayer, CHAN_STATIC, SNOWBALL_SOUND_FREEZE, VOL_NORM, ATTN_NORM, 0, PITCH_NORM);
           
            ExecuteHamB(Ham_TakeDamage, pPlayer, eEnt, pOwner, float(g_eCvar[CVAR_SWU_DAMAGE_USER]), DMG_FREEZE);

            if(g_eCvar[CVAR_SWU_IS_FREEZE_USER])
            {
                remove_task(pPlayer + TASK_USER_FREEZE);
                set_task(float(g_eCvar[CVAR_SWU_FREEZE_TIME_USER]), "@func_reset_user_freeze", pPlayer + TASK_USER_FREEZE);

                rg_set_rendering(pPlayer, kRenderFxGlowShell, 0, 255, 255, kRenderNormal, 16);
                set_entvar(pPlayer, var_maxspeed, -1.0);
            }
        }
    }

    rg_remove_entity(eEnt);
}

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

        set_dhudmessage(0, 255, 255, -1.0, 0.04, .holdtime = 0.8);
        show_dhudmessage(0, "Зимняя разминка^nДо окончания: %i %s", g_iTimer, sSeconds);

        g_iTimer--;
    }
}

@func_reset_user_freeze(pPlayer)
{
    pPlayer -= TASK_USER_FREEZE;

    rg_set_rendering(pPlayer);
    rg_reset_maxspeed(pPlayer);

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

@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]
    );

    AutoExecConfig(true);
}

stock get_origin_front(pPlayer, Float: fOriginEnd[3], Float: fDist)
{
    static Float: fOriginStart[3];

    get_entvar(pPlayer, var_origin, fOriginStart);
    get_entvar(pPlayer, var_v_angle, fOriginEnd);

    fOriginEnd[0] = 0.0;

    engfunc(EngFunc_MakeVectors, fOriginEnd);
    global_get(glb_v_forward, fOriginEnd);

    xs_vec_mul_scalar(fOriginEnd, fDist, fOriginEnd);
    xs_vec_add(fOriginStart, fOriginEnd, fOriginEnd);

    engfunc(EngFunc_TraceLine, fOriginStart, fOriginEnd, DONT_IGNORE_MONSTERS, pPlayer, 0);
    get_tr2(0, TR_vecEndPos, fOriginEnd);
}

stock get_origin_aiming(pPlayer, Float: fOrigin[3])
{
    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, 8192.0, 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_remove_entity(eEnt)
{
    set_entvar(eEnt, var_nextthink, -1.0);
    set_entvar(eEnt, var_flags, FL_KILLME);
}

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();
}

enum _:
{
    Plural,
    Singular,
    Nominative
};

stock correct_word_seconds(iSeconds, sWords[], iWordsLen)
{
    switch(get_numerical_noun_form(iSeconds))
    {
        case Plural: format(sWords, iWordsLen, "секунд");
        case Singular: format(sWords, iWordsLen, "секунды");
        case Nominative: format(sWords, iWordsLen, "секунда");
    }
}

// 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
Да
Поддержка русского языка
Да
Совместимость
  1. REHLDS
Сверху Снизу