home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Amiga 14 / MA_Cover_14.iso / source / c / q1source_amy / qw / client / cl_input.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-12-21  |  13.2 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. {    
  284.     CL_AdjustAngles ();
  285.     
  286.     memset (cmd, 0, sizeof(*cmd));
  287.     
  288.     VectorCopy (cl.viewangles, cmd->angles);
  289.     if (in_strafe.state & 1)
  290.     {
  291.         cmd->sidemove += cl_sidespeed.value * CL_KeyState (&in_right);
  292.         cmd->sidemove -= cl_sidespeed.value * CL_KeyState (&in_left);
  293.     }
  294.  
  295.     cmd->sidemove += cl_sidespeed.value * CL_KeyState (&in_moveright);
  296.     cmd->sidemove -= cl_sidespeed.value * CL_KeyState (&in_moveleft);
  297.  
  298.     cmd->upmove += cl_upspeed.value * CL_KeyState (&in_up);
  299.     cmd->upmove -= cl_upspeed.value * CL_KeyState (&in_down);
  300.  
  301.     if (! (in_klook.state & 1) )
  302.     {    
  303.         cmd->forwardmove += cl_forwardspeed.value * CL_KeyState (&in_forward);
  304.         cmd->forwardmove -= cl_backspeed.value * CL_KeyState (&in_back);
  305.     }    
  306.  
  307. //
  308. // adjust for speed key
  309. //
  310.     if (in_speed.state & 1)
  311.     {
  312.         cmd->forwardmove *= cl_movespeedkey.value;
  313.         cmd->sidemove *= cl_movespeedkey.value;
  314.         cmd->upmove *= cl_movespeedkey.value;
  315.     }    
  316. }
  317.  
  318. int MakeChar (int i)
  319. {
  320.     i &= ~3;
  321.     if (i < -127*4)
  322.         i = -127*4;
  323.     if (i > 127*4)
  324.         i = 127*4;
  325.     return i;
  326. }
  327.  
  328. /*
  329. ==============
  330. CL_FinishMove
  331. ==============
  332. */
  333. void CL_FinishMove (usercmd_t *cmd)
  334. {
  335.     int        i;
  336.     int        ms;
  337.  
  338. //
  339. // allways dump the first two message, because it may contain leftover inputs
  340. // from the last level
  341. //
  342.     if (++cl.movemessages <= 2)
  343.         return;
  344. //
  345. // figure button bits
  346. //    
  347.     if ( in_attack.state & 3 )
  348.         cmd->buttons |= 1;
  349.     in_attack.state &= ~2;
  350.     
  351.     if (in_jump.state & 3)
  352.         cmd->buttons |= 2;
  353.     in_jump.state &= ~2;
  354.  
  355.     // send milliseconds of time to apply the move
  356.     ms = host_frametime * 1000;
  357.     if (ms > 250)
  358.         ms = 100;        // time was unreasonable
  359.     cmd->msec = ms;
  360.  
  361.     VectorCopy (cl.viewangles, cmd->angles);
  362.  
  363.     cmd->impulse = in_impulse;
  364.     in_impulse = 0;
  365.  
  366.  
  367. //
  368. // chop down so no extra bits are kept that the server wouldn't get
  369. //
  370.     cmd->forwardmove = MakeChar (cmd->forwardmove);
  371.     cmd->sidemove = MakeChar (cmd->sidemove);
  372.     cmd->upmove = MakeChar (cmd->upmove);
  373.  
  374.     for (i=0 ; i<3 ; i++)
  375.         cmd->angles[i] = ((int)(cmd->angles[i]*65536.0/360)&65535) * (360.0/65536.0);
  376. }
  377.  
  378. /*
  379. =================
  380. CL_SendCmd
  381. =================
  382. */
  383. void CL_SendCmd (void)
  384. {
  385.     sizebuf_t    buf;
  386.     byte        data[128];
  387.     int            i;
  388.     usercmd_t    *cmd, *oldcmd;
  389.     int            checksumIndex;
  390.     int            lost;
  391.     int            seq_hash;
  392.  
  393.     if (cls.demoplayback)
  394.         return; // sendcmds come from the demo
  395.  
  396.     // save this command off for prediction
  397.     i = cls.netchan.outgoing_sequence & UPDATE_MASK;
  398.     cmd = &cl.frames[i].cmd;
  399.     cl.frames[i].senttime = realtime;
  400.     cl.frames[i].receivedtime = -1;        // we haven't gotten a reply yet
  401.  
  402. //    seq_hash = (cls.netchan.outgoing_sequence & 0xffff) ; // ^ QW_CHECK_HASH;
  403.     seq_hash = cls.netchan.outgoing_sequence;
  404.  
  405.     // get basic movement from keyboard
  406.     CL_BaseMove (cmd);
  407.  
  408.     // allow mice or other external controllers to add to the move
  409.     IN_Move (cmd);
  410.  
  411.     // if we are spectator, try autocam
  412.     if (cl.spectator)
  413.         Cam_Track(cmd);
  414.  
  415.     CL_FinishMove(cmd);
  416.  
  417.     Cam_FinishMove(cmd);
  418.  
  419. // send this and the previous cmds in the message, so
  420. // if the last packet was dropped, it can be recovered
  421.     buf.maxsize = 128;
  422.     buf.cursize = 0;
  423.     buf.data = data;
  424.  
  425.     MSG_WriteByte (&buf, clc_move);
  426.  
  427.     // save the position for a checksum byte
  428.     checksumIndex = buf.cursize;
  429.     MSG_WriteByte (&buf, 0);
  430.  
  431.     // write our lossage percentage
  432.     lost = CL_CalcNet();
  433.     MSG_WriteByte (&buf, (byte)lost);
  434.  
  435.     i = (cls.netchan.outgoing_sequence-2) & UPDATE_MASK;
  436.     cmd = &cl.frames[i].cmd;
  437.     MSG_WriteDeltaUsercmd (&buf, &nullcmd, cmd);
  438.     oldcmd = cmd;
  439.  
  440.     i = (cls.netchan.outgoing_sequence-1) & UPDATE_MASK;
  441.     cmd = &cl.frames[i].cmd;
  442.     MSG_WriteDeltaUsercmd (&buf, oldcmd, cmd);
  443.     oldcmd = cmd;
  444.  
  445.     i = (cls.netchan.outgoing_sequence) & UPDATE_MASK;
  446.     cmd = &cl.frames[i].cmd;
  447.     MSG_WriteDeltaUsercmd (&buf, oldcmd, cmd);
  448.  
  449.     // calculate a checksum over the move commands
  450.     buf.data[checksumIndex] = COM_BlockSequenceCRCByte(
  451.         buf.data + checksumIndex + 1, buf.cursize - checksumIndex - 1,
  452.         seq_hash);
  453.  
  454.     // request delta compression of entities
  455.     if (cls.netchan.outgoing_sequence - cl.validsequence >= UPDATE_BACKUP-1)
  456.         cl.validsequence = 0;
  457.  
  458.     if (cl.validsequence && !cl_nodelta.value && cls.state == ca_active &&
  459.         !cls.demorecording)
  460.     {
  461.         cl.frames[cls.netchan.outgoing_sequence&UPDATE_MASK].delta_sequence = cl.validsequence;
  462.         MSG_WriteByte (&buf, clc_delta);
  463.         MSG_WriteByte (&buf, cl.validsequence&255);
  464.     }
  465.     else
  466.         cl.frames[cls.netchan.outgoing_sequence&UPDATE_MASK].delta_sequence = -1;
  467.  
  468.     if (cls.demorecording)
  469.         CL_WriteDemoCmd(cmd);
  470.  
  471. //
  472. // deliver the message
  473. //
  474.     Netchan_Transmit (&cls.netchan, buf.cursize, buf.data);    
  475. }
  476.  
  477.  
  478.  
  479. /*
  480. ============
  481. CL_InitInput
  482. ============
  483. */
  484. void CL_InitInput (void)
  485. {
  486.     Cmd_AddCommand ("+moveup",IN_UpDown);
  487.     Cmd_AddCommand ("-moveup",IN_UpUp);
  488.     Cmd_AddCommand ("+movedown",IN_DownDown);
  489.     Cmd_AddCommand ("-movedown",IN_DownUp);
  490.     Cmd_AddCommand ("+left",IN_LeftDown);
  491.     Cmd_AddCommand ("-left",IN_LeftUp);
  492.     Cmd_AddCommand ("+right",IN_RightDown);
  493.     Cmd_AddCommand ("-right",IN_RightUp);
  494.     Cmd_AddCommand ("+forward",IN_ForwardDown);
  495.     Cmd_AddCommand ("-forward",IN_ForwardUp);
  496.     Cmd_AddCommand ("+back",IN_BackDown);
  497.     Cmd_AddCommand ("-back",IN_BackUp);
  498.     Cmd_AddCommand ("+lookup", IN_LookupDown);
  499.     Cmd_AddCommand ("-lookup", IN_LookupUp);
  500.     Cmd_AddCommand ("+lookdown", IN_LookdownDown);
  501.     Cmd_AddCommand ("-lookdown", IN_LookdownUp);
  502.     Cmd_AddCommand ("+strafe", IN_StrafeDown);
  503.     Cmd_AddCommand ("-strafe", IN_StrafeUp);
  504.     Cmd_AddCommand ("+moveleft", IN_MoveleftDown);
  505.     Cmd_AddCommand ("-moveleft", IN_MoveleftUp);
  506.     Cmd_AddCommand ("+moveright", IN_MoverightDown);
  507.     Cmd_AddCommand ("-moveright", IN_MoverightUp);
  508.     Cmd_AddCommand ("+speed", IN_SpeedDown);
  509.     Cmd_AddCommand ("-speed", IN_SpeedUp);
  510.     Cmd_AddCommand ("+attack", IN_AttackDown);
  511.     Cmd_AddCommand ("-attack", IN_AttackUp);
  512.     Cmd_AddCommand ("+use", IN_UseDown);
  513.     Cmd_AddCommand ("-use", IN_UseUp);
  514.     Cmd_AddCommand ("+jump", IN_JumpDown);
  515.     Cmd_AddCommand ("-jump", IN_JumpUp);
  516.     Cmd_AddCommand ("impulse", IN_Impulse);
  517.     Cmd_AddCommand ("+klook", IN_KLookDown);
  518.     Cmd_AddCommand ("-klook", IN_KLookUp);
  519.     Cmd_AddCommand ("+mlook", IN_MLookDown);
  520.     Cmd_AddCommand ("-mlook", IN_MLookUp);
  521.  
  522.     Cvar_RegisterVariable (&cl_nodelta);
  523. }
  524.  
  525. /*
  526. ============
  527. CL_ClearStates
  528. ============
  529. */
  530. void CL_ClearStates (void)
  531. {
  532. }
  533.  
  534.