[ReAPI] Пример кастомного оружия с дополнительними свойствами

Сообщения
1,419
Реакции
2,508
Помог
59 раз(а)
С учётом удаления из инвентаря (спасибо voed за подсказку хука):
Код:
/*
* Last update: 09.02.2019
*
* Original code by F@nt0M: https://dev-cs.ru/threads/1983/page-3#post-51426
*/

#include <amxmodx>
#include <fakemeta>
#include <hamsandwich>
#include <reapi>

#pragma semicolon 1

new const PLUGIN_VERSION[] = "1.0";

/****************************************************************************************
****************************************************************************************/

#define IsUserValid(%0) (1 <= %0 <= MaxClients)
#define GetCvarDesc(%0) fmt("%l", %0)

// Режим DEBUG. Раскомментировать если нужно включить команду для выдачи оружия
//#define DEBUG

// Уникальный ID (impulse) для оружия
#define WEAPON_UID            130
// ID оружия (берётся из файла cssdk_const.inc из enum WeaponIdType)
#define WEAPON_ID            WEAPON_AK47
// Получить ID оружия
#define GetWeaponID(%0)        WeaponIdType:get_member(%0, m_iId)
// Является ли оружие нашим кастомным
#define IsCustomWeapon(%0)    bool:(get_entvar(%0, var_impulse) == WEAPON_UID)

// Нужны ли модели
#define MODELS
// Нужна ли модель "w_"
#define MODEL_W

#if defined MODELS
new const g_szModelV[]                = "models/custom/gold/v_gold_ak47.mdl";        // Модель "v_"
new const g_szModelP[]                = "models/custom/gold/p_gold_ak47.mdl";        // Модель "p_"
#if defined MODEL_W
new const g_szModelW[]                = "models/custom/gold/w_gold_ak47.mdl";        // Модель "w_"
#endif
#endif

#if defined DEBUG
// Команда для выдачи оружия
new const g_szGiveWeaponCmd[]       = "give_ak47";
#endif

// Название оружия (информация: https://dev-cs.ru/threads/772/)
new const g_szWeaponName[]            = "weapon_ak47";

/****************************************************************************************
****************************************************************************************/

enum _:CVARS
{
    CVAR_WEAPON_DAMAGE,
    CVAR_WEAPON_CLIP,
    CVAR_WEAPON_AMMO,
    CVAR_TOUCH_ONLY_OWNER
};

new g_eCvar[CVARS];

new HamHook:g_iHamHookDeployPost, HamHook:g_iHamHookReloadPre, HamHook:g_iHamHookTouchPre;
new HookChain:g_iHookChainSetModelPre, HookChain:g_iHookChainAddPlayerItemPre;
new g_iFMFwdRemoveEntityPre;

new g_iActiveWeapons;

/****************************************************************************************
****************************************************************************************/

#if defined MODELS
public plugin_precache()
{
    precache_model(g_szModelV);
    precache_model(g_szModelP);

#if defined MODEL_W
    precache_model(g_szModelW);
#endif
}
#endif

public plugin_init()
{
    register_plugin("[Custom] Weapon: Gold AK-47", PLUGIN_VERSION, "w0w");
    register_dictionary("custom_weapon.ini");

#if defined DEBUG
    register_clcmd(g_szGiveWeaponCmd, "func_CmdGiveWeapon");
#endif

    RegisterHookChain(RG_CBasePlayer_DropPlayerItem, "refwd_PlayerDropPlayerItem_Post", true);
    DisableHookChain(g_iHookChainAddPlayerItemPre = RegisterHookChain(RG_CBasePlayer_AddPlayerItem, "refwd_PlayerAddPlayerItem_Pre", false));

#if defined MODELS
    DisableHamForward(g_iHamHookDeployPost = RegisterHam(Ham_Item_Deploy, g_szWeaponName, "hamfwd_ItemDeploy_Post", true));
#endif
    DisableHookChain(g_iHookChainSetModelPre = RegisterHookChain(RG_CWeaponBox_SetModel, "refwd_WeaponBox_SetModel_Pre", false));

    DisableHamForward(g_iHamHookReloadPre = RegisterHam(Ham_Weapon_Reload, g_szWeaponName, "hamfwd_WeaponReload_Pre", false));
    DisableHamForward(g_iHamHookTouchPre = RegisterHam(Ham_Touch, "weaponbox", "hamfwd_WeaponBox_Touch_Pre", false));

    func_RegisterCvars();
}

public func_CmdGiveWeapon(id)
{
    if(!is_user_alive(id))
        return PLUGIN_HANDLED;

    if(++g_iActiveWeapons == 1)
        func_ManageHooks(true);

    new iWeapon = rg_give_custom_item(id, g_szWeaponName, GT_REPLACE, WEAPON_UID);

    if(is_nullent(iWeapon))
        return PLUGIN_HANDLED;

    if(g_eCvar[CVAR_WEAPON_CLIP])
    {
        rg_set_iteminfo(iWeapon, ItemInfo_iMaxClip, g_eCvar[CVAR_WEAPON_CLIP]);
        rg_set_user_ammo(id, WEAPON_ID, g_eCvar[CVAR_WEAPON_CLIP]);
    }

    if(g_eCvar[CVAR_WEAPON_AMMO])
        rg_set_user_bpammo(id, WEAPON_ID, g_eCvar[CVAR_WEAPON_AMMO]);

    if(g_eCvar[CVAR_WEAPON_DAMAGE])
    {
        set_member(iWeapon, m_Weapon_flBaseDamage, Float:get_member(iWeapon, m_Weapon_flBaseDamage) * g_eCvar[CVAR_WEAPON_DAMAGE]);
    #if WEAPON_ID == WEAPON_M4A1
        set_member(iWeapon, m_M4A1_flBaseDamageSil, Float:get_member(iWeapon, m_M4A1_flBaseDamageSil) * g_eCvar[CVAR_WEAPON_DAMAGE]);
    #elseif WEAPON_ID == WEAPON_USP
        set_member(iWeapon, m_USP_flBaseDamageSil, Float:get_member(iWeapon, m_USP_flBaseDamageSil) * g_eCvar[CVAR_WEAPON_DAMAGE]);
    #elseif WEAPON_ID == WEAPON_FAMAS
        set_member(iWeapon, m_Famas_flBaseDamageBurst, Float:get_member(iWeapon, m_Famas_flBaseDamageBurst) * g_eCvar[CVAR_WEAPON_DAMAGE]);
    #endif
    }

    return PLUGIN_HANDLED;
}

#if defined MODELS
public hamfwd_ItemDeploy_Post(iWeapon)
{
    if(!IsCustomWeapon(iWeapon))
        return HAM_IGNORED;

    new id = get_member(iWeapon, m_pPlayer);

#if defined MODELS
    set_entvar(id, var_viewmodel, g_szModelV);
    set_entvar(id, var_weaponmodel, g_szModelP);
#endif

    return HAM_IGNORED;
}
#endif

public refwd_WeaponBox_SetModel_Pre(const iWeaponBox, const szModel[])
{
    new iWeapon = func_GetWeaponBoxWeapon(iWeaponBox);
    if(iWeapon != NULLENT && IsCustomWeapon(iWeapon))
    {
        SetHookChainArg(2, ATYPE_STRING, g_szModelW);

        if(!(--g_iActiveWeapons))
            func_ManageHooks(false);
    }
}

