home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 113 / EnigmaAmiga113CD.iso / software / sviluppo / quakeworld_src / client / cl_pred.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-06-17  |  5.6 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.