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