public hamfwd_WeaponReload_Pre(iWeapon)
{
    if(!IsCustomWeapon(iWeapon) || get_member(iWeapon, m_Weapon_iClip) < g_eCvar[CVAR_WEAPON_CLIP])
        return HAM_IGNORED;

    new id = get_member(iWeapon, m_pPlayer);
#if WEAPON_ID == WEAPON_M4A1
    func_SendWeaponAnimation(id, get_member(iWeapon, m_Weapon_iWeaponState) & WPNSTATE_M4A1_SILENCED ? 0 : 7);
#elseif WEAPON_ID == WEAPON_USP
    func_SendWeaponAnimation(id, get_member(iWeapon, m_Weapon_iWeaponState) & WPNSTATE_USP_SILENCED ? 0 : 8);
#else
    func_SendWeaponAnimation(id, 0);
#endif

    return HAM_SUPERCEDE;
}

public hamfwd_WeaponBox_Touch_Pre(const iWeaponBox, const id)
{
    new iWeapon = func_GetWeaponBoxWeapon(iWeaponBox);

    if(iWeapon == NULLENT || GetWeaponID(iWeapon) != WEAPON_ID || !IsCustomWeapon(iWeapon))
        return HAM_IGNORED;

    if(g_eCvar[CVAR_TOUCH_ONLY_OWNER] && get_entvar(iWeaponBox, var_owner) == id)
        return HAM_SUPERCEDE;

    EnableHookChain(g_iHookChainAddPlayerItemPre);

    return HAM_IGNORED;
}

stock func_GetWeaponBoxWeapon(const iWeaponBox)
{
    for(new i, iWeapon; i < MAX_ITEM_TYPES; i++)
    {
        iWeapon = get_member(iWeaponBox, m_WeaponBox_rgpPlayerItems, i);
        if(!is_nullent(iWeapon))
            return iWeapon;
    }
    return NULLENT;
}

stock func_SendWeaponAnimation(const id, const iAnimation)
{
    set_entvar(id, var_weaponanim, iAnimation);

    message_begin(MSG_ONE_UNRELIABLE, SVC_WEAPONANIM, .player = id);
    write_byte(iAnimation);
    write_byte(0);
    message_end();
}

/****************************************************************************************
****************************************************************************************/

public fmfwd_RemoveEntity_Pre(const iEnt)
{
    if(!is_entity(iEnt) || !IsCustomWeapon(iEnt))
        return FMRES_IGNORED;

    if(!(--g_iActiveWeapons))
        func_ManageHooks(false);

    return FMRES_IGNORED;
}

public refwd_PlayerDropPlayerItem_Post(const id, const pszItemName[])
{
    new iEnt = GetHookChainReturn(ATYPE_INTEGER);

    if(!is_entity(iEnt))
        return HC_CONTINUE;

    new iWeapon = func_GetWeaponBoxWeapon(iEnt);
    if(iWeapon != NULLENT && IsCustomWeapon(iWeapon))
        EnableHookChain(g_iHookChainSetModelPre);

    return HC_CONTINUE;
}

public refwd_PlayerAddPlayerItem_Pre(const id, const pItem)
{
    DisableHookChain(g_iHookChainAddPlayerItemPre);

    if(!is_entity(pItem))
        return HC_CONTINUE;

    if(IsCustomWeapon(pItem) && ++g_iActiveWeapons == 1)
        func_ManageHooks(true);

    return HC_CONTINUE;
}

func_ManageHooks(bool:bEnable)
{
    if(bEnable)
    {
        if(g_eCvar[CVAR_WEAPON_CLIP])
            EnableHamForward(g_iHamHookReloadPre);
        if(g_eCvar[CVAR_TOUCH_ONLY_OWNER])
            EnableHamForward(g_iHamHookTouchPre);
        EnableHamForward(g_iHamHookDeployPost);
        EnableHookChain(g_iHookChainSetModelPre);
        g_iFMFwdRemoveEntityPre = register_forward(FM_RemoveEntity, "fmfwd_RemoveEntity_Pre", false);
    }
    else
    {
        DisableHookChain(g_iHookChainSetModelPre);
        DisableHamForward(g_iHamHookReloadPre);
        DisableHamForward(g_iHamHookDeployPost);
        EnableHamForward(g_iHamHookTouchPre);
        unregister_forward(FM_RemoveEntity, g_iFMFwdRemoveEntityPre);
    }
}

/****************************************************************************************
****************************************************************************************/

func_RegisterCvars()
{
    new pCvar;

    pCvar = create_cvar("custom_weapon_gold_ak47_clip", "30", FCVAR_NONE, GetCvarDesc("CUSTOM_WEAPON_CVAR_CLIP"), true, 0.0);
    hook_cvar_change(pCvar, "hook_CvarChange_Clip");

    pCvar = create_cvar("custom_weapon_gold_ak47_ammo", "500", FCVAR_NONE, GetCvarDesc("CUSTOM_WEAPON_CVAR_AMMO"), true, 0.0);
    bind_pcvar_num(pCvar, g_eCvar[CVAR_WEAPON_AMMO]);

    pCvar = create_cvar("custom_weapon_gold_ak47_damage", "2", FCVAR_NONE, GetCvarDesc("CUSTOM_WEAPON_CVAR_DAMAGE"), true, 0.0);
    bind_pcvar_num(pCvar, g_eCvar[CVAR_WEAPON_DAMAGE]);

    pCvar = create_cvar("custom_weapon_gold_ak47_touch_only_owner", "0", FCVAR_NONE, GetCvarDesc("CUSTOM_WEAPON_CVAR_TOUCH_ONLY_OWNER"), true, 0.0, true, 1.0);
    bind_pcvar_num(pCvar, g_eCvar[CVAR_TOUCH_ONLY_OWNER]);
}

public hook_CvarChange_Clip(pCvar, const szOldValue[], const szNewValue[])
{
    g_eCvar[CVAR_WEAPON_CLIP] = str_to_num(szNewValue);

    if(g_iActiveWeapons && g_eCvar[CVAR_WEAPON_CLIP] == 0)
        DisableHamForward(g_iHamHookReloadPre);
}

/****************************************************************************************
****************************************************************************************/

public plugin_natives()
{
    register_native("custom_give_weapon_gold_ak47",    "__custom_give_weapon_gold_ak47");
}

public __custom_give_weapon_gold_ak47(iPlugin, iParams)
{
    enum { player = 1 };

    new id = get_param(player);

    if(!IsUserValid(id))
        abort(AMX_ERR_NATIVE, "Player out of range (%i)", id);

    func_CmdGiveWeapon(id);
}
 
Последнее редактирование:
Сообщения
1,661
Реакции
1,486
Помог
24 раз(а)
voed, спасибо за наводку, "администратор"!
 
Сообщения
1,419
Реакции
2,508
Помог
59 раз(а)
С учётом удаления из инвентаря (спасибо voed за подсказку хука):
Код:
/*
* Last update: 09.02.2019
*
* Original code by F@nt0M: https://dev-cs.ru/threads/1983/page-3#post-51426
*/

