diff --git a/rehlds/engine/r_studio.cpp b/rehlds/engine/r_studio.cpp index 30a83ff..b69d443 100644 --- a/rehlds/engine/r_studio.cpp +++ b/rehlds/engine/r_studio.cpp @@ -627,7 +627,11 @@ hull_t *R_StudioHull(model_t *pModel, float frame, int sequence, const vec_t *an pstudiohdr = (studiohdr_t *)Mod_Extradata(pModel); vec_t angles2[3] = { -angles[0], angles[1], angles[2] }; +#ifdef REHLDS_FIXES + SV_StudioSetupUnlagBones( pModel, frame, sequence, angles2, origin, pcontroller, pblending, -1, pEdict ); +#else g_pSvBlendingAPI->SV_StudioSetupBones(pModel, frame, sequence, angles2, origin, pcontroller, pblending, -1, pEdict); +#endif mstudiobbox_t *pbbox = (mstudiobbox_t *)((char *)pstudiohdr + pstudiohdr->hitboxindex); for (int i = 0; i < pstudiohdr->numhitboxes; i++) @@ -874,6 +878,17 @@ void EXT_FUNC AnimationAutomove(const edict_t *pEdict, float flTime) void EXT_FUNC GetBonePosition(const edict_t *pEdict, int iBone, float *rgflOrigin, float *rgflAngles) { pstudiohdr = (studiohdr_t *)Mod_Extradata(g_psv.models[pEdict->v.modelindex]); +#ifdef REHLDS_FIXES + SV_StudioSetupUnlagBones( g_psv.models[pEdict->v.modelindex], + pEdict->v.frame, + pEdict->v.sequence, + pEdict->v.angles, + pEdict->v.origin, + pEdict->v.controller, + pEdict->v.blending, + iBone, + pEdict ); +#else g_pSvBlendingAPI->SV_StudioSetupBones( g_psv.models[pEdict->v.modelindex], pEdict->v.frame, @@ -885,6 +900,7 @@ void EXT_FUNC GetBonePosition(const edict_t *pEdict, int iBone, float *rgflOrigi iBone, pEdict ); +#endif if (rgflOrigin) { @@ -907,6 +923,20 @@ void EXT_FUNC GetAttachment(const edict_t *pEdict, int iAttachment, float *rgflO pattachment = (mstudioattachment_t *)((char *)pstudiohdr + pstudiohdr->attachmentindex); pattachment += iAttachment; +#ifdef REHLDS_FIXES + SV_StudioSetupUnlagBones( + g_psv.models[pEdict->v.modelindex], + pEdict->v.frame, + pEdict->v.sequence, + angles, + pEdict->v.origin, + pEdict->v.controller, + pEdict->v.blending, + pattachment->bone, + pEdict + ); +#else + g_pSvBlendingAPI->SV_StudioSetupBones( g_psv.models[pEdict->v.modelindex], pEdict->v.frame, @@ -918,6 +948,7 @@ void EXT_FUNC GetAttachment(const edict_t *pEdict, int iAttachment, float *rgflO pattachment->bone, pEdict ); +#endif if (rgflOrigin) VectorTransform(pattachment->org, bonetransform[pattachment->bone], rgflOrigin); diff --git a/rehlds/engine/server.h b/rehlds/engine/server.h index 7adca46..3e008c4 100644 --- a/rehlds/engine/server.h +++ b/rehlds/engine/server.h @@ -53,6 +53,7 @@ const int MAX_NAME = 32; #include "pm_defs.h" #include "inst_baseline.h" #include "net_ws.h" +#include "studio_rehlds.h" const int DEFAULT_SOUND_PACKET_VOLUME = 255; const float DEFAULT_SOUND_PACKET_ATTENUATION = 1.0f; @@ -175,6 +176,16 @@ struct rehlds_server_t { #endif }; +#ifdef REHLDS_FIXES +// a1batross: "bone position"-based unlag +typedef struct client_bone_state_s +{ + bonetransform_t bonetransform; + float rotationmatrix[3][4]; + qboolean valid; +} client_bone_state_t; +#endif // REHLDS_FIXES + typedef struct client_frame_s { double senttime; @@ -182,6 +193,9 @@ typedef struct client_frame_s clientdata_t clientdata; weapon_data_t weapondata[64]; packet_entities_t entities; +#ifdef REHLDS_FIXES // a1batross: "bone position"-based unlag + client_bone_state_t bonestate; +#endif // REHLDS_FIXES } client_frame_t; typedef struct client_s diff --git a/rehlds/engine/sv_main.cpp b/rehlds/engine/sv_main.cpp index 8bec12a..580863e 100644 --- a/rehlds/engine/sv_main.cpp +++ b/rehlds/engine/sv_main.cpp @@ -7717,6 +7717,9 @@ void SV_Init(void) Cvar_RegisterVariable(&sv_instancedbaseline); Cvar_RegisterVariable(&sv_contact); Cvar_RegisterVariable(&sv_unlag); +#ifdef REHLDS_FIXES + Cvar_RegisterVariable(&sv_bone_unlag); +#endif Cvar_RegisterVariable(&sv_maxunlag); Cvar_RegisterVariable(&sv_unlagpush); Cvar_RegisterVariable(&sv_unlagsamples); diff --git a/rehlds/engine/sv_user.cpp b/rehlds/engine/sv_user.cpp index 381e014..ceb89ef 100644 --- a/rehlds/engine/sv_user.cpp +++ b/rehlds/engine/sv_user.cpp @@ -59,6 +59,9 @@ cvar_t sv_footsteps = { "mp_footsteps", "1", FCVAR_SERVER, 0.0f, NULL }; cvar_t sv_rollspeed = { "sv_rollspeed", "0.0", 0, 0.0f, NULL }; cvar_t sv_rollangle = { "sv_rollangle", "0.0", 0, 0.0f, NULL }; cvar_t sv_unlag = { "sv_unlag", "1", 0, 0.0f, NULL }; +#ifdef REHLDS_FIXES +cvar_t sv_bone_unlag = { "sv_bone_unlag", "0", 0, 0.0f, NULL }; +#endif // REHLDS_FIXES cvar_t sv_maxunlag = { "sv_maxunlag", "0.5", 0, 0.0f, NULL }; cvar_t sv_unlagpush = { "sv_unlagpush", "0.0", 0, 0.0f, NULL }; cvar_t sv_unlagsamples = { "sv_unlagsamples", "1", 0, 0.0f, NULL }; @@ -1008,6 +1011,10 @@ void SV_RunCmd(usercmd_t *ucmd, int random_seed) gGlobalVariables.frametime = frametime; gEntityInterface.pfnPlayerPostThink(sv_player); gEntityInterface.pfnCmdEnd(sv_player); + +#ifdef REHLDS_FIXES + SV_SaveBoneState( host_client, sv_player ); +#endif if (!host_client->fakeclient) SV_RestoreMove(host_client); @@ -1320,7 +1327,7 @@ void SV_SetupMove(client_t *_host_client) frame = nextFrame; frac = 0.0; } - + for (i = 0; i < nextFrame->entities.num_entities; i++) { state = &nextFrame->entities.entities[i]; @@ -1342,6 +1349,25 @@ void SV_SetupMove(client_t *_host_client) } pnextstate = SV_FindEntInPack(state->number, &frame->entities); + +#ifdef REHLDS_FIXES + if( nextFrame->bonestate.valid ) + { + if( frame->bonestate.valid ) + { + // TODO: interpolate + pos->bonestate = nextFrame->bonestate; + } + else + { + pos->bonestate = nextFrame->bonestate; + } + } + else + { + pos->bonestate.valid = false; + } +#endif // REHLDS_FIXES if (pnextstate) { @@ -1409,7 +1435,11 @@ void SV_RestoreMove(client_t *_host_client) Con_DPrintf("SV_RestoreMove: Tried to restore 'inactive' player %i/%s\n", i, &cli->name[4]); continue; } - + +#ifdef REHLDS_FIXES + pos->bonestate.valid = false; +#endif // REHLDS_FIXES + if (VectorCompare(pos->initial_correction_org, cli->edict->v.origin)) { cli->edict->v.origin[0] = pos->oldorg[0]; @@ -1910,3 +1940,63 @@ void SV_FullUpdate_f(void) gEntityInterface.pfnClientCommand(sv_player); #endif // REHLDS_FIXES } + +#ifdef REHLDS_FIXES +void SV_SaveBoneState(client_t *_host_client, const edict_t *edict) +{ + int num = NUM_FOR_EDICT( edict ); + client_frame_t *frame; + extern bonetransform_t bonetransform; // in r_studio.cpp + extern float rotationmatrix[3][4]; // in r_studio.cpp + + if( !SV_IsPlayerIndex( num )) // just in case + return; + + // get last outgoing frame + frame = &_host_client->frames[SV_UPDATE_MASK & (_host_client->netchan.outgoing_sequence)]; + + // set up bones + g_pSvBlendingAPI->SV_StudioSetupBones( + g_psv.models[edict->v.modelindex], + edict->v.frame, edict->v.sequence, edict->v.angles, edict->v.origin, + edict->v.controller, edict->v.blending, -1, edict + ); + + // copy bones + frame->bonestate.valid = true; + Q_memcpy( frame->bonestate.bonetransform, bonetransform, sizeof( bonetransform )); + Q_memcpy( frame->bonestate.rotationmatrix, rotationmatrix, sizeof( rotationmatrix )); + +} + +void SV_StudioSetupUnlagBones( model_t *pModel, float frame, int sequence, const vec_t *angles, const vec_t *origin, const unsigned char *pcontroller, const unsigned char *pblending, int iBone, const edict_t *edict ) +{ + // a1ba: carefully check everything, otherwise we may get broken bones! + if( edict && sv_bone_unlag.value ) // check is this a server or disabled + { + if( !nofind ) // unlag is enabled + { + if( edict->v.flags & FL_CLIENT ) + { + int num = NUM_FOR_EDICT( edict ); + + if( truepositions[num].active && + !truepositions[num].needrelink && // TODO: will this work for moving clients? + truepositions[num].bonestate.valid ) // bones are correct + { + // in r_studio.cpp + extern bonetransform_t bonetransform; + extern float rotationmatrix[3][4]; + + Q_memcpy( bonetransform, truepositions[num].bonestate.bonetransform, sizeof( bonetransform )); + Q_memcpy( rotationmatrix, truepositions[num].bonestate.rotationmatrix, sizeof( rotationmatrix )); + return; + } + } + } + } + + // fallback to original SV_StudioSetupBones + g_pSvBlendingAPI->SV_StudioSetupBones(pModel, frame, sequence, angles, origin, pcontroller, pblending, iBone, edict); +} +#endif // REHLDS_FIXES diff --git a/rehlds/engine/sv_user.h b/rehlds/engine/sv_user.h index 8da3360..66bde0a 100644 --- a/rehlds/engine/sv_user.h +++ b/rehlds/engine/sv_user.h @@ -49,6 +49,9 @@ typedef struct sv_adjusted_positions_s int deadflag; vec3_t temp_org; int temp_org_setflag; +#ifdef REHLDS_FIXES + client_bone_state_t bonestate; +#endif // REHLDS_FIXES } sv_adjusted_positions_t; typedef struct clc_func_s @@ -71,6 +74,9 @@ extern cvar_t sv_footsteps; extern cvar_t sv_rollspeed; extern cvar_t sv_rollangle; extern cvar_t sv_unlag; +#ifdef REHLDS_FIXES +extern cvar_t sv_bone_unlag; +#endif extern cvar_t sv_maxunlag; extern cvar_t sv_unlagpush; extern cvar_t sv_unlagsamples; @@ -117,3 +123,10 @@ qboolean SV_SetPlayer(int idnum); void SV_ShowServerinfo_f(void); void SV_SendEnts_f(void); void SV_FullUpdate_f(void); + +#ifdef REHLDS_FIXES +void SV_SaveBoneState( client_t *cl, const edict_t *edict ); + +// "bone position"-based sv_unlag +void SV_StudioSetupUnlagBones( model_t *pModel, float frame, int sequence, const vec_t *angles, const vec_t *origin, const unsigned char *pcontroller, const unsigned char *pblending, int iBone, const edict_t *edict ); +#endif // REHLDS_FIXES