CSDM Object

reapi CSDM Object 1.0

Нет прав для скачивания
Автор
Оригинала неизвестно, модификация Flymic24
Исходный код
Sentry:
#include < amxmodx >
#include < amxmisc >
#include < csdm_object >
#include < engine>

#pragma semicolon 1

#define _VERSION        "#0.91"

#define    DMG_AWARD        random_num(3, 10)    //    Награда за урон
#define UPDATE_DELAY    15.0    //    Через сколько можно обновлять
#define BUILD_TIME        10.03    //    Время на постройку
#define UPGRADE_TIME    3.025    //     Время обновления

const  MAX_SENTRY    =    5;        // Лимит

#define PrintModel        "models/csdm/sentrygun_blueprint.mdl"
#define GibsMdl            "models/csdm/sentrygun_gibs.mdl"
#define RoketMdl        "models/csdm/sentrygun_rockets.mdl"

#define WEAPON_LIST        "weapon_sentrygun"

enum _:eAnimSentry{
    _IDLE = 0,    _FIRE, _FIRE_ALT, _FIRE_ROKET
};

enum _:eSentrySound    {
    Build,    Idle,    Fire,    Upgrade, Roket, Explode
};

new szSentryModels[eLevelList][] = {
    "models/csdm/sentrygun1_low.mdl",
    "models/csdm/sentrygun2_low.mdl",
    "models/csdm/sentrygun3_low.mdl"
};

new szUpgradeModels[eLevelList][] = {
    "models/csdm/sentrygun1_heavy.mdl",
    "models/csdm/sentrygun2_heavy.mdl",
    "models/csdm/sentrygun3_heavy.mdl"
};

new szPlayerBoxModel[][] = {
    "models/csdm/p_box_red.mdl",
    "models/csdm/p_box_blue.mdl"
};

new szViewBoxModel[][] = {
    "models/csdm/v_box_red.mdl",
    "models/csdm/v_box_blue.mdl"
};

new szSentrySound[eSentrySound][] = {
    "csdm/sentry_finish.wav",    "csdm/sentry_spot_client.wav",
    "csdm/sentry_shoot3.wav",    "csdm/sentry_generate_metal.wav",
    "csdm/sentry_rocket.wav",    "csdm/sentry_explode.wav"
};

// Health = get_players() * (koef * Level)
const HealthKoef = 50;        //    Hp пушки зависит от числа игроков

new g_CostUpgrade[ 3 ] =    {    10,        11,        12    };        //    Цена постройки
new Float:g_Damage[ 3 ] =     {    10.0,    15.0,    25.0        };    //    Урон наносимый
new Float:g_Reaction[ 3 ] =     {    0.5,    0.3,    0.1        };    //    Время реагирования
new Float:g_FireTime[ 3 ] =     {    0.6,    0.3,    0.1        };    //    Время между выстрелами
const Float:RADIUS_DAMAGE_ROKET = 200.0;        //    Радиус взрыва рокет
const Float:DAMAGE_ROKET = 80.0;        //     Урон от рокет

#define REFERENCE_WEAPON    "weapon_tmp"
#define    _ClassName            "Sentry"

const Float:SENTRY_VEC_Z_OFSET = 45.0;
const Float:SIZE = 16.0;
const ITEM_POSITION = 5;

new HookChain:g_DeathNoticeHook;
new g_Smoke;

public plugin_init()
{
    register_plugin
    (
        "[AMXX] Sentry TF2",
        _VERSION,
        "Flymic24"
    );
 
    RegisterHam(Ham_TraceAttack,    "info_target",    "HamHook_Sentry_TraceAttack",    false);
    RegisterHam(Ham_Killed,            "info_target",    "HamHook_Sentry_Killed",    false);
 
    RegisterHookChain(RG_CBasePlayer_UseEmpty, "HamHook_Sentry_Use", .post = true);
    RegisterHookChain(RG_CBasePlayerWeapon_DefaultDeploy, "CBasePlayerWeapon_DefaultDeploy", false);
 
    DisableHookChain(g_DeathNoticeHook = RegisterHookChain(RG_CSGameRules_DeathNotice, "CSGameRules_DeathNotice", true));
    RegisterHookChain(RG_CBasePlayer_Spawn, "CBasePlayer_OnSpawnEquip", true);
 
    RegisterHam(Ham_Item_PostFrame,    REFERENCE_WEAPON,    "HamHook_Item_PostFrame",    false);
    RegisterHam(Ham_Weapon_PrimaryAttack,    REFERENCE_WEAPON,    "HamHook_Item_PrimaryAttack",    false);
 
    register_message(get_user_msgid("DeathMsg"), "Msg_DeathMsg");
 
    RegisteFunc(REFERENCE_WEAPON);
 
    AMMO_ID = rg_add_ammo_registry(WEAPON_LIST);
    iKey = engfunc(EngFunc_AllocString, _ClassName);
}

public plugin_precache(){
    precache_model(PrintModel);
    precache_model(GibsMdl);
    precache_model(RoketMdl);
 
    for(new i = _Level1; i < eLevelList;    i++){
        precache_model(szSentryModels[i]);
        precache_model(szUpgradeModels[i]);
    }
 
    for(new i = 0; i < sizeof(szPlayerBoxModel); i++){
        precache_model(szPlayerBoxModel[i]);
        precache_model(szViewBoxModel[i]);
    
        if(get_cvar_num("sv_auto_precache_sounds_in_models") == 0) {
            PRECACHE_MODEL2(szViewBoxModel[i]);
        }
    }
 
    for(new i = 0; i < sizeof(szSentrySound); i++)    {
        precache_sound(szSentrySound[i]);
    }
 
    PRECACHE_WEAPONLIST(WEAPON_LIST);
 
    g_Smoke = precache_model("sprites/steam1.spr");
}

/*    *****************
Give custom Sentry
********************/

public CBasePlayer_OnSpawnEquip(const iPlayer){
    if (EquipDelay > 0.0)
        set_task(EquipDelay, "GiveEquip", iPlayer);
    else
        GiveEquip(iPlayer);
}

public GiveEquip(iPlayer)    {
    GiveObject(iPlayer, REFERENCE_WEAPON, iKey, AMMO_ID, MAX_SENTRY);
}

public CBasePlayerWeapon_DefaultDeploy(const iItem, szViewModel[], szWeaponModel[], iAnim, szAnimExt[], skiplocal)    {
    if(!IsCustomItem(iItem))
        return HC_CONTINUE;
 
    new iPlayer;
    if(!(iPlayer = get_member(iItem, m_pPlayer)) || !is_user_connected(iPlayer))
        return HC_CONTINUE;
 
    new iTeam = get_member(iPlayer, m_iTeam) - 1;
 
    SetHookChainArg(2, ATYPE_STRING, szViewBoxModel[iTeam]);
    SetHookChainArg(3, ATYPE_STRING, szPlayerBoxModel[iTeam]);
 
    SetHookChainArg(4, ATYPE_INTEGER, _DRAW);
 
    return HC_CONTINUE;
}

/*******************
Ham hook Sentry
********************/

public Default_Item_Holster(const iItem, const iPlayer)    {
    //    Code
}

public Default_Item_AttachToPlayer(const iItem, const iPlayer)    {
    SetObjectWeaponList(iItem, iPlayer, AMMO_ID, WEAPON_LIST, MAX_SENTRY, ITEM_POSITION);
}

public HamHook_Item_PostFrame(const iItem){
    if(!IsCustomItem(iItem))
        return HAM_IGNORED;
 
    new iPlayer;
    if(!(iPlayer = get_member(iItem, m_pPlayer)) || !is_user_connected(iPlayer))
        return HAM_IGNORED;
 
    if(get_member(iPlayer, m_iAccount) >= g_CostUpgrade[_Level1] && get_member(iItem, m_Weapon_iDefaultAmmo) > 0)    {
        rg_add_account(iPlayer, g_CostUpgrade[_Level1]);
        rg_add_account(iPlayer, -g_CostUpgrade[_Level1]);
    }
 
    new Float:vecSrc[eCoord], Float:vecAiming[eCoord];
    GetPlantOrigin(iPlayer, vecSrc, vecAiming);
 
    engfunc(EngFunc_TraceLine, vecSrc, vecAiming, IGNORE_MISSILE|IGNORE_GLASS|IGNORE_MONSTERS, iPlayer, 0);
 
    new Float:flFraction;    get_tr2(0, TR_flFraction, flFraction);
    new iSentry = iObjectID[iPlayer];
 
    if (flFraction >= 1.0 || !is_user_alive(iPlayer))    {
        if(!is_nullent(iSentry))    {
            UTIL_KillEntity(iSentry);
        }
        iObjectID[iPlayer] = NULLENT;   
        return HAM_IGNORED;
    }
    else if(flFraction < 1.0)    {
        if(is_nullent(iSentry))    {
            iObjectID[iPlayer] = iSentry = SpawnObject(_ClassName, PrintModel, Float:{-SIZE, -SIZE, 0.0}, Float:{SIZE, SIZE, 55.0});
        }
    
        new Float:fVecEnd[eCoord], Float:fVecNormal[eCoord], Float:fAngles[eCoord];
        get_tr2(0, TR_vecEndPos, fVecEnd);
        get_tr2(0, TR_vecPlaneNormal, fVecNormal);
    
        xs_vec_mul_scalar(fVecNormal, 1.0, fVecNormal);
        xs_vec_add(fVecEnd, fVecNormal, fVecEnd);
    
        engfunc(EngFunc_SetOrigin, iSentry, fVecEnd);
    
        if (fVecNormal[2] == 1.0 && CheckLocation(iSentry, fVecEnd, SIZE * 2, SENTRY_VEC_Z_OFSET))    {
            set_entvar(iSentry, var_sequence, _IDLE);
            get_entvar(iPlayer, var_angles, fAngles);
            fAngles[1] -= 180.0;
            fAngles[0] += 12.0;
        }
        else    {
            set_entvar(iSentry, var_sequence, _DRAW);
            vector_to_angle(fVecNormal, fAngles);
            fAngles[0] -= 90.0;
        }
    
        set_entvar(iSentry, var_angles, fAngles);
    }
 
    return HAM_IGNORED;
}

