UsercmdGen.cpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113
  1. /*
  2. ===========================================================================
  3. Doom 3 GPL Source Code
  4. Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
  6. Doom 3 Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. #include "../idlib/precompiled.h"
  21. #pragma hdrstop
  22. #include "Session_local.h"
  23. /*
  24. ================
  25. usercmd_t::ByteSwap
  26. ================
  27. */
  28. void usercmd_t::ByteSwap( void ) {
  29. angles[0] = LittleShort( angles[0] );
  30. angles[1] = LittleShort( angles[1] );
  31. angles[2] = LittleShort( angles[2] );
  32. sequence = LittleLong( sequence );
  33. }
  34. /*
  35. ================
  36. usercmd_t::operator==
  37. ================
  38. */
  39. bool usercmd_t::operator==( const usercmd_t &rhs ) const {
  40. return ( buttons == rhs.buttons &&
  41. forwardmove == rhs.forwardmove &&
  42. rightmove == rhs.rightmove &&
  43. upmove == rhs.upmove &&
  44. angles[0] == rhs.angles[0] &&
  45. angles[1] == rhs.angles[1] &&
  46. angles[2] == rhs.angles[2] &&
  47. impulse == rhs.impulse &&
  48. flags == rhs.flags &&
  49. mx == rhs.mx &&
  50. my == rhs.my );
  51. }
  52. const int KEY_MOVESPEED = 127;
  53. typedef enum {
  54. UB_NONE,
  55. UB_UP,
  56. UB_DOWN,
  57. UB_LEFT,
  58. UB_RIGHT,
  59. UB_FORWARD,
  60. UB_BACK,
  61. UB_LOOKUP,
  62. UB_LOOKDOWN,
  63. UB_STRAFE,
  64. UB_MOVELEFT,
  65. UB_MOVERIGHT,
  66. UB_BUTTON0,
  67. UB_BUTTON1,
  68. UB_BUTTON2,
  69. UB_BUTTON3,
  70. UB_BUTTON4,
  71. UB_BUTTON5,
  72. UB_BUTTON6,
  73. UB_BUTTON7,
  74. UB_ATTACK,
  75. UB_SPEED,
  76. UB_ZOOM,
  77. UB_SHOWSCORES,
  78. UB_MLOOK,
  79. UB_IMPULSE0,
  80. UB_IMPULSE1,
  81. UB_IMPULSE2,
  82. UB_IMPULSE3,
  83. UB_IMPULSE4,
  84. UB_IMPULSE5,
  85. UB_IMPULSE6,
  86. UB_IMPULSE7,
  87. UB_IMPULSE8,
  88. UB_IMPULSE9,
  89. UB_IMPULSE10,
  90. UB_IMPULSE11,
  91. UB_IMPULSE12,
  92. UB_IMPULSE13,
  93. UB_IMPULSE14,
  94. UB_IMPULSE15,
  95. UB_IMPULSE16,
  96. UB_IMPULSE17,
  97. UB_IMPULSE18,
  98. UB_IMPULSE19,
  99. UB_IMPULSE20,
  100. UB_IMPULSE21,
  101. UB_IMPULSE22,
  102. UB_IMPULSE23,
  103. UB_IMPULSE24,
  104. UB_IMPULSE25,
  105. UB_IMPULSE26,
  106. UB_IMPULSE27,
  107. UB_IMPULSE28,
  108. UB_IMPULSE29,
  109. UB_IMPULSE30,
  110. UB_IMPULSE31,
  111. UB_IMPULSE32,
  112. UB_IMPULSE33,
  113. UB_IMPULSE34,
  114. UB_IMPULSE35,
  115. UB_IMPULSE36,
  116. UB_IMPULSE37,
  117. UB_IMPULSE38,
  118. UB_IMPULSE39,
  119. UB_IMPULSE40,
  120. UB_IMPULSE41,
  121. UB_IMPULSE42,
  122. UB_IMPULSE43,
  123. UB_IMPULSE44,
  124. UB_IMPULSE45,
  125. UB_IMPULSE46,
  126. UB_IMPULSE47,
  127. UB_IMPULSE48,
  128. UB_IMPULSE49,
  129. UB_IMPULSE50,
  130. UB_IMPULSE51,
  131. UB_IMPULSE52,
  132. UB_IMPULSE53,
  133. UB_IMPULSE54,
  134. UB_IMPULSE55,
  135. UB_IMPULSE56,
  136. UB_IMPULSE57,
  137. UB_IMPULSE58,
  138. UB_IMPULSE59,
  139. UB_IMPULSE60,
  140. UB_IMPULSE61,
  141. UB_IMPULSE62,
  142. UB_IMPULSE63,
  143. UB_MAX_BUTTONS
  144. } usercmdButton_t;
  145. typedef struct {
  146. const char *string;
  147. usercmdButton_t button;
  148. } userCmdString_t;
  149. userCmdString_t userCmdStrings[] = {
  150. { "_moveUp", UB_UP },
  151. { "_moveDown", UB_DOWN },
  152. { "_left", UB_LEFT },
  153. { "_right", UB_RIGHT },
  154. { "_forward", UB_FORWARD },
  155. { "_back", UB_BACK },
  156. { "_lookUp", UB_LOOKUP },
  157. { "_lookDown", UB_LOOKDOWN },
  158. { "_strafe", UB_STRAFE },
  159. { "_moveLeft", UB_MOVELEFT },
  160. { "_moveRight", UB_MOVERIGHT },
  161. { "_attack", UB_ATTACK },
  162. { "_speed", UB_SPEED },
  163. { "_zoom", UB_ZOOM },
  164. { "_showScores", UB_SHOWSCORES },
  165. { "_mlook", UB_MLOOK },
  166. { "_button0", UB_BUTTON0 },
  167. { "_button1", UB_BUTTON1 },
  168. { "_button2", UB_BUTTON2 },
  169. { "_button3", UB_BUTTON3 },
  170. { "_button4", UB_BUTTON4 },
  171. { "_button5", UB_BUTTON5 },
  172. { "_button6", UB_BUTTON6 },
  173. { "_button7", UB_BUTTON7 },
  174. { "_impulse0", UB_IMPULSE0 },
  175. { "_impulse1", UB_IMPULSE1 },
  176. { "_impulse2", UB_IMPULSE2 },
  177. { "_impulse3", UB_IMPULSE3 },
  178. { "_impulse4", UB_IMPULSE4 },
  179. { "_impulse5", UB_IMPULSE5 },
  180. { "_impulse6", UB_IMPULSE6 },
  181. { "_impulse7", UB_IMPULSE7 },
  182. { "_impulse8", UB_IMPULSE8 },
  183. { "_impulse9", UB_IMPULSE9 },
  184. { "_impulse10", UB_IMPULSE10 },
  185. { "_impulse11", UB_IMPULSE11 },
  186. { "_impulse12", UB_IMPULSE12 },
  187. { "_impulse13", UB_IMPULSE13 },
  188. { "_impulse14", UB_IMPULSE14 },
  189. { "_impulse15", UB_IMPULSE15 },
  190. { "_impulse16", UB_IMPULSE16 },
  191. { "_impulse17", UB_IMPULSE17 },
  192. { "_impulse18", UB_IMPULSE18 },
  193. { "_impulse19", UB_IMPULSE19 },
  194. { "_impulse20", UB_IMPULSE20 },
  195. { "_impulse21", UB_IMPULSE21 },
  196. { "_impulse22", UB_IMPULSE22 },
  197. { "_impulse23", UB_IMPULSE23 },
  198. { "_impulse24", UB_IMPULSE24 },
  199. { "_impulse25", UB_IMPULSE25 },
  200. { "_impulse26", UB_IMPULSE26 },
  201. { "_impulse27", UB_IMPULSE27 },
  202. { "_impulse28", UB_IMPULSE28 },
  203. { "_impulse29", UB_IMPULSE29 },
  204. { "_impulse30", UB_IMPULSE30 },
  205. { "_impulse31", UB_IMPULSE31 },
  206. { "_impulse32", UB_IMPULSE32 },
  207. { "_impulse33", UB_IMPULSE33 },
  208. { "_impulse34", UB_IMPULSE34 },
  209. { "_impulse35", UB_IMPULSE35 },
  210. { "_impulse36", UB_IMPULSE36 },
  211. { "_impulse37", UB_IMPULSE37 },
  212. { "_impulse38", UB_IMPULSE38 },
  213. { "_impulse39", UB_IMPULSE39 },
  214. { "_impulse40", UB_IMPULSE40 },
  215. { "_impulse41", UB_IMPULSE41 },
  216. { "_impulse42", UB_IMPULSE42 },
  217. { "_impulse43", UB_IMPULSE43 },
  218. { "_impulse44", UB_IMPULSE44 },
  219. { "_impulse45", UB_IMPULSE45 },
  220. { "_impulse46", UB_IMPULSE46 },
  221. { "_impulse47", UB_IMPULSE47 },
  222. { "_impulse48", UB_IMPULSE48 },
  223. { "_impulse49", UB_IMPULSE49 },
  224. { "_impulse50", UB_IMPULSE50 },
  225. { "_impulse51", UB_IMPULSE51 },
  226. { "_impulse52", UB_IMPULSE52 },
  227. { "_impulse53", UB_IMPULSE53 },
  228. { "_impulse54", UB_IMPULSE54 },
  229. { "_impulse55", UB_IMPULSE55 },
  230. { "_impulse56", UB_IMPULSE56 },
  231. { "_impulse57", UB_IMPULSE57 },
  232. { "_impulse58", UB_IMPULSE58 },
  233. { "_impulse59", UB_IMPULSE59 },
  234. { "_impulse60", UB_IMPULSE60 },
  235. { "_impulse61", UB_IMPULSE61 },
  236. { "_impulse62", UB_IMPULSE62 },
  237. { "_impulse63", UB_IMPULSE63 },
  238. { NULL, UB_NONE },
  239. };
  240. class buttonState_t {
  241. public:
  242. int on;
  243. bool held;
  244. buttonState_t() { Clear(); };
  245. void Clear( void );
  246. void SetKeyState( int keystate, bool toggle );
  247. };
  248. /*
  249. ================
  250. buttonState_t::Clear
  251. ================
  252. */
  253. void buttonState_t::Clear( void ) {
  254. held = false;
  255. on = 0;
  256. }
  257. /*
  258. ================
  259. buttonState_t::SetKeyState
  260. ================
  261. */
  262. void buttonState_t::SetKeyState( int keystate, bool toggle ) {
  263. if ( !toggle ) {
  264. held = false;
  265. on = keystate;
  266. } else if ( !keystate ) {
  267. held = false;
  268. } else if ( !held ) {
  269. held = true;
  270. on ^= 1;
  271. }
  272. }
  273. const int NUM_USER_COMMANDS = sizeof(userCmdStrings) / sizeof(userCmdString_t);
  274. const int MAX_CHAT_BUFFER = 127;
  275. class idUsercmdGenLocal : public idUsercmdGen {
  276. public:
  277. idUsercmdGenLocal( void );
  278. void Init( void );
  279. void InitForNewMap( void );
  280. void Shutdown( void );
  281. void Clear( void );
  282. void ClearAngles( void );
  283. usercmd_t TicCmd( int ticNumber );
  284. void InhibitUsercmd( inhibit_t subsystem, bool inhibit );
  285. void UsercmdInterrupt( void );
  286. int CommandStringUsercmdData( const char *cmdString );
  287. int GetNumUserCommands( void );
  288. const char * GetUserCommandName( int index );
  289. void MouseState( int *x, int *y, int *button, bool *down );
  290. int ButtonState( int key );
  291. int KeyState( int key );
  292. usercmd_t GetDirectUsercmd( void );
  293. private:
  294. void MakeCurrent( void );
  295. void InitCurrent( void );
  296. bool Inhibited( void );
  297. void AdjustAngles( void );
  298. void KeyMove( void );
  299. void JoystickMove( void );
  300. void MouseMove( void );
  301. void CmdButtons( void );
  302. void Mouse( void );
  303. void Keyboard( void );
  304. void Joystick( void );
  305. void Key( int keyNum, bool down );
  306. idVec3 viewangles;
  307. int flags;
  308. int impulse;
  309. buttonState_t toggled_crouch;
  310. buttonState_t toggled_run;
  311. buttonState_t toggled_zoom;
  312. int buttonState[UB_MAX_BUTTONS];
  313. bool keyState[K_LAST_KEY];
  314. int inhibitCommands; // true when in console or menu locally
  315. int lastCommandTime;
  316. bool initialized;
  317. usercmd_t cmd; // the current cmd being built
  318. usercmd_t buffered[MAX_BUFFERED_USERCMD];
  319. int continuousMouseX, continuousMouseY; // for gui event generatioin, never zerod
  320. int mouseButton; // for gui event generatioin
  321. bool mouseDown;
  322. int mouseDx, mouseDy; // added to by mouse events
  323. int joystickAxis[MAX_JOYSTICK_AXIS]; // set by joystick events
  324. static idCVar in_yawSpeed;
  325. static idCVar in_pitchSpeed;
  326. static idCVar in_angleSpeedKey;
  327. static idCVar in_freeLook;
  328. static idCVar in_alwaysRun;
  329. static idCVar in_toggleRun;
  330. static idCVar in_toggleCrouch;
  331. static idCVar in_toggleZoom;
  332. static idCVar sensitivity;
  333. static idCVar m_pitch;
  334. static idCVar m_yaw;
  335. static idCVar m_strafeScale;
  336. static idCVar m_smooth;
  337. static idCVar m_strafeSmooth;
  338. static idCVar m_showMouseRate;
  339. };
  340. idCVar idUsercmdGenLocal::in_yawSpeed( "in_yawspeed", "140", CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_FLOAT, "yaw change speed when holding down _left or _right button" );
  341. idCVar idUsercmdGenLocal::in_pitchSpeed( "in_pitchspeed", "140", CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_FLOAT, "pitch change speed when holding down look _lookUp or _lookDown button" );
  342. idCVar idUsercmdGenLocal::in_angleSpeedKey( "in_anglespeedkey", "1.5", CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_FLOAT, "angle change scale when holding down _speed button" );
  343. idCVar idUsercmdGenLocal::in_freeLook( "in_freeLook", "1", CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_BOOL, "look around with mouse (reverse _mlook button)" );
  344. idCVar idUsercmdGenLocal::in_alwaysRun( "in_alwaysRun", "0", CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_BOOL, "always run (reverse _speed button) - only in MP" );
  345. idCVar idUsercmdGenLocal::in_toggleRun( "in_toggleRun", "0", CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_BOOL, "pressing _speed button toggles run on/off - only in MP" );
  346. idCVar idUsercmdGenLocal::in_toggleCrouch( "in_toggleCrouch", "0", CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_BOOL, "pressing _movedown button toggles player crouching/standing" );
  347. idCVar idUsercmdGenLocal::in_toggleZoom( "in_toggleZoom", "0", CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_BOOL, "pressing _zoom button toggles zoom on/off" );
  348. idCVar idUsercmdGenLocal::sensitivity( "sensitivity", "5", CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_FLOAT, "mouse view sensitivity" );
  349. idCVar idUsercmdGenLocal::m_pitch( "m_pitch", "0.022", CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_FLOAT, "mouse pitch scale" );
  350. idCVar idUsercmdGenLocal::m_yaw( "m_yaw", "0.022", CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_FLOAT, "mouse yaw scale" );
  351. idCVar idUsercmdGenLocal::m_strafeScale( "m_strafeScale", "6.25", CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_FLOAT, "mouse strafe movement scale" );
  352. idCVar idUsercmdGenLocal::m_smooth( "m_smooth", "1", CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_INTEGER, "number of samples blended for mouse viewing", 1, 8, idCmdSystem::ArgCompletion_Integer<1,8> );
  353. idCVar idUsercmdGenLocal::m_strafeSmooth( "m_strafeSmooth", "4", CVAR_SYSTEM | CVAR_ARCHIVE | CVAR_INTEGER, "number of samples blended for mouse moving", 1, 8, idCmdSystem::ArgCompletion_Integer<1,8> );
  354. idCVar idUsercmdGenLocal::m_showMouseRate( "m_showMouseRate", "0", CVAR_SYSTEM | CVAR_BOOL, "shows mouse movement" );
  355. static idUsercmdGenLocal localUsercmdGen;
  356. idUsercmdGen *usercmdGen = &localUsercmdGen;
  357. /*
  358. ================
  359. idUsercmdGenLocal::idUsercmdGenLocal
  360. ================
  361. */
  362. idUsercmdGenLocal::idUsercmdGenLocal( void ) {
  363. lastCommandTime = 0;
  364. initialized = false;
  365. flags = 0;
  366. impulse = 0;
  367. toggled_crouch.Clear();
  368. toggled_run.Clear();
  369. toggled_zoom.Clear();
  370. toggled_run.on = in_alwaysRun.GetBool();
  371. ClearAngles();
  372. Clear();
  373. }
  374. /*
  375. ================
  376. idUsercmdGenLocal::InhibitUsercmd
  377. ================
  378. */
  379. void idUsercmdGenLocal::InhibitUsercmd( inhibit_t subsystem, bool inhibit ) {
  380. if ( inhibit ) {
  381. inhibitCommands |= 1 << subsystem;
  382. } else {
  383. inhibitCommands &= ( 0xffffffff ^ ( 1 << subsystem ) );
  384. }
  385. }
  386. /*
  387. ===============
  388. idUsercmdGenLocal::ButtonState
  389. Returns (the fraction of the frame) that the key was down
  390. ===============
  391. */
  392. int idUsercmdGenLocal::ButtonState( int key ) {
  393. if ( key<0 || key>=UB_MAX_BUTTONS ) {
  394. return -1;
  395. }
  396. return ( buttonState[key] > 0 ) ? 1 : 0;
  397. }
  398. /*
  399. ===============
  400. idUsercmdGenLocal::KeyState
  401. Returns (the fraction of the frame) that the key was down
  402. bk20060111
  403. ===============
  404. */
  405. int idUsercmdGenLocal::KeyState( int key ) {
  406. if ( key<0 || key>=K_LAST_KEY ) {
  407. return -1;
  408. }
  409. return ( keyState[key] ) ? 1 : 0;
  410. }
  411. //=====================================================================
  412. /*
  413. ================
  414. idUsercmdGenLocal::GetNumUserCommands
  415. ================
  416. */
  417. int idUsercmdGenLocal::GetNumUserCommands( void ) {
  418. return NUM_USER_COMMANDS;
  419. }
  420. /*
  421. ================
  422. idUsercmdGenLocal::GetNumUserCommands
  423. ================
  424. */
  425. const char *idUsercmdGenLocal::GetUserCommandName( int index ) {
  426. if (index >= 0 && index < NUM_USER_COMMANDS) {
  427. return userCmdStrings[index].string;
  428. }
  429. return "";
  430. }
  431. /*
  432. ================
  433. idUsercmdGenLocal::Inhibited
  434. is user cmd generation inhibited
  435. ================
  436. */
  437. bool idUsercmdGenLocal::Inhibited( void ) {
  438. return ( inhibitCommands != 0);
  439. }
  440. /*
  441. ================
  442. idUsercmdGenLocal::AdjustAngles
  443. Moves the local angle positions
  444. ================
  445. */
  446. void idUsercmdGenLocal::AdjustAngles( void ) {
  447. float speed;
  448. if ( toggled_run.on ^ ( in_alwaysRun.GetBool() && idAsyncNetwork::IsActive() ) ) {
  449. speed = idMath::M_MS2SEC * USERCMD_MSEC * in_angleSpeedKey.GetFloat();
  450. } else {
  451. speed = idMath::M_MS2SEC * USERCMD_MSEC;
  452. }
  453. if ( !ButtonState( UB_STRAFE ) ) {
  454. viewangles[YAW] -= speed * in_yawSpeed.GetFloat() * ButtonState( UB_RIGHT );
  455. viewangles[YAW] += speed * in_yawSpeed.GetFloat() * ButtonState( UB_LEFT );
  456. }
  457. viewangles[PITCH] -= speed * in_pitchSpeed.GetFloat() * ButtonState( UB_LOOKUP );
  458. viewangles[PITCH] += speed * in_pitchSpeed.GetFloat() * ButtonState( UB_LOOKDOWN );
  459. }
  460. /*
  461. ================
  462. idUsercmdGenLocal::KeyMove
  463. Sets the usercmd_t based on key states
  464. ================
  465. */
  466. void idUsercmdGenLocal::KeyMove( void ) {
  467. int forward, side, up;
  468. forward = 0;
  469. side = 0;
  470. up = 0;
  471. if ( ButtonState( UB_STRAFE ) ) {
  472. side += KEY_MOVESPEED * ButtonState( UB_RIGHT );
  473. side -= KEY_MOVESPEED * ButtonState( UB_LEFT );
  474. }
  475. side += KEY_MOVESPEED * ButtonState( UB_MOVERIGHT );
  476. side -= KEY_MOVESPEED * ButtonState( UB_MOVELEFT );
  477. up -= KEY_MOVESPEED * toggled_crouch.on;
  478. up += KEY_MOVESPEED * ButtonState( UB_UP );
  479. forward += KEY_MOVESPEED * ButtonState( UB_FORWARD );
  480. forward -= KEY_MOVESPEED * ButtonState( UB_BACK );
  481. cmd.forwardmove = idMath::ClampChar( forward );
  482. cmd.rightmove = idMath::ClampChar( side );
  483. cmd.upmove = idMath::ClampChar( up );
  484. }
  485. /*
  486. =================
  487. idUsercmdGenLocal::MouseMove
  488. =================
  489. */
  490. void idUsercmdGenLocal::MouseMove( void ) {
  491. float mx, my, strafeMx, strafeMy;
  492. static int history[8][2];
  493. static int historyCounter;
  494. int i;
  495. history[historyCounter&7][0] = mouseDx;
  496. history[historyCounter&7][1] = mouseDy;
  497. // allow mouse movement to be smoothed together
  498. int smooth = m_smooth.GetInteger();
  499. if ( smooth < 1 ) {
  500. smooth = 1;
  501. }
  502. if ( smooth > 8 ) {
  503. smooth = 8;
  504. }
  505. mx = 0;
  506. my = 0;
  507. for ( i = 0 ; i < smooth ; i++ ) {
  508. mx += history[ ( historyCounter - i + 8 ) & 7 ][0];
  509. my += history[ ( historyCounter - i + 8 ) & 7 ][1];
  510. }
  511. mx /= smooth;
  512. my /= smooth;
  513. // use a larger smoothing for strafing
  514. smooth = m_strafeSmooth.GetInteger();
  515. if ( smooth < 1 ) {
  516. smooth = 1;
  517. }
  518. if ( smooth > 8 ) {
  519. smooth = 8;
  520. }
  521. strafeMx = 0;
  522. strafeMy = 0;
  523. for ( i = 0 ; i < smooth ; i++ ) {
  524. strafeMx += history[ ( historyCounter - i + 8 ) & 7 ][0];
  525. strafeMy += history[ ( historyCounter - i + 8 ) & 7 ][1];
  526. }
  527. strafeMx /= smooth;
  528. strafeMy /= smooth;
  529. historyCounter++;
  530. if ( idMath::Fabs( mx ) > 1000 || idMath::Fabs( my ) > 1000 ) {
  531. Sys_DebugPrintf( "idUsercmdGenLocal::MouseMove: Ignoring ridiculous mouse delta.\n" );
  532. mx = my = 0;
  533. }
  534. mx *= sensitivity.GetFloat();
  535. my *= sensitivity.GetFloat();
  536. if ( m_showMouseRate.GetBool() ) {
  537. Sys_DebugPrintf( "[%3i %3i = %5.1f %5.1f = %5.1f %5.1f] ", mouseDx, mouseDy, mx, my, strafeMx, strafeMy );
  538. }
  539. mouseDx = 0;
  540. mouseDy = 0;
  541. if ( !strafeMx && !strafeMy ) {
  542. return;
  543. }
  544. if ( ButtonState( UB_STRAFE ) || !( cmd.buttons & BUTTON_MLOOK ) ) {
  545. // add mouse X/Y movement to cmd
  546. strafeMx *= m_strafeScale.GetFloat();
  547. strafeMy *= m_strafeScale.GetFloat();
  548. // clamp as a vector, instead of separate floats
  549. float len = sqrt( strafeMx * strafeMx + strafeMy * strafeMy );
  550. if ( len > 127 ) {
  551. strafeMx = strafeMx * 127 / len;
  552. strafeMy = strafeMy * 127 / len;
  553. }
  554. }
  555. if ( !ButtonState( UB_STRAFE ) ) {
  556. viewangles[YAW] -= m_yaw.GetFloat() * mx;
  557. } else {
  558. cmd.rightmove = idMath::ClampChar( (int)(cmd.rightmove + strafeMx) );
  559. }
  560. if ( !ButtonState( UB_STRAFE ) && ( cmd.buttons & BUTTON_MLOOK ) ) {
  561. viewangles[PITCH] += m_pitch.GetFloat() * my;
  562. } else {
  563. cmd.forwardmove = idMath::ClampChar( (int)(cmd.forwardmove - strafeMy) );
  564. }
  565. }
  566. /*
  567. =================
  568. idUsercmdGenLocal::JoystickMove
  569. =================
  570. */
  571. void idUsercmdGenLocal::JoystickMove( void ) {
  572. float anglespeed;
  573. if ( toggled_run.on ^ ( in_alwaysRun.GetBool() && idAsyncNetwork::IsActive() ) ) {
  574. anglespeed = idMath::M_MS2SEC * USERCMD_MSEC * in_angleSpeedKey.GetFloat();
  575. } else {
  576. anglespeed = idMath::M_MS2SEC * USERCMD_MSEC;
  577. }
  578. if ( !ButtonState( UB_STRAFE ) ) {
  579. viewangles[YAW] += anglespeed * in_yawSpeed.GetFloat() * joystickAxis[AXIS_SIDE];
  580. viewangles[PITCH] += anglespeed * in_pitchSpeed.GetFloat() * joystickAxis[AXIS_FORWARD];
  581. } else {
  582. cmd.rightmove = idMath::ClampChar( cmd.rightmove + joystickAxis[AXIS_SIDE] );
  583. cmd.forwardmove = idMath::ClampChar( cmd.forwardmove + joystickAxis[AXIS_FORWARD] );
  584. }
  585. cmd.upmove = idMath::ClampChar( cmd.upmove + joystickAxis[AXIS_UP] );
  586. }
  587. /*
  588. ==============
  589. idUsercmdGenLocal::CmdButtons
  590. ==============
  591. */
  592. void idUsercmdGenLocal::CmdButtons( void ) {
  593. int i;
  594. cmd.buttons = 0;
  595. // figure button bits
  596. for (i = 0 ; i <= 7 ; i++) {
  597. if ( ButtonState( (usercmdButton_t)( UB_BUTTON0 + i ) ) ) {
  598. cmd.buttons |= 1 << i;
  599. }
  600. }
  601. // check the attack button
  602. if ( ButtonState( UB_ATTACK ) ) {
  603. cmd.buttons |= BUTTON_ATTACK;
  604. }
  605. // check the run button
  606. if ( toggled_run.on ^ ( in_alwaysRun.GetBool() && idAsyncNetwork::IsActive() ) ) {
  607. cmd.buttons |= BUTTON_RUN;
  608. }
  609. // check the zoom button
  610. if ( toggled_zoom.on ) {
  611. cmd.buttons |= BUTTON_ZOOM;
  612. }
  613. // check the scoreboard button
  614. if ( ButtonState( UB_SHOWSCORES ) || ButtonState( UB_IMPULSE19 ) ) {
  615. // the button is toggled in SP mode as well but without effect
  616. cmd.buttons |= BUTTON_SCORES;
  617. }
  618. // check the mouse look button
  619. if ( ButtonState( UB_MLOOK ) ^ in_freeLook.GetInteger() ) {
  620. cmd.buttons |= BUTTON_MLOOK;
  621. }
  622. }
  623. /*
  624. ================
  625. idUsercmdGenLocal::InitCurrent
  626. inits the current command for this frame
  627. ================
  628. */
  629. void idUsercmdGenLocal::InitCurrent( void ) {
  630. memset( &cmd, 0, sizeof( cmd ) );
  631. cmd.flags = flags;
  632. cmd.impulse = impulse;
  633. cmd.buttons |= ( in_alwaysRun.GetBool() && idAsyncNetwork::IsActive() ) ? BUTTON_RUN : 0;
  634. cmd.buttons |= in_freeLook.GetBool() ? BUTTON_MLOOK : 0;
  635. }
  636. /*
  637. ================
  638. idUsercmdGenLocal::MakeCurrent
  639. creates the current command for this frame
  640. ================
  641. */
  642. void idUsercmdGenLocal::MakeCurrent( void ) {
  643. idVec3 oldAngles;
  644. int i;
  645. oldAngles = viewangles;
  646. if ( !Inhibited() ) {
  647. // update toggled key states
  648. toggled_crouch.SetKeyState( ButtonState( UB_DOWN ), in_toggleCrouch.GetBool() );
  649. toggled_run.SetKeyState( ButtonState( UB_SPEED ), in_toggleRun.GetBool() && idAsyncNetwork::IsActive() );
  650. toggled_zoom.SetKeyState( ButtonState( UB_ZOOM ), in_toggleZoom.GetBool() );
  651. // keyboard angle adjustment
  652. AdjustAngles();
  653. // set button bits
  654. CmdButtons();
  655. // get basic movement from keyboard
  656. KeyMove();
  657. // get basic movement from mouse
  658. MouseMove();
  659. // get basic movement from joystick
  660. JoystickMove();
  661. // check to make sure the angles haven't wrapped
  662. if ( viewangles[PITCH] - oldAngles[PITCH] > 90 ) {
  663. viewangles[PITCH] = oldAngles[PITCH] + 90;
  664. } else if ( oldAngles[PITCH] - viewangles[PITCH] > 90 ) {
  665. viewangles[PITCH] = oldAngles[PITCH] - 90;
  666. }
  667. } else {
  668. mouseDx = 0;
  669. mouseDy = 0;
  670. }
  671. for ( i = 0; i < 3; i++ ) {
  672. cmd.angles[i] = ANGLE2SHORT( viewangles[i] );
  673. }
  674. cmd.mx = continuousMouseX;
  675. cmd.my = continuousMouseY;
  676. flags = cmd.flags;
  677. impulse = cmd.impulse;
  678. }
  679. //=====================================================================
  680. /*
  681. ================
  682. idUsercmdGenLocal::CommandStringUsercmdData
  683. Returns the button if the command string is used by the async usercmd generator.
  684. ================
  685. */
  686. int idUsercmdGenLocal::CommandStringUsercmdData( const char *cmdString ) {
  687. for ( userCmdString_t *ucs = userCmdStrings ; ucs->string ; ucs++ ) {
  688. if ( idStr::Icmp( cmdString, ucs->string ) == 0 ) {
  689. return ucs->button;
  690. }
  691. }
  692. return UB_NONE;
  693. }
  694. /*
  695. ================
  696. idUsercmdGenLocal::Init
  697. ================
  698. */
  699. void idUsercmdGenLocal::Init( void ) {
  700. initialized = true;
  701. }
  702. /*
  703. ================
  704. idUsercmdGenLocal::InitForNewMap
  705. ================
  706. */
  707. void idUsercmdGenLocal::InitForNewMap( void ) {
  708. flags = 0;
  709. impulse = 0;
  710. toggled_crouch.Clear();
  711. toggled_run.Clear();
  712. toggled_zoom.Clear();
  713. toggled_run.on = in_alwaysRun.GetBool();
  714. Clear();
  715. ClearAngles();
  716. }
  717. /*
  718. ================
  719. idUsercmdGenLocal::Shutdown
  720. ================
  721. */
  722. void idUsercmdGenLocal::Shutdown( void ) {
  723. initialized = false;
  724. }
  725. /*
  726. ================
  727. idUsercmdGenLocal::Clear
  728. ================
  729. */
  730. void idUsercmdGenLocal::Clear( void ) {
  731. // clears all key states
  732. memset( buttonState, 0, sizeof( buttonState ) );
  733. memset( keyState, false, sizeof( keyState ) );
  734. inhibitCommands = false;
  735. mouseDx = mouseDy = 0;
  736. mouseButton = 0;
  737. mouseDown = false;
  738. }
  739. /*
  740. ================
  741. idUsercmdGenLocal::ClearAngles
  742. ================
  743. */
  744. void idUsercmdGenLocal::ClearAngles( void ) {
  745. viewangles.Zero();
  746. }
  747. /*
  748. ================
  749. idUsercmdGenLocal::TicCmd
  750. Returns a buffered usercmd
  751. ================
  752. */
  753. usercmd_t idUsercmdGenLocal::TicCmd( int ticNumber ) {
  754. // the packetClient code can legally ask for com_ticNumber+1, because
  755. // it is in the async code and com_ticNumber hasn't been updated yet,
  756. // but all other code should never ask for anything > com_ticNumber
  757. if ( ticNumber > com_ticNumber+1 ) {
  758. common->Error( "idUsercmdGenLocal::TicCmd ticNumber > com_ticNumber" );
  759. }
  760. if ( ticNumber <= com_ticNumber - MAX_BUFFERED_USERCMD ) {
  761. // this can happen when something in the game code hitches badly, allowing the
  762. // async code to overflow the buffers
  763. //common->Printf( "warning: idUsercmdGenLocal::TicCmd ticNumber <= com_ticNumber - MAX_BUFFERED_USERCMD\n" );
  764. }
  765. return buffered[ ticNumber & (MAX_BUFFERED_USERCMD-1) ];
  766. }
  767. //======================================================================
  768. /*
  769. ===================
  770. idUsercmdGenLocal::Key
  771. Handles async mouse/keyboard button actions
  772. ===================
  773. */
  774. void idUsercmdGenLocal::Key( int keyNum, bool down ) {
  775. // Sanity check, sometimes we get double message :(
  776. if ( keyState[ keyNum ] == down ) {
  777. return;
  778. }
  779. keyState[ keyNum ] = down;
  780. int action = idKeyInput::GetUsercmdAction( keyNum );
  781. if ( down ) {
  782. buttonState[ action ]++;
  783. if ( !Inhibited() ) {
  784. if ( action >= UB_IMPULSE0 && action <= UB_IMPULSE61 ) {
  785. cmd.impulse = action - UB_IMPULSE0;
  786. cmd.flags ^= UCF_IMPULSE_SEQUENCE;
  787. }
  788. }
  789. } else {
  790. buttonState[ action ]--;
  791. // we might have one held down across an app active transition
  792. if ( buttonState[ action ] < 0 ) {
  793. buttonState[ action ] = 0;
  794. }
  795. }
  796. }
  797. /*
  798. ===================
  799. idUsercmdGenLocal::Mouse
  800. ===================
  801. */
  802. void idUsercmdGenLocal::Mouse( void ) {
  803. int i, numEvents;
  804. numEvents = Sys_PollMouseInputEvents();
  805. if ( numEvents ) {
  806. //
  807. // Study each of the buffer elements and process them.
  808. //
  809. for( i = 0; i < numEvents; i++ ) {
  810. int action, value;
  811. if ( Sys_ReturnMouseInputEvent( i, action, value ) ) {
  812. if ( action >= M_ACTION1 && action <= M_ACTION8 ) {
  813. mouseButton = K_MOUSE1 + ( action - M_ACTION1 );
  814. mouseDown = ( value != 0 );
  815. Key( mouseButton, mouseDown );
  816. } else {
  817. switch ( action ) {
  818. case M_DELTAX:
  819. mouseDx += value;
  820. continuousMouseX += value;
  821. break;
  822. case M_DELTAY:
  823. mouseDy += value;
  824. continuousMouseY += value;
  825. break;
  826. case M_DELTAZ:
  827. int key = value < 0 ? K_MWHEELDOWN : K_MWHEELUP;
  828. value = abs( value );
  829. while( value-- > 0 ) {
  830. Key( key, true );
  831. Key( key, false );
  832. mouseButton = key;
  833. mouseDown = true;
  834. }
  835. break;
  836. }
  837. }
  838. }
  839. }
  840. }
  841. Sys_EndMouseInputEvents();
  842. }
  843. /*
  844. ===============
  845. idUsercmdGenLocal::Keyboard
  846. ===============
  847. */
  848. void idUsercmdGenLocal::Keyboard( void ) {
  849. int numEvents = Sys_PollKeyboardInputEvents();
  850. if ( numEvents ) {
  851. //
  852. // Study each of the buffer elements and process them.
  853. //
  854. int key;
  855. bool state;
  856. for( int i = 0; i < numEvents; i++ ) {
  857. if (Sys_ReturnKeyboardInputEvent( i, key, state )) {
  858. Key ( key, state );
  859. }
  860. }
  861. }
  862. Sys_EndKeyboardInputEvents();
  863. }
  864. /*
  865. ===============
  866. idUsercmdGenLocal::Joystick
  867. ===============
  868. */
  869. void idUsercmdGenLocal::Joystick( void ) {
  870. memset( joystickAxis, 0, sizeof( joystickAxis ) );
  871. }
  872. /*
  873. ================
  874. idUsercmdGenLocal::UsercmdInterrupt
  875. Called asyncronously
  876. ================
  877. */
  878. void idUsercmdGenLocal::UsercmdInterrupt( void ) {
  879. // dedicated servers won't create usercmds
  880. if ( !initialized ) {
  881. return;
  882. }
  883. // init the usercmd for com_ticNumber+1
  884. InitCurrent();
  885. // process the system mouse events
  886. Mouse();
  887. // process the system keyboard events
  888. Keyboard();
  889. // process the system joystick events
  890. Joystick();
  891. // create the usercmd for com_ticNumber+1
  892. MakeCurrent();
  893. // save a number for debugging cmdDemos and networking
  894. cmd.sequence = com_ticNumber+1;
  895. buffered[(com_ticNumber+1) & (MAX_BUFFERED_USERCMD-1)] = cmd;
  896. }
  897. /*
  898. ================
  899. idUsercmdGenLocal::MouseState
  900. ================
  901. */
  902. void idUsercmdGenLocal::MouseState( int *x, int *y, int *button, bool *down ) {
  903. *x = continuousMouseX;
  904. *y = continuousMouseY;
  905. *button = mouseButton;
  906. *down = mouseDown;
  907. }
  908. /*
  909. ================
  910. idUsercmdGenLocal::GetDirectUsercmd
  911. ================
  912. */
  913. usercmd_t idUsercmdGenLocal::GetDirectUsercmd( void ) {
  914. // initialize current usercmd
  915. InitCurrent();
  916. // process the system mouse events
  917. Mouse();
  918. // process the system keyboard events
  919. Keyboard();
  920. // process the system joystick events
  921. Joystick();
  922. // create the usercmd
  923. MakeCurrent();
  924. cmd.duplicateCount = 0;
  925. return cmd;
  926. }