#include <amxmodx>
#include <fakemeta>
#include <hamsandwich>
#include <reapi>

#pragma semicolon 1

new const PLUGIN_VERSION[] = "1.0";

/****************************************************************************************
****************************************************************************************/

#define IsUserValid(%0) (1 <= %0 <= MaxClients)
#define GetCvarDesc(%0) fmt(%0, "%l")

// Режим DEBUG. Раскомментировать если нужно включить команду для выдачи оружия
//#define DEBUG

// Уникальный ID (impulse) для оружия
#define WEAPON_UID            130
// ID оружия (берётся из файла cssdk_const.inc из enum WeaponIdType)
#define WEAPON_ID            WEAPON_AK47
// Получить ID оружия
#define GetWeaponID(%0)        WeaponIdType:get_member(%0, m_iId)
// Является ли оружие нашим кастомным
#define IsCustomWeapon(%0)    bool:(get_entvar(%0, var_impulse) == WEAPON_UID)

// Нужны ли модели
#define MODELS
// Нужна ли модель "w_"
#define MODEL_W

#if defined MODELS
new const g_szModelV[]                = "models/custom/gold/v_gold_ak47.mdl";        // Модель "v_"
new const g_szModelP[]                = "models/custom/gold/p_gold_ak47.mdl";        // Модель "p_"
#if defined MODEL_W
new const g_szModelW[]                = "models/custom/gold/w_gold_ak47.mdl";        // Модель "w_"
#endif
#endif

#if defined DEBUG
// Команда для выдачи оружия
new const g_szGiveWeaponCmd[]       = "give_ak47";
#endif

// Название оружия (информация: https://dev-cs.ru/threads/772/)
new const g_szWeaponName[]            = "weapon_ak47";

/****************************************************************************************
****************************************************************************************/

enum _:CVARS
{
    CVAR_WEAPON_DAMAGE,
    CVAR_WEAPON_CLIP,
    CVAR_WEAPON_AMMO,
    CVAR_TOUCH_ONLY_OWNER
};

new g_eCvar[CVARS];

new HamHook:g_iHamHookDeployPost, HamHook:g_iHamHookReloadPre, HamHook:g_iHamHookTouchPre;
new HookChain:g_iHookChainSetModelPre, HookChain:g_iHookChainAddPlayerItemPre;
new g_iFMFwdRemoveEntityPre;

new g_iActiveWeapons;

/****************************************************************************************
****************************************************************************************/

#if defined MODELS
public plugin_precache()
{
    precache_model(g_szModelV);
    precache_model(g_szModelP);

#if defined MODEL_W
    precache_model(g_szModelW);
#endif
}
#endif

public plugin_init()
{
    register_plugin("[Custom] Weapon: Gold AK-47", PLUGIN_VERSION, "w0w");
    register_dictionary("custom_weapon.ini");

#if defined DEBUG
    register_clcmd(g_szGiveWeaponCmd, "func_CmdGiveWeapon");
#endif

    RegisterHookChain(RG_CBasePlayer_DropPlayerItem, "refwd_PlayerDropPlayerItem_Post", true);
    DisableHookChain(g_iHookChainAddPlayerItemPre = RegisterHookChain(RG_CBasePlayer_AddPlayerItem, "refwd_PlayerAddPlayerItem_Pre", false));

#if defined MODELS
    DisableHamForward(g_iHamHookDeployPost = RegisterHam(Ham_Item_Deploy, g_szWeaponName, "hamfwd_ItemDeploy_Post", true));
#endif
    DisableHookChain(g_iHookChainSetModelPre = RegisterHookChain(RG_CWeaponBox_SetModel, "refwd_WeaponBox_SetModel_Pre", false));

    DisableHamForward(g_iHamHookReloadPre = RegisterHam(Ham_Weapon_Reload, g_szWeaponName, "hamfwd_WeaponReload_Pre", false));
    DisableHamForward(g_iHamHookTouchPre = RegisterHam(Ham_Touch, "weaponbox", "hamfwd_WeaponBox_Touch_Pre", false));

    func_RegisterCvars();
}

public func_CmdGiveWeapon(id)
{
    if(!is_user_alive(id))
        return PLUGIN_HANDLED;

    if(++g_iActiveWeapons == 1)
        func_ManageHooks(true);

    new iWeapon = rg_give_custom_item(id, g_szWeaponName, GT_REPLACE, WEAPON_UID);

    if(is_nullent(iWeapon))
        return PLUGIN_HANDLED;

    if(g_eCvar[CVAR_WEAPON_CLIP])
    {
        rg_set_iteminfo(iWeapon, ItemInfo_iMaxClip, g_eCvar[CVAR_WEAPON_CLIP]);
        rg_set_user_ammo(id, WEAPON_ID, g_eCvar[CVAR_WEAPON_CLIP]);
    }

    if(g_eCvar[CVAR_WEAPON_AMMO])
        rg_set_user_bpammo(id, WEAPON_ID, g_eCvar[CVAR_WEAPON_AMMO]);

    if(g_eCvar[CVAR_WEAPON_DAMAGE])
    {
        set_member(iWeapon, m_Weapon_flBaseDamage, Float:get_member(iWeapon, m_Weapon_flBaseDamage) * g_eCvar[CVAR_WEAPON_DAMAGE]);
    #if WEAPON_ID == WEAPON_M4A1
        set_member(iWeapon, m_M4A1_flBaseDamageSil, Float:get_member(iWeapon, m_M4A1_flBaseDamageSil) * g_eCvar[CVAR_WEAPON_DAMAGE]);
    #elseif WEAPON_ID == WEAPON_USP
        set_member(iWeapon, m_USP_flBaseDamageSil, Float:get_member(iWeapon, m_USP_flBaseDamageSil) * g_eCvar[CVAR_WEAPON_DAMAGE]);
    #elseif WEAPON_ID == WEAPON_FAMAS
        set_member(iWeapon, m_Famas_flBaseDamageBurst, Float:get_member(iWeapon, m_Famas_flBaseDamageBurst) * g_eCvar[CVAR_WEAPON_DAMAGE]);
    #endif
    }

    return PLUGIN_HANDLED;
}

#if defined MODELS
public hamfwd_ItemDeploy_Post(iWeapon)
{
    if(!IsCustomWeapon(iWeapon))
        return HAM_IGNORED;

    new id = get_member(iWeapon, m_pPlayer);

#if defined MODELS
    set_entvar(id, var_viewmodel, g_szModelV);
    set_entvar(id, var_weaponmodel, g_szModelP);
#endif

    return HAM_IGNORED;
}
#endif

public refwd_WeaponBox_SetModel_Pre(const iWeaponBox, const szModel[])
{
    new iWeapon = func_GetWeaponBoxWeapon(iWeaponBox);
    if(iWeapon != NULLENT && IsCustomWeapon(iWeapon))
    {
        SetHookChainArg(2, ATYPE_STRING, g_szModelW);

        if(!(--g_iActiveWeapons))
            func_ManageHooks(false);
    }
}

