cl_pred.c 5.4 KB

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