]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/csqcmodel/cl_model.qc
restructure a bit :)
[xonotic/xonotic-data.pk3dir.git] / qcsrc / csqcmodel / cl_model.qc
index 6fc076b865fb5e3cffd3409cf69f8e5ad0f51bcf..f1607c08d96f915ac5a8eac0e14af15180d0fc52 100644 (file)
  * IN THE SOFTWARE.
  */
 
-// generic CSQC model code
-
 var float autocvar_cl_lerpanim_maxdelta_framegroups = 0.1;
 var float autocvar_cl_nolerp = 0;
 
 .float csqcmodel_lerpfrac;
 .float csqcmodel_lerpfrac2;
 .float csqcmodel_lerpfractime;
+.float csqcmodel_lerpfrac2time;
+.float csqcmodel_teleported;
 
 void CSQCModel_InterpolateAnimation_PreNote(float sf)
 {
-#ifdef CSQCMODELS_HAVE_TWO_FRAMES
-       if(sf & PROPERTY_FRAME)
+#ifdef CSQCMODEL_HAVE_TWO_FRAMES
+       if(sf & CSQCMODEL_PROPERTY_FRAME)
        {
                self.frame3 = self.frame;
                self.frame3time = self.frame1time;
        }
-       if(sf & PROPERTY_FRAME2)
+       if(sf & CSQCMODEL_PROPERTY_FRAME2)
        {
                self.frame4 = self.frame2;
                self.frame4time = self.frame2time;
        }
-       if(sf & PROPERTY_LERPFRAC)
+       if(sf & CSQCMODEL_PROPERTY_LERPFRAC)
        {
                self.csqcmodel_lerpfrac2 = self.csqcmodel_lerpfrac;
+               self.csqcmodel_lerpfrac2time = self.csqcmodel_lerpfractime;
                self.lerpfrac = self.csqcmodel_lerpfrac;
        }
 #else
-       if(sf & PROPERTY_FRAME)
+       if(sf & CSQCMODEL_PROPERTY_FRAME)
        {
                self.frame2 = self.frame;
                self.frame2time = self.frame1time;
-               self.frame1time = time;
        }
 #endif
 }
 
 void CSQCModel_InterpolateAnimation_Note(float sf)
 {
-#ifdef CSQCMODELS_HAVE_TWO_FRAMES
-       if(sf & PROPERTY_FRAME)
+#ifdef CSQCMODEL_HAVE_TWO_FRAMES
+       if(sf & CSQCMODEL_PROPERTY_FRAME)
        {
                self.frame1time = time;
        }
-       if(sf & PROPERTY_FRAME2)
+       if(sf & CSQCMODEL_PROPERTY_FRAME2)
        {
                self.frame2time = time;
        }
-       if(sf & PROPERTY_LERPFRAC)
+       if(sf & CSQCMODEL_PROPERTY_LERPFRAC)
        {
                self.csqcmodel_lerpfrac = self.lerpfrac;
                self.csqcmodel_lerpfractime = time;
        }
 #else
-       if(sf & PROPERTY_FRAME)
+       if(sf & CSQCMODEL_PROPERTY_FRAME)
        {
-               self.frame2 = self.frame;
-               self.frame2time = self.frame1time;
                self.frame1time = time;
        }
 #endif
@@ -85,7 +83,7 @@ void CSQCModel_InterpolateAnimation_Note(float sf)
 
 void CSQCModel_InterpolateAnimation_Do()
 {
-#ifdef CSQCMODELS_HAVE_TWO_FRAMES
+#ifdef CSQCMODEL_HAVE_TWO_FRAMES
        if(autocvar_cl_nolerp || (autocvar_cl_lerpanim_maxdelta_framegroups == 0))
        {
                self.lerpfrac = self.csqcmodel_lerpfrac;
@@ -96,14 +94,39 @@ void CSQCModel_InterpolateAnimation_Do()
        {
                float l13, l24, llf;
                float l24_13;
-               l13 = bound(0, (time - self.frame1time) / autocvar_cl_lerpanim_maxdelta_framegroups, 1);
-               l24 = bound(0, (time - self.frame2time) / autocvar_cl_lerpanim_maxdelta_framegroups, 1);
-               llf = bound(0, (time - self.csqcmodel_lerpfractime) / autocvar_cl_lerpanim_maxdelta_framegroups, 1);
+
+               if(self.frame3time == 0) // if frame1/3 were not previously displayed, only frame1 can make sense
+                       l13 = 1;
+               else
+                       l13 = bound(0, (time - self.frame1time) / autocvar_cl_lerpanim_maxdelta_framegroups, 1);
+
+               if(self.frame4time == 0) // if frame2/4 were not previously displayed, only frame2 can make sense
+                       l24 = 1;
+               else
+                       l24 = bound(0, (time - self.frame2time) / autocvar_cl_lerpanim_maxdelta_framegroups, 1);
+
+               if(self.csqcmodel_lerpfrac2time == 0) // if there is no old lerpfrac (newly displayed model), only lerpfrac makes sense
+                       llf = 1;
+               else
+                       llf = bound(0, (time - self.csqcmodel_lerpfractime) / autocvar_cl_lerpanim_maxdelta_framegroups, 1);
+
                l24_13 = self.csqcmodel_lerpfrac * llf + self.csqcmodel_lerpfrac2 * (1 - llf);
 
                self.lerpfrac  = l24 * l24_13;
                self.lerpfrac4 = (1 - l24) * l24_13;
                self.lerpfrac3 = (1 - l13) * (1 - l24_13);
+
+               if(l24_13 == 0) // if frames 2/4 are not displayed, clear their frametime
+               {
+                       self.frame2time = 0;
+                       self.frame4time = 0;
+               }
+
+               if(l24_13 == 1) // if frames 1/3 are not displayed, clear their frametime
+               {
+                       self.frame1time = 0;
+                       self.frame3time = 0;
+               }
        }
 #else
        if(autocvar_cl_nolerp || (autocvar_cl_lerpanim_maxdelta_framegroups == 0))
@@ -119,8 +142,15 @@ void CSQCModel_InterpolateAnimation_Do()
 
 void CSQCModel_Draw()
 {
-       InterpolateOrigin_Do();
+       // we don't do this for the local player as that one is already handled
+       // by CSQCPlayer_SetCamera()
+       if(!CSQCPlayer_IsLocalPlayer())
+               InterpolateOrigin_Do();
+
+       // TODO csqcplayers: run prediction here too
        CSQCModel_InterpolateAnimation_Do();
+
+       { CSQCMODEL_HOOK_PREDRAW }
 }
 
 void CSQCModel_Read()
@@ -128,31 +158,56 @@ void CSQCModel_Read()
        float sf;
        sf = ReadShort();
 
+       // some nice flags for CSQCMODEL_IF and the hooks
+       float isplayer = (self.entnum >= 1 && self.entnum <= maxclients);
+       float islocalplayer = (self.entnum == player_localentnum);
+       float isnolocalplayer = (isplayer && (self.entnum != player_localentnum));
+
        self.iflags |= IFLAG_ANGLES; // interpolate angles too
 
+       { CSQCMODEL_HOOK_PREUPDATE }
+
        CSQCPlayer_PreUpdate();
        InterpolateOrigin_Undo();
        CSQCModel_InterpolateAnimation_PreNote(sf);
 
-#define PROPERTY(flag,r,w,f) \
+#define CSQCMODEL_IF(cond) if(cond) {
+#define CSQCMODEL_ENDIF }
+#define CSQCMODEL_PROPERTY(flag,t,r,w,f) \
        if(sf & flag) \
                self.f = r();
-#define PROPERTY_SCALED(flag,r,w,f,s,mi,ma) \
+#define CSQCMODEL_PROPERTY_SCALED(flag,t,r,w,f,s,mi,ma) \
        if(sf & flag) \
                self.f = r() / s;
        ALLPROPERTIES
-#undef PROPERTY_SCALED
-#undef PROPERTY
+#undef CSQCMODEL_PROPERTY_SCALED
+#undef CSQCMODEL_PROPERTY
+#undef CSQCMODEL_ENDIF
+#undef CSQCMODEL_IF
+
+       if(sf & CSQCMODEL_PROPERTY_MODELINDEX)
+               setmodelindex(self, self.modelindex); // this retrieves the .model key and sets mins/maxs/absmin/absmax
+
+       if(sf & CSQCMODEL_PROPERTY_TELEPORTED)
+       {
+               self.iflags |= IFLAG_TELEPORTED;
+               self.csqcmodel_teleported = 1;
+       }
        
        CSQCModel_InterpolateAnimation_Note(sf);
        InterpolateOrigin_Note();
        CSQCPlayer_PostUpdate();
 
-#ifdef CSQCMODELS_SUPPORT_GETTAGINFO_BEFORE_DRAW
+       { CSQCMODEL_HOOK_POSTUPDATE }
+
+#ifdef CSQCMODEL_SUPPORT_GETTAGINFO_BEFORE_DRAW
        InterpolateOrigin_Do();
        CSQCModel_InterpolateAnimation_Do();
 #endif
 
+       // relink
+       setorigin(self, self.origin);
+
        // draw it
        self.drawmask = MASK_NORMAL;
        self.predraw = CSQCModel_Draw;