public HamHook_Item_PrimaryAttack(const iItem){
    if(!IsCustomItem(iItem))
        return HAM_IGNORED;
 
    new iPlayer;
    if(!(iPlayer = get_member(iItem, m_pPlayer)) || !is_user_connected(iPlayer))
        return HAM_IGNORED;
 
    new iSentry;
    if (!(iSentry = iObjectID[iPlayer]) || is_nullent(iSentry))
        return HAM_SUPERCEDE;
 
    set_member(iItem, m_Weapon_flNextPrimaryAttack, 1.0);
 
    if (get_entvar(iSentry, var_sequence) == _DRAW){
        client_print(iPlayer, print_center, "Здесь строить нельзя");
        return HAM_SUPERCEDE;
    }
 
    new iClip = get_member(iPlayer, m_rgAmmo, AMMO_ID);
 
    if (--iClip < 0)    {
        client_print(iPlayer, print_center, "Более нельзя ставить");
        return HAM_SUPERCEDE;
    }
 
    if(get_member(iPlayer, m_iAccount) < g_CostUpgrade[_Level1])    {
        client_print(iPlayer, print_center, "Не достаточно средств: %i", g_CostUpgrade[_Level1]);
        return HAM_SUPERCEDE;
    }
 
    set_member(iItem, m_Weapon_iDefaultAmmo, iClip);
    set_member(iPlayer, m_rgAmmo, iClip, AMMO_ID);
 
    BuildObject(iPlayer, iSentry, BUILD_TIME, szSentrySound[Build], _IDLE, UPDATE_DELAY, szUpgradeModels[_Level1]);

    set_entvar(iSentry, var_controller, 0, POS_X);
    set_entvar(iSentry, var_controller, 127, POS_Y);
    set_entvar(iSentry, var_angles, Float:{0.0, 0.0, 0.0});
 
    set_entvar(iSentry, object_target, NULLENT);
 
    rg_add_account(iPlayer, -g_CostUpgrade[_Level1]);
 
    return HAM_SUPERCEDE;
}

/**********************************
Brain to Sentry
**********************************/

#define UPDATE_TIME        0.05

public Object_Think(const iEnt)    {
    if (is_nullent(iEnt))
        return;
 
    new Float:fGameTime = get_gametime();
    new iTeam = get_entvar(iEnt, var_team);
    new iLevel = get_entvar(iEnt, object_level);
    new iOwner = get_entvar(iEnt, object_owner);
 
    if(!is_user_alive(iOwner) || get_member(iOwner, m_iTeam) != iTeam)    {
        UTIL_KillEntity(iEnt);
        return;
    }
 
    SetObjectInfoAim(fGameTime, iTeam, iEnt);
 
    if (get_entvar(iEnt, object_active_time) > fGameTime)    {
        set_entvar(iEnt, var_nextthink, fGameTime + UPDATE_TIME);
        return;
    }
 
    switch(get_entvar(iEnt, object_status))    {
        case _BUILDING:    {
            engfunc(EngFunc_SetModel, iEnt, szSentryModels[iLevel]);
            engfunc(EngFunc_SetSize, iEnt, Float:{-SIZE, -SIZE, 0.0}, Float:{SIZE, SIZE, 55.0});
        
            new Float:fHealth = GetHealthSentry(iLevel);
        
            set_entvar(iEnt, var_takedamage, DAMAGE_YES);
            set_entvar(iEnt, var_health, fHealth);
            set_entvar(iEnt, var_max_health, fHealth);
            set_entvar(iEnt, object_status, _SEARCH);
        }
        case _SEARCH:    {
            new iController1 = get_entvar(iEnt, var_controller, POS_X);
            if (++iController1 > 255) iController1 -= 255;
            set_entvar(iEnt, var_controller, iController1, POS_X);
            set_entvar(iEnt, var_controller, 127, POS_Y);
        
            UTIL_Animation(iEnt, _IDLE);
            
            new iNewTarget = GetSentryTarget(iEnt);
        
            if (is_user_connected(iNewTarget))    {
                SentryTurnToTarget(iEnt, iNewTarget);
                rh_emit_sound2(iEnt, 0, CHAN_STATIC, szSentrySound[Idle]);
                
                set_entvar(iEnt, object_target, iNewTarget);
                set_entvar(iEnt, object_status, _ACTIVE);
            
                set_entvar(iEnt, var_nextthink, fGameTime + g_Reaction[iLevel]);
                return;
            }
        }
        case _ACTIVE:    {
            new iTarget = get_entvar(iEnt, object_target);
        
            if (!is_user_alive(iTarget) || !UTIL_IsVisible(iTarget, iEnt, SENTRY_VEC_Z_OFSET) || IsUseShield(iTarget))    {
                set_entvar(iEnt, object_target, NULLENT);
                set_entvar(iEnt, object_status, _SEARCH);
            }
            else
            {
                new iLevel = get_entvar(iEnt, object_level);
            
                SentryTurnToTarget(iEnt, iTarget);
                if (get_entvar(iEnt, object_state) != _FIRE_ROKET)
                    UTIL_Animation(iEnt);
            
                if (fGameTime > get_entvar(iEnt, var_fuser2))    {
                    UTIL_Animation(iEnt, _FIRE);
                    DefaultAttack(iEnt, iOwner, iTarget);
                    set_entvar(iEnt, object_state, _FIRE);
                    set_entvar(iEnt, var_fuser2, fGameTime + g_FireTime[iLevel]);
                }
            
                if (iLevel == _Level3)    {
                    if (fGameTime > get_entvar(iEnt, var_fuser3))    {
                        UTIL_Animation(iEnt, _FIRE_ROKET);
                        FireRoket(iEnt, iOwner, iTarget, 600.0);
                    
                        set_entvar(iEnt, object_state, _FIRE_ROKET);
                        set_entvar(iEnt, var_fuser2, fGameTime + 1.53);
                        set_entvar(iEnt, var_fuser3, fGameTime + 5.0);
                    }
                }
            }
        }
    }
 
    set_entvar(iEnt, var_nextthink, fGameTime + UPDATE_TIME);
}

public HamHook_Sentry_Use(const pPlayer)    {
    new iEnt, iBody;
    get_user_aiming(pPlayer, iEnt, iBody, floatround(PLANT_RADIUS));
 
    if (!IsCustomObject(iEnt))
        return;
 
    if(get_member(pPlayer, m_iTeam) != get_entvar(iEnt, var_team))
        return;
 
    new iLevel = get_entvar(iEnt, object_level);
 
    if (++iLevel >= eLevelList){
        return;
    }
 
    UpgradeObject(pPlayer, iEnt, iLevel, _IDLE, UPGRADE_TIME, UPDATE_DELAY, g_CostUpgrade[iLevel], szSentrySound[Upgrade], szUpgradeModels[iLevel]);
 
    if (iLevel == _Level3)    {
        set_entvar(iEnt, var_fuser3, get_gametime() + UPGRADE_TIME + 5.0);
    }
}

public Sentry_RoketTouch(const iEnt, const iOther){
    if (is_nullent(iEnt))
        return;
 
    new Float:fVecOrigin[eCoord];    get_entvar(iEnt, var_origin, fVecOrigin);
    UTIL_TE_EXPLOSION(fVecOrigin);
 
    new iOwner = get_entvar(iEnt, var_owner);
    new iVictim = NULLENT;
    while((iVictim = engfunc(EngFunc_FindEntityInSphere, iVictim, fVecOrigin, RADIUS_DAMAGE_ROKET)))
    {
        if(!is_user_alive(iVictim))    continue;
        if(get_member(iVictim, m_iTeam) == get_member(iOwner, m_iTeam))    continue;
    
        ExecuteHamB(Ham_TakeDamage, iVictim, iEnt, iOwner, DAMAGE_ROKET, DMG_GRENADE);
    }
    //    rg_dmg_radius(fVecOrigin, iEnt, iOwner, DAMAGE_ROKET, RADIUS_DAMAGE_ROKET, 0, DMG_GRENADE);
 
    UTIL_KillEntity(iEnt);
}

