home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Amiga 14 / MA_Cover_14.iso / source / c / q1source_amy / qw / client / cl_pred.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-12-21  |  5.5 KB  |  226 lines

  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20. #include "quakedef.h"
  21. #include "winquake.h"
  22.  
  23. cvar_t    cl_nopred = {"cl_nopred","0"};
  24. cvar_t    cl_pushlatency = {"pushlatency","-999"};
  25.  
  26. extern    frame_t        *view_frame;
  27.  
  28. /*
  29. =================
  30. CL_NudgePosition
  31.  
  32. If pmove.origin is in a solid position,
  33. try nudging slightly on all axis to
  34. allow for the cut precision of the net coordinates
  35. =================
  36. */
  37. void CL_NudgePosition (void)
  38. {
  39.     vec3_t    base;
  40.     int        x, y;
  41.  
  42.     if (PM_HullPointContents (&cl.model_precache[1]->hulls[1], 0, pmove.origin) == CONTENTS_EMPTY)
  43.         return;
  44.  
  45.     VectorCopy (pmove.origin, base);
  46.     for (x=-1 ; x<=1 ; x++)
  47.     {
  48.         for (y=-1 ; y<=1 ; y++)
  49.         {
  50.             pmove.origin[0] = base[0] + x * 1.0/8;
  51.             pmove.origin[1] = base[1] + y * 1.0/8;
  52.             if (PM_HullPointContents (&cl.model_precache[1]->hulls[1], 0, pmove.origin) == CONTENTS_EMPTY)
  53.                 return;
  54.         }
  55.     }
  56.     Con_DPrintf ("CL_NudgePosition: stuck\n");
  57. }
  58.  
  59. /*
  60. ==============
  61. CL_PredictUsercmd
  62. ==============
  63. */
  64. void CL_PredictUsercmd (player_state_t *from, player_state_t *to, usercmd_t *u, qboolean spectator)
  65. {
  66.     // split up very long moves
  67.     if (u->msec > 50)
  68.     {
  69.         player_state_t    temp;
  70.         usercmd_t    split;
  71.  
  72.         split = *u;
  73.         split.msec /= 2;
  74.  
  75.         CL_PredictUsercmd (from, &temp, &split, spectator);
  76.         CL_PredictUsercmd (&temp, to, &split, spectator);
  77.         return;
  78.     }
  79.  
  80.     VectorCopy (from->origin, pmove.origin);
  81. //    VectorCopy (from->viewangles, pmove.angles);
  82.     VectorCopy (u->angles, pmove.angles);
  83.     VectorCopy (from->velocity, pmove.velocity);
  84.  
  85.     pmove.oldbuttons = from->oldbuttons;
  86.     pmove.waterjumptime = from->waterjumptime;
  87.     pmove.dead = cl.stats[STAT_HEALTH] <= 0;
  88.     pmove.spectator = spectator;
  89.  
  90.     pmove.cmd = *u;
  91.  
  92.     PlayerMove ();
  93. //for (i=0 ; i<3 ; i++)
  94. //pmove.origin[i] = ((int)(pmove.origin[i]*8))*0.125;
  95.     to->waterjumptime = pmove.waterjumptime;
  96.     to->oldbuttons = pmove.cmd.buttons;
  97.     VectorCopy (pmove.origin, to->origin);
  98.     VectorCopy (pmove.angles, to->viewangles);
  99.     VectorCopy (pmove.velocity, to->velocity);
  100.     to->onground = onground;
  101.  
  102.     to->weaponframe = from->weaponframe;
  103. }
  104.  
  105.  
  106.  
  107. /*
  108. ==============
  109. CL_PredictMove
  110. ==============
  111. */
  112. void CL_PredictMove (void)
  113. {
  114.     int            i;
  115.     float        f;
  116.     frame_t        *from, *to = NULL;
  117.     int            oldphysent;
  118.  
  119.     if (cl_pushlatency.value > 0)
  120.         Cvar_Set ("pushlatency", "0");
  121.  
  122.     if (cl.paused)
  123.         return;
  124.  
  125.     cl.time = realtime - cls.latency - cl_pushlatency.value*0.001;
  126.     if (cl.time > realtime)
  127.         cl.time = realtime;
  128.  
  129.     if (cl.intermission)
  130.         return;
  131.  
  132.     if (!cl.validsequence)
  133.         return;
  134.  
  135.     if (cls.netchan.outgoing_sequence - cls.netchan.incoming_sequence >= UPDATE_BACKUP-1)
  136.         return;
  137.  
  138.     VectorCopy (cl.viewangles, cl.simangles);
  139.  
  140.     // this is the last frame received from the server
  141.     from = &cl.frames[cls.netchan.incoming_sequence & UPDATE_MASK];
  142.  
  143.     // we can now render a frame
  144.     if (cls.state == ca_onserver)
  145.     {    // first update is the final signon stage
  146.         char        text[1024];
  147.  
  148.         cls.state = ca_active;
  149.         sprintf (text, "QuakeWorld: %s", cls.servername);
  150. #ifdef _WIN32
  151.         SetWindowText (mainwindow, text);
  152. #endif
  153.     }
  154.  
  155.     if (cl_nopred.value)
  156.     {
  157.         VectorCopy (from->playerstate[cl.playernum].velocity, cl.simvel);
  158.         VectorCopy (from->playerstate[cl.playernum].origin, cl.simorg);
  159.         return;
  160.     }
  161.  
  162.     // predict forward until cl.time <= to->senttime
  163.     oldphysent = pmove.numphysent;
  164.     CL_SetSolidPlayers (cl.playernum);
  165.  
  166. //    to = &cl.frames[cls.netchan.incoming_sequence & UPDATE_MASK];
  167.  
  168.     for (i=1 ; i<UPDATE_BACKUP-1 && cls.netchan.incoming_sequence+i <
  169.             cls.netchan.outgoing_sequence; i++)
  170.     {
  171.         to = &cl.frames[(cls.netchan.incoming_sequence+i) & UPDATE_MASK];
  172.         CL_PredictUsercmd (&from->playerstate[cl.playernum]
  173.             , &to->playerstate[cl.playernum], &to->cmd, cl.spectator);
  174.         if (to->senttime >= cl.time)
  175.             break;
  176.         from = to;
  177.     }
  178.  
  179.     pmove.numphysent = oldphysent;
  180.  
  181.     if (i == UPDATE_BACKUP-1 || !to)
  182.         return;        // net hasn't deliver packets in a long time...
  183.  
  184.     // now interpolate some fraction of the final frame
  185.     if (to->senttime == from->senttime)
  186.         f = 0;
  187.     else
  188.     {
  189.         f = (cl.time - from->senttime) / (to->senttime - from->senttime);
  190.  
  191.         if (f < 0)
  192.             f = 0;
  193.         if (f > 1)
  194.             f = 1;
  195.     }
  196.  
  197.     for (i=0 ; i<3 ; i++)
  198.         if ( fabs(from->playerstate[cl.playernum].origin[i] - to->playerstate[cl.playernum].origin[i]) > 128)
  199.         {    // teleported, so don't lerp
  200.             VectorCopy (to->playerstate[cl.playernum].velocity, cl.simvel);
  201.             VectorCopy (to->playerstate[cl.playernum].origin, cl.simorg);
  202.             return;
  203.         }
  204.         
  205.     for (i=0 ; i<3 ; i++)
  206.     {
  207.         cl.simorg[i] = from->playerstate[cl.playernum].origin[i] 
  208.             + f*(to->playerstate[cl.playernum].origin[i] - from->playerstate[cl.playernum].origin[i]);
  209.         cl.simvel[i] = from->playerstate[cl.playernum].velocity[i] 
  210.             + f*(to->playerstate[cl.playernum].velocity[i] - from->playerstate[cl.playernum].velocity[i]);
  211.     }        
  212. }
  213.  
  214.  
  215. /*
  216. ==============
  217. CL_InitPrediction
  218. ==============
  219. */
  220. void CL_InitPrediction (void)
  221. {
  222.     Cvar_RegisterVariable (&cl_pushlatency);
  223.     Cvar_RegisterVariable (&cl_nopred);
  224. }
  225.  
  226.