From 799f0f8f824e1e7fe7233541ce7746f7f5739820 Mon Sep 17 00:00:00 2001 From: s1lentq Date: Sat, 21 Jan 2017 22:58:46 +0700 Subject: [PATCH] Reworked rg_give_item, now returns the index of the entity. Add native rg_get_user_footsteps, rg_set_user_footsteps, rg_remove_items_by_slot, rg_drop_item, rg_internal_cmd --- .../scripting/include/reapi_gamedll.inc | 70 ++++- reapi/src/amxxmodule.cpp | 12 +- reapi/src/member_list.cpp | 34 +-- reapi/src/member_list.h | 54 +++- reapi/src/natives/natives_members.cpp | 43 +--- reapi/src/natives/natives_misc.cpp | 239 +++++++++++++----- 6 files changed, 321 insertions(+), 131 deletions(-) diff --git a/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc b/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc index bf96a3a..21a191f 100644 --- a/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc +++ b/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc @@ -127,7 +127,7 @@ native rg_add_account(const index, amount, AccountSet:typeSet = AS_ADD, const bo * @param pszName Classname item * @param type Look at the enum's with name GiveType * -* @return 1 if successfully, 0 otherwise +* @return Index of entity if successfully, -1 otherwise */ native rg_give_item(const index, const pszName[], GiveType:type = GT_APPEND); @@ -259,7 +259,7 @@ native rg_update_teamscores(const iCtsWins = 0, const iTsWins = 0, const bool:bA /* * Creates an entity using Counter-Strike's custom CreateNamedEntity wrapper. * -* @param classname Entity class name +* @param classname Entity classname * @param useHashTable Use this only for known game entities. * NOTE: Do not use this if you use a custom classname. * @@ -338,20 +338,55 @@ native any:rg_get_weapon_info(any:...); native rg_set_weapon_info(const {WeaponIdType,_}:weapon_id, WpnInfo:type, any:...); /* -* Remove all the player's stuff +* Remove all the player's stuff by specific slot. * * @param index Client index +* @param slot Specific slot for remove of each item. * -* @noreturn +* @return 1 if successfully, 0 otherwise * */ -native rg_remove_all_items(const index, const bool:bRemoveSuit = false); +native rg_remove_items_by_slot(const index, const InventorySlotType:slot); /* -* Remove specifed the player's item by class name +* Remove all the player's stuff. * * @param index Client index -* @param item_name Class name item +* @param removeSuit Remove suit +* +* @return 1 if successfully, 0 otherwise +* +*/ +native rg_remove_all_items(const index, const bool:removeSuit = false); + +/* +* Drop specifed the player's item by classname. +* +* @param index Client index +* @param item_name Classname of item +* +* @return 1 if successfully, 0 otherwise +* +*/ +native rg_drop_item(const index, const item_name[]); + +/* +* Execute a client command on the gamedll side. +* +* @param index Client index +* @param command Client command to execute on +* @param arg Optional command arguments +* +* @return 1 if successfully, 0 otherwise +* +*/ +native rg_internal_cmd(const index, const cmd[], const arg[] = ""); + +/* +* Remove specifed the player's item by classname +* +* @param index Client index +* @param item_name Classname of item * * @return 1 if found and remove, 0 otherwise * @@ -456,6 +491,27 @@ native rg_set_user_model(const index, const model[], const bool:update_index = f */ native rg_reset_user_model(const index); +/* +* Enable/Disable footsteps of the player. +* +* @param index Client index +* @param silent To enable silent footsteps of player's +* +* @return 1 if successfully, 0 otherwise +* +*/ +native rg_set_user_footsteps(const index, bool:silent = false); + +/* +* Get the current state footsteps of the player. +* +* @param index Client index +* +* @return 1 if have silent footsteps, 0 otherwise +* +*/ +native rg_get_user_footsteps(const index); + /* * Transfer C4 to player * diff --git a/reapi/src/amxxmodule.cpp b/reapi/src/amxxmodule.cpp index 61611d6..354f2b6 100644 --- a/reapi/src/amxxmodule.cpp +++ b/reapi/src/amxxmodule.cpp @@ -42,7 +42,7 @@ static struct funcreq_t //DECLARE_REQ(BuildPathname), //DECLARE_REQ(BuildPathnameR), DECLARE_REQ(GetAmxAddr), - //DECLARE_REQ(GetAmxVectorNull), + //DECLARE_REQ(GetAmxVectorNull), // AMXX 1.8.3-dev //DECLARE_REQ(PrintSrvConsole), //DECLARE_REQ(GetModname), DECLARE_REQ(GetAmxScriptName), @@ -50,10 +50,10 @@ static struct funcreq_t DECLARE_REQ(FindAmxScriptByAmx), //DECLARE_REQ(FindAmxScriptByName), DECLARE_REQ(SetAmxString), - //DECLARE_REQ(SetAmxStringUTF8Char), - //DECLARE_REQ(SetAmxStringUTF8Cell), + //DECLARE_REQ(SetAmxStringUTF8Char), // AMXX 1.8.3-dev + //DECLARE_REQ(SetAmxStringUTF8Cell), // AMXX 1.8.3-dev DECLARE_REQ(GetAmxString), - //DECLARE_REQ(GetAmxStringNull), + //DECLARE_REQ(GetAmxStringNull), // AMXX 1.8.3-dev //DECLARE_REQ(GetAmxStringLen), //DECLARE_REQ(FormatAmxString), //DECLARE_REQ(CopyAmxMemory), @@ -97,7 +97,7 @@ static struct funcreq_t DECLARE_REQ(RegisterSPForward), DECLARE_REQ(RegisterSPForwardByName), DECLARE_REQ(UnregisterSPForward), - //DECLARE_REQ(MergeDefinition_File), + //DECLARE_REQ(MergeDefinitionFile), //DECLARE_REQ(amx_FindNative), //DECLARE_REQ(GetPlayerFlags), //DECLARE_REQ(GetPlayerEdict), @@ -114,7 +114,7 @@ static struct funcreq_t //DECLARE_REQ(RemoveLibraries), //DECLARE_REQ(OverrideNatives), //DECLARE_REQ(GetLocalInfo), - //DECLARE_REQ(AmxReRegister), + //DECLARE_REQ(AmxReregister), //DECLARE_REQ(RegisterFunctionEx), //DECLARE_REQ(MessageBlock), }; diff --git a/reapi/src/member_list.cpp b/reapi/src/member_list.cpp index 95d4d5c..f9675e4 100644 --- a/reapi/src/member_list.cpp +++ b/reapi/src/member_list.cpp @@ -8,24 +8,24 @@ #define decltypefx(cx, pref, dt, mx) decltype(cx::pref##mx) #endif -#define CLASS_MEMBERS(cx, mx, postf, pref) ((!(postf & (MAX_REGION_RANGE - 1)) ? regmember::current_cell = 1, true : false) || (postf & (MAX_REGION_RANGE - 1)) == regmember::current_cell++) ? regmember([](member_t* ptr){ decltypefx(cx, pref, ., mx) f = {};ptr->size = getTypeSize(f);ptr->max_size = sizeof(f);ptr->offset = offsetof(##cx, ##pref##mx);ptr->type = getMemberType(f);ptr->name = #postf;}) : regmember(#pref#mx) +#define CLASS_MEMBERS(cx, mx, postf, pref, mtbl) ((!(postf & (MAX_REGION_RANGE - 1)) ? regmember::current_cell = 1, true : false) || (postf & (MAX_REGION_RANGE - 1)) == regmember::current_cell++) ? regmember([](member_t* ptr){ decltypefx(cx, pref, ., mx) f = {};ptr->size = getTypeSize(f);ptr->max_size = sizeof(f);ptr->offset = offsetof(##cx, ##pref##mx);ptr->type = getMemberType(f);ptr->name = #postf;ptr->table = memberlist_t::members_tables_e::mtbl;}) : regmember(#pref#mx) -#define GM_MEMBERS(mx) CLASS_MEMBERS(CHalfLifeMultiplay, mx, mx,) -#define GM_VOICE_MEMBERS(mx) CLASS_MEMBERS(CHalfLifeMultiplay, mx, mx, m_VoiceGameMgr.) -#define BASE_MEMBERS(mx) CLASS_MEMBERS(CBaseEntity, mx, mx,) -#define ANIM_MEMBERS(mx) CLASS_MEMBERS(CBaseAnimating, mx, mx,) -#define MONST_MEMBERS(mx) CLASS_MEMBERS(CBaseMonster, mx, mx,) -#define PL_MEMBERS(mx) CLASS_MEMBERS(CBasePlayer, mx, mx,) -#define EVAR_MEMBERS(mx) CLASS_MEMBERS(com_entvars, mx, var_##mx,) -#define PMOVE_MEMBERS(mx) CLASS_MEMBERS(com_playermove, mx, pm_##mx,) -#define MOVEVAR_MEMBERS(mx) CLASS_MEMBERS(movevars_t, mx, mv_##mx,) -#define UCMD_MEMBERS(mx) CLASS_MEMBERS(usercmd_s, mx, ucmd_##mx,) -#define PMTRACE_MEMBERS(mx) CLASS_MEMBERS(pmtrace_s, mx, pmt_##mx,) -#define CSPL_MEMBERS(mx) CLASS_MEMBERS(CCSPlayer, mx, mx,) -#define BASEITEM_MEMBERS(mx) CLASS_MEMBERS(CBasePlayerItem, mx, mx,) -#define BASEWPN_MEMBERS(mx) CLASS_MEMBERS(CBasePlayerWeapon, mx, m_Weapon_##mx, m_) -#define WPNBOX_MEMBERS(mx) CLASS_MEMBERS(CWeaponBox_COM, mx, m_WeaponBox_##mx, m_) -#define ARMOURY_MEMBERS(mx) CLASS_MEMBERS(CArmoury, mx, m_Armoury_##mx, m_) +#define GM_MEMBERS(mx) CLASS_MEMBERS(CHalfLifeMultiplay, mx, mx, , mt_gamerules) +#define GM_VOICE_MEMBERS(mx) CLASS_MEMBERS(CHalfLifeMultiplay, mx, mx, m_VoiceGameMgr., mt_gamerules) +#define BASE_MEMBERS(mx) CLASS_MEMBERS(CBaseEntity, mx, mx, , mt_base) +#define ANIM_MEMBERS(mx) CLASS_MEMBERS(CBaseAnimating, mx, mx, , mt_animating) +#define MONST_MEMBERS(mx) CLASS_MEMBERS(CBaseMonster, mx, mx, , mt_basemonster) +#define PL_MEMBERS(mx) CLASS_MEMBERS(CBasePlayer, mx, mx, , mt_player) +#define EVAR_MEMBERS(mx) CLASS_MEMBERS(com_entvars, mx, var_##mx, , mt_entvars) +#define PMOVE_MEMBERS(mx) CLASS_MEMBERS(com_playermove, mx, pm_##mx, , mt_playermove) +#define MOVEVAR_MEMBERS(mx) CLASS_MEMBERS(movevars_t, mx, mv_##mx, , mt_movevars) +#define UCMD_MEMBERS(mx) CLASS_MEMBERS(usercmd_s, mx, ucmd_##mx, , mt_usercmd) +#define PMTRACE_MEMBERS(mx) CLASS_MEMBERS(pmtrace_s, mx, pmt_##mx, , mt_pmtrace) +#define CSPL_MEMBERS(mx) CLASS_MEMBERS(CCSPlayer, mx, mx, , mt_csplayer) +#define BASEITEM_MEMBERS(mx) CLASS_MEMBERS(CBasePlayerItem, mx, mx, , mt_baseitem) +#define BASEWPN_MEMBERS(mx) CLASS_MEMBERS(CBasePlayerWeapon, mx, m_Weapon_##mx, m_, mt_baseweapon) +#define WPNBOX_MEMBERS(mx) CLASS_MEMBERS(CWeaponBox_COM, mx, m_WeaponBox_##mx, m_, mt_weaponbox) +#define ARMOURY_MEMBERS(mx) CLASS_MEMBERS(CArmoury, mx, m_Armoury_##mx, m_, mt_armoury) inline MType getMemberType(float*) { return MEMBER_FLOAT; } inline MType getMemberType(float) { return MEMBER_FLOAT; } diff --git a/reapi/src/member_list.h b/reapi/src/member_list.h index a6a82d5..ef8e390 100644 --- a/reapi/src/member_list.h +++ b/reapi/src/member_list.h @@ -26,18 +26,9 @@ enum MType MEBMER_USERCMD, // struct usercmd_s }; -struct member_t -{ - uint16 size; - uint16 max_size; - uint32 offset; - const char *name; - MType type; -}; - struct memberlist_t { - member_t *operator[](size_t members) const; + struct member_t *operator[](size_t members) const; enum members_tables_e { @@ -59,6 +50,49 @@ struct memberlist_t }; }; +struct member_t +{ + bool hasTable(memberlist_t::members_tables_e tbl) const; + bool isTypeReturnable() const; + + uint16 size; + uint16 max_size; + uint32 offset; + const char *name; + MType type; + memberlist_t::members_tables_e table; +}; + +inline bool member_t::hasTable(memberlist_t::members_tables_e tbl) const +{ + if (likely(table != tbl)) + return false; + + return true; +} + +inline bool member_t::isTypeReturnable() const +{ + switch (type) { + case MEMBER_FLOAT: + case MEMBER_DOUBLE: + case MEMBER_ENTITY: + case MEMBER_CLASSPTR: + case MEMBER_EDICT: + case MEMBER_INTEGER: + case MEMBER_SHORT: + case MEMBER_BYTE: + case MEMBER_BOOL: + case MEMBER_EVARS: + case MEMBER_PMTRACE: + case MEBMER_USERCMD: + return true; + + default: + return false; + } +} + extern memberlist_t memberlist; // CSGameRules diff --git a/reapi/src/natives/natives_members.cpp b/reapi/src/natives/natives_members.cpp index b1507c4..5f32709 100644 --- a/reapi/src/natives/natives_members.cpp +++ b/reapi/src/natives/natives_members.cpp @@ -20,10 +20,9 @@ cell AMX_NATIVE_CALL set_member(AMX *amx, cell *params) cell* value = getAmxAddr(amx, params[arg_value]); size_t element = (PARAMS_COUNT == 4) ? *getAmxAddr(amx, params[arg_elem]) : 0; - const auto table = memberlist_t::members_tables_e(params[arg_member] / MAX_REGION_RANGE); - if (table == memberlist_t::mt_csplayer) { - CBasePlayer *pPlayer = UTIL_PlayerByIndex(indexOfEdict(pEdict)); - if (unlikely(!pPlayer || !pPlayer->CSPlayer())) { + if (member->hasTable(memberlist_t::mt_csplayer)) { + CBasePlayer *pPlayer = (CBasePlayer *)pEdict->pvPrivateData; + if (unlikely(pPlayer->CSPlayer() == nullptr)) { return FALSE; } @@ -69,8 +68,7 @@ cell AMX_NATIVE_CALL get_member(AMX *amx, cell *params) case 3: { cell* arg3 = getAmxAddr(amx, params[arg_3]); - - if (isTypeReturnable(member->type)) { + if (member->isTypeReturnable()) { dest = nullptr; element = *arg3; } @@ -88,10 +86,9 @@ cell AMX_NATIVE_CALL get_member(AMX *amx, cell *params) break; } - const auto table = memberlist_t::members_tables_e(params[arg_member] / MAX_REGION_RANGE); - if (table == memberlist_t::mt_csplayer) { - CBasePlayer *pPlayer = UTIL_PlayerByIndex(indexOfEdict(pEdict)); - if (!pPlayer || !pPlayer->CSPlayer()) { + if (member->hasTable(memberlist_t::mt_csplayer)) { + CBasePlayer *pPlayer = (CBasePlayer *)pEdict->pvPrivateData; + if (unlikely(pPlayer->CSPlayer() == nullptr)) { return FALSE; } @@ -140,7 +137,7 @@ cell AMX_NATIVE_CALL get_member_game(AMX *amx, cell *params) if (PARAMS_COUNT == 2) { cell* arg3 = getAmxAddr(amx, params[arg_2]); - if (isTypeReturnable(member->type)) { + if (member->isTypeReturnable()) { dest = nullptr; element = *arg3; } @@ -213,7 +210,7 @@ cell AMX_NATIVE_CALL get_entvar(AMX *amx, cell *params) else if (PARAMS_COUNT == 3) { cell* arg3 = getAmxAddr(amx, params[arg_3]); - if (isTypeReturnable(member->type)) + if (member->isTypeReturnable()) { if (member->type == MEMBER_FLOAT) { dest = arg3; @@ -702,25 +699,3 @@ cell get_member(void* pdata, const member_t *member, cell* dest, size_t element, return 0; } - -bool isTypeReturnable(MType type) -{ - switch (type) { - case MEMBER_FLOAT: - case MEMBER_DOUBLE: - case MEMBER_ENTITY: - case MEMBER_CLASSPTR: - case MEMBER_EDICT: - case MEMBER_INTEGER: - case MEMBER_SHORT: - case MEMBER_BYTE: - case MEMBER_BOOL: - case MEMBER_EVARS: - case MEMBER_PMTRACE: - case MEBMER_USERCMD: - return true; - - default: - return false; - } -} diff --git a/reapi/src/natives/natives_misc.cpp b/reapi/src/natives/natives_misc.cpp index 3649ac7..95aa27e 100644 --- a/reapi/src/natives/natives_misc.cpp +++ b/reapi/src/natives/natives_misc.cpp @@ -62,7 +62,7 @@ enum GiveType { GT_APPEND, GT_REPLACE, GT_DROP_AND_REPLACE }; * @param pszName Classname item * @param type Look at the enum's with name GiveType * -* @return 1 if successfully, 0 otherwise +* @return Index of entity if successfully, -1 otherwise * * native rg_give_item(index, const pszName[], GiveType:type = GT_APPEND); */ @@ -81,36 +81,38 @@ cell AMX_NATIVE_CALL rg_give_item(AMX *amx, cell *params) if (type > GT_APPEND) { auto pInfo = g_ReGameApi->GetWeaponSlot(itemName); - if (pInfo != nullptr) + if (pInfo) { - auto pItem = pPlayer->m_rgpPlayerItems[ pInfo->slot ]; - while (pItem != nullptr) { - if (pItem->m_iId == pInfo->id) { - pItem = pItem->m_pNext; - continue; - } - - switch (type) + pPlayer->ForEachItem(pInfo->slot, [pPlayer, pInfo, type](CBasePlayerItem *pItem) + { + if (pItem->m_iId != pInfo->id) { - case GT_DROP_AND_REPLACE: - pPlayer->CSPlayer()->DropPlayerItem(STRING(pItem->pev->classname)); - break; - case GT_REPLACE: - pPlayer->pev->weapons &= ~(1 << pItem->m_iId); - pPlayer->RemovePlayerItem(pItem); - pItem->Kill(); - break; - case GT_APPEND: break; - default: break; + switch (type) + { + case GT_DROP_AND_REPLACE: + pPlayer->CSPlayer()->DropPlayerItem(STRING(pItem->pev->classname)); + break; + case GT_REPLACE: + pPlayer->pev->weapons &= ~(1 << pItem->m_iId); + pPlayer->RemovePlayerItem(pItem); + pItem->Kill(); + break; + case GT_APPEND: + default: + break; + } } - pItem = pItem->m_pNext; - } + return false; + }); } } - pPlayer->CSPlayer()->GiveNamedItemEx(itemName); - return TRUE; + auto pEntity = pPlayer->CSPlayer()->GiveNamedItemEx(itemName); + if (pEntity) + return indexOfPDataAmx(pEntity); + + return AMX_NULLENT; } /* @@ -388,7 +390,7 @@ cell AMX_NATIVE_CALL rg_round_end(AMX *amx, cell *params) CHECK_GAMERULES(); - size_t winstatus = params[arg_win]; + auto winstatus = params[arg_win]; if (winstatus <= 0) { MF_LogError(amx, AMX_ERR_NATIVE, "%s: unknown win status %i", __FUNCTION__, winstatus); return FALSE; @@ -411,9 +413,7 @@ cell AMX_NATIVE_CALL rg_round_end(AMX *amx, cell *params) if (_sentence[0]) Broadcast(_sentence); - if (_message[0]) - CSGameRules()->EndRoundMessage(_message, event); - + CSGameRules()->EndRoundMessage(_message, event); CSGameRules()->TerminateRound(CAmxArg(amx, params[arg_delay]), winstatus); return TRUE; } @@ -445,7 +445,7 @@ cell AMX_NATIVE_CALL rg_update_teamscores(AMX *amx, cell *params) /* * Creates an entity using Counter-Strike's custom CreateNamedEntity wrapper. * -* @param classname Entity class name +* @param classname Entity classname * @param useHashTable Use this only for known game entities. * NOTE: Do not use this if you use a custom classname. * @@ -786,14 +786,44 @@ cell AMX_NATIVE_CALL rg_set_weapon_info(AMX *amx, cell *params) return 1; } +/* +* Remove all the player's stuff by specific slot. +* +* @param index Client index +* @param slot Specific slot for remove of each item. +* +* @return 1 if successfully, 0 otherwise +* +* native rg_remove_items_by_slot(const index, const InventorySlotType:slot); +*/ +cell AMX_NATIVE_CALL rg_remove_items_by_slot(AMX *amx, cell *params) +{ + enum args_e { arg_count, arg_index, arg_slot }; + + CHECK_ISPLAYER(arg_index); + + CBasePlayer *pPlayer = UTIL_PlayerByIndex(params[arg_index]); + CHECK_CONNECTED(pPlayer, arg_index); + + pPlayer->ForEachItem(params[arg_slot], [pPlayer](CBasePlayerItem *pItem) { + pPlayer->pev->weapons &= ~(1 << pItem->m_iId); + pPlayer->RemovePlayerItem(pItem); + pItem->Kill(); + return false; + }); + + return TRUE; +} + /* * Remove all the player's stuff * * @param index Client index +* @param removeSuit Remove suit * -* @noreturn +* @return 1 if successfully, 0 otherwise * -* native rg_remove_all_items(const index, const bool:bRemoveSuit); +* native rg_remove_all_items(const index, const bool:removeSuit = false); */ cell AMX_NATIVE_CALL rg_remove_all_items(AMX *amx, cell *params) { @@ -809,12 +839,60 @@ cell AMX_NATIVE_CALL rg_remove_all_items(AMX *amx, cell *params) } /* -* Remove specifed the player's item by class name +* Drop specifed the player's item by classname. * * @param index Client index -* @param item_name Class name item +* @param item_name Classname of item * -* @noreturn +* @return 1 if successfully, 0 otherwise +* +* native rg_drop_item(const index, const item_name[]); +*/ +cell AMX_NATIVE_CALL rg_drop_item(AMX *amx, cell *params) +{ + enum args_e { arg_count, arg_index, arg_item_name }; + + CHECK_ISPLAYER(arg_index); + + CBasePlayer *pPlayer = UTIL_PlayerByIndex(params[arg_index]); + CHECK_CONNECTED(pPlayer, arg_index); + + pPlayer->CSPlayer()->DropPlayerItem(getAmxString(amx, params[arg_item_name])); + return TRUE; +} + +/* +* Execute a client command on the gamedll side. +* +* @param index Client index +* @param command Client command to execute on +* @param arg Optional command arguments +* +* @return 1 if successfully, 0 otherwise +* +* native rg_internal_cmd(const index, const cmd[], const arg[] = ""); +*/ +cell AMX_NATIVE_CALL rg_internal_cmd(AMX *amx, cell *params) +{ + enum args_e { arg_count, arg_index, arg_cmd, arg_arg }; + + CHECK_ISPLAYER(arg_index); + + CBasePlayer *pPlayer = UTIL_PlayerByIndex(params[arg_index]); + CHECK_CONNECTED(pPlayer, arg_index); + + pPlayer->CSPlayer()->ClientCommand(getAmxString(amx, params[arg_cmd]), getAmxString(amx, params[arg_arg])); + + return TRUE; +} + +/* +* Remove specifed the player's item by classname. +* +* @param index Client index +* @param item_name Classname of item +* +* @return 1 if successfully, 0 otherwise * * native rg_remove_item(const index, const item_name[]); */ @@ -861,16 +939,12 @@ cell AMX_NATIVE_CALL rg_get_user_bpammo(AMX *amx, cell *params) return FALSE; } - for (auto pItem : pPlayer->m_rgpPlayerItems) - { - while (pItem != nullptr) - { - if (pItem->m_iId == weaponId) { - return pPlayer->m_rgAmmo[ static_cast(pItem)->m_iPrimaryAmmoType ]; - } + auto itemFound = (CBasePlayerWeapon *)pPlayer->ForEachItem([pPlayer, weaponId](CBasePlayerItem *pItem) { + return pItem->m_iId == weaponId; + }); - pItem = pItem->m_pNext; - } + if (itemFound) { + return (cell)pPlayer->m_rgAmmo[ itemFound->m_iPrimaryAmmoType ]; } return FALSE; @@ -903,17 +977,13 @@ cell AMX_NATIVE_CALL rg_set_user_bpammo(AMX *amx, cell *params) return FALSE; } - for (auto pItem : pPlayer->m_rgpPlayerItems) - { - while (pItem != nullptr) - { - if (pItem->m_iId == weaponId) { - pPlayer->m_rgAmmo[ static_cast(pItem)->m_iPrimaryAmmoType ] = params[arg_amount]; - return TRUE; - } + auto itemFound = (CBasePlayerWeapon *)pPlayer->ForEachItem([pPlayer, weaponId](CBasePlayerItem *pItem) { + return pItem->m_iId == weaponId; + }); - pItem = pItem->m_pNext; - } + if (itemFound) { + pPlayer->m_rgAmmo[ itemFound->m_iPrimaryAmmoType ] = params[arg_amount]; + return TRUE; } return FALSE; @@ -1185,6 +1255,57 @@ cell AMX_NATIVE_CALL rg_reset_user_model(AMX *amx, cell *params) return TRUE; } +/* +* Enable/Disable footsteps of the player. +* +* @param index Client index +* @param silent To enable silent footsteps of player's +* +* @return 1 if successfully, 0 otherwise +* +* native rg_set_user_footsteps(const index, bool:silent = false); +*/ +cell AMX_NATIVE_CALL rg_set_user_footsteps(AMX *amx, cell *params) +{ + enum args_e { arg_count, arg_index, arg_silent }; + + CHECK_ISPLAYER(arg_index); + + CBasePlayer *pPlayer = UTIL_PlayerByIndex(params[arg_index]); + CHECK_CONNECTED(pPlayer, arg_index); + + if (params[arg_silent]) { + pPlayer->m_flTimeStepSound = 999; + pPlayer->pev->flTimeStepSound = 999; + } else { + pPlayer->m_flTimeStepSound = 0; + pPlayer->pev->flTimeStepSound = 400; + } + + return TRUE; +} + +/* +* Get the current state footsteps of the player. +* +* @param index Client index +* +* @return 1 if have silent footsteps, 0 otherwise +* +* native rg_get_user_footsteps(const index); +*/ +cell AMX_NATIVE_CALL rg_get_user_footsteps(AMX *amx, cell *params) +{ + enum args_e { arg_count, arg_index }; + + CHECK_ISPLAYER(arg_index); + + CBasePlayer *pPlayer = UTIL_PlayerByIndex(params[arg_index]); + CHECK_CONNECTED(pPlayer, arg_index); + + return (cell)(pPlayer->m_flTimeStepSound == 999); +} + /* * Transfer C4 to player * @@ -1654,22 +1775,26 @@ AMX_NATIVE_INFO Misc_Natives_RG[] = { "rg_get_weapon_info", rg_get_weapon_info }, { "rg_set_weapon_info", rg_set_weapon_info }, + { "rg_remove_items_by_slot", rg_remove_items_by_slot }, { "rg_remove_all_items", rg_remove_all_items }, { "rg_remove_item", rg_remove_item }, + { "rg_drop_item", rg_drop_item }, + { "rg_internal_cmd", rg_internal_cmd }, + + { "rg_give_defusekit", rg_give_defusekit }, { "rg_get_user_bpammo", rg_get_user_bpammo }, { "rg_set_user_bpammo", rg_set_user_bpammo }, - { "rg_give_defusekit", rg_give_defusekit }, - { "rg_get_user_armor", rg_get_user_armor }, { "rg_set_user_armor", rg_set_user_armor }, - { "rg_set_user_team", rg_set_user_team }, - { "rg_set_user_model", rg_set_user_model }, { "rg_reset_user_model", rg_reset_user_model }, + { "rg_set_user_footsteps", rg_set_user_footsteps }, + { "rg_get_user_footsteps", rg_get_user_footsteps }, + { "rg_transfer_c4", rg_transfer_c4 }, { "rg_instant_reload_weapons", rg_instant_reload_weapons },