public HamHook_Sentry_Killed(const iVictim, const iAttacker){
    if (is_nullent(iVictim))
        return HAM_IGNORED;
 
    if (!IsCustomObject(iVictim))
        return HAM_IGNORED;
 
    rh_emit_sound2(iVictim, 0, CHAN_STATIC, szSentrySound[Explode]);
 
    new Float:fVecOrigin[eCoord];    get_entvar(iVictim, var_origin, fVecOrigin);
    UTIL_TE_EXPLOSION(fVecOrigin);
 
    new iOwner = get_entvar(iVictim, object_owner);
 
    if (is_user_connected(iOwner))    {
        set_member(iOwner, m_rgAmmo, get_member(iOwner, m_rgAmmo, AMMO_ID) + 1, AMMO_ID);
    }
 
    CObject_Gibs(iVictim, GibsMdl, random_num(0, 11), get_entvar(iVictim, var_skin));
 
    return HAM_IGNORED;
}

public HamHook_Sentry_TraceAttack(iVictim, iAttacker, Float:flDamage, Float:flDirection[3], iTrace, iDamageBits){
    if (!is_user_connected(iAttacker))
        return HAM_IGNORED;
 
    if (!IsCustomObject(iVictim))
        return HAM_IGNORED;
 
    if (get_entvar(iVictim, var_takedamage) != DAMAGE_YES)
        return HAM_SUPERCEDE;
 
    new Float:flEndOrigin[eCoord];    get_tr2(iTrace, TR_vecEndPos, flEndOrigin);
    UTIL_TE_SPARKS(flEndOrigin);
 
    if(get_entvar(iVictim, var_team) == get_member(iAttacker, m_iTeam) /*&& iAttacker != get_entvar(iVictim, object_owner)*/)
        return HAM_SUPERCEDE;
 
    rg_add_account(iAttacker, DMG_AWARD);
 
    return HAM_IGNORED;
}

public ShowObjectInfoAim(const iPlayer, const iEnt, Float:fGameTime)    {
    new Float:iHealth = get_entvar(iEnt, var_health);
 
    new iLevel = get_entvar(iEnt, object_level);
    new iOwner = get_entvar(iEnt, object_owner);
    new iKill = get_entvar(iEnt, object_data1);
    new iTeam = get_entvar(iEnt, var_team);
 
    set_dhudmessage(iTeam == _:TEAM_TERRORIST ? 120 : 0, 0, iTeam == _:TEAM_CT ? 255 : 0, -1.0, 0.35, 0, 0.0, 1.1, 0.0, 0.0);
    show_dhudmessage(iPlayer, fmt("Владелец: %n^nПрочность: %i^nУровень: %i Убийств: %i", iOwner, floatround(iHealth), iLevel + 1, iKill));
 
    if (iLevel < eLevelList - 1)    {
        new Float:fUpdateTime;    get_entvar(iEnt, object_update_time, fUpdateTime);
        if (fGameTime < fUpdateTime)
            show_dhudmessage(iPlayer, fmt("^n^n^nАпгрейд: %i$ Update: %i", g_CostUpgrade[++iLevel], floatround(fUpdateTime - fGameTime)));
        else
            show_dhudmessage(iPlayer, fmt("^n^n^nАпгрейд: %i$ Update: Нажмите на <E>", g_CostUpgrade[++iLevel]));
    }
}

DefaultAttack(const iEnt, const iOwner, const iTarget)    {
    if (is_nullent(iEnt))
        return;
 
    enum _:eData{
        Entity = 0,    Target
    };
 
    new Float:fOrigin[eData][eCoord];
    get_entvar(iEnt, var_origin, fOrigin[Entity]);    fOrigin[Entity][2] += SENTRY_VEC_Z_OFSET;
    get_entvar(iTarget, var_origin, fOrigin[Target]);
 
    new iLevel = get_entvar(iEnt, object_level);
 
    switch(iLevel)
    {
        case _Level1:    UTIL_TE_TRACER(fOrigin[Entity], fOrigin[Target]);
        default:
        {
            fOrigin[Entity][1] += 30.0;
            UTIL_TE_TRACER(fOrigin[Entity], fOrigin[Target]);
        
            fOrigin[Entity][1] -= 60.0;
            UTIL_TE_TRACER(fOrigin[Entity], fOrigin[Target]);
        }
    }
 
    rh_emit_sound2(iEnt, 0, CHAN_STATIC, szSentrySound[Fire]);
    //    engfunc(EngFunc_EmitAmbientSound, iEnt, pos_ent/*coord*/, szSentrySound[Fire], VOL_NORM /*0.5*/, ATTN_NORM, 0, PITCH_NORM);
 
    if (get_entvar(iTarget, var_armorvalue) > g_Damage[iLevel])
        set_entvar(iTarget, var_armorvalue, get_entvar(iTarget, var_armorvalue) - g_Damage[iLevel]);
    else
        ExecuteHamB(Ham_TakeDamage, iTarget, iEnt, iOwner, g_Damage[iLevel], DMG_GRENADE);
 
    if(!is_user_alive(iTarget))    {
        set_entvar(iEnt, object_data1, get_entvar(iEnt, object_data1) + 1);
    }
}

FireRoket(const iEnt, const iOwner, const iTarget, Float:fSpeed)    {
    enum _:eData{
        Entity = 0,    Target,    Velocity, Angles
    };
 
    rh_emit_sound2(iEnt, 0, CHAN_STATIC, szSentrySound[Roket]);
    //    engfunc(EngFunc_EmitAmbientSound, iEnt, pos_ent/*coord*/, szSentrySound[Roket], VOL_NORM /*0.5*/, ATTN_NORM, 0, PITCH_NORM);
 
    new Float:fVecOrigin[eData][eCoord];
 
    get_entvar(iTarget, var_origin, fVecOrigin[ Target ]);
    get_entvar(iEnt, var_origin, fVecOrigin[ Entity ]);    fVecOrigin[Entity][2] += SENTRY_VEC_Z_OFSET;
    get_entvar(iEnt, var_angles, fVecOrigin[ Angles ]);
 
    angle_vector(fVecOrigin[ Angles ], ANGLEVECTOR_FORWARD, fVecOrigin[ Angles ]);
 
    xs_vec_mul_scalar(fVecOrigin[ Angles ], 15.0, fVecOrigin[ Angles ]);
    xs_vec_add(fVecOrigin[ Entity ], fVecOrigin[ Angles ], fVecOrigin[ Entity ]);
 
    message_begin(MSG_BROADCAST, SVC_TEMPENTITY);
    write_byte(TE_SMOKE);
    write_coord_f(fVecOrigin[ Entity ][0]);
    write_coord_f(fVecOrigin[ Entity ][1]);
    write_coord_f(fVecOrigin[ Entity ][2]);
    write_short(g_Smoke);
    write_byte(random_num(5, 8));
    write_byte(5);
    message_end();
 
    new ent;
    if(!(ent = rg_create_entity("info_target")) || is_nullent(ent))
        return;
 
    set_entvar(ent, var_classname, "roket");
 
    engfunc(EngFunc_SetModel, ent, RoketMdl);
    engfunc(EngFunc_SetSize, ent, Float:{ -5.0, -5.0, -5.0 }, Float:{ 5.0, 5.0, 5.0 });
    engfunc(EngFunc_SetOrigin, ent, fVecOrigin[ Entity ]);
 
    xs_vec_sub(fVecOrigin[ Target ], fVecOrigin[ Entity ], fVecOrigin[ Target ]);
    xs_vec_normalize(fVecOrigin[ Target ], fVecOrigin[ Velocity ]);
    xs_vec_mul_scalar(fVecOrigin[ Velocity ], fSpeed, fVecOrigin[ Velocity ]);
    vector_to_angle(fVecOrigin[ Velocity ], fVecOrigin[ Angles ]);
 
    set_entvar(ent, var_movetype, MOVETYPE_FLY);
 
    set_entvar(ent, var_angles, fVecOrigin[ Angles ]);
    set_entvar(ent, var_velocity, fVecOrigin[ Velocity ]);
 
    set_entvar(ent, var_solid, SOLID_TRIGGER);
    set_entvar(ent, var_owner, iOwner);
 
    SetTouch(ent, "Sentry_RoketTouch");
 
    UTIL_Animation(ent, _IDLE);
}

/*******************
Kill Message
********************/

public CSGameRules_DeathNotice(const iVictim, const iAttacker, inflictor)    {
    rh_update_user_info(iAttacker);
    DisableHookChain(g_DeathNoticeHook);
}

public Msg_DeathMsg()    {
    new szClassName[MAX_NAME_LENGTH];    get_msg_arg_string(4, szClassName, charsmax(szClassName));
 
    if(!equali(szClassName, _ClassName) && !equali(szClassName, "roket"))
        return;
 
    new iAttacker = get_msg_arg_int(1);
    new szName[MAX_NAME_LENGTH];    get_user_name(iAttacker, szName, charsmax(szName));
 
    EnableHookChain(g_DeathNoticeHook);
 
    set_user_fake_name(iAttacker, fmt("%.14s [Sentry Gun]", szName));
 
    set_msg_arg_string(4, "teammate");
}