public hamfwd_WeaponReload_Pre(iWeapon)
{
    if(!IsCustomWeapon(iWeapon) || get_member(iWeapon, m_Weapon_iClip) < g_eCvar[CVAR_WEAPON_CLIP])
        return HAM_IGNORED;

    new id = get_member(iWeapon, m_pPlayer);
#if WEAPON_ID == WEAPON_M4A1
    func_SendWeaponAnimation(id, get_member(iWeapon, m_Weapon_iWeaponState) & WPNSTATE_M4A1_SILENCED ? 0 : 7);
#elseif WEAPON_ID == WEAPON_USP
    func_SendWeaponAnimation(id, get_member(iWeapon, m_Weapon_iWeaponState) & WPNSTATE_USP_SILENCED ? 0 : 8);
#else
    func_SendWeaponAnimation(id, 0);
#endif

    return HAM_SUPERCEDE;
}

public hamfwd_WeaponBox_Touch_Pre(const iWeaponBox, const id)
{
    new iWeapon = func_GetWeaponBoxWeapon(iWeaponBox);

    if(iWeapon == NULLENT || GetWeaponID(iWeapon) != WEAPON_ID || !IsCustomWeapon(iWeapon))
        return HAM_IGNORED;

    if(g_eCvar[CVAR_TOUCH_ONLY_OWNER] && get_entvar(iWeaponBox, var_owner) == id)
        return HAM_SUPERCEDE;

    EnableHookChain(g_iHookChainAddPlayerItemPre);

    return HAM_IGNORED;
}

stock func_GetWeaponBoxWeapon(const iWeaponBox)
{
    for(new i, iWeapon; i < MAX_ITEM_TYPES; i++)
    {
        iWeapon = get_member(iWeaponBox, m_WeaponBox_rgpPlayerItems, i);
        if(!is_nullent(iWeapon))
            return iWeapon;
    }
    return NULLENT;
}

stock func_SendWeaponAnimation(const id, const iAnimation)
{
    set_entvar(id, var_weaponanim, iAnimation);

    message_begin(MSG_ONE_UNRELIABLE, SVC_WEAPONANIM, .player = id);
    write_byte(iAnimation);
    write_byte(0);
    message_end();
}

/****************************************************************************************
****************************************************************************************/

public fmfwd_RemoveEntity_Pre(const iEnt)
{
    if(!is_entity(iEnt) || !IsCustomWeapon(iEnt))
        return FMRES_IGNORED;

    if(!(--g_iActiveWeapons))
        func_ManageHooks(false);

    return FMRES_IGNORED;
}

public refwd_PlayerDropPlayerItem_Post(const id, const pszItemName[])
{
    new iEnt = GetHookChainReturn(ATYPE_INTEGER);

    if(!is_entity(iEnt))
        return HC_CONTINUE;

    new iWeapon = func_GetWeaponBoxWeapon(iEnt);
    if(iWeapon != NULLENT && IsCustomWeapon(iWeapon))
        EnableHookChain(g_iHookChainSetModelPre);

    return HC_CONTINUE;
}

public refwd_PlayerAddPlayerItem_Pre(const id, const pItem)
{
    DisableHookChain(g_iHookChainAddPlayerItemPre);

    if(!is_entity(pItem))
        return HC_CONTINUE;

    if(IsCustomWeapon(pItem) && ++g_iActiveWeapons == 1)
        func_ManageHooks(true);

    return HC_CONTINUE;
}

func_ManageHooks(bool:bEnable)
{
    if(bEnable)
    {
        if(g_eCvar[CVAR_WEAPON_CLIP])
            EnableHamForward(g_iHamHookReloadPre);
        if(g_eCvar[CVAR_TOUCH_ONLY_OWNER])
            EnableHamForward(g_iHamHookTouchPre);
        EnableHamForward(g_iHamHookDeployPost);
        EnableHookChain(g_iHookChainSetModelPre);
        g_iFMFwdRemoveEntityPre = register_forward(FM_RemoveEntity, "fmfwd_RemoveEntity_Pre", false);
    }
    else
    {
        DisableHookChain(g_iHookChainSetModelPre);
        DisableHamForward(g_iHamHookReloadPre);
        DisableHamForward(g_iHamHookDeployPost);
        EnableHamForward(g_iHamHookTouchPre);
        unregister_forward(FM_RemoveEntity, g_iFMFwdRemoveEntityPre);
    }
}

/****************************************************************************************
****************************************************************************************/

func_RegisterCvars()
{
    new pCvar;

    pCvar = create_cvar("custom_weapon_gold_ak47_clip", "30", FCVAR_NONE, GetCvarDesc("CUSTOM_WEAPON_CVAR_CLIP"), true, 0.0);
    hook_cvar_change(pCvar, "hook_CvarChange_Clip");

    pCvar = create_cvar("custom_weapon_gold_ak47_ammo", "500", FCVAR_NONE, GetCvarDesc("CUSTOM_WEAPON_CVAR_AMMO"), true, 0.0);
    bind_pcvar_num(pCvar, g_eCvar[CVAR_WEAPON_AMMO]);

    pCvar = create_cvar("custom_weapon_gold_ak47_damage", "2", FCVAR_NONE, GetCvarDesc("CUSTOM_WEAPON_CVAR_DAMAGE"), true, 0.0);
    bind_pcvar_num(pCvar, g_eCvar[CVAR_WEAPON_DAMAGE]);

    pCvar = create_cvar("custom_weapon_gold_ak47_touch_only_owner", "0", FCVAR_NONE, GetCvarDesc("CUSTOM_WEAPON_CVAR_TOUCH_ONLY_OWNER"), true, 0.0, true, 1.0);
    bind_pcvar_num(pCvar, g_eCvar[CVAR_TOUCH_ONLY_OWNER]);
}

public hook_CvarChange_Clip(pCvar, const szOldValue[], const szNewValue[])
{
    g_eCvar[CVAR_WEAPON_CLIP] = str_to_num(szNewValue);

    if(g_iActiveWeapons && g_eCvar[CVAR_WEAPON_CLIP] == 0)
        DisableHamForward(g_iHamHookReloadPre);
}

/****************************************************************************************
****************************************************************************************/

public plugin_natives()
{
    register_native("custom_give_weapon_gold_ak47",    "__custom_give_weapon_gold_ak47");
}

public __custom_give_weapon_gold_ak47(iPlugin, iParams)
{
    enum { player = 1 };

    new id = get_param(player);

    if(!IsUserValid(id))
        abort(AMX_ERR_NATIVE, "Player out of range (%i)", id);

    func_CmdGiveWeapon(id);
}
Стоит иметь ввиду что при указывании GT_APPEND в rg_give_custom_item кастомное оружие не будет выдано. Можно его удалять с помощью rg_remove_item или выкидывать с помощью rg_drop_item.
 
Последнее редактирование:
Сообщения
2,144
Реакции
1,223
Помог
44 раз(а)
Сообщения
2,809
Реакции
1,658
Помог
74 раз(а)
GT_APPEND будет пытаться дать оружее. Если оно у игрока уже есть - ничего не произойдет.
GT_REPLACE - даст оружее игроку и патроны в любом случае, даже если оно уже есть у игрока

