Cstrike: Fix defuser/nvgs not being called with CS_OnBuy and fix wrong shield CSI constants

This commit is contained in:
Arkshine 2015-09-09 01:06:54 +02:00
parent eb0222455a
commit d08e1357dd
7 changed files with 200 additions and 28 deletions

View File

@ -40,10 +40,11 @@ GetWeaponInfoFunc GetWeaponInfo;
int CurrentItemId;
bool TriggeredFromCommand;
StringHashMap<int> ItemAliasList;
// m_iTeam and m_iMenu from CBasePlayer.
TypeDescription TeamDesc;
TypeDescription MenuDesc;
// Engine global variables.
server_static_t *ServerStatic;
server_t *Server;
@ -80,16 +81,6 @@ const char *CMD_ARGV(int i)
return g_engfuncs.pfnCmd_Argv(i);
}
void OnEmitSound(edict_t *entity, int channel, const char *sample, float volume, float attenuation, int fFlags, int pitch)
{
// If shield is blocked with CS_OnBuy, we need to block the pickup sound ("items/gunpickup2.wav")
// as well played right after. Why this sound is not contained in GiveShield()?
g_pengfuncsTable->pfnEmitSound = nullptr;
RETURN_META(MRES_SUPERCEDE);
}
DETOUR_DECL_STATIC1(C_ClientCommand, void, edict_t*, pEdict) // void ClientCommand(edict_t *pEntity)
{
const char *command = CMD_ARGV(0);
@ -97,7 +88,7 @@ DETOUR_DECL_STATIC1(C_ClientCommand, void, edict_t*, pEdict) // void ClientComma
CurrentItemId = CSI_NONE;
// Purpose is to retrieve an item id based on alias name or selected item from menu,
// to be used in OnBuy* forwards.
// to be used in CS_OnBuy* forwards.
if ((ForwardOnBuyAttempt != -1 || ForwardOnBuy != -1) && command && *command)
{
int itemId = CSI_NONE;
@ -179,8 +170,41 @@ DETOUR_DECL_STATIC1(C_ClientCommand, void, edict_t*, pEdict) // void ClientComma
return;
}
// CS_OnBuy()
// -
// This forward should be called right before game gives the item.
// All items except shield, defuser and nvgs, games executes in the following order:
// GiveNamedItem -> AddAccount
// Forward is fired on GiveNamedItem.
// Shield only:
// GiveShield -> AddAccount -> EmitSound
// Forward is fired on GiveShield.
// Defusal kit only:
// m_bHasDefuser(true) -> StatusIcon -> pev_body(1) -> AddAccount -> EmitSound -> ItemStatus
// Forward is fired on StatusIcon.
// Nightvision only:
// EmitSound -> m_bHasNightVision(true) -> AddAccount -> ItemStatus
// Forward is fired on EmitSound.
TriggeredFromCommand = CurrentItemId != CSI_NONE;
if (TriggeredFromCommand)
{
if (CurrentItemId == CSI_NVGS)
{
g_pengfuncsTable->pfnEmitSound = OnEmitSound;
}
else if (CurrentItemId == CSI_DEFUSER)
{
GET_OFFSET_NO_ERROR("CBasePlayer", m_bHasDefuser);
if (!get_pdata<bool>(pEdict, m_bHasDefuser))
{
EnableMessageHooks();
}
}
}
DETOUR_STATIC_CALL(C_ClientCommand)(pEdict);
TriggeredFromCommand = false;
@ -203,6 +227,69 @@ edict_s* OnCreateNamedEntity(int classname)
RETURN_META_VALUE(MRES_IGNORED, 0);
}
void OnEmitSound(edict_t *entity, int channel, const char *sample, float volume, float attenuation, int fFlags, int pitch)
{
if (TriggeredFromCommand)
{
switch (CurrentItemId)
{
case CSI_NVGS:
{
auto client = ENTINDEX(entity);
if (!MF_IsPlayerAlive(client) || MF_ExecuteForward(ForwardOnBuy, static_cast<cell>(client), CSI_NVGS) <= 0)
{
g_pengfuncsTable->pfnEmitSound = nullptr;
RETURN_META(MRES_IGNORED);
}
}
case CSI_DEFUSER:
case CSI_SHIELD:
{
g_pengfuncsTable->pfnEmitSound = nullptr;
RETURN_META(MRES_SUPERCEDE);
}
}
}
RETURN_META(MRES_IGNORED);
}
bool OnMessageItemStatus(edict_t *pPlayer)
{
if (TriggeredFromCommand && (CurrentItemId == CSI_DEFUSER || CurrentItemId == CSI_NVGS))
{
if (!g_pengfuncsTable->pfnEmitSound)
{
return true; // Block message
}
DisableMessageHooks();
}
return false;
}
bool OnMessageStatusIcon(edict_t *pPlayer)
{
if (TriggeredFromCommand && CurrentItemId == CSI_DEFUSER)
{
auto client = ENTINDEX(pPlayer);
if (MF_IsPlayerAlive(client) && MF_ExecuteForward(ForwardOnBuy, static_cast<cell>(client), CSI_DEFUSER) > 0)
{
GET_OFFSET_NO_ERROR_RET("CBasePlayer", m_bHasDefuser);
set_pdata<bool>(pPlayer, m_bHasDefuser, false);
return true; // Block message
}
DisableMessageHooks();
}
return false;
}
DETOUR_DECL_MEMBER0(GiveDefaultItems, void) // void CBasePlayer::GiveDefaultItems(void)
{
if (NoKifesMode)
@ -234,11 +321,11 @@ DETOUR_DECL_MEMBER1(GiveNamedItem, void, const char*, pszName) // void CBasePlay
DETOUR_DECL_MEMBER1(GiveShield, void, bool, bRetire) // void CBasePlayer::GiveShield(bool bRetire)
{
if (TriggeredFromCommand && CurrentItemId == CSI_SHIELDGUN)
if (TriggeredFromCommand && CurrentItemId == CSI_SHIELD)
{
int client = TypeConversion.cbase_to_id(this);
if (MF_IsPlayerAlive(client) && MF_ExecuteForward(ForwardOnBuy, static_cast<cell>(client), CSI_SHIELDGUN) > 0)
if (MF_IsPlayerAlive(client) && MF_ExecuteForward(ForwardOnBuy, static_cast<cell>(client), CSI_SHIELD) > 0)
{
// If shield blocked, we need to hook EmitSound to block pickup sound played right after.
g_pengfuncsTable->pfnEmitSound = OnEmitSound;
@ -256,11 +343,28 @@ DETOUR_DECL_MEMBER2(AddAccount, void, int, amount, bool, bTrackChange) // void C
{
if (TriggeredFromCommand)
{
if (CurrentItemId == CSI_NONE)
switch (CurrentItemId)
{
case CSI_DEFUSER:
{
G_HL_TypeConversion.cbase_to_entvar(this)->body = 0;
g_pengfuncsTable->pfnEmitSound = OnEmitSound; // To block pickup sound.
EnableMessageHooks(); // To block ItemStatus
break;
}
case CSI_NVGS:
{
GET_OFFSET_NO_ERROR("CBasePlayer", m_bHasNightVision);
set_pdata<bool>(G_HL_TypeConversion.cbase_to_edict(this), m_bHasNightVision, false);
EnableMessageHooks(); // To block ItemStatus
break;
}
case CSI_NONE:
{
return;
}
}
}
DETOUR_MEMBER_CALL(AddAccount)(amount, bTrackChange);
}

View File

@ -25,6 +25,7 @@ void InitGlobalVars();
void ShutdownHacks();
void ToggleDetour_ClientCommands(bool enable);
void ToggleDetour_BuyCommands(bool enable);
void OnEmitSound(edict_t *entity, int channel, const char *sample, float volume, float attenuation, int fFlags, int pitch);
extern AMX_NATIVE_INFO CstrikeNatives[];

View File

@ -93,6 +93,12 @@ void OnServerActivate_Post(edict_t *pEdictList, int edictCount, int clientMax)
DisableMessageHooks();
}
void OnPluginsUnloaded()
{
// Force to disable all hooks at map change.
DisableMessageHooks(true);
}
void OnAmxxDetach()
{
ConfigManager->RemoveUserConfigHook("CommandsAliases", &ItemsManager);

View File

@ -1358,7 +1358,13 @@ static cell AMX_NATIVE_CALL cs_set_user_zoom(AMX *amx, cell *params)
int mode = params[3];
int weapon = *static_cast<int *>(MF_PlayerPropAddr(index, Player_CurrentWeapon));
Players[index].ResetZoom();
CPlayer& player = Players[index];
if (player.GetZoom())
{
DisableMessageHooks();
player.ResetZoom();
}
if (type == CS_RESET_ZOOM)
{
@ -1406,7 +1412,7 @@ static cell AMX_NATIVE_CALL cs_set_user_zoom(AMX *amx, cell *params)
if (!mode)
{
Players[index].SetZoom(value);
player.SetZoom(value);
EnableMessageHooks();
}

View File

@ -21,11 +21,13 @@
bool ShouldBlock;
bool ShouldBlockHLTV;
bool ShouldDisableHooks;
bool RetrieveWeaponName;
ke::AString CurrentWeaponName;
int ArgPosition;
int MessageIdArmorType;
int MessageIdItemStatus;
int MessageIdHLTV;
int MessageIdMoney;
int MessageIdResetHUD;
@ -37,6 +39,9 @@ int MessageIdTeamInfo;
int MessageIdTextMsg;
int MessageIdWeaponList;
extern bool OnMessageStatusIcon(edict_t *pPlayer);
extern bool OnMessageItemStatus(edict_t *pPlayer);
struct UserMsg
{
const char* name;
@ -46,6 +51,7 @@ struct UserMsg
UserMsg MessagesList[] =
{
{ "ArmorType" , &MessageIdArmorType },
{ "ItemStatus" , &MessageIdItemStatus },
{ "HLTV" , &MessageIdHLTV },
{ "Money" , &MessageIdMoney },
{ "ResetHUD" , &MessageIdResetHUD },
@ -105,7 +111,30 @@ void OnMessageBegin(int msg_dest, int msg_type, const float *pOrigin, edict_t *p
int index = ENTINDEX(pEntity);
if (Players[index].GetZoom())
{
Players[index].ResetZoom();
DisableMessageHooks();
}
}
else if (msg_type == MessageIdStatusIcon)
{
if (OnMessageStatusIcon(pEntity))
{
ShouldBlock = true;
ShouldDisableHooks = true;
RETURN_META(MRES_SUPERCEDE);
}
}
else if (msg_type == MessageIdItemStatus)
{
if (OnMessageItemStatus(pEntity))
{
ShouldBlock = true;
ShouldDisableHooks = true;
RETURN_META(MRES_SUPERCEDE);
}
}
break;
}
@ -143,7 +172,8 @@ void OnWriteByte(int value)
{
RETURN_META(MRES_SUPERCEDE);
}
else if (RetrieveWeaponName && ++ArgPosition == 7 && value >= 0 && value < MAX_WEAPONS)
if (RetrieveWeaponName && ++ArgPosition == 7 && value >= 0 && value < MAX_WEAPONS)
{
strncopy(WeaponNameList[value], CurrentWeaponName.chars(), sizeof(WeaponNameList[value]));
}
@ -153,6 +183,11 @@ void OnWriteByte(int value)
void OnWriteString(const char *value)
{
if (ShouldBlock)
{
RETURN_META(MRES_SUPERCEDE);
}
if (RetrieveWeaponName)
{
CurrentWeaponName = value;
@ -166,9 +201,17 @@ void OnMessageEnd(void)
if (ShouldBlock)
{
ShouldBlock = false;
if (ShouldDisableHooks)
{
ShouldDisableHooks = false;
DisableMessageHooks();
}
RETURN_META(MRES_SUPERCEDE);
}
else if (RetrieveWeaponName)
if (RetrieveWeaponName)
{
RetrieveWeaponName = false;
ArgPosition = 0;
@ -177,8 +220,12 @@ void OnMessageEnd(void)
RETURN_META(MRES_IGNORED);
}
size_t RefCount;
void EnableMessageHooks()
{
++RefCount;
if (!g_pengfuncsTable->pfnMessageBegin)
{
g_pengfuncsTable->pfnMessageBegin = OnMessageBegin;
@ -188,10 +235,18 @@ void EnableMessageHooks()
}
}
void DisableMessageHooks()
void DisableMessageHooks(bool force)
{
if (force)
{
RefCount = 1;
}
if (--RefCount == 0)
{
g_pengfuncsTable->pfnMessageBegin = nullptr;
g_pengfuncsTable->pfnWriteByte = nullptr;
g_pengfuncsTable->pfnWriteString = nullptr;
g_pengfuncsTable->pfnMessageEnd = nullptr;
}
}

View File

@ -26,6 +26,6 @@ extern int MessageIdTeamInfo;
extern int MessageIdTextMsg;
void EnableMessageHooks();
void DisableMessageHooks();
void DisableMessageHooks(bool force = false);
#endif // CSTRIKE_USER_MESSAGES_H

View File

@ -80,7 +80,7 @@
//#define FN_AMXX_PLUGINSUNLOADING OnPluginsUnloading
/** All plugins are now unloaded */
//#define FN_AMXX_PLUGINSUNLOADED OnPluginsUnloaded
#define FN_AMXX_PLUGINSUNLOADED OnPluginsUnloaded
/**** METAMOD ****/