/*******************
Stock
********************/
stock GetSentryTarget(const iEntity)    {
    new iTarget = NULLENT, Float:fLen = 0.0, Float:fLenMax = 9999.0;
    new iTeam = get_entvar(iEntity, var_team);
 
    for (new id = 1; id <= MaxClients; id++)    {
        if (!is_user_alive(id))    continue;
        if (get_member(id, m_iTeam) == iTeam)    continue;
        if (!UTIL_IsVisible(id, iEntity, SENTRY_VEC_Z_OFSET))    continue;
        if (IsUseShield(id))    continue;
    
        fLen = entity_range(id, iEntity);
    
        if(fLen < fLenMax)    {
            fLenMax = fLen;
            iTarget = id;
        }
    }
    return iTarget;
}

stock Float:GetHealthSentry(Level)    {
    return float(get_playersnum_ex(GetPlayers_ExcludeHLTV) * (HealthKoef * ++Level));
}

stock SentryTurnToTarget(const iSentry, const iTarget)
{
    enum _:eData    {
        Entity,    Target, Angles
    };
 
    new Float:fVecOrigin[eData][eCoord];
 
    get_entvar(iSentry, var_origin, fVecOrigin[ Entity ]);    fVecOrigin[Entity][2] += SENTRY_VEC_Z_OFSET;
    get_entvar(iSentry, var_angles, fVecOrigin[Angles]);
    get_entvar(iTarget, var_origin, fVecOrigin[ Target ]);
 
    new Float:fDirection[eCoord];
    fDirection[0] = fVecOrigin[ Target ][0] - fVecOrigin[ Entity ][0];
    fDirection[1] = fVecOrigin[ Target ][1] - fVecOrigin[ Entity ][1];
    fDirection[2] = fVecOrigin[ Target ][2] - fVecOrigin[ Entity ][2];
 
    new Float:fShootAngles[3];    vector_to_angle(fDirection, fShootAngles);
    new Float:fRotatorAngle = fShootAngles[1] - fVecOrigin[Angles][1];

    if(fRotatorAngle < 0.0) {
        fRotatorAngle += 360.0;
    }

    set_controller(iSentry, POS_X, fRotatorAngle);
    set_controller(iSentry, POS_Y, -fShootAngles[0] + 360.0);
}
Dispenser:
#include < amxmodx >
#include < csdm_object >

#pragma semicolon 1

#define _VERSION        "#0.8.2"

#define    DMG_AWARD        random_num(3, 10)    //    Награда за урон
#define UPDATE_DELAY    7.0            //    Через сколько можно обновлять
#define BUILD_TIME        10.0        //    Время на постройку
#define UPGRADE_TIME    1.23        //     Время обновления

#define MAX_DISPENCER    3        // Лимит

#define PrintModel        "models/csdm/dispenser_blueprint.mdl"
#define GibsMdl            "models/csdm/dispenser_gibs.mdl"
#define HealthSpr        "sprites/csdm/dispenser_heal.spr"
#define ActivateSound    "buttons/button9.wav"

#define WEAPON_LIST        "weapon_dispenser"

#define    SIZE            16.0

new szClassActive[][16] = {    //    Классы обьектов
    "Sentry",    "DispenserHP",    "_tripmine"
};

const POSITION_NUM = 2;
const Float:MAX_HP = 255.0;        //    Максимум до скольки пополнять хп
const Float:MAX_AP = 100.0;        //    Максимум до скольки пополнять броню

new szDispenserModels[eLevelList][] = {
    "models/csdm/dispenser1_light.mdl",
    "models/csdm/dispenser2_light.mdl",
    "models/csdm/dispenser3_light.mdl"
};

new szUpgradeModels[eLevelList][] = {
    "models/csdm/dispenser1.mdl",
    "models/csdm/dispenser2.mdl",
    "models/csdm/dispenser3.mdl"
};

new szPlayerBoxModel[][] = {
    "models/csdm/p_box_red.mdl",
    "models/csdm/p_box_blue.mdl"
};

new szViewBoxModel[][] = {
    "models/csdm/v_box_red.mdl",
    "models/csdm/v_box_blue.mdl"
};

new g_CostUpgrade[3] =    {    11,        12,        13    };        //    Цена
new Float:g_Health[3] =    {    100.0,    150.0,    200.0    };    //    Hp
new Float:g_HealthRadius[3] =    {    100.0,    150.0,    300.0    };        //    Радиус действия
new Float:g_AddHealth[3] =    {    5.0,    15.0,    25.0        };        //    По сколько hp лечить

#define REFERENCE_WEAPON    "weapon_ump45"
#define    _ClassName            "DispenserHP"

new gBeam;

public plugin_init()
{
    register_plugin
    (
        "[AMXX] Health Dispenser",
        _VERSION,
        "Flymic24"
    );
 
    RegisterHam(Ham_TraceAttack,    "info_target",    "HamHook_Dispenser_TraceAttack",    false);
    RegisterHam(Ham_Killed,            "info_target",    "HamHook_Dispenser_Killed",    false);
 
    RegisterHookChain(RG_CBasePlayer_UseEmpty, "HamHook_Dispenser_Use", .post = true);
    RegisterHookChain(RG_CBasePlayerWeapon_DefaultDeploy, "CBasePlayerWeapon_DefaultDeploy", false);
 
    RegisterHookChain(RG_CBasePlayer_Spawn, "CBasePlayer_OnSpawnEquip", true);
 
    RegisterHam(Ham_Item_PostFrame,    REFERENCE_WEAPON,    "HamHook_Item_PostFrame",    false);
    RegisterHam(Ham_Weapon_PrimaryAttack,    REFERENCE_WEAPON,    "HamHook_Item_PrimaryAttack",    false);
 
    RegisteFunc(REFERENCE_WEAPON);
 
    AMMO_ID = rg_add_ammo_registry(WEAPON_LIST);
    iKey = engfunc(EngFunc_AllocString, _ClassName);
}

public plugin_precache(){
    precache_model(HealthSpr);
    precache_sound(ActivateSound);
    precache_model(PrintModel);
    precache_model(GibsMdl);
 
    for(new i = _Level1; i < eLevelList;    i++){
        precache_model(szDispenserModels[i]);
        precache_model(szUpgradeModels[i]);
    }
 
    for(new i = 0; i < sizeof(szPlayerBoxModel); i++){
        precache_model(szPlayerBoxModel[i]);
        precache_model(szViewBoxModel[i]);
    
        if(get_cvar_num("sv_auto_precache_sounds_in_models") == 0) {
            PRECACHE_MODEL2(szViewBoxModel[i]);
        }
    }
 
    gBeam = precache_model("sprites/csdm/tok.spr");
 
    PRECACHE_WEAPONLIST(WEAPON_LIST);
}

/*    *****************
Give custom dispenser
********************/

public CBasePlayer_OnSpawnEquip(const iPlayer){
    if (EquipDelay > 0.0)
        set_task(EquipDelay, "GiveEquip", iPlayer);
    else
        GiveEquip(iPlayer);
}

public GiveEquip(iPlayer)    {
    GiveObject(iPlayer, REFERENCE_WEAPON, iKey, AMMO_ID, MAX_DISPENCER);
}

public CBasePlayerWeapon_DefaultDeploy(const iItem, szViewModel[], szWeaponModel[], iAnim, szAnimExt[], skiplocal)    {
    if(!IsCustomItem(iItem))
        return HC_CONTINUE;
 
    new iPlayer;
    if(!(iPlayer = get_member(iItem, m_pPlayer)) || !is_user_connected(iPlayer))
        return HC_CONTINUE;
 
    new iTeam = get_member(iPlayer, m_iTeam) - 1;
 
    SetHookChainArg(2, ATYPE_STRING, szViewBoxModel[iTeam]);
    SetHookChainArg(3, ATYPE_STRING, szPlayerBoxModel[iTeam]);
 
    SetHookChainArg(4, ATYPE_INTEGER, _DRAW);
 
    return HC_CONTINUE;
}

/*******************
Ham hook dispenser
********************/

public Default_Item_Holster(const iItem, const iPlayer)    {
    //    Code
}

public Default_Item_AttachToPlayer(const iItem, const iPlayer)    {
    SetObjectWeaponList(iItem, iPlayer, AMMO_ID, WEAPON_LIST, MAX_DISPENCER, POSITION_NUM);
}

