control.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program 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. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /***********************************************************************************************
  19. *** Confidential - Westwood Studios ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : Commando *
  23. * *
  24. * $Archive:: /Commando/Code/Combat/control.cpp $*
  25. * *
  26. * $Author:: Byon_g $*
  27. * *
  28. * $Modtime:: 2/21/02 5:08p $*
  29. * *
  30. * $Revision:: 34 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. #include "control.h"
  36. #include "wwdebug.h"
  37. #include "input.h"
  38. #include "wwmath.h"
  39. #include "wwpacket.h"
  40. #include "chunkio.h"
  41. #include "debug.h"
  42. #include <memory.h>
  43. #include "combat.h"
  44. //#include "clientinterpmodels.h"
  45. #include "encoderlist.h"
  46. #include "bitpackids.h"
  47. // Should pack analogs of 1 and -1 into single bit
  48. //
  49. // TSS 03/08/99: I have scaled the floats down to bytes.... more optimisation later!
  50. //
  51. ControlClass & ControlClass::operator = (const ControlClass & src)
  52. {
  53. OneTimeBooleanBits = src.OneTimeBooleanBits;
  54. ContinuousBooleanBits = src.ContinuousBooleanBits;
  55. memcpy( AnalogValues, src.AnalogValues, sizeof(AnalogValues) );
  56. return *this;
  57. }
  58. /*
  59. **
  60. */
  61. enum {
  62. CHUNKID_VARIABLES = 914991110,
  63. MICROCHUNKID_ONE_TIME_BOOL = 1,
  64. MICROCHUNKID_CONTINUOUS_BOOL,
  65. MICROCHUNKID_ANALOG,
  66. MICROCHUNKID_PENDING_ONE_TIME_BOOL,
  67. MICROCHUNKID_PENDING_CONTINUOUS_BOOL,
  68. };
  69. bool ControlClass::Save( ChunkSaveClass & csave )
  70. {
  71. csave.Begin_Chunk( CHUNKID_VARIABLES );
  72. WRITE_MICRO_CHUNK( csave, MICROCHUNKID_ONE_TIME_BOOL, OneTimeBooleanBits );
  73. WRITE_MICRO_CHUNK( csave, MICROCHUNKID_CONTINUOUS_BOOL, ContinuousBooleanBits );
  74. WRITE_MICRO_CHUNK( csave, MICROCHUNKID_PENDING_ONE_TIME_BOOL, PendingOneTimeBooleanBits );
  75. WRITE_MICRO_CHUNK( csave, MICROCHUNKID_PENDING_CONTINUOUS_BOOL, PendingContinuousBooleanBits );
  76. csave.Begin_Micro_Chunk(MICROCHUNKID_ANALOG);
  77. csave.Write(&AnalogValues[0],sizeof(AnalogValues));
  78. csave.End_Micro_Chunk();
  79. csave.End_Chunk();
  80. return true;
  81. }
  82. bool ControlClass::Load( ChunkLoadClass &cload )
  83. {
  84. while (cload.Open_Chunk()) {
  85. switch(cload.Cur_Chunk_ID()) {
  86. case CHUNKID_VARIABLES:
  87. while (cload.Open_Micro_Chunk()) {
  88. switch(cload.Cur_Micro_Chunk_ID()) {
  89. READ_MICRO_CHUNK( cload, MICROCHUNKID_ONE_TIME_BOOL, OneTimeBooleanBits );
  90. READ_MICRO_CHUNK( cload, MICROCHUNKID_CONTINUOUS_BOOL, ContinuousBooleanBits );
  91. READ_MICRO_CHUNK( cload, MICROCHUNKID_PENDING_ONE_TIME_BOOL, PendingOneTimeBooleanBits );
  92. READ_MICRO_CHUNK( cload, MICROCHUNKID_PENDING_CONTINUOUS_BOOL, PendingContinuousBooleanBits );
  93. case MICROCHUNKID_ANALOG:
  94. cload.Read( &AnalogValues[0],sizeof(AnalogValues) );
  95. break;
  96. default:
  97. Debug_Say(( "Unrecognized Control Variable chunkID\n" ));
  98. break;
  99. }
  100. cload.Close_Micro_Chunk();
  101. }
  102. break;
  103. default:
  104. Debug_Say(( "Unrecognized Control chunkID\n" ));
  105. break;
  106. }
  107. cload.Close_Chunk();
  108. }
  109. return true;
  110. }
  111. //JITTER
  112. void ControlClass::Clear_Boolean( void )
  113. {
  114. WWASSERT( (8 * sizeof(ControlClass::OneTimeBooleanBits)) >= ControlClass::NUM_BOOLEAN_ONE_TIME );
  115. WWASSERT( (8 * sizeof(ControlClass::ContinuousBooleanBits)) >= ControlClass::NUM_BOOLEAN_CONTINUOUS );
  116. OneTimeBooleanBits = 0;
  117. ContinuousBooleanBits = 0;
  118. }
  119. void ControlClass::Clear_Control( void )
  120. {
  121. WWASSERT( (8 * sizeof(ControlClass::OneTimeBooleanBits)) >= ControlClass::NUM_BOOLEAN_ONE_TIME );
  122. WWASSERT( (8 * sizeof(ControlClass::ContinuousBooleanBits)) >= ControlClass::NUM_BOOLEAN_CONTINUOUS );
  123. OneTimeBooleanBits = 0;
  124. ContinuousBooleanBits = 0;
  125. memset( AnalogValues, 0, sizeof(AnalogValues) );
  126. }
  127. enum {
  128. CONTROL_MOVE_FORWARD = 0,
  129. CONTROL_MOVE_BACKWARD,
  130. CONTROL_MOVE_LEFT,
  131. CONTROL_MOVE_RIGHT,
  132. CONTROL_MOVE_UP,
  133. CONTROL_MOVE_DOWN,
  134. CONTROL_TURN_LEFT,
  135. CONTROL_TURN_RIGHT,
  136. } CONTROL_MOVE_BITS;
  137. //-----------------------------------------------------------------------------
  138. void ControlClass::Import_Cs( BitStreamClass & packet )
  139. {
  140. // Or in the new one time bits
  141. ULONG otb_bits = packet.Get(otb_bits, BITPACK_ONE_TIME_BOOLEAN_BITS);
  142. OneTimeBooleanBits |= otb_bits;
  143. packet.Get(ContinuousBooleanBits, BITPACK_CONTINUOUS_BOOLEAN_BITS);
  144. #if 01
  145. packet.Get(AnalogValues[ANALOG_MOVE_FORWARD], BITPACK_ANALOG_VALUES);
  146. packet.Get(AnalogValues[ANALOG_MOVE_LEFT], BITPACK_ANALOG_VALUES);
  147. packet.Get(AnalogValues[ANALOG_MOVE_UP], BITPACK_ANALOG_VALUES);
  148. packet.Get(AnalogValues[ANALOG_TURN_LEFT], BITPACK_ANALOG_VALUES);
  149. #else
  150. int control_move;
  151. packet.Get( control_move, BITPACK_CONTROL_MOVES_CS);
  152. AnalogValues[ANALOG_MOVE_FORWARD] = 0.0f;
  153. AnalogValues[ANALOG_MOVE_LEFT] = 0.0f;
  154. AnalogValues[ANALOG_MOVE_UP] = 0.0f;
  155. AnalogValues[ANALOG_TURN_LEFT] = 0.0f;
  156. if ( control_move & (1<<CONTROL_MOVE_FORWARD) ) {
  157. AnalogValues[ANALOG_MOVE_FORWARD] = 1.0f;
  158. }
  159. if ( control_move & (1<<CONTROL_MOVE_BACKWARD) ) {
  160. AnalogValues[ANALOG_MOVE_FORWARD] = -1.0f;
  161. }
  162. if ( control_move & (1<<CONTROL_MOVE_LEFT) ) {
  163. AnalogValues[ANALOG_MOVE_LEFT] = 1.0f;
  164. }
  165. if ( control_move & (1<<CONTROL_MOVE_RIGHT) ) {
  166. AnalogValues[ANALOG_MOVE_LEFT] = -1.0f;
  167. }
  168. if ( control_move & (1<<CONTROL_MOVE_UP) ) {
  169. AnalogValues[ANALOG_MOVE_UP] = 1.0f;
  170. }
  171. if ( control_move & (1<<CONTROL_MOVE_DOWN) ) {
  172. AnalogValues[ANALOG_MOVE_UP] = -1.0f;
  173. }
  174. if ( control_move & (1<<CONTROL_TURN_LEFT) ) {
  175. AnalogValues[ANALOG_TURN_LEFT] = 1.0f;
  176. }
  177. if ( control_move & (1<<CONTROL_TURN_RIGHT) ) {
  178. AnalogValues[ANALOG_TURN_LEFT] = -1.0f;
  179. }
  180. #endif
  181. for (int i = 0; i < ANALOG_CONTROL_COUNT; i++) {
  182. if (fabs(AnalogValues[i]) < 0.005) {
  183. //
  184. // The code elsewhere has no tolerance for precision error on this
  185. // value around zero...
  186. //
  187. AnalogValues[i] = 0;
  188. }
  189. }
  190. }
  191. //-----------------------------------------------------------------------------
  192. void ControlClass::Export_Cs( BitStreamClass & packet )
  193. {
  194. // packet.Add(OneTimeBooleanBits, BITPACK_ONE_TIME_BOOLEAN_BITS);
  195. packet.Add(PendingOneTimeBooleanBits, BITPACK_ONE_TIME_BOOLEAN_BITS);
  196. PendingOneTimeBooleanBits = 0;
  197. // packet.Add(ContinuousBooleanBits, BITPACK_CONTINUOUS_BOOLEAN_BITS);
  198. packet.Add(PendingContinuousBooleanBits, BITPACK_CONTINUOUS_BOOLEAN_BITS);
  199. PendingContinuousBooleanBits = 0;
  200. #if 01
  201. packet.Add(AnalogValues[ANALOG_MOVE_FORWARD], BITPACK_ANALOG_VALUES);
  202. packet.Add(AnalogValues[ANALOG_MOVE_LEFT], BITPACK_ANALOG_VALUES);
  203. packet.Add(AnalogValues[ANALOG_MOVE_UP], BITPACK_ANALOG_VALUES);
  204. packet.Add(AnalogValues[ANALOG_TURN_LEFT], BITPACK_ANALOG_VALUES);
  205. #else
  206. int control_move = 0;
  207. if ( AnalogValues[ANALOG_MOVE_FORWARD] > 0.5f ) {
  208. control_move |= 1<<CONTROL_MOVE_FORWARD;
  209. }
  210. if ( AnalogValues[ANALOG_MOVE_FORWARD] < -0.5f ) {
  211. control_move |= 1<<CONTROL_MOVE_BACKWARD;
  212. }
  213. if ( AnalogValues[ANALOG_MOVE_LEFT] > 0.5f ) {
  214. control_move |= 1<<CONTROL_MOVE_LEFT;
  215. }
  216. if ( AnalogValues[ANALOG_MOVE_LEFT] < -0.5f ) {
  217. control_move |= 1<<CONTROL_MOVE_RIGHT;
  218. }
  219. if ( AnalogValues[ANALOG_MOVE_UP] > 0.5f ) {
  220. control_move |= 1<<CONTROL_MOVE_UP;
  221. }
  222. if ( AnalogValues[ANALOG_MOVE_UP] < -0.5f ) {
  223. control_move |= 1<<CONTROL_MOVE_DOWN;
  224. }
  225. if ( AnalogValues[ANALOG_TURN_LEFT] > 0.5f ) {
  226. control_move |= 1<<CONTROL_TURN_LEFT;
  227. }
  228. if ( AnalogValues[ANALOG_TURN_LEFT] < -0.5f ) {
  229. control_move |= 1<<CONTROL_TURN_RIGHT;
  230. }
  231. packet.Add( control_move, BITPACK_CONTROL_MOVES_CS);
  232. #endif
  233. }
  234. //-----------------------------------------------------------------------------
  235. void ControlClass::Import_Sc(BitStreamClass & packet)
  236. {
  237. packet.Get(ContinuousBooleanBits, BITPACK_CONTINUOUS_BOOLEAN_BITS);
  238. #if 01
  239. packet.Get(AnalogValues[ANALOG_MOVE_FORWARD], BITPACK_ANALOG_VALUES);
  240. packet.Get(AnalogValues[ANALOG_MOVE_LEFT], BITPACK_ANALOG_VALUES);
  241. packet.Get(AnalogValues[ANALOG_MOVE_UP], BITPACK_ANALOG_VALUES);
  242. packet.Get(AnalogValues[ANALOG_TURN_LEFT], BITPACK_ANALOG_VALUES);
  243. #else
  244. int control_move;
  245. packet.Get( control_move, BITPACK_CONTROL_MOVES_SC);
  246. AnalogValues[ANALOG_MOVE_FORWARD] = 0.0f;
  247. AnalogValues[ANALOG_MOVE_LEFT] = 0.0f;
  248. AnalogValues[ANALOG_MOVE_UP] = 0.0f;
  249. if ( control_move & (1<<CONTROL_MOVE_FORWARD) ) {
  250. AnalogValues[ANALOG_MOVE_FORWARD] = 1.0f;
  251. }
  252. if ( control_move & (1<<CONTROL_MOVE_BACKWARD) ) {
  253. AnalogValues[ANALOG_MOVE_FORWARD] = -1.0f;
  254. }
  255. if ( control_move & (1<<CONTROL_MOVE_LEFT) ) {
  256. AnalogValues[ANALOG_MOVE_LEFT] = 1.0f;
  257. }
  258. if ( control_move & (1<<CONTROL_MOVE_RIGHT) ) {
  259. AnalogValues[ANALOG_MOVE_LEFT] = -1.0f;
  260. }
  261. if ( control_move & (1<<CONTROL_MOVE_UP) ) {
  262. AnalogValues[ANALOG_MOVE_UP] = 1.0f;
  263. }
  264. if ( control_move & (1<<CONTROL_MOVE_DOWN) ) {
  265. AnalogValues[ANALOG_MOVE_UP] = -1.0f;
  266. }
  267. /* if ( control_move & (1<<CONTROL_TURN_LEFT) ) {
  268. AnalogValues[ANALOG_TURN_LEFT] = 1.0f;
  269. }
  270. if ( control_move & (1<<CONTROL_TURN_RIGHT) ) {
  271. AnalogValues[ANALOG_TURN_LEFT] = -1.0f;
  272. }*/
  273. #endif
  274. for (int i = 0; i < ANALOG_CONTROL_COUNT; i++) {
  275. if (fabs(AnalogValues[i]) < 0.005) {
  276. //
  277. // The code elsewhere has no tolerance for precision error on this
  278. // value around zero...
  279. //
  280. AnalogValues[i] = 0;
  281. }
  282. }
  283. }
  284. //-----------------------------------------------------------------------------
  285. void ControlClass::Export_Sc(BitStreamClass & packet)
  286. {
  287. packet.Add(ContinuousBooleanBits, BITPACK_CONTINUOUS_BOOLEAN_BITS);
  288. #if 01
  289. packet.Add(AnalogValues[ANALOG_MOVE_FORWARD], BITPACK_ANALOG_VALUES);
  290. packet.Add(AnalogValues[ANALOG_MOVE_LEFT], BITPACK_ANALOG_VALUES);
  291. packet.Add(AnalogValues[ANALOG_MOVE_UP], BITPACK_ANALOG_VALUES);
  292. packet.Add(AnalogValues[ANALOG_TURN_LEFT], BITPACK_ANALOG_VALUES);
  293. #else
  294. int control_move = 0;
  295. if ( AnalogValues[ANALOG_MOVE_FORWARD] > 0.5f ) {
  296. control_move |= 1<<CONTROL_MOVE_FORWARD;
  297. }
  298. if ( AnalogValues[ANALOG_MOVE_FORWARD] < -0.5f ) {
  299. control_move |= 1<<CONTROL_MOVE_BACKWARD;
  300. }
  301. if ( AnalogValues[ANALOG_MOVE_LEFT] > 0.5f ) {
  302. control_move |= 1<<CONTROL_MOVE_LEFT;
  303. }
  304. if ( AnalogValues[ANALOG_MOVE_LEFT] < -0.5f ) {
  305. control_move |= 1<<CONTROL_MOVE_RIGHT;
  306. }
  307. if ( AnalogValues[ANALOG_MOVE_UP] > 0.5f ) {
  308. control_move |= 1<<CONTROL_MOVE_UP;
  309. }
  310. if ( AnalogValues[ANALOG_MOVE_UP] < -0.5f ) {
  311. control_move |= 1<<CONTROL_MOVE_DOWN;
  312. }
  313. /* if ( AnalogValues[ANALOG_TURN_LEFT] > 0.5f ) {
  314. control_move |= 1<<CONTROL_TURN_LEFT;
  315. }
  316. if ( AnalogValues[ANALOG_TURN_LEFT] < -0.5f ) {
  317. control_move |= 1<<CONTROL_TURN_RIGHT;
  318. }*/
  319. packet.Add( control_move, BITPACK_CONTROL_MOVES_SC);
  320. #endif
  321. }
  322. //-----------------------------------------------------------------------------
  323. /*
  324. float ControlClass::Get_Clamp(AnalogControl control)
  325. {
  326. //
  327. // This will definitely need improving...
  328. //
  329. float clamp;
  330. switch (control) {
  331. case ANALOG_MOVE_FORWARD :
  332. clamp = Input::Get_Clamp(INPUT_FUNCTION_RUN_FORWARD);
  333. break;
  334. case ANALOG_MOVE_LEFT :
  335. clamp = Input::Get_Clamp(INPUT_FUNCTION_RUN_LEFT);
  336. break;
  337. case ANALOG_MOVE_UP :
  338. clamp = Input::Get_Clamp(INPUT_FUNCTION_RUN_FORWARD);
  339. break;
  340. case ANALOG_TURN_LEFT :
  341. clamp = Input::Get_Clamp(INPUT_FUNCTION_TURN_LEFT);
  342. break;
  343. case ANALOG_WEAPON_UP :
  344. clamp = Input::Get_Clamp(INPUT_FUNCTION_WEAPON_UP);
  345. break;
  346. case ANALOG_WEAPON_LEFT :
  347. // clamp = 1.0f;
  348. clamp = Input::Get_Clamp(INPUT_FUNCTION_WEAPON_LEFT);
  349. break;
  350. default:
  351. WWASSERT(0);
  352. }
  353. WWASSERT(clamp > 0);
  354. return clamp;
  355. }
  356. */
  357. /*
  358. BYTE ControlClass::Scale_Analog(float clamp, float unscaled)
  359. {
  360. WWASSERT(unscaled > -clamp - WWMATH_EPSILON);
  361. WWASSERT(unscaled < +clamp + WWMATH_EPSILON);
  362. return (BYTE) (255 * WWMath::Clamp((unscaled + clamp) / (2 * clamp)));
  363. }
  364. float ControlClass::Unscale_Analog(float clamp, BYTE scaled)
  365. {
  366. float unscaled;
  367. if (scaled == 127) { // scaling perturbs zero, special-case it
  368. unscaled = 0;
  369. } else {
  370. unscaled = scaled / 255.0f * 2 * clamp - clamp;
  371. }
  372. WWASSERT(unscaled > -clamp - WWMATH_EPSILON);
  373. WWASSERT(unscaled < +clamp + WWMATH_EPSILON);
  374. return unscaled;
  375. }
  376. */
  377. void ControlClass::Set_Boolean( BooleanControl bcontrol, bool state )
  378. {
  379. int control = bcontrol;
  380. if ( control >= BOOLEAN_CONTINUOUS_FIRST ) {
  381. control -= BOOLEAN_CONTINUOUS_FIRST;
  382. if (state) ContinuousBooleanBits |= (1 << control);
  383. else ContinuousBooleanBits &= ~(1 << control);
  384. PendingContinuousBooleanBits |= ContinuousBooleanBits;
  385. } else {
  386. control -= BOOLEAN_ONE_TIME_FIRST;
  387. if (state) OneTimeBooleanBits |= (1 << control);
  388. else OneTimeBooleanBits &= ~(1 << control);
  389. PendingOneTimeBooleanBits |= OneTimeBooleanBits;
  390. }
  391. }
  392. bool ControlClass::Get_Boolean( BooleanControl bcontrol )
  393. {
  394. int control = bcontrol;
  395. if ( control >= BOOLEAN_CONTINUOUS_FIRST ) {
  396. control -= BOOLEAN_CONTINUOUS_FIRST;
  397. return ( ContinuousBooleanBits & (1 << control ) ) ? true : false;
  398. } else {
  399. control -= BOOLEAN_ONE_TIME_FIRST;
  400. return ( OneTimeBooleanBits & (1 << control ) ) ? true : false;
  401. }
  402. }
  403. void ControlClass::Set_Precision(void)
  404. {
  405. cEncoderList::Set_Precision(BITPACK_ONE_TIME_BOOLEAN_BITS, NUM_BOOLEAN_ONE_TIME);
  406. cEncoderList::Set_Precision(BITPACK_CONTINUOUS_BOOLEAN_BITS, NUM_BOOLEAN_CONTINUOUS);
  407. cEncoderList::Set_Precision(BITPACK_CONTROL_MOVES_CS, CONTROL_TURN_RIGHT+1); // 8
  408. cEncoderList::Set_Precision(BITPACK_CONTROL_MOVES_SC, CONTROL_MOVE_DOWN+1); // 6
  409. //
  410. // TSS: I think that analog values are within this range, except for
  411. // DEBUG_RAPID_MOVE...
  412. //
  413. cEncoderList::Set_Precision(BITPACK_ANALOG_VALUES, -1.0, 1.0, 0.01);
  414. /*
  415. //
  416. // Proof that zero does not map to zero...
  417. //
  418. cPacket test;
  419. float zero = 0.0f;
  420. test.Add(zero, BITPACK_ANALOG_VALUES);
  421. float zero2 = -999;
  422. test.Get(zero2, BITPACK_ANALOG_VALUES);
  423. */
  424. }