Cstrike: cs_set/reset_user_model/team - Stagger user's info updates across multiple frames (bug 3134)
This commit is contained in:
@ -42,11 +42,16 @@ StringHashMap<int> ItemAliasList;
|
||||
int TeamOffset;
|
||||
int MenuOffset;
|
||||
|
||||
server_static_t *ServerStatic;
|
||||
double *RealTime;
|
||||
|
||||
void InitializeHacks()
|
||||
{
|
||||
CtrlDetours_ClientCommand(true);
|
||||
CtrlDetours_BuyCommands(true);
|
||||
CtrlDetours_Natives(true);
|
||||
|
||||
InitGlobalVars();
|
||||
}
|
||||
|
||||
void ShutdownHacks()
|
||||
@ -301,8 +306,8 @@ void CtrlDetours_ClientCommand(bool set)
|
||||
#endif
|
||||
ClientCommandDetour = DETOUR_CREATE_STATIC_FIXED(C_ClientCommand, base);
|
||||
|
||||
OffsetConfig->GetOffsetByClass("CBasePlayer", "m_iTeam", &TeamOffset);
|
||||
OffsetConfig->GetOffsetByClass("CBasePlayer", "m_iMenu", &MenuOffset);
|
||||
CommonConfig->GetOffsetByClass("CBasePlayer", "m_iTeam", &TeamOffset);
|
||||
CommonConfig->GetOffsetByClass("CBasePlayer", "m_iMenu", &MenuOffset);
|
||||
|
||||
if (!ClientCommandDetour || !UseBotArgs || !BotArgs || !TeamOffset || !MenuOffset)
|
||||
{
|
||||
@ -506,3 +511,28 @@ void CtrlDetours_Natives(bool set)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InitGlobalVars()
|
||||
{
|
||||
void *address = nullptr;
|
||||
|
||||
#if defined(WIN32)
|
||||
|
||||
int offset = 0;
|
||||
|
||||
if (CommonConfig->GetOffset("svs", &offset))
|
||||
{
|
||||
uintptr_t base = *reinterpret_cast<uintptr_t*>(reinterpret_cast<byte*>(g_engfuncs.pfnGetCurrentPlayer) + offset);
|
||||
ServerStatic = reinterpret_cast<server_static_t*>(base - 4);
|
||||
}
|
||||
#else
|
||||
if (CommonConfig->GetMemSig("svs", &address))
|
||||
{
|
||||
ServerStatic = reinterpret_cast<server_static_t*>(address);
|
||||
}
|
||||
#endif
|
||||
if (CommonConfig->GetAddress("realtime", &address))
|
||||
{
|
||||
RealTime = reinterpret_cast<double*>(*reinterpret_cast<uintptr_t*>(address));
|
||||
}
|
||||
}
|
@ -17,8 +17,10 @@
|
||||
#include <amxxmodule.h>
|
||||
#include <IGameConfigs.h>
|
||||
#include <CDetour/detours.h>
|
||||
#include <engine_strucs.h>
|
||||
|
||||
void InitializeHacks();
|
||||
void InitGlobalVars();
|
||||
void ShutdownHacks();
|
||||
void ToggleDetour_ClientCommands(bool enable);
|
||||
void ToggleDetour_BuyCommands(bool enable);
|
||||
@ -26,7 +28,7 @@ void ToggleDetour_BuyCommands(bool enable);
|
||||
extern AMX_NATIVE_INFO CstrikeNatives[];
|
||||
|
||||
extern IGameConfig *MainConfig;
|
||||
extern IGameConfig *OffsetConfig;
|
||||
extern IGameConfig *CommonConfig;
|
||||
|
||||
extern int ForwardInternalCommand;
|
||||
extern int ForwardOnBuy;
|
||||
@ -40,6 +42,10 @@ extern UTIL_FindEntityByStringFunc CS_UTIL_FindEntityByString;
|
||||
|
||||
extern CDetour *GiveDefaultItemsDetour;
|
||||
extern enginefuncs_t *g_pengfuncsTable;
|
||||
extern DLL_FUNCTIONS *g_pFunctionTable;
|
||||
extern bool NoKifesMode;
|
||||
|
||||
extern server_static_t *ServerStatic;
|
||||
extern double *RealTime;
|
||||
|
||||
#endif // CSTRIKE_HACKS_H
|
||||
|
@ -18,9 +18,7 @@
|
||||
#include "CstrikeUserMessages.h"
|
||||
#include "CstrikeHLTypeConversion.h"
|
||||
#include <CDetour/detours.h>
|
||||
|
||||
CCstrikePlayer g_players[33];
|
||||
int Zooming[33];
|
||||
#include <am-vector.h>
|
||||
|
||||
bool NoKifesMode = false;
|
||||
|
||||
@ -536,7 +534,7 @@ static cell AMX_NATIVE_CALL cs_set_user_team(AMX *amx, cell *params)
|
||||
set_pdata<int>(pPlayer, m_iModelName, model);
|
||||
}
|
||||
|
||||
MDLL_ClientUserInfoChanged(pPlayer, GETINFOKEYBUFFER(pPlayer));
|
||||
Players[index].ResetModel(pPlayer);
|
||||
|
||||
char teaminfo[32];
|
||||
|
||||
@ -863,17 +861,11 @@ static cell AMX_NATIVE_CALL cs_set_user_model(AMX *amx, cell *params)
|
||||
return 0;
|
||||
}
|
||||
|
||||
char modelName[32];
|
||||
int length;
|
||||
const char *newModel = MF_GetAmxString(amx, params[2], 0, &length);
|
||||
|
||||
strcpy(modelName, MF_GetAmxString(amx, params[2], 0, &length));
|
||||
|
||||
g_players[index].SetModel(modelName);
|
||||
g_players[index].SetModelled(true);
|
||||
|
||||
EnableMessageHooks();
|
||||
|
||||
SETCLIENTKEYVALUE(index, GETINFOKEYBUFFER(pPlayer), "model", const_cast<char*>(g_players[index].GetModel()));
|
||||
Players[index].SetModel(newModel);
|
||||
Players[index].UpdateModel(MF_GetPlayerEdict(index));
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -886,9 +878,7 @@ static cell AMX_NATIVE_CALL cs_reset_user_model(AMX *amx, cell *params)
|
||||
CHECK_PLAYER(index);
|
||||
edict_t *pPlayer = MF_GetPlayerEdict(index);
|
||||
|
||||
g_players[index].SetModelled(false);
|
||||
|
||||
MDLL_ClientUserInfoChanged(pPlayer, GETINFOKEYBUFFER(pPlayer));
|
||||
Players[index].ResetModel(pPlayer);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -1317,7 +1307,7 @@ 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));
|
||||
|
||||
Zooming[index] = 0;
|
||||
Players[index].ResetZoom();
|
||||
|
||||
if (type == CS_RESET_ZOOM)
|
||||
{
|
||||
@ -1365,7 +1355,7 @@ static cell AMX_NATIVE_CALL cs_set_user_zoom(AMX *amx, cell *params)
|
||||
|
||||
if (!mode)
|
||||
{
|
||||
Zooming[index] = value;
|
||||
Players[index].SetZoom(value);
|
||||
EnableMessageHooks();
|
||||
}
|
||||
|
||||
@ -1766,42 +1756,3 @@ AMX_NATIVE_INFO CstrikeNatives[] =
|
||||
|
||||
{nullptr, nullptr}
|
||||
};
|
||||
|
||||
void ClientDisconnect(edict_t *pEntity)
|
||||
{
|
||||
int index = ENTINDEX(pEntity);
|
||||
g_players[index].SetModelled(false);
|
||||
Zooming[index] = 0;
|
||||
|
||||
RETURN_META(MRES_IGNORED);
|
||||
}
|
||||
|
||||
void ClientUserInfoChanged(edict_t *pEntity, char *infobuffer)
|
||||
{
|
||||
int index = ENTINDEX(pEntity);
|
||||
|
||||
if(g_players[index].GetModelled() && pEntity->v.deadflag == DEAD_NO)
|
||||
{
|
||||
RETURN_META(MRES_SUPERCEDE);
|
||||
}
|
||||
else
|
||||
{
|
||||
RETURN_META(MRES_IGNORED);
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerPostThink(edict_t* pPlayer)
|
||||
{
|
||||
int entityIndex = ENTINDEX(pPlayer);
|
||||
|
||||
if(g_players[entityIndex].GetModelled())
|
||||
{
|
||||
if (g_players[entityIndex].GetInspectModel() && strcmp(g_players[entityIndex].GetModel(), GETCLIENTKEYVALUE(GETINFOKEYBUFFER(pPlayer), "model")) != 0)
|
||||
{
|
||||
//LOG_CONSOLE(PLID, "%s should have model %s and currently has %s", STRING(pPlayer->v.netname), (char*)g_players[entityIndex].GetModel(), GETCLIENTKEYVALUE(GETINFOKEYBUFFER(pPlayer), "model"));
|
||||
SETCLIENTKEYVALUE(entityIndex, GETINFOKEYBUFFER(pPlayer), "model", (char*)g_players[entityIndex].GetModel());
|
||||
g_players[entityIndex].SetInspectModel(false);
|
||||
}
|
||||
}
|
||||
RETURN_META(MRES_IGNORED);
|
||||
}
|
||||
|
@ -12,47 +12,49 @@
|
||||
//
|
||||
|
||||
#include "CstrikePlayer.h"
|
||||
#include <string.h> // strcpy()
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Construction/Destruction
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
CPlayer Players[33];
|
||||
ke::Vector<int> ModelsUpdateQueue;
|
||||
|
||||
CCstrikePlayer::CCstrikePlayer()
|
||||
void ClientDisconnect(edict_t *pEntity)
|
||||
{
|
||||
modelled = false;
|
||||
inspectModel = false;
|
||||
int index = ENTINDEX(pEntity);
|
||||
|
||||
Players[index].ResetModel();
|
||||
Players[index].ResetZoom();
|
||||
|
||||
RETURN_META(MRES_IGNORED);
|
||||
}
|
||||
|
||||
bool CCstrikePlayer::GetModelled()
|
||||
void ClientUserInfoChanged(edict_t *pEntity, char *infobuffer)
|
||||
{
|
||||
return modelled;
|
||||
if (pEntity->pvPrivateData)
|
||||
{
|
||||
Players[ENTINDEX(pEntity)].UpdateModel(pEntity);
|
||||
}
|
||||
|
||||
RETURN_META(MRES_IGNORED);
|
||||
}
|
||||
|
||||
bool CCstrikePlayer::SetModelled(bool modelledIn)
|
||||
void SetClientKeyValue(int clientIndex, char *infobuffer, const char *key, const char *value)
|
||||
{
|
||||
if (!modelledIn)
|
||||
SetInspectModel(false);
|
||||
if (!strcmp(key, "model") && Players[clientIndex].HasModel(value))
|
||||
{
|
||||
RETURN_META(MRES_SUPERCEDE);
|
||||
}
|
||||
|
||||
return modelled = modelledIn;
|
||||
RETURN_META(MRES_IGNORED);
|
||||
}
|
||||
|
||||
const char* CCstrikePlayer::GetModel()
|
||||
void StartFrame()
|
||||
{
|
||||
return model;
|
||||
}
|
||||
if (ModelsUpdateQueue.empty())
|
||||
{
|
||||
g_pFunctionTable->pfnStartFrame = nullptr;
|
||||
RETURN_META(MRES_IGNORED);
|
||||
}
|
||||
|
||||
void CCstrikePlayer::SetModel(const char* modelIn)
|
||||
{
|
||||
strcpy(model, modelIn);
|
||||
}
|
||||
ServerStatic->clients[ModelsUpdateQueue.popCopy()].sendinfo = true;
|
||||
|
||||
bool CCstrikePlayer::GetInspectModel()
|
||||
{
|
||||
return inspectModel;
|
||||
}
|
||||
|
||||
void CCstrikePlayer::SetInspectModel(bool inspectModelIn)
|
||||
{
|
||||
inspectModel = inspectModelIn;
|
||||
RETURN_META(MRES_IGNORED);
|
||||
}
|
||||
|
@ -11,30 +11,125 @@
|
||||
// Counter-Strike Module
|
||||
//
|
||||
|
||||
#if !defined(INCLUDED_CCSTRIKEPLAYER)
|
||||
#define INCLUDED_CCSTRIKEPLAYER
|
||||
#ifndef _CSTRIKE_PLAYER_H_
|
||||
#define _CSTRIKE_PLAYER_H_
|
||||
|
||||
class CCstrikePlayer
|
||||
#include <amxxmodule.h>
|
||||
#include "CstrikeUtils.h"
|
||||
#include "CstrikeHacks.h"
|
||||
#include <am-vector.h>
|
||||
|
||||
extern ke::Vector<int> ModelsUpdateQueue;
|
||||
|
||||
void StartFrame();
|
||||
void ClientUserInfoChanged(edict_t *pEntity, char *infobuffer);
|
||||
void SetClientKeyValue(int clientIndex, char *infobuffer, const char *key, const char *value);
|
||||
|
||||
class CPlayer
|
||||
{
|
||||
public:
|
||||
CCstrikePlayer();
|
||||
public:
|
||||
|
||||
bool GetModelled();
|
||||
bool SetModelled(bool modelledIn);
|
||||
const char* GetModel();
|
||||
void SetModel(const char* modelIn);
|
||||
CPlayer()
|
||||
{
|
||||
ResetModel();
|
||||
ResetZoom();
|
||||
}
|
||||
|
||||
bool GetInspectModel();
|
||||
void SetInspectModel(bool inspectModelIn);
|
||||
bool HasModel(const char *model = nullptr)
|
||||
{
|
||||
if (*m_Model != '\0')
|
||||
{
|
||||
if (model && *model)
|
||||
{
|
||||
return strcmp(m_Model, model) != 0;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
bool inspectModel;
|
||||
bool modelled;
|
||||
char model[32];
|
||||
return false;
|
||||
}
|
||||
|
||||
void SetModel(const char* modelIn)
|
||||
{
|
||||
if (modelIn && *modelIn)
|
||||
{
|
||||
strncopy(m_Model, modelIn, sizeof(m_Model));
|
||||
}
|
||||
else
|
||||
{
|
||||
ResetModel();
|
||||
}
|
||||
}
|
||||
|
||||
void ResetModel(edict_t *pPlayer = nullptr)
|
||||
{
|
||||
*m_Model = '\0';
|
||||
|
||||
if (pPlayer)
|
||||
{
|
||||
MDLL_ClientUserInfoChanged(pPlayer, GETINFOKEYBUFFER(pPlayer));
|
||||
|
||||
PostponeModeUpdate(ENTINDEX(pPlayer) - 1);
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateModel(edict_t *pPlayer)
|
||||
{
|
||||
if (!HasModel())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
char *infobuffer = GETINFOKEYBUFFER(pPlayer);
|
||||
|
||||
if (strcmp(GETCLIENTKEYVALUE(infobuffer, "model"), m_Model) != 0)
|
||||
{
|
||||
int index = ENTINDEX(pPlayer);
|
||||
|
||||
SETCLIENTKEYVALUE(index, infobuffer, "model", m_Model);
|
||||
|
||||
PostponeModeUpdate(index - 1);
|
||||
}
|
||||
}
|
||||
|
||||
int GetZoom()
|
||||
{
|
||||
return m_Zooming;
|
||||
}
|
||||
|
||||
void SetZoom(int value)
|
||||
{
|
||||
m_Zooming = value;
|
||||
}
|
||||
|
||||
void ResetZoom()
|
||||
{
|
||||
m_Zooming = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void PostponeModeUpdate(int index)
|
||||
{
|
||||
ServerStatic->clients[index].sendinfo = false;
|
||||
|
||||
ModelsUpdateQueue.append(index);
|
||||
|
||||
if (!g_pFunctionTable->pfnStartFrame)
|
||||
{
|
||||
g_pFunctionTable->pfnStartFrame = StartFrame;
|
||||
g_pFunctionTable->pfnClientUserInfoChanged = ClientUserInfoChanged;
|
||||
g_pengfuncsTable->pfnSetClientKeyValue = SetClientKeyValue;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
char m_Model[32];
|
||||
int m_Zooming;
|
||||
};
|
||||
|
||||
extern CCstrikePlayer g_players[33];
|
||||
extern int Zooming[33];
|
||||
extern CPlayer Players[33];
|
||||
|
||||
#endif // !defined(INCLUDED_CCSTRIKEPLAYER)
|
||||
#endif // _CSTRIKE_PLAYER_H_
|
||||
|
@ -76,14 +76,15 @@ void OnMessageBegin(int msg_dest, int msg_type, const float *pOrigin, edict_t *p
|
||||
if (msg_type == MessageIdSetFOV)
|
||||
{
|
||||
int index = ENTINDEX(pEntity);
|
||||
int zoom = Players[index].GetZoom();
|
||||
|
||||
if (Zooming[index])
|
||||
if (zoom)
|
||||
{
|
||||
GET_OFFSET_NO_ERROR("CBasePlayer", m_iFOV);
|
||||
|
||||
if (get_pdata<int>(pEntity, m_iFOV) != Zooming[index])
|
||||
if (get_pdata<int>(pEntity, m_iFOV) != zoom)
|
||||
{
|
||||
set_pdata<int>(pEntity, m_iFOV, Zooming[index]);
|
||||
set_pdata<int>(pEntity, m_iFOV, zoom);
|
||||
|
||||
ShouldBlock = true;
|
||||
ShouldBlockHLTV = true;
|
||||
@ -96,11 +97,8 @@ void OnMessageBegin(int msg_dest, int msg_type, const float *pOrigin, edict_t *p
|
||||
{
|
||||
int index = ENTINDEX(pEntity);
|
||||
|
||||
if (Zooming[index])
|
||||
Zooming[index] = 0;
|
||||
|
||||
if (g_players[index].GetModelled())
|
||||
g_players[index].SetInspectModel(true);
|
||||
if (Players[index].GetZoom())
|
||||
Players[index].ResetZoom();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -78,7 +78,7 @@ bool UTIL_CheckForPublic(const char *publicname);
|
||||
static int member = -1; \
|
||||
if (member == -1) \
|
||||
{ \
|
||||
if (!OffsetConfig->GetOffsetByClass(classname, #member, &member) || member < 0)\
|
||||
if (!CommonConfig->GetOffsetByClass(classname, #member, &member) || member < 0)\
|
||||
{ \
|
||||
MF_LogError(amx, AMX_ERR_NATIVE, "Invalid %s offset. Native %s is disabled", #member, __FUNCTION__);\
|
||||
return 0; \
|
||||
@ -89,7 +89,7 @@ bool UTIL_CheckForPublic(const char *publicname);
|
||||
static int member = -1; \
|
||||
if (member == -1) \
|
||||
{ \
|
||||
if (!OffsetConfig->GetOffsetByClass(classname, #member, &member) || member < 0)\
|
||||
if (!CommonConfig->GetOffsetByClass(classname, #member, &member) || member < 0)\
|
||||
{ \
|
||||
return; \
|
||||
} \
|
||||
|
@ -17,9 +17,10 @@
|
||||
#include "CstrikeHacks.h"
|
||||
#include "CstrikeHLTypeConversion.h"
|
||||
#include <IGameConfigs.h>
|
||||
#include "engine_strucs.h"
|
||||
|
||||
IGameConfig *MainConfig;
|
||||
IGameConfig *OffsetConfig;
|
||||
IGameConfig *CommonConfig;
|
||||
IGameConfigManager *ConfigManager;
|
||||
|
||||
int AmxxCheckGame(const char *game)
|
||||
@ -49,7 +50,7 @@ void OnAmxxAttach()
|
||||
|
||||
error[0] = '\0';
|
||||
|
||||
if (!ConfigManager->LoadGameConfigFile("common.games", &OffsetConfig, error, sizeof(error)) && error[0] != '\0')
|
||||
if (!ConfigManager->LoadGameConfigFile("common.games", &CommonConfig, error, sizeof(error)) && error[0] != '\0')
|
||||
{
|
||||
MF_Log("Could not read common.games gamedata: %s", error);
|
||||
return;
|
||||
@ -79,12 +80,17 @@ void OnPluginsLoaded()
|
||||
{
|
||||
G_OffsetHandler = new OffsetHandler;
|
||||
}
|
||||
|
||||
// Used with model natives, enabled on demand.
|
||||
g_pengfuncsTable->pfnSetClientKeyValue = nullptr;
|
||||
g_pFunctionTable->pfnClientUserInfoChanged = nullptr;
|
||||
g_pFunctionTable->pfnStartFrame = nullptr;
|
||||
}
|
||||
|
||||
void OnAmxxDetach()
|
||||
{
|
||||
ConfigManager->CloseGameConfigFile(MainConfig);
|
||||
ConfigManager->CloseGameConfigFile(OffsetConfig);
|
||||
ConfigManager->CloseGameConfigFile(CommonConfig);
|
||||
|
||||
ShutdownHacks();
|
||||
}
|
||||
|
@ -122,11 +122,11 @@
|
||||
// #define FN_ClientKill ClientKill /* pfnClientKill() (wd) Player has typed "kill" */
|
||||
// #define FN_ClientPutInServer ClientPutInServer /* pfnClientPutInServer() (wd) Client is entering the game */
|
||||
// #define FN_ClientCommand ClientCommand /* pfnClientCommand() (wd) Player has sent a command (typed or from a bind) */
|
||||
#define FN_ClientUserInfoChanged ClientUserInfoChanged /* pfnClientUserInfoChanged() (wd) Client has updated their setinfo structure */
|
||||
// #define FN_ClientUserInfoChanged ClientUserInfoChanged /* pfnClientUserInfoChanged() (wd) Client has updated their setinfo structure */
|
||||
// #define FN_ServerActivate ServerActivate /* pfnServerActivate() (wd) Server is starting a new map */
|
||||
// #define FN_ServerDeactivate ServerDeactivate /* pfnServerDeactivate() (wd) Server is leaving the map (shutdown or changelevel); SDK2 */
|
||||
// #define FN_PlayerPreThink PlayerPreThink /* pfnPlayerPreThink() */
|
||||
#define FN_PlayerPostThink PlayerPostThink /* pfnPlayerPostThink() */
|
||||
// #define FN_PlayerPostThink PlayerPostThink /* pfnPlayerPostThink() */
|
||||
// #define FN_StartFrame StartFrame /* pfnStartFrame() */
|
||||
// #define FN_ParmsNewLevel ParmsNewLevel /* pfnParmsNewLevel() */
|
||||
// #define FN_ParmsChangeLevel ParmsChangeLevel /* pfnParmsChangeLevel() */
|
||||
|
Reference in New Issue
Block a user