public HamHook_Item_PostFrame(const iItem){
    if(!IsCustomItem(iItem))
        return HAM_IGNORED;
 
    new iPlayer;
    if(!(iPlayer = get_member(iItem, m_pPlayer)) || !is_user_connected(iPlayer))
        return HAM_IGNORED;
 
    if(get_member(iPlayer, m_iAccount) >= g_CostUpgrade[_Level1] && get_member(iItem, m_Weapon_iDefaultAmmo) > 0)    {
        rg_add_account(iPlayer, g_CostUpgrade[_Level1]);
        rg_add_account(iPlayer, -g_CostUpgrade[_Level1]);
    }
 
    new Float:vecSrc[eCoord], Float:vecAiming[eCoord];
    GetPlantOrigin(iPlayer, vecSrc, vecAiming);
 
    engfunc(EngFunc_TraceLine, vecSrc, vecAiming, IGNORE_MISSILE|IGNORE_GLASS|IGNORE_MONSTERS, iPlayer, 0);
 
    new Float:flFraction;    get_tr2(0, TR_flFraction, flFraction);
    new iDispenser = iObjectID[iPlayer];
 
    if (flFraction >= 1.0 || !is_user_alive(iPlayer))    {
        if(!is_nullent(iDispenser))    {
            UTIL_KillEntity(iDispenser);
        }
        iObjectID[iPlayer] = NULLENT;   
        return HAM_IGNORED;
    }
    else if(flFraction < 1.0)    {
        if(is_nullent(iDispenser))    {
            iObjectID[iPlayer] = iDispenser = SpawnObject(_ClassName, PrintModel, Float:{-SIZE, -SIZE, 0.0}, Float:{SIZE, SIZE, 55.0});
        }
    
        new Float:fVecEnd[eCoord], Float:fVecNormal[eCoord], Float:fAngles[eCoord];
        get_tr2(0, TR_vecEndPos, fVecEnd);
        get_tr2(0, TR_vecPlaneNormal, fVecNormal);
    
        xs_vec_mul_scalar(fVecNormal, 1.0, fVecNormal);
        xs_vec_add(fVecEnd, fVecNormal, fVecEnd);
    
        engfunc(EngFunc_SetOrigin, iDispenser, fVecEnd);
    
        if (fVecNormal[2] == 1.0 && CheckLocation(iDispenser, fVecEnd, SIZE * 2))    {
            set_entvar(iDispenser, var_sequence, _IDLE);
            get_entvar(iPlayer, var_angles, fAngles);
            fAngles[1] -= 180.0;
            fAngles[0] += 12.0;
        }
        else    {
            set_entvar(iDispenser, var_sequence, _DRAW);
            vector_to_angle(fVecNormal, fAngles);
            fAngles[0] -= 90.0;
        }
    
        set_entvar(iDispenser, var_angles, fAngles);
    }
 
    return HAM_IGNORED;
}

public HamHook_Item_PrimaryAttack(const iItem){
    if(!IsCustomItem(iItem))
        return HAM_IGNORED;
 
    new iPlayer;
    if(!(iPlayer = get_member(iItem, m_pPlayer)) || !is_user_connected(iPlayer))
        return HAM_IGNORED;
 
    new iDispenser;
    if (!(iDispenser = iObjectID[iPlayer]) || is_nullent(iDispenser))
        return HAM_SUPERCEDE;
 
    if (get_entvar(iDispenser, var_sequence) == _DRAW){
        client_print(iPlayer, print_center, "Здесь строить нельзя");
        return HAM_SUPERCEDE;
    }
 
    new iClip = get_member(iPlayer, m_rgAmmo, AMMO_ID);
 
    if (--iClip < 0)    {
        client_print(iPlayer, print_center, "Более нельзя ставить");
        return HAM_SUPERCEDE;
    }
 
    if(get_member(iPlayer, m_iAccount) < g_CostUpgrade[_Level1])    {
        client_print(iPlayer, print_center, "Не достаточно средств: %i", g_CostUpgrade[_Level1]);
        return HAM_SUPERCEDE;
    }
 
    set_member(iItem, m_Weapon_flNextPrimaryAttack, 1.0);
    set_member(iItem, m_Weapon_iDefaultAmmo, iClip);
    set_member(iPlayer, m_rgAmmo, iClip, AMMO_ID);
 
    BuildObject(iPlayer, iDispenser, BUILD_TIME, ActivateSound, _IDLE, UPDATE_DELAY, szUpgradeModels[_Level1]);
 
    rg_add_account(iPlayer, -g_CostUpgrade[_Level1]);
 
    return HAM_SUPERCEDE;
}

/**********************************
Create dispenser and other effect
**********************************/

DispenserEffect(const iPlayer, Float:iAmmout){
    if (get_entvar(iPlayer, var_health) >= MAX_HP && get_entvar(iPlayer, var_armorvalue) >= MAX_AP)
        return false;
 
    new iEnt = rg_create_entity("env_sprite");
 
    if(is_nullent(iEnt))
        return false;
 
    new Float: fVecOrigin[eCoord];    get_entvar(iPlayer, var_origin, fVecOrigin);    fVecOrigin[2] += 40.0;
 
    engfunc(EngFunc_SetOrigin, iEnt, fVecOrigin);
    engfunc(EngFunc_SetModel, iEnt, HealthSpr);
 
    set_entvar(iEnt, var_solid, SOLID_NOT);
    set_entvar(iEnt, var_movetype, MOVETYPE_FLY);
    set_entvar(iEnt, var_scale, 0.2);
    set_entvar(iEnt, var_velocity, {0.0, 0.0, 30.0});
    set_entvar(iEnt, var_frame, iAmmout);
    set_entvar(iEnt, var_nextthink, get_gametime() + 1.5);
 
    SetThink(iEnt, "RemoveEntThink");
 
    return true;
}

/**********************************
Brain to dispenser
**********************************/

#define UPDATE_TIME        0.05

public Object_Think(const iEntity)    {
    if (is_nullent(iEntity))
        return;
 
    new Float:fGameTime = get_gametime();
    new iTeam = get_entvar(iEntity, var_team);
    new iLevel = get_entvar(iEntity, object_level);
    new iOwner = get_entvar(iEntity, object_owner);
 
    if(!is_user_alive(iOwner) || get_member(iOwner, m_iTeam) != iTeam){
        UTIL_KillEntity(iEntity);
        return;
    }
 
    SetObjectInfoAim(fGameTime, iTeam, iEntity);
 
    if (get_entvar(iEntity, object_active_time) > fGameTime)    {
        set_entvar(iEntity, var_nextthink, fGameTime + UPDATE_TIME);
        return;
    }
 
    switch(get_entvar(iEntity, object_status)){
        case _BUILDING:    {
            engfunc(EngFunc_SetModel, iEntity, szDispenserModels[iLevel]);
            engfunc(EngFunc_SetSize, iEntity, Float:{-SIZE, -SIZE, 0.0}, Float:{SIZE, SIZE, 55.0});
            
            set_entvar(iEntity, var_takedamage, DAMAGE_YES);
            set_entvar(iEntity, var_health, g_Health[iLevel]);
            set_entvar(iEntity, var_max_health, g_Health[iLevel]);
            set_entvar(iEntity, object_status, _ACTIVE);
            set_entvar(iEntity, object_active_time, fGameTime);
        }
        case _ACTIVE:    {
            new Float:fVecOrigin[eCoord];    get_entvar(iEntity, var_origin, fVecOrigin);
            
            new iEnt = NULLENT;
            while((iEnt = engfunc(EngFunc_FindEntityInSphere, iEnt, fVecOrigin, g_HealthRadius[iLevel])))
            {
                if (!UTIL_IsVisible(iEnt, iEntity))    continue;
            
                if(is_user_alive(iEnt) && get_member(iEnt, m_iTeam) == iTeam)    {
                    if (DispenserEffect(iEnt, g_AddHealth[iLevel])){
                    //    ExecuteHamB(Ham_TakeHealth, iEnt, g_AddHealth[iLevel], DMG_GENERIC);
                        
                        set_entvar(iEnt, var_health, floatmin(Float:get_entvar(iEnt, var_health) + g_AddHealth[iLevel], MAX_HP));
                        set_entvar(iEnt, var_armorvalue, floatmin(Float:get_entvar(iEnt, var_armorvalue) + g_AddHealth[iLevel], MAX_AP));
                    }
                }
                else if(IsActiveEnt(iEnt, iTeam))    {
                    set_entvar(iEnt, var_health, floatmin(Float:get_entvar(iEnt, var_health) + g_AddHealth[iLevel], Float:get_entvar(iEnt, var_max_health)));
                    UTIL_TE_BEAMENTS(iEnt, iEntity, gBeam);
                }
            }
            
            set_entvar(iEntity, object_active_time, fGameTime + 2.0);
        }
    }
 
    set_entvar(iEntity, var_nextthink, fGameTime + UPDATE_TIME);
}

public HamHook_Dispenser_Use(const pPlayer)    {
    new iEnt, iBody;
    get_user_aiming(pPlayer, iEnt, iBody, floatround(PLANT_RADIUS));
 
    if (!IsCustomObject(iEnt))
        return;
 
    if(get_member(pPlayer, m_iTeam) != get_entvar(iEnt, var_team))
        return;
 
    new iLevel = get_entvar(iEnt, object_level);
 
    if (++iLevel >= eLevelList){
        return;
    }
 
    UpgradeObject(pPlayer, iEnt, iLevel, _IDLE, UPGRADE_TIME, UPDATE_DELAY, g_CostUpgrade[iLevel], ActivateSound, szUpgradeModels[iLevel]);
}

public HamHook_Dispenser_Killed(const iVictim, const iAttacker){
    if (is_nullent(iVictim))
        return HAM_IGNORED;
    
    if (!IsCustomObject(iVictim))
        return HAM_IGNORED;
 
    new Float:fVecOrigin[eCoord];    get_entvar(iVictim, var_origin, fVecOrigin);
    UTIL_TE_EXPLOSION(fVecOrigin);
 
    new iOwner = get_entvar(iVictim, object_owner);
 
    if (is_user_connected(iOwner))    {
        set_member(iOwner, m_rgAmmo, get_member(iOwner, m_rgAmmo, AMMO_ID) + 1, AMMO_ID);
    }
 
    CObject_Gibs(iVictim, GibsMdl, 3, get_entvar(iVictim, var_skin));
 
    return HAM_IGNORED;
}

