Open Source Tomb Raider Engine
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

OpenRaider.cpp 43KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198
  1. /*!
  2. * \file src/OpenRaider.cpp
  3. * \brief Main Game Object
  4. *
  5. * \author xythobuz
  6. */
  7. #include <cstdio>
  8. #include <cstring>
  9. #include <assert.h>
  10. #include "WindowSDL.h"
  11. #include "config.h"
  12. #include "Console.h"
  13. #include "Game.h"
  14. #include "main.h"
  15. #include "math/math.h"
  16. #include "Menu.h"
  17. #include "Sound.h"
  18. #include "TombRaider.h"
  19. #include "utils/strings.h"
  20. #include "utils/time.h"
  21. #include "OpenRaider.h"
  22. OpenRaider::OpenRaider() {
  23. mRunning = false;
  24. mFPS = false;
  25. mBaseDir = NULL;
  26. mPakDir = NULL;
  27. mAudioDir = NULL;
  28. mDataDir = NULL;
  29. for (int i = 0; i < ActionEventCount; i++)
  30. keyBindings[i] = unknownKey;
  31. }
  32. OpenRaider::~OpenRaider() {
  33. if (mBaseDir)
  34. delete mBaseDir;
  35. if (mPakDir)
  36. delete mPakDir;
  37. if (mAudioDir)
  38. delete mAudioDir;
  39. if (mDataDir)
  40. delete mDataDir;
  41. }
  42. int OpenRaider::initialize() {
  43. // Initialize Windowing
  44. int error = getWindow().initialize();
  45. if (error != 0) {
  46. printf("Could not initialize Window (%d)!\n", error);
  47. return -1;
  48. }
  49. // Initialize OpenGL
  50. error = getWindow().initializeGL();
  51. if (error != 0) {
  52. printf("Could not initialize OpenGL (%d)!\n", error);
  53. return -2;
  54. }
  55. error = getWindow().initializeFont();
  56. if (error != 0) {
  57. printf("Could not initialize SDL-TTF (%d)!\n", error);
  58. return -3;
  59. }
  60. error = getSound().initialize();
  61. if (error != 0) {
  62. printf("Could not initialize Sound (%d)!\n", error);
  63. return -4;
  64. }
  65. // Initialize game engine
  66. error = getGame().initialize();
  67. if (error != 0) {
  68. printf("Could not initialize Game Engine (%d)!\n", error);
  69. return -5;
  70. }
  71. #ifdef DEBUG
  72. mFPS = true;
  73. #endif
  74. getMenu().setVisible(true);
  75. systemTimerReset();
  76. return 0;
  77. }
  78. int OpenRaider::loadConfig(const char *config) {
  79. assert(config != NULL);
  80. assert(config[0] != '\0');
  81. char *configFile = fullPath(config, 0);
  82. getConsole().print("Loading config from \"%s\"...", configFile);
  83. FILE *f = fopen(configFile, "r");
  84. if (f == NULL) {
  85. getConsole().print("Could not open file!");
  86. return -1;
  87. }
  88. char buffer[256];
  89. while (fgets(buffer, 256, f) != NULL) {
  90. int error = command(buffer);
  91. if (error != 0) {
  92. getConsole().print("Error Code: %d", error);
  93. }
  94. }
  95. fclose(f);
  96. return 0;
  97. }
  98. int OpenRaider::command(const char *command) {
  99. assert(command != NULL);
  100. assert(command[0] != '\0');
  101. int returnValue = 0;
  102. char *cmd = bufferString("%s", command);
  103. size_t length = strlen(cmd);
  104. // Command ends at '\n' or # when a comment begins
  105. for (size_t i = 0; i < length; i++) {
  106. if (cmd[i] == '\n' || cmd[i] == '#') {
  107. cmd[i] = '\0';
  108. break;
  109. }
  110. }
  111. char *strtokState;
  112. char *token = strtok_r(cmd, " \t", &strtokState);
  113. if (token != NULL) {
  114. // token is the command to execute
  115. // get arguments
  116. std::vector<char *> args;
  117. char *next;
  118. while ((next = strtok_r(NULL, " \t", &strtokState)) != NULL) {
  119. args.push_back(next);
  120. }
  121. // Execute
  122. returnValue = this->command(token, &args);
  123. }
  124. free(cmd);
  125. return returnValue;
  126. }
  127. int OpenRaider::command(const char *command, std::vector<char *> *args) {
  128. assert(command != NULL);
  129. assert(command[0] != '\0');
  130. assert(args != NULL);
  131. if (strcmp(command, "set") == 0) {
  132. if (args->size() != 2) {
  133. getConsole().print("Invalid use of set-command");
  134. return -1;
  135. } else {
  136. return set(args->at(0), args->at(1));
  137. }
  138. } else if (strcmp(command, "bind") == 0) {
  139. if (args->size() != 2) {
  140. getConsole().print("Invalid use of bind-command");
  141. return -2;
  142. } else {
  143. return bind(args->at(0), args->at(1));
  144. }
  145. } else if (strcmp(command, "quit") == 0) {
  146. exit(0);
  147. } else if (strcmp(command, "load") == 0) {
  148. if (!mRunning) {
  149. getConsole().print("Use load command interactively!");
  150. return -999;
  151. }
  152. char *tmp = bufferString("%s/%s", mPakDir, args->at(0));
  153. int error = getGame().loadLevel(tmp);
  154. delete [] tmp;
  155. return error;
  156. } else if (strcmp(command, "sshot") == 0) {
  157. if (!mRunning) {
  158. getConsole().print("Use sshot command interactively!");
  159. return -999;
  160. }
  161. char *filename = bufferString("%s/sshots/%s", mBaseDir, VERSION);
  162. bool console = (args->size() > 0) && (strcmp(args->at(0), "console") == 0);
  163. bool menu = (args->size() > 0) && (strcmp(args->at(0), "menu") == 0);
  164. if (!console) {
  165. getConsole().setVisible(false);
  166. if (menu)
  167. getMenu().setVisible(true);
  168. frame();
  169. frame(); // Double buffered
  170. }
  171. getRender().screenShot(filename);
  172. if (!console) {
  173. getConsole().setVisible(true);
  174. if (menu)
  175. getMenu().setVisible(false);
  176. }
  177. getConsole().print("Screenshot stored...");
  178. delete filename;
  179. } else if (strcmp(command, "mode") == 0) {
  180. if (args->size() > 0) {
  181. char *mode = args->at(0);
  182. if (strcmp(mode, "wireframe") == 0) {
  183. if (getGame().isLoaded()) {
  184. getRender().setMode(Render::modeWireframe);
  185. getConsole().print("Wireframe mode");
  186. } else {
  187. getConsole().print("Load a level to set this mode!");
  188. return -3;
  189. }
  190. } else if (strcmp(mode, "solid") == 0) {
  191. if (getGame().isLoaded()) {
  192. getRender().setMode(Render::modeSolid);
  193. getConsole().print("Solid mode");
  194. } else {
  195. getConsole().print("Load a level to set this mode!");
  196. return -4;
  197. }
  198. } else if (strcmp(mode, "texture") == 0) {
  199. if (getGame().isLoaded()) {
  200. getRender().setMode(Render::modeTexture);
  201. getConsole().print("Texture mode");
  202. } else {
  203. getConsole().print("Load a level to set this mode!");
  204. return -5;
  205. }
  206. } else if (strcmp(mode, "vertexlight") == 0) {
  207. if (getGame().isLoaded()) {
  208. getRender().setMode(Render::modeVertexLight);
  209. getConsole().print("Vertexlight mode");
  210. } else {
  211. getConsole().print("Load a level to set this mode!");
  212. return -6;
  213. }
  214. } else if (strcmp(mode, "titlescreen") == 0) {
  215. getRender().setMode(Render::modeLoadScreen);
  216. getConsole().print("Titlescreen mode");
  217. } else {
  218. getConsole().print("Invalid use of mode command (%s)!", mode);
  219. return -7;
  220. }
  221. } else {
  222. getConsole().print("Invalid use of mode command!");
  223. return -8;
  224. }
  225. } else if (strcmp(command, "move") == 0) {
  226. if (!mRunning) {
  227. getConsole().print("Use move command interactively!");
  228. return -999;
  229. }
  230. if (args->size() > 0) {
  231. if (getGame().isLoaded()) {
  232. char *move = args->at(0);
  233. if (strcmp(move, "walk") == 0) {
  234. getGame().mLara->moveType = worldMoveType_walk;
  235. getConsole().print("Lara is walking...");
  236. } else if (strcmp(move, "fly") == 0) {
  237. getGame().mLara->moveType = worldMoveType_fly;
  238. getConsole().print("Lara is flying...");
  239. } else if (strcmp(move, "noclip") == 0) {
  240. getGame().mLara->moveType = worldMoveType_noClipping;
  241. getConsole().print("Lara is noclipping...");
  242. } else {
  243. getConsole().print("Invalid use of move command (%s)!", move);
  244. return -9;
  245. }
  246. } else {
  247. getConsole().print("Load a level to change the movement type!");
  248. return -10;
  249. }
  250. } else {
  251. getConsole().print("Invalid use of move command!");
  252. return -11;
  253. }
  254. } else if (strcmp(command, "sound") == 0) {
  255. if ((!mRunning) || (!getGame().isLoaded())) {
  256. getConsole().print("Use sound command interactively!");
  257. return -999;
  258. }
  259. if (args->size() > 0) {
  260. getSound().play(atoi(args->at(0)));
  261. } else {
  262. getConsole().print("Invalid use of sound command!");
  263. return -12;
  264. }
  265. } else if (strcmp(command, "animate") == 0) {
  266. if ((!mRunning) || (!getGame().isLoaded())) {
  267. getConsole().print("Use animate command interactively!");
  268. return -999;
  269. }
  270. if (args->size() > 0) {
  271. char c = args->at(0)[0];
  272. if (c == 'n') {
  273. // Step all skeletal models to their next animation
  274. if (getRender().getFlags() & Render::fAnimateAllModels) {
  275. for (unsigned int i = 0; i < getRender().mModels.size(); i++) {
  276. SkeletalModel *m = getRender().mModels[i];
  277. if (m->getAnimation() < ((int)m->model->animation.size() - 1))
  278. m->setAnimation(m->getAnimation() + 1);
  279. else
  280. if (m->getAnimation() != 0)
  281. m->setAnimation(0);
  282. }
  283. } else {
  284. getConsole().print("Animations need to be enabled!");
  285. }
  286. } else if (c == 'p') {
  287. // Step all skeletal models to their previous animation
  288. if (getRender().getFlags() & Render::fAnimateAllModels) {
  289. for (unsigned int i = 0; i < getRender().mModels.size(); i++) {
  290. SkeletalModel *m = getRender().mModels[i];
  291. if (m->getAnimation() > 0)
  292. m->setAnimation(m->getAnimation() - 1);
  293. else
  294. if (m->model->animation.size() > 0)
  295. m->setAnimation(m->model->animation.size() - 1);
  296. }
  297. } else {
  298. getConsole().print("Animations need to be enabled!");
  299. }
  300. } else {
  301. // Enable or disable animating all skeletal models
  302. bool b;
  303. if (readBool(args->at(0), &b) < 0) {
  304. getConsole().print("Pass BOOL to animate command!");
  305. return -13;
  306. }
  307. if (b)
  308. getRender().setFlags(Render::fAnimateAllModels);
  309. else
  310. getRender().clearFlags(Render::fAnimateAllModels);
  311. getConsole().print(b ? "Animating all models" : "No longer animating all models");
  312. }
  313. } else {
  314. getConsole().print("Invalid use of animate command!");
  315. return -14;
  316. }
  317. } else if (strcmp(command, "light") == 0) {
  318. if (args->size() > 0) {
  319. bool b;
  320. if (readBool(args->at(0), &b) < 0) {
  321. getConsole().print("Pass BOOL to light command!");
  322. return -15;
  323. }
  324. if (b)
  325. getRender().setFlags(Render::fGL_Lights);
  326. else
  327. getRender().clearFlags(Render::fGL_Lights);
  328. getConsole().print("GL-Lights are now %s", b ? "on" : "off");
  329. } else {
  330. getConsole().print("Invalid use of light-command!");
  331. return -16;
  332. }
  333. } else if (strcmp(command, "fog") == 0) {
  334. if (args->size() > 0) {
  335. bool b;
  336. if (readBool(args->at(0), &b) < 0) {
  337. getConsole().print("Pass BOOL to fog command!");
  338. return -17;
  339. }
  340. if (b)
  341. getRender().setFlags(Render::fFog);
  342. else
  343. getRender().clearFlags(Render::fFog);
  344. getConsole().print("Fog is now %s", b ? "on" : "off");
  345. } else {
  346. getConsole().print("Invalid use of fog-command!");
  347. return -18;
  348. }
  349. } else if (strcmp(command, "hop") == 0) {
  350. if (args->size() > 0) {
  351. bool b;
  352. if (readBool(args->at(0), &b) < 0) {
  353. getConsole().print("Pass BOOL to hop command!");
  354. return -19;
  355. }
  356. if (b)
  357. getWorld().setFlag(World::fEnableHopping);
  358. else
  359. getWorld().clearFlag(World::fEnableHopping);
  360. getConsole().print("Room hopping is now %s", b ? "on" : "off");
  361. } else {
  362. getConsole().print("Invalid use of hop-command!");
  363. return -20;
  364. }
  365. } else if (strcmp(command, "viewmodel") == 0) {
  366. if ((!mRunning) || (!getGame().isLoaded())) {
  367. getConsole().print("Use viewmodel command interactively!");
  368. return -999;
  369. }
  370. if (getGame().mLara) {
  371. SkeletalModel *smdl = static_cast<SkeletalModel *>(getGame().mLara->tmpHook);
  372. skeletal_model_t *mdl = getWorld().getModel(atoi(args->at(0)));
  373. if (smdl)
  374. smdl->setModel(mdl);
  375. }
  376. //m_render.ViewModel(LARA, atoi(cmd));
  377. } else if (strcmp(command, "pos") == 0) {
  378. if (getGame().mLara) {
  379. getConsole().print("Position:");
  380. getConsole().print(" Room %i (0x%X)", getGame().mLara->room, getWorld().getRoomInfo(getGame().mLara->room));
  381. getConsole().print(" %.1fx %.1fy %.1fz", getGame().mLara->pos[0], getGame().mLara->pos[1], getGame().mLara->pos[2]);
  382. getConsole().print(" %.1f Yaw %.1f Pitch", OR_RAD_TO_DEG(getGame().mLara->angles[1]), OR_RAD_TO_DEG(getGame().mLara->angles[2]));
  383. } else {
  384. getConsole().print("Load a level to get Laras position!");
  385. return -21;
  386. }
  387. } else if (strcmp(command, "vmodel") == 0) {
  388. if (args->size() > 0) {
  389. bool b;
  390. if (readBool(args->at(0), &b) < 0) {
  391. getConsole().print("Pass BOOL to vmodel command!");
  392. return -22;
  393. }
  394. if (b)
  395. getRender().setFlags(Render::fViewModel);
  396. else
  397. getRender().clearFlags(Render::fViewModel);
  398. getConsole().print("Viewmodel is now %s", b ? "on" : "off");
  399. } else {
  400. getConsole().print("Invalid use of vmodel-command!");
  401. return -23;
  402. }
  403. } else if (strcmp(command, "ralpha") == 0) {
  404. if (args->size() > 0) {
  405. bool b;
  406. if (readBool(args->at(0), &b) < 0) {
  407. getConsole().print("Pass BOOL to ralpha command!");
  408. return -24;
  409. }
  410. if (b)
  411. getRender().setFlags(Render::fRoomAlpha);
  412. else
  413. getRender().clearFlags(Render::fRoomAlpha);
  414. getConsole().print("Room Alpha is now %s", b ? "on" : "off");
  415. } else {
  416. getConsole().print("Invalid use of ralpha-command!");
  417. return -25;
  418. }
  419. } else if (strcmp(command, "portal") == 0) {
  420. if (args->size() > 0) {
  421. bool b;
  422. if (readBool(args->at(0), &b) < 0) {
  423. getConsole().print("Pass BOOL to portal command!");
  424. return -26;
  425. }
  426. if (b)
  427. getRender().setFlags(Render::fPortals);
  428. else
  429. getRender().clearFlags(Render::fPortals);
  430. getConsole().print("Portals are now %s", b ? "on" : "off");
  431. } else {
  432. getConsole().print("Invalid use of portal-command!");
  433. return -27;
  434. }
  435. } else if (strcmp(command, "vis") == 0) {
  436. if (args->size() > 0) {
  437. bool b;
  438. if (readBool(args->at(0), &b) < 0) {
  439. getConsole().print("Pass BOOL to vis command!");
  440. return -28;
  441. }
  442. if (b)
  443. getRender().setFlags(Render::fUsePortals);
  444. else
  445. getRender().clearFlags(Render::fUsePortals);
  446. getConsole().print("Portals are now %s", b ? "on" : "off");
  447. } else {
  448. getConsole().print("Invalid use of vis-command!");
  449. return -29;
  450. }
  451. } else if (strcmp(command, "upf") == 0) {
  452. if (args->size() > 0) {
  453. bool b;
  454. if (readBool(args->at(0), &b) < 0) {
  455. getConsole().print("Pass BOOL to upf command!");
  456. return -30;
  457. }
  458. if (b)
  459. getRender().setFlags(Render::fUpdateRoomListPerFrame);
  460. else
  461. getRender().clearFlags(Render::fUpdateRoomListPerFrame);
  462. getConsole().print("URLPF is now %s", b ? "on" : "off");
  463. } else {
  464. getConsole().print("Invalid use of upf-command!");
  465. return -31;
  466. }
  467. } else if (strcmp(command, "sprite") == 0) {
  468. if (args->size() > 0) {
  469. bool b;
  470. if (readBool(args->at(0), &b) < 0) {
  471. getConsole().print("Pass BOOL to sprite command!");
  472. return -34;
  473. }
  474. if (b)
  475. getRender().setFlags(Render::fSprites);
  476. else
  477. getRender().clearFlags(Render::fSprites);
  478. getConsole().print("Sprites are now %s", b ? "on" : "off");
  479. } else {
  480. getConsole().print("Invalid use of sprite-command!");
  481. return -35;
  482. }
  483. } else if (strcmp(command, "roommodel") == 0) {
  484. if (args->size() > 0) {
  485. bool b;
  486. if (readBool(args->at(0), &b) < 0) {
  487. getConsole().print("Pass BOOL to roommodel command!");
  488. return -36;
  489. }
  490. if (b)
  491. getRender().setFlags(Render::fRoomModels);
  492. else
  493. getRender().clearFlags(Render::fRoomModels);
  494. getConsole().print("Roommodels are now %s", b ? "on" : "off");
  495. } else {
  496. getConsole().print("Invalid use of roommodel-command!");
  497. return -37;
  498. }
  499. } else if (strcmp(command, "entmodel") == 0) {
  500. if (args->size() > 0) {
  501. bool b;
  502. if (readBool(args->at(0), &b) < 0) {
  503. getConsole().print("Pass BOOL to entmodel command!");
  504. return -38;
  505. }
  506. if (b)
  507. getRender().setFlags(Render::fEntityModels);
  508. else
  509. getRender().clearFlags(Render::fEntityModels);
  510. getConsole().print("Entmodels are now %s", b ? "on" : "off");
  511. } else {
  512. getConsole().print("Invalid use of entmodel-command!");
  513. return -39;
  514. }
  515. } else if (strcmp(command, "oneroom") == 0) {
  516. if (args->size() > 0) {
  517. bool b;
  518. if (readBool(args->at(0), &b) < 0) {
  519. getConsole().print("Pass BOOL to oneroom command!");
  520. return -40;
  521. }
  522. if (b)
  523. getRender().setFlags(Render::fOneRoom);
  524. else
  525. getRender().clearFlags(Render::fOneRoom);
  526. getConsole().print("Rendering one room is now %s", b ? "on" : "off");
  527. } else {
  528. getConsole().print("Invalid use of oneroom-command!");
  529. return -41;
  530. }
  531. } else if (strcmp(command, "allrooms") == 0) {
  532. if (args->size() > 0) {
  533. bool b;
  534. if (readBool(args->at(0), &b) < 0) {
  535. getConsole().print("Pass BOOL to allrooms command!");
  536. return -42;
  537. }
  538. if (b)
  539. getRender().setFlags(Render::fAllRooms);
  540. else
  541. getRender().clearFlags(Render::fAllRooms);
  542. getConsole().print("Rendering all rooms is now %s", b ? "on" : "off");
  543. } else {
  544. getConsole().print("Invalid use of allrooms-command!");
  545. return -43;
  546. }
  547. } else if (strcmp(command, "ponytail") == 0) {
  548. if (args->size() > 0) {
  549. bool b;
  550. if (readBool(args->at(0), &b) < 0) {
  551. getConsole().print("Pass BOOL to ponytail command!");
  552. return -44;
  553. }
  554. if (b)
  555. getRender().setFlags(Render::fRenderPonytail);
  556. else
  557. getRender().clearFlags(Render::fRenderPonytail);
  558. getConsole().print("Ponytail is now %s", b ? "on" : "off");
  559. } else {
  560. getConsole().print("Invalid use of ponytail-command!");
  561. return -45;
  562. }
  563. } else if (strcmp(command, "pigtail") == 0) {
  564. if ((!mRunning) || (!getGame().isLoaded())) {
  565. getConsole().print("Use pigtail command interactively!");
  566. return -999;
  567. }
  568. if (args->size() > 0) {
  569. bool b;
  570. if (readBool(args->at(0), &b) < 0) {
  571. getConsole().print("Pass BOOL to pigtail command!");
  572. return -46;
  573. }
  574. SkeletalModel *tmp = static_cast<SkeletalModel *>(getGame().mLara->tmpHook);
  575. tmp->model->pigtails = b;
  576. if (b) {
  577. tmp->model->ponyOff -= 20;
  578. tmp->model->ponytail[1] -= 32;
  579. } else {
  580. tmp->model->ponyOff += 20;
  581. tmp->model->ponytail[1] += 32;
  582. }
  583. getConsole().print("Pigtail is now %s", b ? "on" : "off");
  584. } else {
  585. getConsole().print("Invalid use of pigtail-command!");
  586. return -47;
  587. }
  588. } else if (strcmp(command, "ponypos") == 0) {
  589. if ((!mRunning) || (!getGame().isLoaded())) {
  590. getConsole().print("Use ponypos command interactively!");
  591. return -999;
  592. }
  593. if (args->size() > 3) {
  594. SkeletalModel *tmp = static_cast<SkeletalModel *>(getGame().mLara->tmpHook);
  595. tmp->model->ponytail[0] = (float)atof(args->at(0));
  596. tmp->model->ponytail[1] = (float)atof(args->at(1));
  597. tmp->model->ponytail[2] = (float)atof(args->at(2));
  598. tmp->model->ponytailAngle = (float)atof(args->at(3));
  599. } else {
  600. getConsole().print("Invalid use of ponypos-command!");
  601. return -48;
  602. }
  603. } else if (strcmp(command, "help") == 0) {
  604. if (args->size() == 0) {
  605. getConsole().print("Available commands:");
  606. getConsole().print(" load - load a level");
  607. getConsole().print(" set - set a parameter");
  608. getConsole().print(" bind - bind a keyboard/mouse action");
  609. getConsole().print(" sshot - make a screenshot");
  610. getConsole().print(" move - [walk|fly|noclip]");
  611. getConsole().print(" sound - INT - Test play sound");
  612. getConsole().print(" mode - MODE - Render mode");
  613. getConsole().print(" animate - [BOOL|n|p] - Animate models");
  614. getConsole().print(" light - BOOL - GL Lights");
  615. getConsole().print(" fog - BOOL - GL Fog");
  616. getConsole().print(" hop - BOOL - Room hop");
  617. getConsole().print(" viewmodel - INT - Change Laras model");
  618. getConsole().print(" pos - Print position info");
  619. getConsole().print(" vmodel - BOOL - View Model");
  620. getConsole().print(" ralpha - BOOL - Room Alpha");
  621. getConsole().print(" portal - BOOL");
  622. getConsole().print(" vis - BOOL - Use Portals");
  623. getConsole().print(" upf - BOOL - Update Room List Per Frame");
  624. getConsole().print(" sprite - BOOL");
  625. getConsole().print(" roommodel - BOOL");
  626. getConsole().print(" entmodel - BOOL");
  627. getConsole().print(" oneroom - BOOL");
  628. getConsole().print(" allrooms - BOOL");
  629. getConsole().print(" ponytail - BOOL");
  630. getConsole().print(" pigtail - BOOL");
  631. getConsole().print(" ponypos - FLOAT FLOAT FLOAT FLOAT - x y z angle");
  632. getConsole().print(" help - print command help");
  633. getConsole().print(" quit - exit OpenRaider");
  634. getConsole().print("Use help COMMAND to get additional info");
  635. } else if (args->size() == 1) {
  636. return help(args->at(0));
  637. } else {
  638. getConsole().print("Invalid use of help-command");
  639. return -49;
  640. }
  641. } else {
  642. getConsole().print("Unknown command: %s ", command);
  643. return -50;
  644. }
  645. return 0;
  646. }
  647. int OpenRaider::help(const char *cmd) {
  648. assert(cmd != NULL);
  649. assert(cmd[0] != '\0');
  650. if (strcmp(cmd, "set") == 0) {
  651. getConsole().print("set-Command Usage:");
  652. getConsole().print(" set VAR VAL");
  653. getConsole().print("Available Variables:");
  654. getConsole().print(" basedir STRING");
  655. getConsole().print(" pakdir STRING");
  656. getConsole().print(" audiodir STRING");
  657. getConsole().print(" datadir STRING");
  658. getConsole().print(" font STRING");
  659. getConsole().print(" gldriver STRING");
  660. getConsole().print(" size \"INTxINT\"");
  661. getConsole().print(" fullscreen BOOL");
  662. getConsole().print(" audio BOOL");
  663. getConsole().print(" volume BOOL");
  664. getConsole().print(" mouse_x FLOAT");
  665. getConsole().print(" mouse_y FLOAT");
  666. getConsole().print(" fps BOOL");
  667. getConsole().print("Enclose STRINGs with \"\"!");
  668. getConsole().print("size expects a STRING in the specified format");
  669. } else if (strcmp(cmd, "bind") == 0) {
  670. getConsole().print("bind-Command Usage:");
  671. getConsole().print(" bind ACTION KEY");
  672. getConsole().print("Available Actions:");
  673. getConsole().print(" menu");
  674. getConsole().print(" console");
  675. getConsole().print(" forward");
  676. getConsole().print(" backward");
  677. getConsole().print(" left");
  678. getConsole().print(" right");
  679. getConsole().print(" jump");
  680. getConsole().print(" crouch");
  681. getConsole().print(" use");
  682. getConsole().print(" holster");
  683. getConsole().print("Key-Format:");
  684. getConsole().print(" 'a' or '1' for character/number keys");
  685. getConsole().print(" \"leftctrl\" for symbols and special keys");
  686. } else if (strcmp(cmd, "load") == 0) {
  687. getConsole().print("load-Command Usage:");
  688. getConsole().print(" load levelfile.name");
  689. } else if (strcmp(cmd, "game") == 0) {
  690. getConsole().print("Use \"game help\" for more info");
  691. } else if (strcmp(cmd, "sshot") == 0) {
  692. getConsole().print("sshot-Command Usage:");
  693. getConsole().print(" sshot [console|menu]");
  694. getConsole().print("Add console/menu to capture them too");
  695. } else if (strcmp(cmd, "sound") == 0) {
  696. getConsole().print("sound-Command Usage:");
  697. getConsole().print(" sound INT");
  698. getConsole().print("Where INT is a valid sound ID integer");
  699. } else if (strcmp(cmd, "move") == 0) {
  700. getConsole().print("move-Command Usage:");
  701. getConsole().print(" move COMMAND");
  702. getConsole().print("Where COMMAND is one of the following:");
  703. getConsole().print(" walk");
  704. getConsole().print(" fly");
  705. getConsole().print(" noclip");
  706. } else if (strcmp(cmd, "mode") == 0) {
  707. getConsole().print("mode-Command Usage:");
  708. getConsole().print(" mode MODE");
  709. getConsole().print("Where MODE is one of the following:");
  710. getConsole().print(" wireframe");
  711. getConsole().print(" solid");
  712. getConsole().print(" texture");
  713. getConsole().print(" vertexlight");
  714. getConsole().print(" titlescreen");
  715. } else if (strcmp(cmd, "animate") == 0) {
  716. getConsole().print("animate-Command Usage:");
  717. getConsole().print(" animate [n|p|BOOL]");
  718. getConsole().print("Where the commands have the following meaning:");
  719. getConsole().print(" BOOL to (de)activate animating all models");
  720. getConsole().print(" n to step all models to their next animation");
  721. getConsole().print(" p to step all models to their previous animation");
  722. } else {
  723. getConsole().print("No help available for %s", cmd);
  724. return -1;
  725. }
  726. return 0;
  727. }
  728. char *OpenRaider::expandDirectoryNames(const char *s) {
  729. assert(s != NULL);
  730. assert(s[0] != '\0');
  731. if (mBaseDir != NULL) {
  732. const char *base = "$(basedir)";
  733. if (strstr(s, base) != NULL) {
  734. return stringReplace(s, base, mBaseDir);
  735. }
  736. }
  737. if (mPakDir != NULL) {
  738. const char *pak = "$(pakdir)";
  739. if (strstr(s, pak) != NULL) {
  740. return stringReplace(s, pak, mPakDir);
  741. }
  742. }
  743. if (mAudioDir != NULL) {
  744. const char *audio = "$(audiodir)";
  745. if (strstr(s, audio) != NULL) {
  746. return stringReplace(s, audio, mAudioDir);
  747. }
  748. }
  749. if (mDataDir != NULL) {
  750. const char *data = "$(datadir)";
  751. if (strstr(s, data) != NULL) {
  752. return stringReplace(s, data, mDataDir);
  753. }
  754. }
  755. return NULL;
  756. }
  757. #define CHANGE_DIR_WITH_EXPANSION(a) do { \
  758. char *quotes = stringRemoveQuotes(value); \
  759. char *tmp = expandDirectoryNames(quotes); \
  760. if (tmp == NULL) { \
  761. a = fullPath(quotes, 0); \
  762. } else { \
  763. a = fullPath(tmp, 0); \
  764. delete [] tmp; \
  765. } \
  766. delete [] quotes; \
  767. } while(false)
  768. int OpenRaider::set(const char *var, const char *value) {
  769. assert(var != NULL);
  770. assert(var[0] != '\0');
  771. assert(value != NULL);
  772. assert(value[0] != '\0');
  773. if (strcmp(var, "size") == 0) {
  774. // value has format like "\"1024x768\""
  775. unsigned int w = DEFAULT_WIDTH, h = DEFAULT_HEIGHT;
  776. if (sscanf(value, "\"%5dx%5d\"", &w, &h) != 2) {
  777. getConsole().print("set-size-Error: Invalid value (%s)", value);
  778. return -2;
  779. }
  780. getWindow().setSize(w, h);
  781. } else if (strcmp(var, "fullscreen") == 0) {
  782. bool fullscreen = false;
  783. if (readBool(value, &fullscreen) != 0) {
  784. getConsole().print("set-fullscreen-Error: Invalid value (%s)", value);
  785. return -3;
  786. }
  787. getWindow().setFullscreen(fullscreen);
  788. } else if (strcmp(var, "gldriver") == 0) {
  789. getWindow().setDriver(value);
  790. } else if (strcmp(var, "audio") == 0) {
  791. bool audio = false;
  792. if (readBool(value, &audio) != 0) {
  793. getConsole().print("set-audio-Error: Invalid value (%s)", value);
  794. return -4;
  795. }
  796. getSound().setEnabled(audio);
  797. } else if (strcmp(var, "volume") == 0) {
  798. float vol = 1.0f;
  799. if (sscanf(value, "%5f", &vol) != 1) {
  800. getConsole().print("set-volume-Error: Invalid value (%s)", value);
  801. return -5;
  802. }
  803. getSound().setVolume(vol);
  804. } else if (strcmp(var, "mouse_x") == 0) {
  805. float sense = 1.0f;
  806. if (sscanf(value, "%5f", &sense) != 1) {
  807. getConsole().print("set-mouse_x-Error: Invalid value (%s)", value);
  808. return -6;
  809. }
  810. getCamera().setSensitivityX(OR_DEG_TO_RAD(sense));
  811. } else if (strcmp(var, "mouse_y") == 0) {
  812. float sense = 1.0f;
  813. if (sscanf(value, "%5f", &sense) != 1) {
  814. getConsole().print("set-mouse_y-Error: Invalid value (%s)", value);
  815. return -7;
  816. }
  817. getCamera().setSensitivityY(OR_DEG_TO_RAD(sense));
  818. } else if (strcmp(var, "fps") == 0) {
  819. bool fps = false;
  820. if (readBool(value, &fps) != 0) {
  821. getConsole().print("set-fps-Error: Invalid value (%s)", value);
  822. return -8;
  823. }
  824. mFPS = fps;
  825. } else if (strcmp(var, "basedir") == 0) {
  826. CHANGE_DIR_WITH_EXPANSION(mBaseDir);
  827. } else if (strcmp(var, "pakdir") == 0) {
  828. CHANGE_DIR_WITH_EXPANSION(mPakDir);
  829. } else if (strcmp(var, "audiodir") == 0) {
  830. CHANGE_DIR_WITH_EXPANSION(mAudioDir);
  831. } else if (strcmp(var, "datadir") == 0) {
  832. CHANGE_DIR_WITH_EXPANSION(mDataDir);
  833. } else if (strcmp(var, "font") == 0) {
  834. char *quotes = stringReplace(value, "\"", "");
  835. char *tmp = expandDirectoryNames(quotes);
  836. if (tmp == NULL) {
  837. getWindow().setFont(quotes);
  838. } else {
  839. getWindow().setFont(tmp);
  840. delete [] tmp;
  841. }
  842. delete [] quotes;
  843. } else {
  844. getConsole().print("set-Error: Unknown variable (%s = %s)", var, value);
  845. return -1;
  846. }
  847. return 0;
  848. }
  849. int OpenRaider::bind(const char *action, const char *key) {
  850. assert(action != NULL);
  851. assert(action[0] != '\0');
  852. assert(key != NULL);
  853. assert(key[0] != '\0');
  854. const char *tmp = action;
  855. if (action[0] == '+')
  856. tmp++;
  857. if (strcmp(tmp, "menu") == 0) {
  858. return bind(menuAction, key);
  859. } else if (strcmp(tmp, "console") == 0) {
  860. return bind(consoleAction, key);
  861. } else if (strcmp(tmp, "forward") == 0) {
  862. return bind(forwardAction, key);
  863. } else if (strcmp(tmp, "backward") == 0) {
  864. return bind(backwardAction, key);
  865. } else if (strcmp(tmp, "left") == 0) {
  866. return bind(leftAction, key);
  867. } else if (strcmp(tmp, "right") == 0) {
  868. return bind(rightAction, key);
  869. } else if (strcmp(tmp, "jump") == 0) {
  870. return bind(jumpAction, key);
  871. } else if (strcmp(tmp, "crouch") == 0) {
  872. return bind(crouchAction, key);
  873. } else if (strcmp(tmp, "use") == 0) {
  874. return bind(useAction, key);
  875. } else if (strcmp(tmp, "holster") == 0) {
  876. return bind(holsterAction, key);
  877. } else {
  878. getConsole().print("bind-Error: Unknown action (%s --> %s)", key, action);
  879. return -1;
  880. }
  881. }
  882. int OpenRaider::bind(ActionEvents action, const char *key) {
  883. assert(action < ActionEventCount);
  884. assert(key != NULL);
  885. assert(key[0] != '\0');
  886. size_t length = strlen(key);
  887. if ((key[0] == '\'') && (key[length - 1] == '\'') && (length == 3)) {
  888. // Literal character like w, a, s, d, 0, 1...
  889. char c = key[1];
  890. if (((c >= '0') && (c <= '9'))
  891. || ((c >= 'a') && (c <= 'z'))) {
  892. keyBindings[action] = (KeyboardButton)c;
  893. } else {
  894. getConsole().print("bind-\'\'-Error: Unknown key (%s)", key);
  895. return -1;
  896. }
  897. } else if ((key[0] == '\"') && (key[length - 1] == '\"')) {
  898. // Special characters like tilde, esc, quote...
  899. char *tmp = stringRemoveQuotes(key);
  900. if (strcmp(tmp, "quote") == 0) {
  901. keyBindings[action] = quoteKey;
  902. } else if (strcmp(tmp, "backslash") == 0) {
  903. keyBindings[action] = backslashKey;
  904. } else if (strcmp(tmp, "backspace") == 0) {
  905. keyBindings[action] = backspaceKey;
  906. } else if (strcmp(tmp, "capslock") == 0) {
  907. keyBindings[action] = capslockKey;
  908. } else if (strcmp(tmp, "comma") == 0) {
  909. keyBindings[action] = commaKey;
  910. } else if (strcmp(tmp, "del") == 0) {
  911. keyBindings[action] = delKey;
  912. } else if (strcmp(tmp, "up") == 0) {
  913. keyBindings[action] = upKey;
  914. } else if (strcmp(tmp, "down") == 0) {
  915. keyBindings[action] = downKey;
  916. } else if (strcmp(tmp, "left") == 0) {
  917. keyBindings[action] = leftKey;
  918. } else if (strcmp(tmp, "right") == 0) {
  919. keyBindings[action] = rightKey;
  920. } else if (strcmp(tmp, "end") == 0) {
  921. keyBindings[action] = endKey;
  922. } else if (strcmp(tmp, "equals") == 0) {
  923. keyBindings[action] = equalsKey;
  924. } else if (strcmp(tmp, "escape") == 0) {
  925. keyBindings[action] = escapeKey;
  926. } else if (strcmp(tmp, "f1") == 0) {
  927. keyBindings[action] = f1Key;
  928. } else if (strcmp(tmp, "f2") == 0) {
  929. keyBindings[action] = f2Key;
  930. } else if (strcmp(tmp, "f3") == 0) {
  931. keyBindings[action] = f3Key;
  932. } else if (strcmp(tmp, "f4") == 0) {
  933. keyBindings[action] = f4Key;
  934. } else if (strcmp(tmp, "f5") == 0) {
  935. keyBindings[action] = f5Key;
  936. } else if (strcmp(tmp, "f6") == 0) {
  937. keyBindings[action] = f6Key;
  938. } else if (strcmp(tmp, "f7") == 0) {
  939. keyBindings[action] = f7Key;
  940. } else if (strcmp(tmp, "f8") == 0) {
  941. keyBindings[action] = f8Key;
  942. } else if (strcmp(tmp, "f9") == 0) {
  943. keyBindings[action] = f9Key;
  944. } else if (strcmp(tmp, "f10") == 0) {
  945. keyBindings[action] = f10Key;
  946. } else if (strcmp(tmp, "f11") == 0) {
  947. keyBindings[action] = f11Key;
  948. } else if (strcmp(tmp, "f12") == 0) {
  949. keyBindings[action] = f12Key;
  950. } else if (strcmp(tmp, "backquote") == 0) {
  951. keyBindings[action] = backquoteKey;
  952. } else if (strcmp(tmp, "home") == 0) {
  953. keyBindings[action] = homeKey;
  954. } else if (strcmp(tmp, "insert") == 0) {
  955. keyBindings[action] = insertKey;
  956. } else if (strcmp(tmp, "leftalt") == 0) {
  957. keyBindings[action] = leftaltKey;
  958. } else if (strcmp(tmp, "leftctrl") == 0) {
  959. keyBindings[action] = leftctrlKey;
  960. } else if (strcmp(tmp, "leftbracket") == 0) {
  961. keyBindings[action] = leftbracketKey;
  962. } else if (strcmp(tmp, "leftgui") == 0) {
  963. keyBindings[action] = leftguiKey;
  964. } else if (strcmp(tmp, "leftshift") == 0) {
  965. keyBindings[action] = leftshiftKey;
  966. } else if (strcmp(tmp, "minus") == 0) {
  967. keyBindings[action] = minusKey;
  968. } else if (strcmp(tmp, "numlock") == 0) {
  969. keyBindings[action] = numlockKey;
  970. } else if (strcmp(tmp, "pagedown") == 0) {
  971. keyBindings[action] = pagedownKey;
  972. } else if (strcmp(tmp, "pageup") == 0) {
  973. keyBindings[action] = pageupKey;
  974. } else if (strcmp(tmp, "pause") == 0) {
  975. keyBindings[action] = pauseKey;
  976. } else if (strcmp(tmp, "dot") == 0) {
  977. keyBindings[action] = dotKey;
  978. } else if (strcmp(tmp, "rightalt") == 0) {
  979. keyBindings[action] = rightaltKey;
  980. } else if (strcmp(tmp, "rightctrl") == 0) {
  981. keyBindings[action] = rightctrlKey;
  982. } else if (strcmp(tmp, "enter") == 0) {
  983. keyBindings[action] = enterKey;
  984. } else if (strcmp(tmp, "rightgui") == 0) {
  985. keyBindings[action] = rightguiKey;
  986. } else if (strcmp(tmp, "rightbracket") == 0) {
  987. keyBindings[action] = rightbracketKey;
  988. } else if (strcmp(tmp, "rightshift") == 0) {
  989. keyBindings[action] = rightshiftKey;
  990. } else if (strcmp(tmp, "scrolllock") == 0) {
  991. keyBindings[action] = scrolllockKey;
  992. } else if (strcmp(tmp, "semicolon") == 0) {
  993. keyBindings[action] = semicolonKey;
  994. } else if (strcmp(tmp, "slash") == 0) {
  995. keyBindings[action] = slashKey;
  996. } else if (strcmp(tmp, "space") == 0) {
  997. keyBindings[action] = spaceKey;
  998. } else if (strcmp(tmp, "tab") == 0) {
  999. keyBindings[action] = tabKey;
  1000. } else if (strcmp(tmp, "leftmouse") == 0) {
  1001. keyBindings[action] = leftmouseKey;
  1002. } else if (strcmp(tmp, "middlemouse") == 0) {
  1003. keyBindings[action] = middlemouseKey;
  1004. } else if (strcmp(tmp, "rightmouse") == 0) {
  1005. keyBindings[action] = rightmouseKey;
  1006. } else {
  1007. getConsole().print("bind-\"\"-Error: Unknown key (%s)", key);
  1008. delete [] tmp;
  1009. return -2;
  1010. }
  1011. delete [] tmp;
  1012. } else {
  1013. getConsole().print("bind-Error: Unknown key (%s)", key);
  1014. return -3;
  1015. }
  1016. return 0;
  1017. }
  1018. void OpenRaider::run() {
  1019. assert(mRunning == false);
  1020. mRunning = true;
  1021. while (mRunning) {
  1022. frame();
  1023. }
  1024. }
  1025. void OpenRaider::frame() {
  1026. assert(mRunning == true);
  1027. static clock_t fpsSum = 0, fpsCount = 0;
  1028. static int fps = 0;
  1029. clock_t startTime = systemTimerGet();
  1030. // Get keyboard and mouse input
  1031. getWindow().eventHandling();
  1032. // Clear screen
  1033. glClearColor(0.00f, 0.00f, 0.00f, 1.0f);
  1034. glClear(GL_COLOR_BUFFER_BIT);
  1035. // Draw game scene
  1036. getRender().display();
  1037. // Draw 2D overlays (console and menu)
  1038. getWindow().glEnter2D();
  1039. getConsole().display();
  1040. getMenu().display();
  1041. // Draw FPS counter
  1042. if (mFPS)
  1043. getWindow().drawText(10, getWindow().mHeight - 20, 0.5f, OR_BLUE, "%dFPS", fps);
  1044. #ifdef DEBUG
  1045. // Draw debug infos
  1046. if (getGame().isLoaded()) {
  1047. for (int i = 0; i < 3; i++) {
  1048. getWindow().drawText(10, getWindow().mHeight - ((4 - i) * 20), 0.5f, OR_BLUE, "%.2f (%.2f)",
  1049. getGame().mLara->pos[i] / 256.0f, getGame().mLara->angles[i]);
  1050. }
  1051. }
  1052. #endif
  1053. getWindow().glExit2D();
  1054. // Put new frame on screen
  1055. getWindow().swapBuffersGL();
  1056. // Calculate FPS display value
  1057. fpsCount++;
  1058. fpsSum += (systemTimerGet() - startTime);
  1059. if (fpsSum >= 500) {
  1060. // Update every 500ms
  1061. fps = (int)((float)fpsCount * (1000.0f / (float)fpsSum));
  1062. fpsCount = fpsSum = 0;
  1063. }
  1064. }
  1065. void OpenRaider::handleKeyboard(KeyboardButton key, bool pressed) {
  1066. assert(key < unknownKey);
  1067. assert(mRunning == true);
  1068. if ((keyBindings[menuAction] == key) && pressed) {
  1069. getMenu().setVisible(!getMenu().isVisible());
  1070. } else if (!getMenu().isVisible()) {
  1071. if ((keyBindings[consoleAction] == key) && pressed) {
  1072. getConsole().setVisible(!getConsole().isVisible());
  1073. } else if (!getConsole().isVisible()) {
  1074. for (int i = forwardAction; i < ActionEventCount; i++) {
  1075. if (keyBindings[i] == key) {
  1076. getGame().handleAction((ActionEvents)i, pressed);
  1077. }
  1078. }
  1079. } else {
  1080. getConsole().handleKeyboard(key, pressed);
  1081. }
  1082. } else {
  1083. getMenu().handleKeyboard(key, pressed);
  1084. }
  1085. getWindow().setMousegrab(!(getMenu().isVisible() || getConsole().isVisible()));
  1086. }
  1087. void OpenRaider::handleText(char *text, bool notFinished) {
  1088. assert(text != NULL);
  1089. assert(text[0] != '\0');
  1090. assert(mRunning == true);
  1091. if ((getConsole().isVisible()) && (!getMenu().isVisible())) {
  1092. getConsole().handleText(text, notFinished);
  1093. }
  1094. }
  1095. void OpenRaider::handleMouseClick(unsigned int x, unsigned int y, KeyboardButton button, bool released) {
  1096. assert(button < unknownKey);
  1097. assert(mRunning == true);
  1098. if (getMenu().isVisible()) {
  1099. getMenu().handleMouseClick(x, y, button, released);
  1100. } else if (!getConsole().isVisible()) {
  1101. for (int i = forwardAction; i < ActionEventCount; i++) {
  1102. if (keyBindings[i] == button) {
  1103. getGame().handleAction((ActionEvents)i, !released);
  1104. }
  1105. }
  1106. }
  1107. }
  1108. void OpenRaider::handleMouseMotion(int xrel, int yrel) {
  1109. assert((xrel != 0) || (yrel != 0));
  1110. assert(mRunning == true);
  1111. if ((!getConsole().isVisible()) && (!getMenu().isVisible())) {
  1112. getGame().handleMouseMotion(xrel, yrel);
  1113. }
  1114. }
  1115. void OpenRaider::handleMouseScroll(int xrel, int yrel) {
  1116. assert((xrel != 0) || (yrel != 0));
  1117. assert(mRunning == true);
  1118. if ((getConsole().isVisible()) && (!getMenu().isVisible())) {
  1119. getConsole().handleMouseScroll(xrel, yrel);
  1120. }
  1121. }