From 3602610d138a5e0aa5847c2f05c0f5caaac9133e Mon Sep 17 00:00:00 2001 From: Rudolf Polzer Date: Thu, 22 Nov 2012 16:46:03 +0100 Subject: [PATCH] new and VERY broken cvar: cl_csad --- qcsrc/client/autocvars.qh | 1 + qcsrc/client/csqcmodel_hooks.qc | 85 +++++++++++++++++++++++++++--- qcsrc/common/animdecide.qc | 78 ++++++++++++++------------- qcsrc/common/animdecide.qh | 6 ++- qcsrc/common/csqcmodel_settings.qh | 4 +- qcsrc/common/util.qc | 7 ++- qcsrc/common/util.qh | 2 +- qcsrc/csqcmodellib/cl_model.qc | 4 +- qcsrc/server/cl_player.qc | 2 +- qcsrc/server/cl_weaponsystem.qc | 8 +-- 10 files changed, 141 insertions(+), 56 deletions(-) diff --git a/qcsrc/client/autocvars.qh b/qcsrc/client/autocvars.qh index 74baf61fd..1cc460381 100644 --- a/qcsrc/client/autocvars.qh +++ b/qcsrc/client/autocvars.qh @@ -403,3 +403,4 @@ float autocvar_cl_precacheplayermodels; float autocvar_cl_deathglow; float autocvar_developer_csqcentities; float autocvar_sv_player_jumpanim_minfall; +float autocvar_cl_csad; diff --git a/qcsrc/client/csqcmodel_hooks.qc b/qcsrc/client/csqcmodel_hooks.qc index 24ec0a2e3..aafa68670 100644 --- a/qcsrc/client/csqcmodel_hooks.qc +++ b/qcsrc/client/csqcmodel_hooks.qc @@ -1,4 +1,4 @@ -void CSQCModel_Hook_PreDraw(); +void CSQCModel_Hook_PreDraw(float isplayer); .float isplayermodel; @@ -270,8 +270,10 @@ void CSQCPlayer_ForceModel_Apply(float islocalplayer) // FEATURE: fallback frames .float csqcmodel_saveframe; .float csqcmodel_saveframe2; +#ifdef CSQCMODEL_HAVE_TWO_FRAMES .float csqcmodel_saveframe3; .float csqcmodel_saveframe4; +#endif .float csqcmodel_framecount; #define IS_DEAD_FRAME(f) ((f) == 0 || (f) == 1) @@ -279,15 +281,19 @@ void CSQCPlayer_FallbackFrame_PreUpdate(void) { self.frame = self.csqcmodel_saveframe; self.frame2 = self.csqcmodel_saveframe2; +#ifdef CSQCMODEL_HAVE_TWO_FRAMES self.frame3 = self.csqcmodel_saveframe3; self.frame4 = self.csqcmodel_saveframe4; +#endif } void CSQCPlayer_FallbackFrame_PostUpdate(float isnew) { self.csqcmodel_saveframe = self.frame; self.csqcmodel_saveframe2 = self.frame2; +#ifdef CSQCMODEL_HAVE_TWO_FRAMES self.csqcmodel_saveframe3 = self.frame3; self.csqcmodel_saveframe4 = self.frame4; +#endif // hack for death animations: set their frametime to zero in case a // player "pops in" @@ -300,8 +306,10 @@ void CSQCPlayer_FallbackFrame_PostUpdate(float isnew) } FIX_FRAMETIME(frame, frame1time) FIX_FRAMETIME(frame2, frame2time) +#ifdef CSQCMODEL_HAVE_TWO_FRAMES FIX_FRAMETIME(frame3, frame3time) FIX_FRAMETIME(frame4, frame4time) +#endif } self.csqcmodel_isdead = IS_DEAD_FRAME(self.frame); } @@ -329,8 +337,10 @@ void CSQCPlayer_FallbackFrame_Apply(void) { self.frame = CSQCPlayer_FallbackFrame(self.frame); self.frame2 = CSQCPlayer_FallbackFrame(self.frame2); +#ifdef CSQCMODEL_HAVE_TWO_FRAMES self.frame3 = CSQCPlayer_FallbackFrame(self.frame3); self.frame4 = CSQCPlayer_FallbackFrame(self.frame4); +#endif } // FEATURE: auto tag_index @@ -357,7 +367,7 @@ void CSQCModel_AutoTagIndex_Apply(void) { entity oldself = self; self = self.tag_entity; - CSQCModel_Hook_PreDraw(); + CSQCModel_Hook_PreDraw((self.entnum >= 1 && self.entnum <= maxclients)); self = oldself; } @@ -545,7 +555,16 @@ void CSQCPlayer_GlowMod_Apply(void) // general functions .float csqcmodel_predraw_run; -void CSQCModel_Hook_PreDraw() +.float anim_frame; +.float anim_frame1time; +.float anim_frame2; +.float anim_frame2time; +.float anim_saveframe; +.float anim_saveframe1time; +.float anim_saveframe2; +.float anim_saveframe2time; +.float anim_prev_pmove_flags; +void CSQCModel_Hook_PreDraw(float isplayer) { if(self.csqcmodel_predraw_run == framecount) return; @@ -564,7 +583,59 @@ void CSQCModel_Hook_PreDraw() CSQCPlayer_ForceModel_Apply(self.entnum == player_localnum + 1); CSQCPlayer_GlowMod_Apply(); CSQCPlayer_LOD_Apply(); - CSQCPlayer_FallbackFrame_Apply(); + if(!isplayer || !autocvar_cl_csad) + CSQCPlayer_FallbackFrame_Apply(); + else + { + // we know that frame3 and frame4 fields, used by InterpolateAnimation, are left alone - but that is all we know! + float doblend = FALSE; + float flg = 0; + if(self == csqcplayer) + { + if(self.pmove_flags & PMF_ONGROUND) + flg |= FL_ONGROUND; + if(!(self.pmove_flags & PMF_JUMPRELEASED)) + if(self.anim_prev_pmove_flags & PMF_JUMPRELEASED) + animdecide_setaction(self, ANIMACTION_JUMP, TRUE); + self.anim_prev_pmove_flags = self.pmove_flags; + } + else + { + traceline(self.origin + '0 0 1' * self.maxs_z, self.origin + '0 0 1' * (self.mins_z - 4), MOVE_NOMONSTERS, self); + if(trace_startsolid || trace_fraction < 1) + flg |= FL_ONGROUND; + } + animdecide_setframes(self, flg, doblend, anim_frame, anim_frame1time, anim_frame2, anim_frame2time); + float sf = 0; + if(self.anim_saveframe != self.anim_frame || self.anim_saveframe1time != self.anim_frame1time) + sf |= CSQCMODEL_PROPERTY_FRAME; + if(self.anim_saveframe2 != self.anim_frame2 || self.anim_saveframe2time != self.anim_frame2time) + sf |= CSQCMODEL_PROPERTY_FRAME2; + self.anim_saveframe = self.anim_frame; + self.anim_saveframe1time = self.anim_frame1time; + self.anim_saveframe = self.anim_frame2; + self.anim_saveframe2time = self.anim_frame2time; + if(sf) + { + CSQCModel_InterpolateAnimation_2To4_PreNote(sf | CSQCMODEL_PROPERTY_LERPFRAC); + self.lerpfrac = (doblend ? 0.5 : 0); + self.frame = self.anim_frame; + self.frame1time = self.anim_frame1time; + self.frame = self.anim_frame2; + self.frame2time = self.anim_frame2time; + CSQCModel_InterpolateAnimation_2To4_Note(sf | CSQCMODEL_PROPERTY_LERPFRAC, FALSE); + } + CSQCModel_InterpolateAnimation_2To4_Do(); + if(doblend) + { + // build a skeletonobject + } + else + { + // remove skeletonobject if any + // all is done + } + } } CSQCModel_AutoTagIndex_Apply(); @@ -578,7 +649,8 @@ void CSQCModel_Hook_PreUpdate(float isnew, float isplayer, float islocalplayer) CSQCModel_Effects_PreUpdate(); if(self.isplayermodel) { - CSQCPlayer_FallbackFrame_PreUpdate(); + if(!isplayer || !autocvar_cl_csad) + CSQCPlayer_FallbackFrame_PreUpdate(); CSQCPlayer_ForceModel_PreUpdate(); } } @@ -592,7 +664,8 @@ void CSQCModel_Hook_PostUpdate(float isnew, float isplayer, float islocalplayer) if(self.isplayermodel) { CSQCPlayer_ForceModel_PostUpdate(); - CSQCPlayer_FallbackFrame_PostUpdate(isnew); + if(!isplayer || !autocvar_cl_csad) + CSQCPlayer_FallbackFrame_PostUpdate(isnew); } CSQCModel_Effects_PostUpdate(); } diff --git a/qcsrc/common/animdecide.qc b/qcsrc/common/animdecide.qc index 5110fc047..9a76f5ffc 100644 --- a/qcsrc/common/animdecide.qc +++ b/qcsrc/common/animdecide.qc @@ -45,34 +45,35 @@ void animdecide_init(entity e) { - e.anim_die1 = animfixfps(e, '0 1 0.5'); // 2 seconds - e.anim_die2 = animfixfps(e, '1 1 0.5'); // 2 seconds - e.anim_draw = animfixfps(e, '2 1 3'); - e.anim_duckwalk = animfixfps(e, '4 1 1'); - e.anim_duckjump = animfixfps(e, '5 1 10'); - e.anim_duckidle = animfixfps(e, '6 1 1'); - e.anim_idle = animfixfps(e, '7 1 1'); - e.anim_jump = animfixfps(e, '8 1 10'); - e.anim_pain1 = animfixfps(e, '9 1 2'); // 0.5 seconds - e.anim_pain2 = animfixfps(e, '10 1 2'); // 0.5 seconds - e.anim_shoot = animfixfps(e, '11 1 5'); // analyze models and set framerate - e.anim_taunt = animfixfps(e, '12 1 0.33'); - e.anim_run = animfixfps(e, '13 1 1'); - e.anim_runbackwards = animfixfps(e, '14 1 1'); - e.anim_strafeleft = animfixfps(e, '15 1 1'); - e.anim_straferight = animfixfps(e, '16 1 1'); - e.anim_forwardright = animfixfps(e, '19 1 1'); - e.anim_forwardleft = animfixfps(e, '20 1 1'); - e.anim_backright = animfixfps(e, '21 1 1'); - e.anim_backleft = animfixfps(e, '22 1 1'); - e.anim_melee = animfixfps(e, '23 1 1'); - e.anim_duckwalkbackwards = animfixfps(e, '24 1 1'); - e.anim_duckwalkstrafeleft = animfixfps(e, '25 1 1'); - e.anim_duckwalkstraferight = animfixfps(e, '26 1 1'); - e.anim_duckwalkforwardright = animfixfps(e, '27 1 1'); - e.anim_duckwalkforwardleft = animfixfps(e, '28 1 1'); - e.anim_duckwalkbackright = animfixfps(e, '29 1 1'); - e.anim_duckwalkbackleft = animfixfps(e, '30 1 1'); + vector none = '0 0 0'; + e.anim_die1 = animfixfps(e, '0 1 0.5', none); // 2 seconds + e.anim_die2 = animfixfps(e, '1 1 0.5', none); // 2 seconds + e.anim_draw = animfixfps(e, '2 1 3', none); + e.anim_duckwalk = animfixfps(e, '4 1 1', none); + e.anim_duckjump = animfixfps(e, '5 1 10', none); + e.anim_duckidle = animfixfps(e, '6 1 1', none); + e.anim_idle = animfixfps(e, '7 1 1', none); + e.anim_jump = animfixfps(e, '8 1 10', none); + e.anim_pain1 = animfixfps(e, '9 1 2', none); // 0.5 seconds + e.anim_pain2 = animfixfps(e, '10 1 2', none); // 0.5 seconds + e.anim_shoot = animfixfps(e, '11 1 5', none); // analyze models and set framerate + e.anim_taunt = animfixfps(e, '12 1 0.33', none); + e.anim_run = animfixfps(e, '13 1 1', none); + e.anim_runbackwards = animfixfps(e, '14 1 1', none); + e.anim_strafeleft = animfixfps(e, '15 1 1', none); + e.anim_straferight = animfixfps(e, '16 1 1', none); + e.anim_forwardright = animfixfps(e, '19 1 1', '16 1 1'); + e.anim_forwardleft = animfixfps(e, '20 1 1', '15 1 1'); + e.anim_backright = animfixfps(e, '21 1 1', '16 1 1'); + e.anim_backleft = animfixfps(e, '22 1 1', '15 1 1'); + e.anim_melee = animfixfps(e, '23 1 1', '11 1 1'); + e.anim_duckwalkbackwards = animfixfps(e, '24 1 1', '4 1 1'); + e.anim_duckwalkstrafeleft = animfixfps(e, '25 1 1', '4 1 1'); + e.anim_duckwalkstraferight = animfixfps(e, '26 1 1', '4 1 1'); + e.anim_duckwalkforwardright = animfixfps(e, '27 1 1', '4 1 1'); + e.anim_duckwalkforwardleft = animfixfps(e, '28 1 1', '4 1 1'); + e.anim_duckwalkbackright = animfixfps(e, '29 1 1', '4 1 1'); + e.anim_duckwalkbackleft = animfixfps(e, '30 1 1', '4 1 1'); } #define ANIMPRIO_IDLE 0 @@ -210,7 +211,7 @@ vector animdecide_getloweranim(entity e) // can't get here } -void animdecide_setimplicitstate(entity e) +void animdecide_setimplicitstate(entity e, float flg) { float s; s = 0; @@ -241,13 +242,14 @@ void animdecide_setimplicitstate(entity e) if(v_y < -fabs(v_x) * 0.5) s |= ANIMIMPLICITSTATE_LEFT; } - if(!(e.flags & FL_ONGROUND)) + if(!(flg & FL_ONGROUND)) s |= ANIMIMPLICITSTATE_INAIR; // detect some kinds of otherwise misdetected jumps if(!(e.anim_implicit_state & ANIMIMPLICITSTATE_INAIR) && (s & ANIMIMPLICITSTATE_INAIR)) { // ground to air transition - do we want to reset jump anim? + if(e.anim_lower_action != ANIMACTION_JUMP || time > e.anim_lower_time + 0.2) if(e.anim_lower_implicit_action != ANIMACTION_JUMP || time > e.anim_lower_implicit_time + 0.2) { traceline(e.origin + '0 0 1' * e.maxs_z, e.origin + '0 0 1' * (e.mins_z - autocvar_sv_player_jumpanim_minfall), MOVE_NOMONSTERS, e); @@ -265,9 +267,9 @@ void animdecide_setimplicitstate(entity e) e.anim_implicit_time = time; } } -void animdecide_setframes(entity e, float support_blending) +void animdecide_setframes(entity e, float flg, float support_blending, .float fld_frame, .float fld_frame1time, .float fld_frame2, .float fld_frame2time) { - animdecide_setimplicitstate(e); + animdecide_setimplicitstate(e, flg); // _x: frame // _y: start time // _z: priority @@ -282,17 +284,17 @@ void animdecide_setframes(entity e, float support_blending) { if(e.frame1time != upper_y || e.frame2time != lower_y) BITXOR_ASSIGN(e.effects, EF_RESTARTANIM_BIT); - e.frame = upper_x; - e.frame1time = upper_y; - e.frame2 = lower_x; - e.frame2time = lower_y; + e.fld_frame = upper_x; + e.fld_frame1time = upper_y; + e.fld_frame2 = lower_x; + e.fld_frame2time = lower_y; } else { if(e.frame1time != upper_y) BITXOR_ASSIGN(e.effects, EF_RESTARTANIM_BIT); - e.frame = upper_x; - e.frame1time = upper_y; + e.fld_frame = upper_x; + e.fld_frame1time = upper_y; } } diff --git a/qcsrc/common/animdecide.qh b/qcsrc/common/animdecide.qh index fe15345ab..071646f96 100644 --- a/qcsrc/common/animdecide.qh +++ b/qcsrc/common/animdecide.qh @@ -1,6 +1,9 @@ // client side frame inferring void animdecide_init(entity e); -void animdecide_setframes(entity e, float support_blending); + +// flags to pass here +float FL_ONGROUND = 512; +void animdecide_setframes(entity e, float flg, float support_blending, .float fld_frame, .float fld_frame1time, .float fld_frame2, .float fld_frame2time); // please network this one .float anim_state; @@ -23,6 +26,7 @@ void animdecide_setstate(entity e, float newstate, float restart); #define ANIMIMPLICITSTATE_BACKWARDS 4 #define ANIMIMPLICITSTATE_LEFT 8 #define ANIMIMPLICITSTATE_RIGHT 16 +#define ANIMIMPLICITSTATE_JUMPRELEASED 32 // explicit actions (networked); negative values are for lower body void animdecide_setaction(entity e, float action, float restart); diff --git a/qcsrc/common/csqcmodel_settings.qh b/qcsrc/common/csqcmodel_settings.qh index 96c8aacf9..028ce9b8c 100644 --- a/qcsrc/common/csqcmodel_settings.qh +++ b/qcsrc/common/csqcmodel_settings.qh @@ -1,5 +1,5 @@ // define this if svqc code wants to use .frame2 and .lerpfrac -#define CSQCMODEL_HAVE_TWO_FRAMES +//#define CSQCMODEL_HAVE_TWO_FRAMES // don't define this ever //#define CSQCMODEL_SUPPORT_GETTAGINFO_BEFORE_DRAW @@ -47,7 +47,7 @@ #define CSQCMODEL_HOOK_POSTUPDATE \ CSQCModel_Hook_PostUpdate(isnew, isplayer, islocalplayer); #define CSQCMODEL_HOOK_PREDRAW \ - CSQCModel_Hook_PreDraw(); + CSQCModel_Hook_PreDraw(isplayer); #define CSQCPLAYER_HOOK_POSTCAMERASETUP // force updates of player entities that often even if unchanged diff --git a/qcsrc/common/util.qc b/qcsrc/common/util.qc index 79fd219a2..7b08c2c5c 100644 --- a/qcsrc/common/util.qc +++ b/qcsrc/common/util.qc @@ -2473,13 +2473,18 @@ vector vec3(float x, float y, float z) return v; } -vector animfixfps(entity e, vector a) +vector animfixfps(entity e, vector a, vector b) { // multi-frame anim: keep as-is if(a_y == 1) { float dur; dur = frameduration(e.modelindex, a_x); + if(dur <= 0 && b_y) + { + a = b; + dur = frameduration(e.modelindex, a_x); + } if(dur > 0) a_z = 1.0 / dur; } diff --git a/qcsrc/common/util.qh b/qcsrc/common/util.qh index a9c3859cf..a5b1d985c 100644 --- a/qcsrc/common/util.qh +++ b/qcsrc/common/util.qh @@ -364,4 +364,4 @@ void FindConnectedComponent(entity e, .entity fld, findNextEntityNearFunction_t vector vec3(float x, float y, float z); -vector animfixfps(entity e, vector a); +vector animfixfps(entity e, vector a, vector b); diff --git a/qcsrc/csqcmodellib/cl_model.qc b/qcsrc/csqcmodellib/cl_model.qc index 065e5495c..b2157f5dd 100644 --- a/qcsrc/csqcmodellib/cl_model.qc +++ b/qcsrc/csqcmodellib/cl_model.qc @@ -94,9 +94,9 @@ void CSQCModel_InterpolateAnimation_1To2_Note(float sf, float set_times) void CSQCModel_InterpolateAnimation_Note(float sf) { #ifdef CSQCMODEL_HAVE_TWO_FRAMES - CSQCModel_InterpolateAnimation_2To4_Note(sf, FALSE); + CSQCModel_InterpolateAnimation_2To4_Note(sf, TRUE); #else - CSQCModel_InterpolateAnimation_1To2_Note(sf, FALSE); + CSQCModel_InterpolateAnimation_1To2_Note(sf, TRUE); #endif } diff --git a/qcsrc/server/cl_player.qc b/qcsrc/server/cl_player.qc index 1791bfeef..c6f67a206 100644 --- a/qcsrc/server/cl_player.qc +++ b/qcsrc/server/cl_player.qc @@ -245,7 +245,7 @@ void player_anim (void) animbits |= ANIMSTATE_DUCK; animdecide_setstate(self, animbits, FALSE); - animdecide_setframes(self, FALSE); + animdecide_setframes(self, self.flags, FALSE, frame, frame1time, frame2, frame2time); if (self.weaponentity) { diff --git a/qcsrc/server/cl_weaponsystem.qc b/qcsrc/server/cl_weaponsystem.qc index 4ab5ade72..e2e547a23 100644 --- a/qcsrc/server/cl_weaponsystem.qc +++ b/qcsrc/server/cl_weaponsystem.qc @@ -343,10 +343,10 @@ void CL_WeaponEntity_SetModel(string name) setmodel(self, strcat("models/weapons/h_", name, ".iqm")); // precision set below // preset some defaults that work great for renamed zym files (which don't need an animinfo) - self.anim_fire1 = animfixfps(self, '0 1 0.01'); - self.anim_fire2 = animfixfps(self, '1 1 0.01'); - self.anim_idle = animfixfps(self, '2 1 0.01'); - self.anim_reload = animfixfps(self, '3 1 0.01'); + self.anim_fire1 = animfixfps(self, '0 1 0.01', '0 0 0'); + self.anim_fire2 = animfixfps(self, '1 1 0.01', '0 0 0'); + self.anim_idle = animfixfps(self, '2 1 0.01', '0 0 0'); + self.anim_reload = animfixfps(self, '3 1 0.01', '0 0 0'); // if we have a "weapon" tag, let's attach the v_ model to it ("invisible hand" style model) // if we don't, this is a "real" animated model -- 2.39.2