public HamHook_Dispenser_TraceAttack(iVictim, iAttacker, Float:flDamage, Float:flDirection[3], iTrace, iDamageBits){
    if (!is_user_connected(iAttacker))
        return HAM_IGNORED;
 
    if (!IsCustomObject(iVictim))
        return HAM_IGNORED;
 
    if (get_entvar(iVictim, var_takedamage) != DAMAGE_YES)
        return HAM_SUPERCEDE;
 
    new Float:flEndOrigin[eCoord];    get_tr2(iTrace, TR_vecEndPos, flEndOrigin);
    UTIL_TE_SPARKS(flEndOrigin);
 
    if(get_entvar(iVictim, var_team) == get_member(iAttacker, m_iTeam) /*&& iAttacker != get_entvar(iVictim, object_owner)*/)
        return HAM_SUPERCEDE;
 
    rg_add_account(iAttacker, DMG_AWARD);
 
    return HAM_IGNORED;
}

public ShowObjectInfoAim(const iPlayer, const iEnt, Float:fGameTime)    {
    new Float:iHealth = get_entvar(iEnt, var_health);
    new iLevel = get_entvar(iEnt, object_level);
    new iOwner = get_entvar(iEnt, object_owner);
    new iTeam = get_entvar(iEnt, var_team);
 
    set_dhudmessage(iTeam == _:TEAM_TERRORIST ? 120 : 0, 0, iTeam == _:TEAM_CT ? 255 : 0, -1.0, 0.35, 0, 0.0, 1.1, 0.0, 0.0);
    show_dhudmessage(iPlayer, fmt("Владелец: %n^nПрочность: %i^nУровень: %i", iOwner, floatround(iHealth), iLevel + 1));
 
    if (iLevel < eLevelList - 1)    {
        new Float:fUpdateTime;    get_entvar(iEnt, object_update_time, fUpdateTime);
        if (fGameTime < fUpdateTime)
            show_dhudmessage(iPlayer, fmt("^n^n^nАпгрейд: %i$ Update: %i", g_CostUpgrade[iLevel + 1], floatround(fUpdateTime - fGameTime)));
        else
            show_dhudmessage(iPlayer, fmt("^n^n^nАпгрейд: %i$ Update: Нажмите на <E>", g_CostUpgrade[iLevel + 1]));
    }
}

/*******************
Stock
********************/

bool: IsActiveEnt(const iEnt, const iTeam)    {
    if (is_nullent(iEnt))
        return false;
 
    if (get_entvar(iEnt, var_health) >= get_entvar(iEnt, var_max_health))
        return false;
 
    if (get_entvar(iEnt, var_team) != iTeam)
        return false;
 
    for(new a = 0; a < sizeof(szClassActive); a++)    {
        if (FClassnameIs(iEnt, szClassActive[a]))    {
            return true;
        }
    }
    return false;
}
Lasermine:
/*
    Благодарность:
        * KORD_12.7            - Beam entities include
*/

#include < amxmodx >
#include < csdm_object >
#include < beams >

#pragma semicolon 1

#define VERSION        "1.0"

#define MAX_MINE_ONE_PLAYER        99    // Лимит
#define MINE_COST                1    // Цена

#define REWARD_DAMAGE    random_num(1, 3)
#define REWARD_KILLED    400        // Награда разрушение
#define REWARD_OWNER    2        // Награда за убийсво миной
#define MINE_HEALTH        100.0    // Жизни
#define MINE_DAMAGE        10.0    // Урон
#define MINE_WIDTH        20.0    // Ширина луча
#define MINE_NOISE        10        // Искажение

#define SIZE_MINE        8.0        // Размер мины

enum _:eModels {
    TripModel, PlayerModel, PrintModel, GibsMdl, SprT,    SprCT
};

new szTripModel[eModels][MAX_RESOURCE_PATH_LENGTH] = {
    "models/v_lasermine.mdl",
    "models/p_lasermine.mdl",
    "models/laser_blueprint.mdl",
    "models/lasermine_gibs.mdl",
    "sprites/laser_T.spr",
    "sprites/laser_CT.spr"
};

enum _:eSounds{
    Charge,    Activate,    Hit,    HitEnemy
};

new szTripSound[eSounds][MAX_RESOURCE_PATH_LENGTH] = {
    "weapons/mine_charge.wav",
    "weapons/mine_activate.wav",
    "weapons/sparks.wav",
    "ambience/beamstart9.wav"
};

enum _:eAnimList     {
    Idle = 0, Idle2, Arm1, Place, fIdGet, Holster, Draw, World, Ground
};

new szClassActive[][16] = {    //    Классы обьектов
    "Sentry",    "DispenserHP",    "_tripmine"
};

#define _ClassName        "_tripmine"

#define PlantTime        1.0        //    Через сколько можно ставить повторно
#define ActivationTime    2.0        //    Время активации после установки

#define REFERENCE_WEAPON    "weapon_mac10"
#define WEAPON_LIST        "weapon_lasermine"

const POSITION_NUM = 1;

new HookChain:g_DeathNoticeHook;

public plugin_init()
{
    register_plugin
    (
        "[AMXX] TripMine",
        VERSION,
        "Flymic24 (modified)"
    );
 
    RegisterHam(Ham_TraceAttack,    "info_target",    "HamHook_TripMine_TraceAttack", false);
    RegisterHam(Ham_Killed,            "info_target",    "HamHook_TripMine_Killed", false);
 
    RegisterHookChain(RG_CBasePlayerWeapon_DefaultDeploy, "CBasePlayerWeapon_DefaultDeploy", false);
 
    DisableHookChain(g_DeathNoticeHook = RegisterHookChain(RG_CSGameRules_DeathNotice, "CSGameRules_DeathNotice", true));
    RegisterHookChain(RG_CBasePlayer_Spawn, "CBasePlayer_OnSpawnEquip", true);
 
    RegisterHam(Ham_Weapon_WeaponIdle,        REFERENCE_WEAPON,     "HamHook_Item_WeaponIdle",    false);
    RegisterHam(Ham_Item_PostFrame,    REFERENCE_WEAPON,    "HamHook_Item_PostFrame",    false);
    RegisterHam(Ham_Weapon_PrimaryAttack,    REFERENCE_WEAPON,    "HamHook_Item_PrimaryAttack",    false);
 
    register_message(get_user_msgid("DeathMsg"), "Msg_DeathMsg");
 
    RegisteFunc(REFERENCE_WEAPON);
 
    AMMO_ID = rg_add_ammo_registry(WEAPON_LIST);
    iKey = engfunc(EngFunc_AllocString, _ClassName);
}

public plugin_precache(){
    for(new a = 0; a < sizeof szTripSound; a++)    precache_sound(szTripSound[a]);
    for(new b = 0; b < sizeof szTripModel; b++)    precache_model(szTripModel[b]);
 
    if(get_cvar_num("sv_auto_precache_sounds_in_models") == 0) {
        PRECACHE_MODEL2(szTripModel[TripModel]);
    }
 
    PRECACHE_WEAPONLIST(WEAPON_LIST);
}

/*    *****************
Give custom dispenser
********************/

public CBasePlayer_OnSpawnEquip(const iPlayer){
    if (EquipDelay > 0.0)
        set_task(EquipDelay, "GiveEquip", iPlayer);
    else
        GiveEquip(iPlayer);
}

public GiveEquip(iPlayer)    {
    GiveObject(iPlayer, REFERENCE_WEAPON, iKey, AMMO_ID, MAX_MINE_ONE_PLAYER);
}

public CBasePlayerWeapon_DefaultDeploy(const iItem, szViewModel[], szWeaponModel[], iAnim, szAnimExt[], skiplocal)    {
    if(!IsCustomItem(iItem))
        return HC_CONTINUE;
 
    new iPlayer;
    if(!(iPlayer = get_member(iItem, m_pPlayer)) || !is_user_connected(iPlayer))
        return HC_CONTINUE;
 
    SetHookChainArg(2, ATYPE_STRING, szTripModel[TripModel]);
    SetHookChainArg(3, ATYPE_STRING, szTripModel[PlayerModel]);
 
    SetHookChainArg(4, ATYPE_INTEGER, Draw);
 
    return HC_CONTINUE;
}

/*******************
Ham hook TripMine
********************/

public Default_Item_Holster(const iItem, const iPlayer)    {
    //    Code
}

public Default_Item_AttachToPlayer(const iItem, const iPlayer)    {
    SetObjectWeaponList(iItem, iPlayer, AMMO_ID, WEAPON_LIST, MAX_MINE_ONE_PLAYER, POSITION_NUM);
}