GT_DROP_AND_REPLACE - то же самое, что и GT_REPLACE, только старое оружее будет выкидываться и плагин будет выдавать новое
By Hanter?
 
Сообщения
1,419
Реакции
2,508
Помог
59 раз(а)
GT_REPLACE - даст оружее игроку и патроны в любом случае, даже если оно уже есть у игрока
GT_REPLACE как и последнее удалит все оружия из слота, если всегда 1 оружие в слоте то конечно проблем не будет и это нормальный вариант.
10 Фев 2019
Ещё один пример: замена ножа + WeaponList + в нативе есть параметр replace (true/false) который определяет нужно ли удалять все оружия в том слоте куда выдаётся кастомный предмет. Именно в этом варианте толку нет, но если выдаётся например в слот пистолетов то нормально.

Дропа тут нет потому что пришлось бы костылить ибо это дроп ножа можно сказать.
В func_ShowWeaponList нужно дополнительно ещё самостоятельно менять на какое оружие будет заменяться (CSW_KNIFE) и слот write_byte(2); (2 = 3 слот).

Код:
/*
* Last update: 10.02.2019
*
* Original code by F@nt0M: https://dev-cs.ru/threads/1983/page-3#post-51426
*/

#include <amxmodx>
#include <fakemeta>
#include <hamsandwich>
#include <reapi>

#pragma semicolon 1

new const PLUGIN_VERSION[] = "1.0";

/****************************************************************************************
****************************************************************************************/

#define IsUserValid(%0) (1 <= %0 <= MaxClients)
#define GetCvarDesc(%0) fmt(%0, "%l")

// Режим DEBUG. Раскомментировать если нужно включить команду для выдачи оружия
#define DEBUG

// Уникальный ID (impulse) для оружия
#define WEAPON_UID            132
// ID оружия (берётся из файла cssdk_const.inc из enum WeaponIdType)
#define WEAPON_ID            WEAPON_KNIFE
// Получить ID оружия
#define GetWeaponID(%0)        WeaponIdType:get_member(%0, m_iId)
// Является ли оружие нашим кастомным
#define IsCustomWeapon(%0)    bool:(get_entvar(%0, var_impulse) == WEAPON_UID)

// Нужны ли модели
#define MODELS
// Нужна ли модель "w_"
#define MODEL_W

#if defined MODELS
new const g_szModelV[]                = "models/custom/weapons/v_taser.mdl";        // Модель "v_"
new const g_szModelP[]                = "models/custom/weapons/p_taser.mdl";        // Модель "p_"
#if defined MODEL_W
new const g_szModelW[]                = "models/custom/weapons/w_taser.mdl";        // Модель "w_"
#endif
#endif

#if defined DEBUG
// Команда для выдачи оружия
new const g_szGiveWeaponCmd[]        = "give_taser";
#endif

// Название оружия (информация: https://dev-cs.ru/threads/772/)
new const g_szWeaponName[]            = "weapon_knife";

// Звук когда ударяешь игрока
new const g_szSoundDamage[]            = "custom/weapons/electroweapon.wav";

/****************************************************************************************
****************************************************************************************/

enum _:CVARS
{
    Float:CVAR_WEAPON_DAMAGE,
    Float:CVAR_WEAPON_COOLDOWN,
#if WEAPON_ID != WEAPON_KNIFE
    CVAR_TOUCH_ONLY_OWNER
#endif
};

new g_eCvar[CVARS];

enum _:HAM_HOOKS
{
    HamHook:HAM_HOOK_DEPLOY_POST,
    HamHook:HAM_HOOK_TOUCH_PRE
};

new HamHook:g_iHamHook[HAM_HOOKS];

enum _:HOOK_CHAINS
{
#if WEAPON_ID != WEAPON_KNIFE
    HookChain:HOOKCHAIN_SETMODEL_PRE,
#endif
    HookChain:HOOKCHAIN_ADDPLAYERITEM_PRE,
    HookChain:HOOKCHAIN_TAKEDAMAGE_PRE
};

new HookChain:g_iHookChain[HOOK_CHAINS];
new g_iFMFwdRemoveEntityPre;

enum (+= 100)
{
    TASK_ID_FREEZE
};

new g_iActiveWeapons;
new g_iMsgWeaponList;
new g_iMsgScreenFade;

new Float:g_flElectroShockTime[MAX_PLAYERS+1];
new g_pSpriteElectro;

/****************************************************************************************
****************************************************************************************/

public plugin_precache()
{
#if defined MODELS
    precache_model(g_szModelV);
    precache_model(g_szModelP);

#if defined MODEL_W
    precache_model(g_szModelW);
#endif
#endif

    precache_generic("sprites/weapon_taser.txt");
    precache_generic("sprites/taser.spr");

    g_pSpriteElectro = precache_model("sprites/spark1.spr");
    precache_sound(g_szSoundDamage);
}

public plugin_init()
{
    register_plugin("[Custom] Weapon: Taser", PLUGIN_VERSION, "w0w");
    register_dictionary("custom_weapon.ini");

#if defined DEBUG
    register_clcmd(g_szGiveWeaponCmd, "func_CmdGiveWeapon");
#endif
    register_clcmd("weapon_taser", "func_ClCmdSelectWeapon");

    g_iMsgWeaponList = get_user_msgid("WeaponList");
    g_iMsgScreenFade = get_user_msgid("ScreenFade");

#if WEAPON_ID != WEAPON_KNIFE
    RegisterHookChain(RG_CBasePlayer_DropPlayerItem, "refwd_PlayerDropPlayerItem_Post", true);
#endif
    DisableHookChain(g_iHookChain[HOOKCHAIN_ADDPLAYERITEM_PRE] = RegisterHookChain(RG_CBasePlayer_AddPlayerItem, "refwd_PlayerAddPlayerItem_Pre", false));
    RegisterHam(Ham_Item_AddToPlayer, g_szWeaponName, "hamfwd_PlayerAddPlayerItem_Post", true);

#if defined MODELS
    DisableHamForward(g_iHamHook[HAM_HOOK_DEPLOY_POST] = RegisterHam(Ham_Item_Deploy, g_szWeaponName, "hamfwd_ItemDeploy_Post", true));
#endif
#if WEAPON_ID != WEAPON_KNIFE
    DisableHookChain(g_iHookChain[HOOKCHAIN_SETMODEL_PRE] = RegisterHookChain(RG_CWeaponBox_SetModel, "refwd_WeaponBox_SetModel_Pre", false));
#endif
    DisableHookChain(g_iHookChain[HOOKCHAIN_TAKEDAMAGE_PRE] = RegisterHookChain(RG_CBasePlayer_TakeDamage, "refwd_PlayerTakeDamage_Pre", false));

    DisableHamForward(g_iHamHook[HAM_HOOK_TOUCH_PRE] = RegisterHam(Ham_Touch, "weaponbox", "hamfwd_WeaponBox_Touch_Pre", false));

    func_RegisterCvars();
}

public func_ClCmdSelectWeapon(id)
{
    engclient_cmd(id, g_szWeaponName);
}

