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