public HamHook_Item_WeaponIdle(const pItem)    {
    if(!IsCustomItem(pItem))
        return HAM_IGNORED;
 
    new iPlayer;
    if(!(iPlayer = get_member(pItem, m_pPlayer)) || !is_user_connected(iPlayer))
        return HAM_IGNORED;
 
    if (get_member(pItem, m_Weapon_flTimeWeaponIdle) > 0.0)
        return HAM_IGNORED;
 
    switch(random_num(Idle, Idle2))    {
        case Idle: {
            set_member(pItem, m_Weapon_flTimeWeaponIdle, 3.0);
            rg_weapon_send_animation(pItem, Idle);
        }
        case Idle2:    {
            set_member(pItem, m_Weapon_flTimeWeaponIdle, 2.0);
            rg_weapon_send_animation(pItem, Idle2);        
        }
    }
 
    return HAM_SUPERCEDE;
}

public HamHook_Item_PostFrame(const iItem){
    if(!IsCustomItem(iItem))
        return HAM_IGNORED;
 
    new iPlayer;
    if(!(iPlayer = get_member(iItem, m_pPlayer)) || !is_user_connected(iPlayer))
        return HAM_IGNORED;
 
    if(get_member(iPlayer, m_iAccount) >= MINE_COST && get_member(iItem, m_Weapon_iDefaultAmmo) > 0)    {
        rg_add_account(iPlayer, MINE_COST);
        rg_add_account(iPlayer, -MINE_COST);
    }
 
    new Float:vecSrc[eCoord], Float:vecAiming[eCoord];
    GetPlantOrigin(iPlayer, vecSrc, vecAiming);
 
    engfunc(EngFunc_TraceLine, vecSrc, vecAiming, IGNORE_MISSILE|IGNORE_GLASS|IGNORE_MONSTERS, iPlayer, 0);
 
    new Float:flFraction;    get_tr2(0, TR_flFraction, flFraction);
    new iMine = iObjectID[iPlayer];
 
    if (flFraction >= 1.0 || !is_user_alive(iPlayer))    {
        if(!is_nullent(iMine))    {
            UTIL_KillEntity(iMine);
        }
        iObjectID[iPlayer] = NULLENT;    
        return HAM_IGNORED;
    }
    else if(flFraction < 1.0)    {
        if(is_nullent(iMine))    {
            iMine = iObjectID[iPlayer] = SpawnObject(_ClassName, szTripModel[PrintModel], Float:{-SIZE_MINE, -SIZE_MINE, -SIZE_MINE}, Float:{SIZE_MINE, SIZE_MINE, SIZE_MINE});
        }
     
        new Float:fVecEnd[eCoord], Float:fVecNormal[eCoord], Float:fAngles[eCoord];
        get_tr2(0, TR_vecEndPos, fVecEnd);
        get_tr2(0, TR_vecPlaneNormal, fVecNormal);
     
        xs_vec_mul_scalar(fVecNormal, SIZE_MINE, fVecNormal);
        xs_vec_add(fVecEnd, fVecNormal, fVecEnd);
     
        engfunc(EngFunc_SetOrigin, iMine, fVecEnd);
     
        vector_to_angle(fVecNormal, fAngles);
        fAngles[0] -= 90.0;
        set_entvar(iMine, var_angles, fAngles);
     
        set_entvar(iMine, var_sequence, CheckLocation(iMine, fVecEnd, SIZE_MINE * 1.5, .fOfsetZ = 0.0, .bCheckDoor = false) ? Idle : Idle2);
    }
 
    return HAM_IGNORED;
}

public HamHook_Item_PrimaryAttack(const iItem){
    if(!IsCustomItem(iItem))
        return HAM_IGNORED;
 
    new iPlayer;
    if(!(iPlayer = get_member(iItem, m_pPlayer)) || !is_user_connected(iPlayer))
        return HAM_IGNORED;
 
    new iMine;
    if (!(iMine = iObjectID[iPlayer]) || is_nullent(iMine))
        return HAM_SUPERCEDE;
 
    if (get_entvar(iMine, var_sequence) == Idle2){
        client_print(iPlayer, print_center, "Здесь строить нельзя");
        return HAM_SUPERCEDE;
    }
 
    new iClip = get_member(iPlayer, m_rgAmmo, AMMO_ID);
 
    if (--iClip < 0)    {
        client_print(iPlayer, print_center, "Более нельзя ставить");
        return HAM_SUPERCEDE;
    }
 
    if(get_member(iPlayer, m_iAccount) < MINE_COST)    {
        client_print(iPlayer, print_center, "Не достаточно средств: %i", MINE_COST);
        return HAM_SUPERCEDE;
    }
 
    set_member(iItem, m_Weapon_flTimeWeaponIdle, 0.36);
    set_member(iItem, m_Weapon_flNextPrimaryAttack, PlantTime);
 
    set_member(iItem, m_Weapon_iDefaultAmmo, iClip);
    set_member(iPlayer, m_rgAmmo, iClip, AMMO_ID);
 
    rg_add_account(iPlayer, -MINE_COST);
 
    rg_weapon_send_animation(iItem, Place);
 
    Build_TripMine(iPlayer, iMine);
 
    return HAM_SUPERCEDE;
}

/*******************
Kill Message
********************/

public CSGameRules_DeathNotice(const iVictim, const iAttacker, inflictor)    {
    rh_update_user_info(iAttacker);
    DisableHookChain(g_DeathNoticeHook);
}

public Msg_DeathMsg()    {
    new szClassName[16];    get_msg_arg_string(4, szClassName, charsmax(szClassName));
 
    if(!equali(szClassName, _ClassName))
        return;
 
    new iAttacker = get_msg_arg_int(1);
    new szName[MAX_NAME_LENGTH];    get_user_name(iAttacker, szName, charsmax(szName));
 
    EnableHookChain(g_DeathNoticeHook);
 
    set_user_fake_name(iAttacker, fmt("%.14s [Lasermine]", szName));
 
    set_msg_arg_string(4, "teammate");
}

public ShowObjectInfoAim(const iPlayer, const iEnt, Float:fGameTime)    {
    new Float:fHealth = get_entvar(iEnt, var_health);
    new iKill = get_entvar(iEnt, object_data1);
    new iOwner = get_entvar(iEnt, object_owner);
    new iTeam = get_entvar(iEnt, var_team);
 
    set_dhudmessage(iTeam == _:TEAM_TERRORIST ? 120 : 0, 0, iTeam == _:TEAM_CT ? 255 : 0, -1.0, 0.35, 0, 0.0, 1.1, 0.0, 0.0);
    show_dhudmessage(iPlayer, fmt("Владелец: %n^nПрочность: %i^nУбийств: %i", iOwner, floatround(fHealth), iKill));
}

#define UPDATE_TIME        0.1