public func_CmdGiveWeapon(id, bool:bReplace)
{
    if(!is_user_alive(id))
        return PLUGIN_HANDLED;

    if(++g_iActiveWeapons == 1)
        func_ManageHooks(true);

    if(!bReplace)
        rg_remove_item(id, g_szWeaponName);
    new iWeapon = rg_give_custom_item(id, g_szWeaponName, !bReplace ? GT_APPEND : GT_REPLACE, WEAPON_UID);

    if(is_nullent(iWeapon))
        return PLUGIN_HANDLED;

    if(g_eCvar[CVAR_WEAPON_DAMAGE])
    {
        set_member(iWeapon, m_Weapon_flBaseDamage, Float:get_member(iWeapon, m_Weapon_flBaseDamage) * g_eCvar[CVAR_WEAPON_DAMAGE]);
    #if WEAPON_ID == WEAPON_M4A1
        set_member(iWeapon, m_M4A1_flBaseDamageSil, Float:get_member(iWeapon, m_M4A1_flBaseDamageSil) * g_eCvar[CVAR_WEAPON_DAMAGE]);
    #elseif WEAPON_ID == WEAPON_USP
        set_member(iWeapon, m_USP_flBaseDamageSil, Float:get_member(iWeapon, m_USP_flBaseDamageSil) * g_eCvar[CVAR_WEAPON_DAMAGE]);
    #elseif WEAPON_ID == WEAPON_FAMAS
        set_member(iWeapon, m_Famas_flBaseDamageBurst, Float:get_member(iWeapon, m_Famas_flBaseDamageBurst) * g_eCvar[CVAR_WEAPON_DAMAGE]);
    #endif
    }

    return PLUGIN_HANDLED;
}

public hamfwd_PlayerAddPlayerItem_Post(const pItem, const id)
{
    if(!is_entity(pItem))
        return HC_CONTINUE;

    if(IsCustomWeapon(pItem))
        func_ShowWeaponList(id, true);
    else
        func_ShowWeaponList(id, false);

    return HC_CONTINUE;
}

#if defined MODELS
public hamfwd_ItemDeploy_Post(iWeapon)
{
    if(!IsCustomWeapon(iWeapon))
        return HAM_IGNORED;

    new id = get_member(iWeapon, m_pPlayer);

    set_entvar(id, var_viewmodel, g_szModelV);
    set_entvar(id, var_weaponmodel, g_szModelP);

    return HAM_IGNORED;
}
#endif

#if WEAPON_ID != WEAPON_KNIFE
public refwd_WeaponBox_SetModel_Pre(const iWeaponBox, const szModel[])
{
    new iWeapon = func_GetWeaponBoxWeapon(iWeaponBox);
    if(iWeapon != NULLENT && IsCustomWeapon(iWeapon))
    {
        SetHookChainArg(2, ATYPE_STRING, g_szModelW);

        if(!(--g_iActiveWeapons))
            func_ManageHooks(false);
    }
}
#endif

public refwd_PlayerTakeDamage_Pre(const iVictim, iInflictor, iAttacker, Float:flDamage, iBitsDamageType)
{
    if(!is_user_connected(iAttacker) || iVictim == iAttacker)
        return HC_CONTINUE;

    new iWeapon = get_member(iAttacker, m_pActiveItem);

    if(!IsCustomWeapon(iWeapon))
        return HC_CONTINUE;

    static Float:flGameTime;
    flGameTime = get_gametime();

    if(flGameTime - g_flElectroShockTime[iAttacker] > g_eCvar[CVAR_WEAPON_COOLDOWN])
    {
        if(g_eCvar[CVAR_WEAPON_DAMAGE])
            SetHookChainArg(4, ATYPE_FLOAT, g_eCvar[CVAR_WEAPON_DAMAGE]);

        g_flElectroShockTime[iAttacker] = flGameTime;

        new Float:flOrigin[3];
        get_entvar(iVictim, var_origin, flOrigin);

        func_ElectroRing(flOrigin);
        func_ElectroSound(flOrigin);

        rg_set_rendering(iVictim, kRenderFxGlowShell, 141.0, 14.0, 246.0, kRenderNormal, 0.0);
        func_ScreenFade(iVictim, 0, 0, 4, 141, 14, 246, 200);
        set_entvar(iVictim, var_flags, get_entvar(iVictim, var_flags) | FL_FROZEN);

        remove_task(iVictim+TASK_ID_FREEZE);
        set_task(g_eCvar[CVAR_WEAPON_COOLDOWN], "func_DeleteFroze", iVictim+TASK_ID_FREEZE);
    }
    else
    {
        if(g_eCvar[CVAR_WEAPON_DAMAGE])
            SetHookChainArg(4, ATYPE_FLOAT, g_eCvar[CVAR_WEAPON_DAMAGE] / 3.0);
    }

    return HC_CONTINUE;
}

public hamfwd_WeaponBox_Touch_Pre(const iWeaponBox, const id)
{
    new iWeapon = func_GetWeaponBoxWeapon(iWeaponBox);

    if(iWeapon == NULLENT || GetWeaponID(iWeapon) != WEAPON_ID || !IsCustomWeapon(iWeapon))
        return HAM_IGNORED;

    if(g_eCvar[CVAR_TOUCH_ONLY_OWNER] && get_entvar(iWeaponBox, var_owner) == id)
        return HAM_SUPERCEDE;

    EnableHookChain(g_iHookChain[HOOKCHAIN_ADDPLAYERITEM_PRE]);

    return HAM_IGNORED;
}

public func_DeleteFroze(id)
{
    id -= TASK_ID_FREEZE;

    if(is_user_alive(id))
        func_RemoveFreeze(id);
}

func_RemoveFreeze(id)
{
    new iRenderFx, Float:flColor[3], iRenderMode, Float:flAmount;
    rg_get_rendering(id, iRenderFx, flColor[0], flColor[1], flColor[2], iRenderMode, flAmount);

    if(iRenderFx == kRenderFxGlowShell && flColor[0] == 141.0 && flColor[1] == 14.0 && flColor[2] == 246.0 && iRenderMode == kRenderNormal && !flAmount)
        rg_set_rendering(id, kRenderFxGlowShell, 0.0, 0.0, 0.0, kRenderNormal, 0.0);

    set_entvar(id, var_flags, get_entvar(id, var_flags) & ~FL_FROZEN);
    func_ScreenFade(id, 0, 0, 0, 0, 0, 0, 0, 1);
}

func_ElectroSound(Float:flOrigin[3])
{
    new iEnt = rg_create_entity("info_target", true);
    set_entvar(iEnt, var_origin, flOrigin);
    rh_emit_sound2(iEnt, 0, CHAN_WEAPON, g_szSoundDamage, VOL_NORM, ATTN_NORM, 0, PITCH_NORM);
    set_entvar(iEnt, var_flags, FL_KILLME);
}

func_ElectroRing(const Float:flOrigin[3])
{
    message_begin_f(MSG_PVS, SVC_TEMPENTITY, flOrigin);
    write_byte(TE_BEAMCYLINDER);
    write_coord_f(flOrigin[0]);
    write_coord_f(flOrigin[1]);
    write_coord_f(flOrigin[2]);
    write_coord_f(flOrigin[0]);
    write_coord_f(flOrigin[1]);
    write_coord_f(flOrigin[2] + 100.0);
    write_short(g_pSpriteElectro);
    write_byte(0);
    write_byte(0);
    write_byte(4);
    write_byte(60);
    write_byte(0);
    write_byte(41);
    write_byte(148);
    write_byte(255);
    write_byte(200);
    write_byte(0);
    message_end();
}

