cl_input.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534
  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. // cl.input.c -- builds an intended movement command to send to the server
  16. #include "quakedef.h"
  17. cvar_t cl_nodelta = {"cl_nodelta","0"};
  18. /*
  19. ===============================================================================
  20. KEY BUTTONS
  21. Continuous button event tracking is complicated by the fact that two different
  22. input sources (say, mouse button 1 and the control key) can both press the
  23. same button, but the button should only be released when both of the
  24. pressing key have been released.
  25. When a key event issues a button command (+forward, +attack, etc), it appends
  26. its key number as a parameter to the command so it can be matched up with
  27. the release.
  28. state bit 0 is the current state of the key
  29. state bit 1 is edge triggered on the up to down transition
  30. state bit 2 is edge triggered on the down to up transition
  31. ===============================================================================
  32. */
  33. kbutton_t in_mlook, in_klook;
  34. kbutton_t in_left, in_right, in_forward, in_back;
  35. kbutton_t in_lookup, in_lookdown, in_moveleft, in_moveright;
  36. kbutton_t in_strafe, in_speed, in_use, in_jump, in_attack;
  37. kbutton_t in_up, in_down;
  38. int in_impulse;
  39. void KeyDown (kbutton_t *b)
  40. {
  41. int k;
  42. char *c;
  43. c = Cmd_Argv(1);
  44. if (c[0])
  45. k = atoi(c);
  46. else
  47. k = -1; // typed manually at the console for continuous down
  48. if (k == b->down[0] || k == b->down[1])
  49. return; // repeating key
  50. if (!b->down[0])
  51. b->down[0] = k;
  52. else if (!b->down[1])
  53. b->down[1] = k;
  54. else
  55. {
  56. Con_Printf ("Three keys down for a button!\n");
  57. return;
  58. }
  59. if (b->state & 1)
  60. return; // still down
  61. b->state |= 1 + 2; // down + impulse down
  62. }
  63. void KeyUp (kbutton_t *b)
  64. {
  65. int k;
  66. char *c;
  67. c = Cmd_Argv(1);
  68. if (c[0])
  69. k = atoi(c);
  70. else
  71. { // typed manually at the console, assume for unsticking, so clear all
  72. b->down[0] = b->down[1] = 0;
  73. b->state = 4; // impulse up
  74. return;
  75. }
  76. if (b->down[0] == k)
  77. b->down[0] = 0;
  78. else if (b->down[1] == k)
  79. b->down[1] = 0;
  80. else
  81. return; // key up without coresponding down (menu pass through)
  82. if (b->down[0] || b->down[1])
  83. return; // some other key is still holding it down
  84. if (!(b->state & 1))
  85. return; // still up (this should not happen)
  86. b->state &= ~1; // now up
  87. b->state |= 4; // impulse up
  88. }
  89. void IN_KLookDown (void) {KeyDown(&in_klook);}
  90. void IN_KLookUp (void) {KeyUp(&in_klook);}
  91. void IN_MLookDown (void) {KeyDown(&in_mlook);}
  92. void IN_MLookUp (void) {
  93. KeyUp(&in_mlook);
  94. if ( !(in_mlook.state&1) && lookspring.value)
  95. V_StartPitchDrift();
  96. }
  97. void IN_UpDown(void) {KeyDown(&in_up);}
  98. void IN_UpUp(void) {KeyUp(&in_up);}
  99. void IN_DownDown(void) {KeyDown(&in_down);}
  100. void IN_DownUp(void) {KeyUp(&in_down);}
  101. void IN_LeftDown(void) {KeyDown(&in_left);}
  102. void IN_LeftUp(void) {KeyUp(&in_left);}
  103. void IN_RightDown(void) {KeyDown(&in_right);}
  104. void IN_RightUp(void) {KeyUp(&in_right);}
  105. void IN_ForwardDown(void) {KeyDown(&in_forward);}
  106. void IN_ForwardUp(void) {KeyUp(&in_forward);}
  107. void IN_BackDown(void) {KeyDown(&in_back);}
  108. void IN_BackUp(void) {KeyUp(&in_back);}
  109. void IN_LookupDown(void) {KeyDown(&in_lookup);}
  110. void IN_LookupUp(void) {KeyUp(&in_lookup);}
  111. void IN_LookdownDown(void) {KeyDown(&in_lookdown);}
  112. void IN_LookdownUp(void) {KeyUp(&in_lookdown);}
  113. void IN_MoveleftDown(void) {KeyDown(&in_moveleft);}
  114. void IN_MoveleftUp(void) {KeyUp(&in_moveleft);}
  115. void IN_MoverightDown(void) {KeyDown(&in_moveright);}
  116. void IN_MoverightUp(void) {KeyUp(&in_moveright);}
  117. void IN_SpeedDown(void) {KeyDown(&in_speed);}
  118. void IN_SpeedUp(void) {KeyUp(&in_speed);}
  119. void IN_StrafeDown(void) {KeyDown(&in_strafe);}
  120. void IN_StrafeUp(void) {KeyUp(&in_strafe);}
  121. void IN_AttackDown(void) {KeyDown(&in_attack);}
  122. void IN_AttackUp(void) {KeyUp(&in_attack);}
  123. void IN_UseDown (void) {KeyDown(&in_use);}
  124. void IN_UseUp (void) {KeyUp(&in_use);}
  125. void IN_JumpDown (void) {KeyDown(&in_jump);}
  126. void IN_JumpUp (void) {KeyUp(&in_jump);}
  127. void IN_Impulse (void) {in_impulse=Q_atoi(Cmd_Argv(1));}
  128. /*
  129. ===============
  130. CL_KeyState
  131. Returns 0.25 if a key was pressed and released during the frame,
  132. 0.5 if it was pressed and held
  133. 0 if held then released, and
  134. 1.0 if held for the entire time
  135. ===============
  136. */
  137. float CL_KeyState (kbutton_t *key)
  138. {
  139. float val;
  140. qboolean impulsedown, impulseup, down;
  141. impulsedown = key->state & 2;
  142. impulseup = key->state & 4;
  143. down = key->state & 1;
  144. val = 0;
  145. if (impulsedown && !impulseup)
  146. if (down)
  147. val = 0.5; // pressed and held this frame
  148. else
  149. val = 0; // I_Error ();
  150. if (impulseup && !impulsedown)
  151. if (down)
  152. val = 0; // I_Error ();
  153. else
  154. val = 0; // released this frame
  155. if (!impulsedown && !impulseup)
  156. if (down)
  157. val = 1.0; // held the entire frame
  158. else
  159. val = 0; // up the entire frame
  160. if (impulsedown && impulseup)
  161. if (down)
  162. val = 0.75; // released and re-pressed this frame
  163. else
  164. val = 0.25; // pressed and released this frame
  165. key->state &= 1; // clear impulses
  166. return val;
  167. }
  168. //==========================================================================
  169. cvar_t cl_upspeed = {"cl_upspeed","200"};
  170. cvar_t cl_forwardspeed = {"cl_forwardspeed","200", true};
  171. cvar_t cl_backspeed = {"cl_backspeed","200", true};
  172. cvar_t cl_sidespeed = {"cl_sidespeed","350"};
  173. cvar_t cl_movespeedkey = {"cl_movespeedkey","2.0"};
  174. cvar_t cl_yawspeed = {"cl_yawspeed","140"};
  175. cvar_t cl_pitchspeed = {"cl_pitchspeed","150"};
  176. cvar_t cl_anglespeedkey = {"cl_anglespeedkey","1.5"};
  177. /*
  178. ================
  179. CL_AdjustAngles
  180. Moves the local angle positions
  181. ================
  182. */
  183. void CL_AdjustAngles (void)
  184. {
  185. float speed;
  186. float up, down;
  187. if (in_speed.state & 1)
  188. speed = host_frametime * cl_anglespeedkey.value;
  189. else
  190. speed = host_frametime;
  191. if (!(in_strafe.state & 1))
  192. {
  193. cl.viewangles[YAW] -= speed*cl_yawspeed.value*CL_KeyState (&in_right);
  194. cl.viewangles[YAW] += speed*cl_yawspeed.value*CL_KeyState (&in_left);
  195. cl.viewangles[YAW] = anglemod(cl.viewangles[YAW]);
  196. }
  197. if (in_klook.state & 1)
  198. {
  199. V_StopPitchDrift ();
  200. cl.viewangles[PITCH] -= speed*cl_pitchspeed.value * CL_KeyState (&in_forward);
  201. cl.viewangles[PITCH] += speed*cl_pitchspeed.value * CL_KeyState (&in_back);
  202. }
  203. up = CL_KeyState (&in_lookup);
  204. down = CL_KeyState(&in_lookdown);
  205. cl.viewangles[PITCH] -= speed*cl_pitchspeed.value * up;
  206. cl.viewangles[PITCH] += speed*cl_pitchspeed.value * down;
  207. if (up || down)
  208. V_StopPitchDrift ();
  209. if (cl.viewangles[PITCH] > 80)
  210. cl.viewangles[PITCH] = 80;
  211. if (cl.viewangles[PITCH] < -70)
  212. cl.viewangles[PITCH] = -70;
  213. if (cl.viewangles[ROLL] > 50)
  214. cl.viewangles[ROLL] = 50;
  215. if (cl.viewangles[ROLL] < -50)
  216. cl.viewangles[ROLL] = -50;
  217. }
  218. /*
  219. ================
  220. CL_BaseMove
  221. Send the intended movement message to the server
  222. ================
  223. */
  224. void CL_BaseMove (usercmd_t *cmd)
  225. {
  226. CL_AdjustAngles ();
  227. memset (cmd, 0, sizeof(*cmd));
  228. VectorCopy (cl.viewangles, cmd->angles);
  229. if (in_strafe.state & 1)
  230. {
  231. cmd->sidemove += cl_sidespeed.value * CL_KeyState (&in_right);
  232. cmd->sidemove -= cl_sidespeed.value * CL_KeyState (&in_left);
  233. }
  234. cmd->sidemove += cl_sidespeed.value * CL_KeyState (&in_moveright);
  235. cmd->sidemove -= cl_sidespeed.value * CL_KeyState (&in_moveleft);
  236. cmd->upmove += cl_upspeed.value * CL_KeyState (&in_up);
  237. cmd->upmove -= cl_upspeed.value * CL_KeyState (&in_down);
  238. if (! (in_klook.state & 1) )
  239. {
  240. cmd->forwardmove += cl_forwardspeed.value * CL_KeyState (&in_forward);
  241. cmd->forwardmove -= cl_backspeed.value * CL_KeyState (&in_back);
  242. }
  243. //
  244. // adjust for speed key
  245. //
  246. if (in_speed.state & 1)
  247. {
  248. cmd->forwardmove *= cl_movespeedkey.value;
  249. cmd->sidemove *= cl_movespeedkey.value;
  250. cmd->upmove *= cl_movespeedkey.value;
  251. }
  252. }
  253. int MakeChar (int i)
  254. {
  255. i &= ~3;
  256. if (i < -127*4)
  257. i = -127*4;
  258. if (i > 127*4)
  259. i = 127*4;
  260. return i;
  261. }
  262. /*
  263. ==============
  264. CL_FinishMove
  265. ==============
  266. */
  267. void CL_FinishMove (usercmd_t *cmd)
  268. {
  269. int i;
  270. int ms;
  271. //
  272. // allways dump the first two message, because it may contain leftover inputs
  273. // from the last level
  274. //
  275. if (++cl.movemessages <= 2)
  276. return;
  277. //
  278. // figure button bits
  279. //
  280. if ( in_attack.state & 3 )
  281. cmd->buttons |= 1;
  282. in_attack.state &= ~2;
  283. if (in_jump.state & 3)
  284. cmd->buttons |= 2;
  285. in_jump.state &= ~2;
  286. // send milliseconds of time to apply the move
  287. ms = host_frametime * 1000;
  288. if (ms > 250)
  289. ms = 100; // time was unreasonable
  290. cmd->msec = ms;
  291. VectorCopy (cl.viewangles, cmd->angles);
  292. cmd->impulse = in_impulse;
  293. in_impulse = 0;
  294. //
  295. // chop down so no extra bits are kept that the server wouldn't get
  296. //
  297. cmd->forwardmove = MakeChar (cmd->forwardmove);
  298. cmd->sidemove = MakeChar (cmd->sidemove);
  299. cmd->upmove = MakeChar (cmd->upmove);
  300. for (i=0 ; i<3 ; i++)
  301. cmd->angles[i] = ((int)(cmd->angles[i]*65536.0/360)&65535) * (360.0/65536.0);
  302. }
  303. /*
  304. =================
  305. CL_SendCmd
  306. =================
  307. */
  308. void CL_SendCmd (void)
  309. {
  310. sizebuf_t buf;
  311. byte data[128];
  312. int i;
  313. usercmd_t *cmd, *oldcmd;
  314. int checksumIndex;
  315. int lost;
  316. int seq_hash;
  317. if (cls.demoplayback)
  318. return; // sendcmds come from the demo
  319. // save this command off for prediction
  320. i = cls.netchan.outgoing_sequence & UPDATE_MASK;
  321. cmd = &cl.frames[i].cmd;
  322. cl.frames[i].senttime = realtime;
  323. cl.frames[i].receivedtime = -1; // we haven't gotten a reply yet
  324. // seq_hash = (cls.netchan.outgoing_sequence & 0xffff) ; // ^ QW_CHECK_HASH;
  325. seq_hash = cls.netchan.outgoing_sequence;
  326. // get basic movement from keyboard
  327. CL_BaseMove (cmd);
  328. // allow mice or other external controllers to add to the move
  329. IN_Move (cmd);
  330. // if we are spectator, try autocam
  331. if (cl.spectator)
  332. Cam_Track(cmd);
  333. CL_FinishMove(cmd);
  334. Cam_FinishMove(cmd);
  335. // send this and the previous cmds in the message, so
  336. // if the last packet was dropped, it can be recovered
  337. buf.maxsize = 128;
  338. buf.cursize = 0;
  339. buf.data = data;
  340. MSG_WriteByte (&buf, clc_move);
  341. // save the position for a checksum byte
  342. checksumIndex = buf.cursize;
  343. MSG_WriteByte (&buf, 0);
  344. // write our lossage percentage
  345. lost = CL_CalcNet();
  346. MSG_WriteByte (&buf, (byte)lost);
  347. i = (cls.netchan.outgoing_sequence-2) & UPDATE_MASK;
  348. cmd = &cl.frames[i].cmd;
  349. MSG_WriteDeltaUsercmd (&buf, &nullcmd, cmd);
  350. oldcmd = cmd;
  351. i = (cls.netchan.outgoing_sequence-1) & UPDATE_MASK;
  352. cmd = &cl.frames[i].cmd;
  353. MSG_WriteDeltaUsercmd (&buf, oldcmd, cmd);
  354. oldcmd = cmd;
  355. i = (cls.netchan.outgoing_sequence) & UPDATE_MASK;
  356. cmd = &cl.frames[i].cmd;
  357. MSG_WriteDeltaUsercmd (&buf, oldcmd, cmd);
  358. // calculate a checksum over the move commands
  359. buf.data[checksumIndex] = COM_BlockSequenceCRCByte(
  360. buf.data + checksumIndex + 1, buf.cursize - checksumIndex - 1,
  361. seq_hash);
  362. // request delta compression of entities
  363. if (cls.netchan.outgoing_sequence - cl.validsequence >= UPDATE_BACKUP-1)
  364. cl.validsequence = 0;
  365. if (cl.validsequence && !cl_nodelta.value && cls.state == ca_active &&
  366. !cls.demorecording)
  367. {
  368. cl.frames[cls.netchan.outgoing_sequence&UPDATE_MASK].delta_sequence = cl.validsequence;
  369. MSG_WriteByte (&buf, clc_delta);
  370. MSG_WriteByte (&buf, cl.validsequence&255);
  371. }
  372. else
  373. cl.frames[cls.netchan.outgoing_sequence&UPDATE_MASK].delta_sequence = -1;
  374. if (cls.demorecording)
  375. CL_WriteDemoCmd(cmd);
  376. //
  377. // deliver the message
  378. //
  379. Netchan_Transmit (&cls.netchan, buf.cursize, buf.data);
  380. }
  381. /*
  382. ============
  383. CL_InitInput
  384. ============
  385. */
  386. void CL_InitInput (void)
  387. {
  388. Cmd_AddCommand ("+moveup",IN_UpDown);
  389. Cmd_AddCommand ("-moveup",IN_UpUp);
  390. Cmd_AddCommand ("+movedown",IN_DownDown);
  391. Cmd_AddCommand ("-movedown",IN_DownUp);
  392. Cmd_AddCommand ("+left",IN_LeftDown);
  393. Cmd_AddCommand ("-left",IN_LeftUp);
  394. Cmd_AddCommand ("+right",IN_RightDown);
  395. Cmd_AddCommand ("-right",IN_RightUp);
  396. Cmd_AddCommand ("+forward",IN_ForwardDown);
  397. Cmd_AddCommand ("-forward",IN_ForwardUp);
  398. Cmd_AddCommand ("+back",IN_BackDown);
  399. Cmd_AddCommand ("-back",IN_BackUp);
  400. Cmd_AddCommand ("+lookup", IN_LookupDown);
  401. Cmd_AddCommand ("-lookup", IN_LookupUp);
  402. Cmd_AddCommand ("+lookdown", IN_LookdownDown);
  403. Cmd_AddCommand ("-lookdown", IN_LookdownUp);
  404. Cmd_AddCommand ("+strafe", IN_StrafeDown);
  405. Cmd_AddCommand ("-strafe", IN_StrafeUp);
  406. Cmd_AddCommand ("+moveleft", IN_MoveleftDown);
  407. Cmd_AddCommand ("-moveleft", IN_MoveleftUp);
  408. Cmd_AddCommand ("+moveright", IN_MoverightDown);
  409. Cmd_AddCommand ("-moveright", IN_MoverightUp);
  410. Cmd_AddCommand ("+speed", IN_SpeedDown);
  411. Cmd_AddCommand ("-speed", IN_SpeedUp);
  412. Cmd_AddCommand ("+attack", IN_AttackDown);
  413. Cmd_AddCommand ("-attack", IN_AttackUp);
  414. Cmd_AddCommand ("+use", IN_UseDown);
  415. Cmd_AddCommand ("-use", IN_UseUp);
  416. Cmd_AddCommand ("+jump", IN_JumpDown);
  417. Cmd_AddCommand ("-jump", IN_JumpUp);
  418. Cmd_AddCommand ("impulse", IN_Impulse);
  419. Cmd_AddCommand ("+klook", IN_KLookDown);
  420. Cmd_AddCommand ("-klook", IN_KLookUp);
  421. Cmd_AddCommand ("+mlook", IN_MLookDown);
  422. Cmd_AddCommand ("-mlook", IN_MLookUp);
  423. Cvar_RegisterVariable (&cl_nodelta);
  424. }
  425. /*
  426. ============
  427. CL_ClearStates
  428. ============
  429. */
  430. void CL_ClearStates (void)
  431. {
  432. }