public Object_Think(const iMine)    {
    if (is_nullent(iMine))
        return;
 
    new iOwner = get_entvar(iMine, object_owner);
    new iBeam = get_entvar(iMine, var_impulse);
    new iTeam = get_entvar(iMine, var_team);
 
    new Float:fGameTime = get_gametime();
 
    if(!is_user_alive(iOwner) || get_member(iOwner, m_iTeam) != iTeam)    {
        if(!is_nullent(iBeam))    UTIL_KillEntity(iBeam);
     
        UTIL_KillEntity(iMine);
        return;
    }
 
    SetObjectInfoAim(fGameTime, iTeam, iMine);
 
    if (get_entvar(iMine, object_active_time) > fGameTime)    {
        set_entvar(iMine, var_nextthink, fGameTime + UPDATE_TIME);
        return;
    }
 
    new Float:fVecSrc[eCoord], Float:fVecEnd[eCoord];
 
    switch(get_entvar(iMine, object_status))    {
        case _BUILDING:    {
            new Float:m_vecDir[eCoord];    get_entvar(iMine, var_startpos, m_vecDir);
            get_entvar(iMine, var_origin, fVecSrc);
            xs_vec_copy(fVecSrc, fVecEnd);
     
            xs_vec_mul_scalar(m_vecDir, SIZE_MINE, m_vecDir);
            xs_vec_add(fVecSrc, m_vecDir, fVecSrc);
         
            get_entvar(iMine, var_startpos, m_vecDir);
            xs_vec_mul_scalar(m_vecDir, 32.0, m_vecDir);
            xs_vec_add(fVecEnd, m_vecDir, fVecEnd);
         
            engfunc(EngFunc_TraceLine, fVecSrc, fVecEnd, DONT_IGNORE_MONSTERS, iMine, 0);
         
            new Float:flFraction;    get_tr2(0, TR_flFraction, flFraction);
         
            if(flFraction == 1.0)
            {
                new iPlayer = NULLENT;
                while((iPlayer = engfunc(EngFunc_FindEntityInSphere, iPlayer, fVecSrc, SIZE_MINE * 1.5)))
                {
                    if(is_user_alive(iPlayer))    {
                        set_entvar(iMine, var_nextthink, fGameTime + UPDATE_TIME);
                        return;
                    }
                }
             
                rh_emit_sound2(iMine, 0, CHAN_BODY, szTripSound[ Charge ], 0.0, ATTN_NORM, SND_STOP, 0);
                rh_emit_sound2(iMine, 0, CHAN_ITEM, szTripSound[ Activate ]);

                TripMine_MakeBeam(iMine);
             
                set_entvar(iMine, var_solid, SOLID_BBOX);
                set_entvar(iMine, var_renderfx, kRenderFxGlowShell);
                set_entvar(iMine, var_rendermode, kRenderNormal);
                set_entvar(iMine, var_takedamage, DAMAGE_YES);
                set_entvar(iMine, var_health, MINE_HEALTH);
                set_entvar(iMine, var_max_health, MINE_HEALTH);
                set_entvar(iMine, var_renderamt, MINE_WIDTH);
                set_entvar(iMine, object_status, _ACTIVE);
             
                switch(iTeam)
                {
                    case TEAM_TERRORIST:    set_entvar(iMine, var_rendercolor, Float:{255.0, 0.0, 0.0} );
                    case TEAM_CT: set_entvar(iMine, var_rendercolor, Float:{0.0, 0.0, 255.0} );
                }
            }
         
            set_entvar(iMine, var_nextthink, fGameTime + UPDATE_TIME);
            return;
        }
        case _ACTIVE:    {
            if(is_nullent(iBeam))    {
                set_entvar(iMine, var_nextthink, fGameTime + UPDATE_TIME);
                return;
            }
         
            get_entvar(iMine, var_origin, fVecSrc);
            get_entvar(iMine, var_endpos, fVecEnd);
         
            new iTrace = create_tr2();
            engfunc(EngFunc_TraceLine, fVecSrc, fVecEnd, DONT_IGNORE_MONSTERS, iMine, iTrace);
         
            new pHit = get_tr2(iTrace, TR_pHit);
            get_tr2(iTrace, TR_vecEndPos, fVecEnd);
         
            Beam_SetStartPos(iBeam, fVecEnd);
            Beam_SetNoise(iBeam, 0);
         
            if (IsActiveEnt(pHit, iTeam))    {
                if (get_entvar(pHit, var_takedamage) != DAMAGE_NO)    {
                    ExecuteHamB(Ham_TakeDamage, pHit, iOwner, iOwner, MINE_DAMAGE, DMG_GENERIC);
                    UTIL_TE_SPARKS(fVecEnd);
                }
            }
            else if (is_user_alive(pHit))    {
                Beam_SetNoise(iBeam, MINE_NOISE);
             
                UTIL_TE_SPARKS(fVecEnd);
             
                if(get_member(pHit, m_iTeam) == iTeam)
                {
                    rh_emit_sound2(pHit, pHit, CHAN_BODY, szTripSound[ Hit ]);
                }
                else
                {
                    rh_emit_sound2(pHit, pHit, CHAN_BODY, szTripSound[ HitEnemy ]);
                 
                    if (get_entvar(pHit, var_takedamage) != DAMAGE_NO)
                        ExecuteHamB(Ham_TakeDamage, pHit, iMine, iOwner, MINE_DAMAGE, DMG_GENERIC);
                     
                    if (!is_user_alive(pHit))
                    {
                        rg_add_account(iOwner, REWARD_OWNER);
                         
                        if (!is_nullent(iMine))
                            set_entvar(iMine, object_data1, get_entvar(iMine, object_data1) + 1);
                    }
                }
            }
         
            free_tr2(iTrace);
        }
    }
 
    set_entvar(iMine, var_nextthink, fGameTime + UPDATE_TIME);
}

public HamHook_TripMine_TraceAttack(iVictim, iAttacker, Float:flDamage, Float:flDir[3], iTrace, iDamageBits){
    if(!is_user_connected(iAttacker))
        return HAM_IGNORED;
 
    if (!IsCustomObject(iVictim))
        return HAM_IGNORED;
 
    if (get_entvar(iVictim, var_takedamage) != DAMAGE_YES)
        return HAM_SUPERCEDE;
 
    new Float:flEndOrigin[eCoord];    get_tr2(iTrace, TR_vecEndPos, flEndOrigin);
    UTIL_TE_SPARKS(flEndOrigin);
 
    if(get_entvar(iVictim, var_team) == get_member(iAttacker, m_iTeam) /*&& iAttacker != get_entvar(iVictim, object_owner)*/)
        return HAM_SUPERCEDE;
 
    rg_add_account(iAttacker, REWARD_DAMAGE);
 
    return HAM_IGNORED;
}

public HamHook_TripMine_Killed(const iMine, const iAttacker){
    if (is_nullent(iMine))
        return HAM_IGNORED;
 
    if (!IsCustomObject(iMine))
        return HAM_IGNORED;
 
    new iBeam = get_entvar(iMine, var_impulse);
 
    if(!is_nullent(iBeam))    UTIL_KillEntity(iBeam);
 
    new Float:fVecOrigin[eCoord];    get_entvar(iMine, var_origin, fVecOrigin);
    UTIL_TE_EXPLOSION(fVecOrigin);
 
    new iOwner = get_entvar(iMine, object_owner);
    new iTeam = get_entvar(iMine, var_team);
 
    if (is_user_connected(iAttacker) && get_member(iAttacker, m_iTeam) != iTeam)
    {
        rg_add_account(iAttacker, REWARD_KILLED);
     
        client_print_color(iOwner, print_team_default,"^3[^4Действие^3]^4 %n [laser destroyed]", iAttacker);
        client_print_color(iAttacker, print_team_default, "^3[^4Действие^3]!y Вы взорвали мину. Ваша награда: ^3%i^4$!", REWARD_KILLED);
    }
 
    if (is_user_connected(iOwner))    {
        set_member(iOwner, m_rgAmmo, get_member(iOwner, m_rgAmmo, AMMO_ID) + 1, AMMO_ID);
    }
 
    CObject_Gibs(iMine, szTripModel[GibsMdl], 3);
 
    return HAM_IGNORED;
}

Build_TripMine(const iPlayer, const iEnt)    {
    if (!is_user_alive(iPlayer) || is_nullent(iEnt))
        return;
 
    new iTeam = get_member(iPlayer, m_iTeam);
    new Float:fGameTime = get_gametime();
 
    enum _:eData    {
        Max, Min
    };
    new Float:fSize[eData][eCoord];
    get_entvar(iEnt, var_maxs, fSize[Max]);    get_entvar(iEnt, var_mins, fSize[Min]);
 
    engfunc(EngFunc_SetModel, iEnt, szTripModel[TripModel]);
    engfunc(EngFunc_SetSize, iEnt, fSize[Min], fSize[Max]);
 
    set_entvar(iEnt, var_team, iTeam);
    set_entvar(iEnt, object_owner, iPlayer);
    set_entvar(iEnt, object_status, _BUILDING);
 
    set_entvar(iEnt, var_body, 3);
    set_entvar(iEnt, var_rendermode, kRenderTransAdd);
    set_entvar(iEnt, var_renderamt, 255.0);
 
    UTIL_Animation(iEnt, World);
 
    set_entvar(iEnt, var_nextthink, fGameTime);
    set_entvar(iEnt, object_active_time, fGameTime + ActivationTime);
 
    SetThink(iEnt, "Object_Think");
 
    new Float:m_vecDir[eCoord];    get_entvar(iEnt, var_angles, m_vecDir);    m_vecDir[0] += 90.0;
    set_entvar(iEnt, var_angles, m_vecDir);
 
    rh_emit_sound2(iEnt, 0, CHAN_BODY, szTripSound[ Charge ]);
 
    engfunc(EngFunc_MakeVectors, m_vecDir);
    get_global_vector(GL_v_forward, m_vecDir);
 
    m_vecDir[2] = -m_vecDir[2];
 
    set_entvar(iEnt, var_startpos, m_vecDir);
 
    iObjectID[iPlayer] = NULLENT;
}

TripMine_MakeBeam(const iMine){
    new iBeam = Beam_Create(get_entvar(iMine, var_team) == TEAM_TERRORIST ? szTripModel[SprT] : szTripModel[SprCT], MINE_WIDTH);
 
    new Float:m_vecDir[eCoord], Float:fVecSrc[eCoord], Float:fVecOrigin[eCoord];
    get_entvar(iMine, var_startpos, m_vecDir);
    get_entvar(iMine, var_origin, fVecSrc);
 
    xs_vec_copy(fVecSrc, fVecOrigin);
    xs_vec_mul_scalar(m_vecDir, 8128.0, m_vecDir);
    xs_vec_add(fVecSrc, m_vecDir, fVecSrc);
 
    Beam_PointsInit(iBeam, fVecSrc, fVecOrigin);
    Beam_SetScrollRate(iBeam, 255.0);
    Beam_SetBrightness(iBeam, 255.0);
    Beam_SetNoise(iBeam, 0);
 
    set_entvar(iMine, var_impulse, iBeam);
    set_entvar(iMine, var_endpos, fVecSrc);
}

bool: IsActiveEnt(const iEnt, const iTeam)    {
    if (is_nullent(iEnt))
        return false;
 
    if (get_entvar(iEnt, var_health) >= get_entvar(iEnt, var_max_health))
        return false;
 
    if (get_entvar(iEnt, var_team) != iTeam)
        return false;
 
    for(new a = 0; a < sizeof(szClassActive); a++)    {
        if (FClassnameIs(iEnt, szClassActive[a]))    {
            return true;
        }
    }
    return false;
}
Требования
ReApi, REGAMEDLL, rehlds последних версий
Требование ReAPI
Да
Поддержка русского языка
Да
Совместимость
  1. REHLDS
Сверху Снизу