func_ShowWeaponList(id, bool:bShow)
{
    message_begin(MSG_ONE, g_iMsgWeaponList, .player = id);
    {
        if(bShow)
            write_string("weapon_taser");        // WeaponName
        else
            write_string(g_szWeaponName);        // WeaponName
        write_byte(-1);                        // PrimaryAmmoID
        write_byte(-1);                        // PrimaryAmmoMaxAmount
        write_byte(-1);                        // SecondaryAmmoID
        write_byte(-1);                        // SecondaryAmmoMaxAmount
        write_byte(2);                        // SlotID (0...N)
        write_byte(1);                        // NumberInSlot (1...N)
        write_byte(CSW_KNIFE);                // WeaponID
        write_byte(0);                        // Flags
    }
    message_end();
}

stock func_GetWeaponBoxWeapon(const iWeaponBox)
{
    for(new i, iWeapon; i < MAX_ITEM_TYPES; i++)
    {
        iWeapon = get_member(iWeaponBox, m_WeaponBox_rgpPlayerItems, i);
        if(!is_nullent(iWeapon))
            return iWeapon;
    }
    return NULLENT;
}

stock func_SendWeaponAnimation(const id, const iAnimation)
{
    set_entvar(id, var_weaponanim, iAnimation);

    message_begin(MSG_ONE_UNRELIABLE, SVC_WEAPONANIM, .player = id);
    write_byte(iAnimation);
    write_byte(0);
    message_end();
}

stock func_ScreenFade(id, iDuration, iHoldTime, iFlags, iRed, iGreen, iBlue, iAlpha, iReliable = 0)
{
    if(id)
        message_begin(iReliable ? MSG_ONE : MSG_ONE_UNRELIABLE, g_iMsgScreenFade, .player = id);
    else
        message_begin(iReliable ? MSG_ALL : MSG_BROADCAST, g_iMsgScreenFade);

    write_short(iDuration);
    write_short(iHoldTime);
    write_short(iFlags);
    write_byte(iRed);
    write_byte(iGreen);
    write_byte(iBlue);
    write_byte(iAlpha);
    message_end();
}

// Получаем всю информацию о свечении игрока
stock rg_get_rendering(id, &iRenderFx = kRenderFxNone, &Float:flRed = 0.0, &Float:flGreen = 0.0, &Float:flBlue = 0.0, &iRenderMode = kRenderNormal, &Float:flAmount = 0.0)
{
    new Float:flRenderColor[3];
    get_entvar(id, var_rendercolor, flRenderColor);

    iRenderFx = get_entvar(id, var_renderfx);

    flRed = flRenderColor[0];
    flGreen = flRenderColor[1];
    flBlue = flRenderColor[2];

    iRenderMode = get_entvar(id, var_rendermode);
    flAmount = get_entvar(id, var_renderamt);
}

stock rg_set_rendering(iEnt, iRenderFx = kRenderFxNone, Float:flRed, Float:flGreen, Float:flBlue, iRender = kRenderNormal, Float:flAmount)
{
    new Float:flRenderColor[3];
    flRenderColor[0] = flRed;
    flRenderColor[1] = flGreen;
    flRenderColor[2] = flBlue;

    set_entvar(iEnt, var_renderfx, iRenderFx);
    set_entvar(iEnt, var_rendercolor, flRenderColor);
    set_entvar(iEnt, var_rendermode, iRender);
    set_entvar(iEnt, var_renderamt, flAmount);

    return 1;
}

/****************************************************************************************
****************************************************************************************/

public fmfwd_RemoveEntity_Pre(const iEnt)
{
    if(!is_entity(iEnt) || !IsCustomWeapon(iEnt))
        return FMRES_IGNORED;

    if(!(--g_iActiveWeapons))
        func_ManageHooks(false);

    return FMRES_IGNORED;
}

#if WEAPON_ID != WEAPON_KNIFE
public refwd_PlayerDropPlayerItem_Post(const id, const pszItemName[])
{
    new iEnt = GetHookChainReturn(ATYPE_INTEGER);

    if(!is_entity(iEnt))
        return HC_CONTINUE;

    new iWeapon = func_GetWeaponBoxWeapon(iEnt);
    if(iWeapon != NULLENT && IsCustomWeapon(iWeapon))
        EnableHookChain(g_iHookChain[HOOKCHAIN_SETMODEL_PRE]);

    return HC_CONTINUE;
}
#endif

public refwd_PlayerAddPlayerItem_Pre(const id, const pItem)
{
    DisableHookChain(g_iHookChain[HOOKCHAIN_ADDPLAYERITEM_PRE]);

    server_print("refwd_PlayerAddPlayerItem_Pre -> id: %d || pItem: %d", id, pItem);
    if(!is_entity(pItem) || !IsCustomWeapon(pItem))
        return HC_CONTINUE;

    if(++g_iActiveWeapons == 1)
        func_ManageHooks(true);

    return HC_CONTINUE;
}

func_ManageHooks(bool:bEnable)
{
    if(bEnable)
    {
        if(g_eCvar[CVAR_TOUCH_ONLY_OWNER])
            EnableHamForward(g_iHamHook[HAM_HOOK_TOUCH_PRE]);
        EnableHamForward(g_iHamHook[HAM_HOOK_DEPLOY_POST]);
    #if WEAPON_ID != WEAPON_KNIFE
        EnableHookChain(g_iHookChain[HOOKCHAIN_SETMODEL_PRE]);
    #endif
        EnableHookChain(g_iHookChain[HOOKCHAIN_SETMODEL_PRE]);
        EnableHookChain(g_iHookChain[HOOKCHAIN_TAKEDAMAGE_PRE]);
        g_iFMFwdRemoveEntityPre = register_forward(FM_RemoveEntity, "fmfwd_RemoveEntity_Pre", false);
    }
    else
    {
    #if WEAPON_ID != WEAPON_KNIFE
        DisableHookChain(g_iHookChain[HOOKCHAIN_SETMODEL_PRE]);
    #endif
        DisableHookChain(g_iHookChain[HOOKCHAIN_TAKEDAMAGE_PRE]);
        DisableHamForward(g_iHamHook[HAM_HOOK_DEPLOY_POST]);
        EnableHamForward(g_iHamHook[HAM_HOOK_TOUCH_PRE]);
        unregister_forward(FM_RemoveEntity, g_iFMFwdRemoveEntityPre);
    }
}

/****************************************************************************************
****************************************************************************************/

