diff --git a/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc b/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc index 56930ec..03d4865 100644 --- a/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc +++ b/reapi/extra/amxmodx/scripting/include/reapi_gamedll.inc @@ -357,17 +357,19 @@ native rg_set_user_armor(const index, armorvalue, ArmorType:armortype); /* * Sets the client's team without killing the player, and sets the client model. +* @note To obtain of TeamName use the following: +* new TeamName:team = get_member(id, m_iTeam); * * @param index Client index * @param team Team id -* @param model Internal model +* @param model Internal model, use MODEL_AUTO for a random appearance or if MODEL_UNASSIGNED not update it. * * @param send_teaminfo If true, a TeamInfo message will be sent * -* @noreturn +* @return 1 if successfully, 0 otherwise * */ -native rg_set_user_team(const index, {TeamName,_}:team, {ModelName,_}:model = MODEL_UNASSIGNED, bool:send_teaminfo = true); +native rg_set_user_team(const index, {TeamName,_}:team, {ModelName,_}:model = MODEL_AUTO, bool:send_teaminfo = true); /* * Sets the client's player model. @@ -376,7 +378,7 @@ native rg_set_user_team(const index, {TeamName,_}:team, {ModelName,_}:model = MO * @param model Model name * @param update_index If true, the modelindex is updated as well * -* @noreturn +* @return 1 if successfully, 0 otherwise * */ native rg_set_user_model(const index, const model[], bool:update_index = false); @@ -386,7 +388,18 @@ native rg_set_user_model(const index, const model[], bool:update_index = false); * * @param index Client index * -* @noreturn +* @return 1 if successfully, 0 otherwise * */ native rg_reset_user_model(const index); + +/* +* Transfer C4 to player +* +* @param index Client index +* @param receiver Receiver index, if 0 so will transfer a random to player +* +* @return 1 if successfully, 0 otherwise +* +*/ +native rg_transfer_c4(const index, const receiver = 0); diff --git a/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc b/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc index 461def8..e5ed5a0 100644 --- a/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc +++ b/reapi/extra/amxmodx/scripting/include/reapi_gamedll_const.inc @@ -101,7 +101,8 @@ enum ModelName MODEL_T_GUERILLA, MODEL_CT_VIP, MODEL_T_MILITIA, - MODEL_CT_SPETSNAZ + MODEL_CT_SPETSNAZ, + MODEL_AUTO }; enum diff --git a/reapi/include/cssdk/dlls/player.h b/reapi/include/cssdk/dlls/player.h index 6d1854b..44fece9 100644 --- a/reapi/include/cssdk/dlls/player.h +++ b/reapi/include/cssdk/dlls/player.h @@ -148,7 +148,7 @@ enum RewardType RT_VIP_RESCUED_MYSELF }; -typedef enum +enum PLAYER_ANIM { PLAYER_IDLE, PLAYER_WALK, @@ -161,10 +161,9 @@ typedef enum PLAYER_LARGE_FLINCH, PLAYER_RELOAD, PLAYER_HOLDBOMB +}; -} PLAYER_ANIM; - -typedef enum +enum _Menu { Menu_OFF, Menu_ChooseTeam, @@ -181,19 +180,17 @@ typedef enum Menu_Radio2, Menu_Radio3, Menu_ClientBuy +}; -} _Menu; - -typedef enum +enum TeamName { UNASSIGNED, TERRORIST, CT, SPECTATOR, +}; -} TeamName; - -typedef enum +enum ModelName { MODEL_UNASSIGNED, MODEL_URBAN, @@ -206,11 +203,11 @@ typedef enum MODEL_GUERILLA, MODEL_VIP, MODEL_MILITIA, - MODEL_SPETSNAZ + MODEL_SPETSNAZ, + MODEL_AUTO +}; -} ModelName; - -typedef enum +enum JoinState { JOINED, SHOWLTEXT, @@ -219,9 +216,9 @@ typedef enum PICKINGTEAM, GETINTOGAME -} JoinState; +}; -typedef enum +enum TrackCommands { CMD_SAY = 0, CMD_SAYTEAM, @@ -233,9 +230,9 @@ typedef enum CMD_NIGHTVISION, COMMANDS_TO_TRACK, -} TrackCommands; +}; -typedef struct +struct RebuyStruct { int m_primaryWeapon; int m_primaryAmmo; @@ -248,9 +245,9 @@ typedef struct int m_nightVision; int m_armor; -} RebuyStruct; +}; -typedef enum +enum ThrowDirection { THROW_NONE, THROW_FORWARD, @@ -260,7 +257,7 @@ typedef enum THROW_GRENADE, THROW_HITVEL_MINUS_AIRVEL -} ThrowDirection; +}; enum sbar_data { @@ -270,13 +267,7 @@ enum sbar_data SBAR_END }; -typedef enum -{ - SILENT, - CALM, - INTENSE - -} MusicState; +enum MusicState { SILENT, CALM, INTENSE }; class CCSPlayer; diff --git a/reapi/src/natives/natives_misc.cpp b/reapi/src/natives/natives_misc.cpp index e428a49..ff89c22 100644 --- a/reapi/src/natives/natives_misc.cpp +++ b/reapi/src/natives/natives_misc.cpp @@ -928,16 +928,18 @@ cell AMX_NATIVE_CALL rg_set_user_armor(AMX *amx, cell *params) /* * Sets the client's team without killing the player, and sets the client model. +* @note To obtain of TeamName use the following: +* new TeamName:team = get_member(id, m_iTeam); * * @param index Client index * @param team Team id -* @param model Internal model +* @param model Internal model, use MODEL_AUTO for a random appearance or if MODEL_UNASSIGNED not update it. * * @param send_teaminfo If true, a TeamInfo message will be sent * -* @noreturn +* @return 1 if successfully, 0 otherwise * -* native rg_set_user_team(const index, {TeamName,_}:team, {ModelName,_}:model = MODEL_UNASSIGNED, bool:send_teaminfo = true); +* native rg_set_user_team(const index, {TeamName,_}:team, {ModelName,_}:model = MODEL_AUTO, bool:send_teaminfo = true); */ cell AMX_NATIVE_CALL rg_set_user_team(AMX *amx, cell *params) { @@ -973,7 +975,7 @@ cell AMX_NATIVE_CALL rg_set_user_team(AMX *amx, cell *params) CSGameRules()->m_iNumTerrorist--; if (pPlayer->m_bHasC4 && !CSGameRules()->m_fTeamCount && CSGameRules()->m_bMapHasBombTarget) { - if (RemovePlayerItem(pPlayer, "weapon_c4")) { + if (CSGameRules()->m_iNumTerrorist > 0 && RemovePlayerItem(pPlayer, "weapon_c4")) { pPlayer->m_bHasC4 = false; pPlayer->pev->body = 0; @@ -983,6 +985,8 @@ cell AMX_NATIVE_CALL rg_set_user_team(AMX *amx, cell *params) MESSAGE_END(); CSGameRules()->GiveC4(); + } else if (pPlayer->IsAlive()) {// are still alive + pPlayer->CSPlayer()->DropPlayerItem("weapon_c4"); } } break; @@ -1003,11 +1007,15 @@ cell AMX_NATIVE_CALL rg_set_user_team(AMX *amx, cell *params) } } - if (args[arg_model] != MODEL_UNASSIGNED) { - pPlayer->m_iModelName = args[arg_model]; - } + if (args[arg_model] > MODEL_UNASSIGNED) { + if (args[arg_model] != MODEL_AUTO) { + pPlayer->m_iModelName = args[arg_model]; + } else { + pPlayer->m_iModelName = GetModelAuto(pPlayer->m_iTeam); + } - pPlayer->CSPlayer()->SetPlayerModel(pPlayer->m_bHasC4); + pPlayer->CSPlayer()->SetPlayerModel(pPlayer->m_bHasC4); + } if (params[arg_sendinfo] != 0) { MESSAGE_BEGIN(MSG_ALL, gmsgTeamInfo); @@ -1027,7 +1035,7 @@ cell AMX_NATIVE_CALL rg_set_user_team(AMX *amx, cell *params) * @param model Model name * @param update_index If true, the modelindex is updated as well * -* @noreturn +* @return 1 if successfully, 0 otherwise * * native rg_set_user_model(const index, const model[], bool:update_index = false); */ @@ -1067,7 +1075,7 @@ cell AMX_NATIVE_CALL rg_set_user_model(AMX *amx, cell *params) * * @param index Client index * -* @noreturn +* @return 1 if successfully, 0 otherwise * * native rg_reset_user_model(const index); */ @@ -1085,6 +1093,66 @@ cell AMX_NATIVE_CALL rg_reset_user_model(AMX *amx, cell *params) pPlayer->CSPlayer()->SetPlayerModelEx(""); pPlayer->CSPlayer()->SetPlayerModel(pPlayer->m_bHasC4); + return TRUE; +} + +/* +* Transfer C4 to player +* +* @param index Client index +* @param receiver Receiver index, if 0 so will transfer a random to player +* +* @return 1 if successfully, 0 otherwise +* +* native rg_transfer_c4(const index, const receiver = 0); +*/ +cell AMX_NATIVE_CALL rg_transfer_c4(AMX *amx, cell *params) +{ + enum args_e { arg_count, arg_index, arg_receiver }; + + CHECK_ISPLAYER(arg_index); + + CBasePlayer *pPlayer = g_ReGameFuncs->UTIL_PlayerByIndex(params[arg_index]); + if (pPlayer == nullptr || pPlayer->has_disconnected) { + MF_LogError(amx, AMX_ERR_NATIVE, "%s: player %i is not connected", __FUNCTION__, params[arg_index]); + return FALSE; + } + + if (!pPlayer->m_bHasC4 || !RemovePlayerItem(pPlayer, "weapon_c4")) + return FALSE; + + pPlayer->m_bHasC4 = false; + pPlayer->pev->body = 0; + + MESSAGE_BEGIN(MSG_ONE, gmsgStatusIcon, NULL, pPlayer->pev); + WRITE_BYTE(STATUSICON_HIDE); + WRITE_STRING("c4"); + MESSAGE_END(); + + if (params[arg_receiver] != 0 && params[arg_receiver] <= gpGlobals->maxClients) { + CBasePlayer *pReceiver = g_ReGameFuncs->UTIL_PlayerByIndex(params[arg_receiver]); + if (pReceiver == nullptr || pReceiver->has_disconnected) { + MF_LogError(amx, AMX_ERR_NATIVE, "%s: player %i is not connected", __FUNCTION__, params[arg_receiver]); + return FALSE; + } + + pReceiver->m_bHasC4 = true; + pReceiver->pev->body = 1; + pReceiver->CSPlayer()->GiveNamedItemEx("weapon_c4"); + + MESSAGE_BEGIN(MSG_ONE, gmsgStatusIcon, NULL, pReceiver->pev); + WRITE_BYTE(STATUSICON_SHOW); + WRITE_STRING("c4"); + WRITE_BYTE(0); + WRITE_BYTE(160); + WRITE_BYTE(0); + MESSAGE_END(); + } else { + auto flags = pPlayer->pev->flags; + pPlayer->pev->flags |= FL_DORMANT; + CSGameRules()->GiveC4(); + pPlayer->pev->flags = flags; + } return TRUE; } @@ -1131,6 +1199,8 @@ AMX_NATIVE_INFO Misc_Natives_RG[] = { "rg_set_user_model", rg_set_user_model }, { "rg_reset_user_model", rg_reset_user_model }, + { "rg_transfer_c4", rg_transfer_c4 }, + { nullptr, nullptr } }; diff --git a/reapi/src/reapi_utils.cpp b/reapi/src/reapi_utils.cpp index 8503161..8dff8eb 100644 --- a/reapi/src/reapi_utils.cpp +++ b/reapi/src/reapi_utils.cpp @@ -63,3 +63,34 @@ void SendItemStatus(CBasePlayer *pPlayer) WRITE_BYTE(itemStatus); MESSAGE_END(); } + +struct { + TeamName team; + ModelName model; + +} modelStruct[] = { + { TERRORIST, MODEL_TERROR }, + { TERRORIST, MODEL_LEET }, + { TERRORIST, MODEL_ARCTIC }, + { TERRORIST, MODEL_GUERILLA }, + { CT, MODEL_URBAN }, + { CT, MODEL_GSG9 }, + { CT, MODEL_GIGN }, + { CT, MODEL_SAS }, +}; + +ModelName GetModelAuto(TeamName team) +{ + int cur = 0; + const int numSkin = 4; + for (auto& it : modelStruct) { + if (it.team != team) { + ++cur; + continue; + } + + return modelStruct[RANDOM_LONG(cur, cur + numSkin - 1)].model; + } + + return MODEL_UNASSIGNED; +} diff --git a/reapi/src/reapi_utils.h b/reapi/src/reapi_utils.h index 576387f..637c369 100644 --- a/reapi/src/reapi_utils.h +++ b/reapi/src/reapi_utils.h @@ -121,5 +121,6 @@ void Broadcast(const char *sentence); void UpdateTeamScores(); bool RemovePlayerItem(CBasePlayer *pPlayer, const char* szItemName); void SendItemStatus(CBasePlayer *pPlayer); +ModelName GetModelAuto(TeamName team); extern void __declspec(noreturn) UTIL_SysError(const char *fmt, ...);