2
0
mirror of https://github.com/rehlds/rehlds.git synced 2025-01-16 08:38:10 +03:00

Better hitbox tracking

Exposed SV_SetupMove/SV_RestoreMove to the API
This commit is contained in:
dreamstalker 2015-07-12 15:31:19 +04:00
parent 39179e694b
commit 91112615cb
8 changed files with 271 additions and 2 deletions

View File

@ -1350,6 +1350,247 @@ void SV_SetupMove(client_t *_host_client)
}
}
/* <c0030> ../engine/sv_user.c:1426 */
bool EXT_FUNC SV_SetupMoveEx_api(IGameClient* client, float* rewindTime)
{
struct client_s *cl;
float cl_interptime;
client_frame_t *nextFrame;
entity_state_t *state;
sv_adjusted_positions_t *pos;
float frac;
entity_state_t *pnextstate;
int i;
client_frame_t *frame;
vec3_t origin;
vec3_t delta;
client_t* _host_client = client->GetClient();
#ifdef REHLDS_FIXES
double targettime; //FP precision fix
#else
float targettime;
#endif // REHLDS_FIXES
Q_memset(truepositions, 0, sizeof(truepositions));
nofind = 1;
if (!gEntityInterface.pfnAllowLagCompensation())
return false;
if (sv_unlag.value == 0.0f || !_host_client->lw || !_host_client->lc)
return false;
if (g_psvs.maxclients <= 1 || !_host_client->active)
return false;
nofind = 0;
for (int i = 0; i < g_psvs.maxclients; i++)
{
cl = &g_psvs.clients[i];
if (cl == _host_client || !cl->active)
continue;
truepositions[i].oldorg[0] = cl->edict->v.origin[0];
truepositions[i].oldorg[1] = cl->edict->v.origin[1];
truepositions[i].oldorg[2] = cl->edict->v.origin[2];
truepositions[i].oldabsmin[0] = cl->edict->v.absmin[0];
truepositions[i].oldabsmin[1] = cl->edict->v.absmin[1];
truepositions[i].oldabsmin[2] = cl->edict->v.absmin[2];
truepositions[i].oldabsmax[0] = cl->edict->v.absmax[0];
truepositions[i].oldabsmax[1] = cl->edict->v.absmax[1];
truepositions[i].active = 1;
truepositions[i].oldabsmax[2] = cl->edict->v.absmax[2];
}
float clientLatency = _host_client->latency;
if (clientLatency > 1.5)
clientLatency = 1.5f;
if (sv_maxunlag.value != 0.0f)
{
if (sv_maxunlag.value < 0.0)
Cvar_SetValue("sv_maxunlag", 0.0);
if (clientLatency >= sv_maxunlag.value)
clientLatency = sv_maxunlag.value;
}
cl_interptime = _host_client->lastcmd.lerp_msec / 1000.0f;
if (cl_interptime > 0.1)
cl_interptime = 0.1f;
if (_host_client->next_messageinterval > cl_interptime)
cl_interptime = (float)_host_client->next_messageinterval;
#ifdef REHLDS_FIXES
// FP Precision fix (targettime is double there, not float)
if (rewindTime) {
targettime = realtime - *rewindTime;
} else {
targettime = realtime - clientLatency - cl_interptime + sv_unlagpush.value;
}
#else
if (rewindTime) {
targettime = float(realtime - clientLatency - cl_interptime + sv_unlagpush.value);
} else {
targettime = float(realtime - *rewindTime);
}
#endif // REHLDS_FIXES
if (targettime > realtime)
targettime = realtime;
if (SV_UPDATE_BACKUP <= 0)
{
Q_memset(truepositions, 0, sizeof(truepositions));
nofind = 1;
return false;
}
frame = nextFrame = NULL;
for (i = 0; i < SV_UPDATE_BACKUP; i++, frame = nextFrame)
{
nextFrame = &_host_client->frames[SV_UPDATE_MASK & (_host_client->netchan.outgoing_sequence + ~i)];
for (int j = 0; j < nextFrame->entities.num_entities; j++)
{
state = &nextFrame->entities.entities[j];
#ifdef REHLDS_OPT_PEDANTIC
if (state->number <= 0)
continue;
if (state->number > g_psvs.maxclients)
break; // players are always in the beginning of the list, no need to look more
#else
if (state->number <= 0 || state->number > g_psvs.maxclients)
continue;
#endif
pos = &truepositions[state->number - 1];
if (pos->deadflag)
continue;
if (state->health <= 0)
pos->deadflag = 1;
if (state->effects & EF_NOINTERP)
pos->deadflag = 1;
if (pos->temp_org_setflag)
{
if (SV_UnlagCheckTeleport(state->origin, pos->temp_org))
pos->deadflag = 1;
}
else
{
pos->temp_org_setflag = 1;
}
pos->temp_org[0] = state->origin[0];
pos->temp_org[1] = state->origin[1];
pos->temp_org[2] = state->origin[2];
}
if (targettime > nextFrame->senttime)
break;
}
if (i >= SV_UPDATE_BACKUP || targettime - nextFrame->senttime > 1.0)
{
Q_memset(truepositions, 0, 0xB00u);
nofind = 1;
return false;
}
if (frame)
{
float timeDiff = float(frame->senttime - nextFrame->senttime);
if (timeDiff == 0.0)
frac = 0.0;
else
{
frac = float((targettime - nextFrame->senttime) / timeDiff);
if (frac <= 1.0)
{
if (frac < 0.0)
frac = 0.0;
}
else
frac = 1.0;
}
}
else
{
frame = nextFrame;
frac = 0.0;
}
for (i = 0; i < nextFrame->entities.num_entities; i++)
{
state = &nextFrame->entities.entities[i];
if (state->number <= 0 || state->number > g_psvs.maxclients)
continue;
cl = &g_psvs.clients[state->number - 1];
if (cl == _host_client || !cl->active)
continue;
pos = &truepositions[state->number - 1];
if (pos->deadflag)
continue;
if (!pos->active)
{
Con_DPrintf("tried to store off position of bogus player %i/%s\n", i, cl->name);
continue;
}
pnextstate = SV_FindEntInPack(state->number, &frame->entities);
if (pnextstate)
{
delta[0] = pnextstate->origin[0] - state->origin[0];
delta[1] = pnextstate->origin[1] - state->origin[1];
delta[2] = pnextstate->origin[2] - state->origin[2];
VectorMA(state->origin, frac, delta, origin);
}
else
{
origin[0] = state->origin[0];
origin[1] = state->origin[1];
origin[2] = state->origin[2];
}
pos->neworg[0] = origin[0];
pos->neworg[1] = origin[1];
pos->neworg[2] = origin[2];
pos->initial_correction_org[0] = origin[0];
pos->initial_correction_org[1] = origin[1];
pos->initial_correction_org[2] = origin[2];
if (!VectorCompare(origin, cl->edict->v.origin))
{
cl->edict->v.origin[0] = origin[0];
cl->edict->v.origin[1] = origin[1];
cl->edict->v.origin[2] = origin[2];
SV_LinkEdict(cl->edict, 0);
pos->needrelink = 1;
}
}
return true;
}
void EXT_FUNC SV_RestoreMove_api(IGameClient* client) {
SV_RestoreMove(client->GetClient());
}
/* <c01e6> ../engine/sv_user.c:1670 */
void SV_RestoreMove(client_t *_host_client)
{

View File

@ -138,7 +138,9 @@ void SV_GetTrueOrigin(int player, vec_t *origin);
void SV_GetTrueMinMax(int player, float **fmin, float **fmax);
entity_state_t *SV_FindEntInPack(int index, packet_entities_t *pack);
void SV_SetupMove(client_t *_host_client);
bool SV_SetupMoveEx_api(IGameClient* client, float* rewindTime);
void SV_RestoreMove(client_t *_host_client);
void SV_RestoreMove_api(IGameClient* client);
void SV_ParseStringCommand(client_t *pSenderClient);
void SV_ParseDelta(client_t *pSenderClient);
void SV_EstablishTimeBase(client_t *cl, usercmd_t *cmds, int dropped, int numbackup, int numcmds);

View File

@ -35,7 +35,7 @@
#include "model.h"
#define REHLDS_API_VERSION_MAJOR 1
#define REHLDS_API_VERSION_MINOR 3
#define REHLDS_API_VERSION_MINOR 4
//Steam_NotifyClientConnect hook
typedef IHookChain<qboolean, IGameClient*, const void*, unsigned int> IRehldsHook_Steam_NotifyClientConnect;
@ -200,6 +200,9 @@ struct RehldsFuncs_t {
void(*MSG_EndBitWriting)(sizebuf_t *buf);
void*(*SZ_GetSpace)(sizebuf_t *buf, int length);
bool(*GetHitboxCorners)(int hitboxId, float* /* [8*3] */ corners, int* pGroupId);
void(*SetupHitboxTracing)();
bool(*SV_SetupMoveEx)(IGameClient* client, float* rewindTime);
void(*SV_RestoreMove)(IGameClient* client);
};
class IRehldsApi {

View File

@ -33,6 +33,7 @@ class IGameClient;
#include "archtypes.h"
#include "const.h"
#include "netadr.h"
#include "usercmd.h"
#include "common_rehlds.h"
#include "userid_rehlds.h"
@ -67,6 +68,9 @@ public:
virtual bool IsConnected() = 0;
virtual void SetConnected(bool connected) = 0;
virtual usercmd_t* GetLastCommand() = 0;
virtual float GetLatency() = 0;
// this must be the last virtual function in class
#ifdef REHLDS_SELF

View File

@ -119,6 +119,10 @@ bool EXT_FUNC GetHitboxCorners(int hitboxId, float* /* [8*3] */ corners, int* pG
return true;
}
void EXT_FUNC SetupHitboxTracing() {
g_studio_numhulls = 0;
}
CRehldsServerStatic g_RehldsServerStatic;
CRehldsServerData g_RehldsServerData;
CRehldsHookchains g_RehldsHookchains;
@ -154,7 +158,10 @@ RehldsFuncs_t g_RehldsApiFuncs =
&MSG_WriteBitVec3Coord,
&MSG_EndBitWriting,
&SZ_GetSpace,
&GetHitboxCorners
&GetHitboxCorners,
&SetupHitboxTracing,
&SV_SetupMoveEx_api,
&SV_RestoreMove_api
};
sizebuf_t* EXT_FUNC GetNetMessage_api()

View File

@ -32,6 +32,7 @@
#include "rehlds_interfaces_impl.h"
extern bool GetHitboxCorners(int hitboxId, float* /* [8*3] */ corners, int* pGroupId);
extern void SetupHitboxTracing();
//Steam_NotifyClientConnect
typedef IHookChainImpl<qboolean, IGameClient*, const void*, unsigned int> CRehldsHook_Steam_NotifyClientConnect;

View File

@ -70,6 +70,14 @@ void EXT_FUNC CGameClient::SetConnected(bool connected) {
m_pClient->connected = connected ? 1 : 0;
}
usercmd_t* EXT_FUNC CGameClient::GetLastCommand() {
return &m_pClient->lastcmd;
}
float EXT_FUNC CGameClient::GetLatency() {
return m_pClient->latency;
}
INetChan* EXT_FUNC CGameClient::GetNetChan()
{
return &m_NetChan;

View File

@ -77,6 +77,9 @@ public:
virtual bool IsConnected();
virtual void SetConnected(bool connected);
virtual usercmd_t* GetLastCommand();
virtual float GetLatency();
virtual client_t* GetClient();
};