func_RegisterCvars()
{
    new pCvar;

    pCvar = create_cvar("custom_weapon_taser_damage", "5.0", FCVAR_NONE, GetCvarDesc("CUSTOM_WEAPON_TASER_CVAR_DAMAGE"), true, 0.0);
    bind_pcvar_float(pCvar, g_eCvar[CVAR_WEAPON_DAMAGE]);

    pCvar = create_cvar("custom_weapon_taser_cooldown", "5.0", FCVAR_NONE, GetCvarDesc("CUSTOM_WEAPON_TASER_CVAR_COOLDOWN"), true, 0.0);
    bind_pcvar_float(pCvar, g_eCvar[CVAR_WEAPON_COOLDOWN]);

#if WEAPON_ID != WEAPON_KNIFE
    pCvar = create_cvar("custom_weapon_taser_touch_only_owner", "0", FCVAR_NONE, GetCvarDesc("CUSTOM_WEAPON_CVAR_TOUCH_ONLY_OWNER"), true, 0.0, true, 1.0);
    bind_pcvar_num(pCvar, g_eCvar[CVAR_TOUCH_ONLY_OWNER]);
#endif

    AutoExecConfig(true, "custom_weapon_taser");
}

/****************************************************************************************
****************************************************************************************/

public plugin_natives()
{
    register_native("custom_give_weapon_taser",    "__custom_give_weapon_taser");
}

public __custom_give_weapon_taser(iPlugin, iParams)
{
    enum { player = 1, replaceitem };

    new id = get_param(player);

    if(!IsUserValid(id))
        abort(AMX_ERR_NATIVE, "Player out of range (%i)", id);

    new bool:bReplace = bool:get_param(replaceitem);

    func_CmdGiveWeapon(id, bReplace);
}
 
Последнее редактирование:
Сообщения
1,661
Реакции
1,486
Помог
24 раз(а)
Хука на скорость я не вижу почему-то.
 
Сообщения
1,661
Реакции
1,486
Помог
24 раз(а)
Ну какое ж это кастомное оружие если скорость нельзя поменять.
 
Сообщения
1,419
Реакции
2,508
Помог
59 раз(а)
Ну какое ж это кастомное оружие если скорость нельзя поменять.
Про скорость оружия только вчера фантом напомнил, я и забыл вообще. Да и отдачу тоже можно править. Надо бы тоже пример сделать с этим.
 
Сообщения
1,661
Реакции
1,486
Помог
24 раз(а)
Код:
RegisterHam(Ham_CS_Item_GetMaxSpeed, sEntity, "@CWeapon__GetMaxSpeed_Pre", false);

@CWeapon__GetMaxSpeed_Pre(iEntity)
{
    if (!IsValidSkinImpulse(iEntity))
        return HAM_IGNORED;

    SetHamReturnFloat(Float:get_entvar(iEntity, var_maxspeed));
    return HAM_OVERRIDE;
}
Не подведи меня.

Скорость можно при выдаче записать, либо сразу выставлять.
 
Сообщения
1,419
Реакции
2,508
Помог
59 раз(а)
Код:
RegisterHam(Ham_CS_Item_GetMaxSpeed, sEntity, "@CWeapon__GetMaxSpeed_Pre", false);

@CWeapon__GetMaxSpeed_Pre(iEntity)
{
    if (!IsValidSkinImpulse(iEntity))
        return HAM_IGNORED;

    SetHamReturnFloat(Float:get_entvar(iEntity, var_maxspeed));
    return HAM_OVERRIDE;
}
Не подведи меня.

Скорость можно при выдаче записать, либо сразу выставлять.
А, так ты про скорость игрока когда держит кастом оружие. В примере fantom уже есть такое. Я имел ввиду скорость стрельбы с оружия, отдача и так далее.
 
Сообщения
11
Реакции
0
Помог
1 раз(а)
Почему бы не заменить FM_RemoveEntity на Ham_RemovePlayerItem для g_szWeaponName и Ham_Item_Kill для "weaponbox"?
 
Сообщения
2,491
Реакции
2,790
Помог
61 раз(а)
w0w мб захочешь, то напишешь полностью независимый плагин с АПИ, который позволит каждому зарегистрировать кастомные оружия. Также лучше если там можно будет заодно менять звуки выстрелов, анимации. А тортиком на вишенке будет возможность использовать собственные выстрелы (лук/арбалет/пейнтбол/гранатомет). Помню где-то пробегало подобное в зомби модах. Было бы не плохо в перспективе.
 
Сообщения
52
Реакции
78
fantom, звуки, анимации - редактируются в самой модели. Если звуки можно заменить при помощи ивента(непосредственно в самом .qc файле), то анимации при помощи кода никак изменить нельзя, только созданием новых в ручную. По поводу этого:
А тортиком на вишенке будет возможность использовать собственные выстрелы (лук/арбалет/пейнтбол/гранатомет). Помню где-то пробегало подобное в зомби модах. Было бы не плохо в перспективе.
Я не совсем понял, что Вы имеете ввиду.
 
Последнее редактирование:
Сообщения
1,419
Реакции
2,508
Помог
59 раз(а)
w0w мб захочешь, то напишешь полностью независимый плагин с АПИ, который позволит каждому зарегистрировать кастомные оружия. Также лучше если там можно будет заодно менять звуки выстрелов, анимации. А тортиком на вишенке будет возможность использовать собственные выстрелы (лук/арбалет/пейнтбол/гранатомет). Помню где-то пробегало подобное в зомби модах. Было бы не плохо в перспективе.
Пока нет и представления как это можно было бы сделать, но возможно конечно и облегчило бы работу. Сейчас функциональная пушка не очень сложного характера выходит где-то в 1.5к строк кода, скоро думаю выложу как закончу. А так нет времени чтобы что-то объемное сейчас делать.

звуки, анимации - редактируются в самой модели. Если звуки можно заменить при помощи ивента(непосредственно в самом .qc файле), то анимации при помощи кода никак изменить нельзя, только созданием новых в ручную.
Никто и не говорит про создание звуков прямо в плагине или анимаций, просто чтобы было удобнее всё это включать или выключать. Кроме того, если я не ошибаюсь, в .qc файле нельзя заменять звук.

Я не совсем понял, что Вы имеете ввиду.
Ну если в модели есть свои звуки, то можно будет их включить.
 
Сообщения
52
Реакции
78
w0w, fantom написал про "замену" звуков и анимаций. Я знаю, что с помощью скриптинга можно включать/выключать многое, но чтобы менять то, что на прямую не зависит от кода :scratch_one-s_head:Т.к. не разбираюсь в PAWN'е, многого написать не могу.
По поводу замены звуков модели в .qc файле:
Путь.png
Вызываем событие, указываем на каком кадре должен проигрываться звук и путь до него.
 
Сообщения
2,491
Реакции
2,790
Помог
61 раз(а)
Quasar, w0w, я всего то навсего имел ввиду предоставить возможность делать проще кастомные оружия. Чтобы не быо 100500 плагинов копипасты. А один, который предоставляет АПИ. А как оно там будет внутри уже вопрос реализации
 
Сообщения
1,419
Реакции
2,508
Помог
59 раз(а)
Quasar, w0w, я всего то навсего имел ввиду предоставить возможность делать проще кастомные оружия. Чтобы не быљо 100500 плагинов копипасты. А один, который предоставляет АПИ. А как оно там будет внутри уже вопрос реализации
Да, в этом и главная проблема в принципе, нужно продумывать как это всё реализовать.
 

Пользователи, просматривающие эту тему

Сейчас на форуме нет ни одного пользователя.
Сверху Снизу