xoreos  0.0.5
module.cpp
Go to the documentation of this file.
1 /* xoreos - A reimplementation of BioWare's Aurora engine
2  *
3  * xoreos is the legal property of its developers, whose names
4  * can be found in the AUTHORS file distributed with this source
5  * distribution.
6  *
7  * xoreos is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 3
10  * of the License, or (at your option) any later version.
11  *
12  * xoreos is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with xoreos. If not, see <http://www.gnu.org/licenses/>.
19  */
20 
25 #include "src/common/util.h"
26 #include "src/common/maths.h"
27 #include "src/common/error.h"
28 #include "src/common/ustring.h"
29 #include "src/common/readfile.h"
30 #include "src/common/filepath.h"
31 #include "src/common/filelist.h"
32 #include "src/common/configman.h"
33 
34 #include "src/aurora/types.h"
35 #include "src/aurora/rimfile.h"
36 #include "src/aurora/gff3file.h"
37 #include "src/aurora/dlgfile.h"
38 
39 #include "src/graphics/camera.h"
40 
43 
44 #include "src/sound/sound.h"
45 
46 #include "src/events/events.h"
47 
53 
55 #include "src/engines/kotor/area.h"
58 
60 
63 
65 
66 namespace Engines {
67 
68 namespace KotOR {
69 
70 bool Module::Action::operator<(const Action &s) const {
71  return timestamp < s.timestamp;
72 }
73 
74 
77  _console(&console),
78  _hasModule(false),
79  _running(false),
81  _exit(false),
83  _fade(new Graphics::Aurora::FadeQuad()),
84  _ingame(new IngameGUI(*this)),
85  _dialog(new DialogGUI(*this)),
87  _freeCamEnabled(false),
88  _prevTimestamp(0),
89  _frameTime(0),
90  _forwardBtnPressed(false),
91  _backwardsBtnPressed(false),
92  _pcRunning(false),
93  _pcPositionLoaded(false),
94  _inDialog(false),
95  _cameraHeight(0.0f) {
96 
97 }
98 
100  try {
101  clear();
102  } catch (...) {
103  }
104 }
105 
107  unload(true);
108 }
109 
110 void Module::load(const Common::UString &module, const Common::UString &entryLocation,
111  ObjectType entryLocationType) {
112 
113  if (isRunning()) {
114  // We are currently running a module. Schedule a safe change instead
115 
116  changeModule(module, entryLocation, entryLocationType);
117  return;
118  }
119 
120  // We are not currently running a module. Directly load the new module
121  loadModule(module, entryLocation, entryLocationType);
122 }
123 
124 void Module::loadModule(const Common::UString &module, const Common::UString &entryLocation,
125  ObjectType entryLocationType) {
126  _ingame->hide();
127 
128  LoadScreen loadScreen(module, _console);
129  loadScreen.show();
130 
131  unload(false);
132 
133  _module = module;
134 
135  _entryLocation = entryLocation;
136  _entryLocationType = entryLocationType;
137 
138  try {
139 
140  load();
141 
142  } catch (Common::Exception &e) {
143  _module.clear();
144 
145  e.add("Failed loading module \"%s\"", module.c_str());
146  throw e;
147  }
148 
149  int northAxis;
150  float mapPt1X, mapPt1Y, mapPt2X, mapPt2Y;
151  float worldPt1X, worldPt1Y, worldPt2X, worldPt2Y;
152 
153  northAxis = _area->getNorthAxis();
154  _area->getMapPoint1(mapPt1X, mapPt1Y);
155  _area->getMapPoint2(mapPt2X, mapPt2Y);
156  _area->getWorldPoint1(worldPt1X, worldPt1Y);
157  _area->getWorldPoint2(worldPt2X, worldPt2Y);
158 
159  Common::UString mapId;
160  if (_module.contains('_'))
161  mapId = _module.substr(++_module.findFirst("_"), _module.end());
162  else
163  mapId = _module.substr(_module.getPosition(3), _module.end());
164  _ingame->setMinimap(mapId, northAxis,
165  worldPt1X, worldPt1Y, worldPt2X, worldPt2Y,
166  mapPt1X, mapPt1Y, mapPt2X, mapPt2Y);
167 
168  _newModule.clear();
169 
170  _hasModule = true;
171 
172  loadScreen.hide();
173 
174  _ingame->show();
175 }
176 
178  _pc.reset(pc);
179 }
180 
182  return _pc.get();
183 }
184 
186  return *_fade;
187 }
188 
189 bool Module::isLoaded() const {
190  return _hasModule && _area && _pc;
191 }
192 
193 bool Module::isRunning() const {
194  return !EventMan.quitRequested() && _running && !_exit;
195 }
196 
197 void Module::exit() {
198  _exit = true;
199 }
200 
202  // TODO: Module::showMenu()
203 }
204 
205 void Module::load() {
206  loadTexturePack();
207  loadResources();
208  loadIFO();
209  loadArea();
210 }
211 
213  // Add all available resource files for the module.
214  // Apparently, the original game prefers ERFs over RIMs. This is
215  // exploited by the KotOR2 TSL Restored Content Mod.
216 
217  // General module resources
218  _resources.push_back(Common::ChangeID());
219  if (!indexOptionalArchive (_module + ".erf", 1000, &_resources.back()))
220  indexMandatoryArchive(_module + ".rim", 1000, &_resources.back());
221 
222  // Scripts
223  _resources.push_back(Common::ChangeID());
224  if (!indexOptionalArchive (_module + "_s.erf", 1001, &_resources.back()))
225  indexMandatoryArchive(_module + "_s.rim", 1001, &_resources.back());
226 
227  // Dialogs, KotOR2 only
228  _resources.push_back(Common::ChangeID());
229  if (!indexOptionalArchive(_module + "_dlg.erf", 1002, &_resources.back()))
230  indexOptionalArchive(_module + "_dlg.rim", 1002, &_resources.back());
231 
232  // Layouts, Xbox only
233  _resources.push_back(Common::ChangeID());
234  indexOptionalArchive(_module + "_a.rim" , 1003, &_resources.back());
235 
236  // Textures, Xbox only
237  _resources.push_back(Common::ChangeID());
238  indexOptionalArchive(_module + "_adx.rim", 1004, &_resources.back());
239 }
240 
242  _ifo.load();
243 
244  _tag = _ifo.getTag();
245  _name = _ifo.getName().getString();
246 
247  readScripts(*_ifo.getGFF());
248 }
249 
251  _area.reset(new Area(*this, _ifo.getEntryArea()));
252 }
253 
254 static const char * const texturePacks[3] = {
255  "swpc_tex_tpc.erf", // Worst
256  "swpc_tex_tpb.erf", // Medium
257  "swpc_tex_tpa.erf" // Best
258 };
259 
261  const int level = ConfigMan.getInt("texturepack");
262  if (_currentTexturePack == level)
263  // Nothing to do
264  return;
265 
266  const int oldTexturePack = _currentTexturePack;
267 
269 
270  status("Loading texture pack %d", level);
272 
273  // If we already had a texture pack loaded, reload all textures
274  if (oldTexturePack != -1)
275  TextureMan.reloadAll();
276 
277  _currentTexturePack = level;
278 }
279 
280 void Module::unload(bool completeUnload) {
281  GfxMan.pauseAnimations();
282 
283  _party.clear();
284 
285  leaveArea();
286  unloadArea();
287 
288  if (completeUnload) {
289  unloadPC();
291 
292  _globalNumbers.clear();
293  _globalBooleans.clear();
294 
295  _availableParty.clear();
296  }
297 
298  unloadIFO();
299  unloadResources();
300 
301  _eventQueue.clear();
302  _delayedActions.clear();
303 
304  _newModule.clear();
305  _hasModule = false;
306 
307  _module.clear();
308 
311 }
312 
314  std::list<Common::ChangeID>::reverse_iterator r;
315  for (r = _resources.rbegin(); r != _resources.rend(); ++r)
316  deindexResources(*r);
317 
318  _resources.clear();
319 }
320 
322  _ifo.unload();
323 }
324 
326  _area.reset();
327 }
328 
330  _pc.reset();
331 }
332 
335  _currentTexturePack = -1;
336 }
337 
338 void Module::changeModule(const Common::UString &module, const Common::UString &entryLocation,
339  ObjectType entryLocationType) {
340 
341  _newModule = module;
342 
343  _entryLocation = entryLocation;
344  _entryLocationType = entryLocationType;
345 }
346 
348  if (_newModule.empty())
349  return;
350 
351  _console->hide();
352 
353  const Common::UString newModule = _newModule;
354  const Common::UString entryLocation = _entryLocation;
355  const ObjectType entryLocationType = _entryLocationType;
356 
357  unload(false);
358 
359  _exit = true;
360 
361  loadModule(newModule, entryLocation, entryLocationType);
362  enter();
363 }
364 
366  if (!_hasModule)
367  throw Common::Exception("Module::enter(): Lacking a module?!?");
368 
369  _console->printf("Entering module \"%s\"", _name.c_str());
370 
371  Common::UString startMovie = _ifo.getStartMovie();
372  if (!startMovie.empty())
373  playVideo(startMovie);
374 
375  float entryX, entryY, entryZ, entryAngle;
376  if (!getEntryObjectLocation(entryX, entryY, entryZ, entryAngle))
377  getEntryIFOLocation(entryX, entryY, entryZ, entryAngle);
378 
379  if (_pc) {
380  if (_pcPositionLoaded) {
381  _pc->getPosition(entryX, entryY, entryZ);
382  _pcPositionLoaded = false;
383  } else
384  _pc->setPosition(entryX, entryY, entryZ);
385 
386  _ingame->setPosition(entryX, entryY);
387  _pc->show();
388  } else {
389  usePC(new Creature());
390  _pc->createFakePC();
391  }
392 
393  if (_party.empty()) {
394  addToParty(_pc.get());
395  }
396 
397  if (!_pc)
398  throw Common::Exception("Module::enter(): Lacking a PC?!?");
399 
400  _cameraHeight = _pc->getCameraHeight();
401 
402  float cameraDistance, cameraPitch, cameraHeight;
403  _area->getCameraStyle(cameraDistance, cameraPitch, cameraHeight);
404 
405  SatelliteCam.setTarget(entryX, entryY, entryZ + _cameraHeight);
406  SatelliteCam.setDistance(cameraDistance);
407  SatelliteCam.setPitch(cameraPitch);
408  SatelliteCam.setHeight(cameraHeight);
409  SatelliteCam.update(0);
410 
411  _ingame->setRotation(Common::rad2deg(SatelliteCam.getYaw()));
412 
413  enterArea();
414 
415  _area->notifyPCMoved();
416 
417  GfxMan.resumeAnimations();
418 
419  _running = true;
420  _exit = false;
421 
422  _ingame->show();
423 }
424 
426  float &entryX, float &entryY, float &entryZ, float &entryAngle) {
427 
428  if (object.empty())
429  return false;
430 
432 
433 
434  KotOR::Object *kotorObject = 0;
435  while (!kotorObject && search->get()) {
436  kotorObject = KotOR::ObjectContainer::toObject(search->next());
437  if (!kotorObject || !(kotorObject->getType() & location))
438  kotorObject = 0;
439  }
440 
441  if (!kotorObject)
442  return false;
443 
444  // TODO: Entry orientation
445 
446  kotorObject->getPosition(entryX, entryY, entryZ);
447  entryAngle = 0.0f;
448 
449  return true;
450 }
451 
452 bool Module::getEntryObjectLocation(float &entryX, float &entryY, float &entryZ, float &entryAngle) {
453  return getObjectLocation(_entryLocation, _entryLocationType, entryX, entryY, entryZ, entryAngle);
454 }
455 
456 void Module::getEntryIFOLocation(float &entryX, float &entryY, float &entryZ, float &entryAngle) {
457  _ifo.getEntryPosition(entryX, entryY, entryZ);
458 
459  float entryDirX, entryDirY;
460  _ifo.getEntryDirection(entryDirX, entryDirY);
461 
462  entryAngle = -Common::rad2deg(atan2(entryDirX, entryDirY));
463 }
464 
466  _ingame->hide();
467 
468  leaveArea();
469 
470  _running = false;
471  _exit = true;
472 }
473 
475  GfxMan.lockFrame();
476 
477  _area->show();
478 
479  runScript(kScriptModuleLoad , this, _pc.get());
480  runScript(kScriptModuleStart, this, _pc.get());
481  runScript(kScriptEnter , this, _pc.get());
482 
483  GfxMan.unlockFrame();
484 
485  _area->runScript(kScriptEnter, _area.get(), _pc.get());
486 }
487 
489  if (_area) {
490  _area->runScript(kScriptExit, _area.get(), _pc.get());
491 
492  _area->hide();
493  }
494 
495  runScript(kScriptExit, this, _pc.get());
496 }
497 
499  Creature *creature = ObjectContainer::toCreature(object);
500  if (creature && !creature->getConversation().empty()) {
501  startConversation(creature->getConversation(), creature);
502  return;
503  }
504 
505  Situated *situated = ObjectContainer::toSituated(object);
506  if (situated && !situated->getConversation().empty()) {
507  startConversation(situated->getConversation(), situated);
508  return;
509  }
510 
511  Placeable *placeable = ObjectContainer::toPlaceable(object);
512  if (placeable) {
513  if (placeable->hasInventory()) {
515  stopPCMovement();
516 
517  _ingame->showContainer(placeable->getInventory());
518  placeable->close(_pc.get());
519  placeable->runScript(kScriptDisturbed, placeable, _pc.get());
520  _prevTimestamp = EventMan.getTimestamp();
521  }
522  }
523 }
524 
525 void Module::addEvent(const Events::Event &event) {
526  _eventQueue.push_back(event);
527 }
528 
530  if (!isRunning())
531  return;
532 
533  replaceModule();
534 
535  if (!isRunning())
536  return;
537 
538  uint32 now = SDL_GetTicks();
539  _frameTime = (now - _prevTimestamp) / 1000.f;
540  _prevTimestamp = now;
541 
542  handleEvents();
543  handleActions();
544 
545  GfxMan.lockFrame();
546 
547  _area->processCreaturesActions(_frameTime);
548 
549  if (!_freeCamEnabled) {
551  SatelliteCam.update(_frameTime);
552  }
553 
554  GfxMan.unlockFrame();
555 }
556 
558  for (EventQueue::const_iterator event = _eventQueue.begin(); event != _eventQueue.end(); ++event) {
559  // Handle console
560  if (_console->isVisible()) {
561  _console->processEvent(*event);
562  continue;
563  }
564 
565  // Conversation/cutscene
566  if (_inDialog) {
567  _dialog->addEvent(*event);
568  continue;
569  }
570 
571  if (event->type == Events::kEventKeyDown) {
572  // Menu
573  if (event->key.keysym.sym == SDLK_ESCAPE) {
574  showMenu();
575  continue;
576  }
577 
578  // Console
579  if ((event->key.keysym.sym == SDLK_d) && (event->key.keysym.mod & KMOD_CTRL)) {
580  _console->show();
581  continue;
582  }
583  }
584 
585  // PC movement
586  switch (event->type) {
588  case Events::kEventKeyUp:
589  if (event->key.keysym.scancode == SDL_SCANCODE_W) {
590  _forwardBtnPressed = event->type == Events::kEventKeyDown;
591  } else if (event->key.keysym.scancode == SDL_SCANCODE_S) {
593  }
594  break;
595  }
596 
597  // Camera
598  if (!_console->isVisible()) {
599  if (_freeCamEnabled) {
600  if (FreeRoamCam.handleCameraInput(*event))
601  continue;
602  }
603  else if (SatelliteCam.handleCameraInput(*event))
604  continue;
605  }
606 
607  _area->addEvent(*event);
608  _ingame->addEvent(*event);
609  }
610 
611  _eventQueue.clear();
612 
613  if (_freeCamEnabled)
614  CameraMan.update();
615 
616  _area->processEventQueue();
617  _ingame->processEventQueue();
618  _dialog->processEventQueue();
619 
620  if (_inDialog && !_dialog->isConversationActive()) {
621  _dialog->hide();
622  _ingame->show();
623  _inDialog = false;
624  }
625 }
626 
628  if (!_pc)
629  return;
630 
631  bool haveMovement = false;
632 
634  float x, y, z;
635  _pc->getPosition(x, y, z);
636  float yaw = SatelliteCam.getYaw();
637  float moveRate = _pc->getRunRate();
638  float newX, newY;
639 
641  _pc->setOrientation(0, 0, 1, Common::rad2deg(yaw));
642  newX = x - moveRate * sin(yaw) * _frameTime;
643  newY = y + moveRate * cos(yaw) * _frameTime;
644  haveMovement = true;
645  } else if (_backwardsBtnPressed && !_forwardBtnPressed) {
646  _pc->setOrientation(0, 0, 1, 180 + Common::rad2deg(yaw));
647  newX = x + moveRate * sin(yaw) * _frameTime;
648  newY = y - moveRate * cos(yaw) * _frameTime;
649  haveMovement = true;
650  }
651 
652  if (haveMovement) {
653  z = _area->evaluateElevation(_pc.get(), newX, newY);
654  if (z != FLT_MIN) {
655  if (!_area->testCollision(glm::vec3(x, y, z + 0.1f),
656  glm::vec3(newX, newY, z + 0.1f)))
657  movePC(newX, newY, z);
658  }
659  }
660  }
661 
662  const float *position = CameraMan.getPosition();
663  SoundMan.setListenerPosition(position[0], position[1], position[2]);
664  const float *orientation = CameraMan.getOrientation();
665  SoundMan.setListenerOrientation(orientation[0], orientation[1], orientation[2], 0.0f, 1.0f, 0.0f);
666 
667  _ingame->setRotation(Common::rad2deg(SatelliteCam.getYaw()));
668 
669  if (haveMovement && !_pcRunning) {
670  _pc->playAnimation(Common::UString("run"), false, -1.0f);
671  _pcRunning = true;
672  } else if (!haveMovement && _pcRunning) {
673  _pc->playDefaultAnimation();
674  _pcRunning = false;
675  }
676 }
677 
679  uint32 now = EventMan.getTimestamp();
680 
681  while (!_delayedActions.empty()) {
682  ActionQueue::iterator action = _delayedActions.begin();
683 
684  if (now < action->timestamp)
685  break;
686 
687  if (action->type == kActionScript)
688  ScriptContainer::runScript(action->script, action->state,
689  action->owner, action->triggerer);
690 
691  _delayedActions.erase(action);
692  }
693 }
694 
695 void Module::movePC(float x, float y, float z) {
696  if (!_pc)
697  return;
698 
699  _pc->setPosition(x, y, z);
700  _ingame->setPosition(x, y);
701  movedPC();
702 }
703 
704 void Module::movePC(const Common::UString &module, const Common::UString &object, ObjectType type) {
705  if (module.empty() || (module == _module)) {
706  float x, y, z, angle;
707  if (getObjectLocation(object, type, x, y, z, angle))
708  movePC(x, y, z);
709 
710  return;
711  }
712 
713  load(module, object, type);
714 }
715 
717  if (!_pc)
718  return;
719 
720  float x, y, z;
721  _pc->getPosition(x, y, z);
722 
723  SatelliteCam.setTarget(x, y, z + _cameraHeight);
724 
725  if (_freeCamEnabled) {
726  CameraMan.setPosition(x, y, z + _cameraHeight);
727  CameraMan.update();
728  }
729 
730  _area->evaluateTriggers(x, y);
731 
732  if (!_freeCamEnabled)
733  _area->notifyPCMoved();
734 }
735 
737  return _party.size();
738 }
739 
740 void Module::addToParty(Creature *creature) {
741  _party.push_back(creature);
742 
743  if (_party.size() == 1)
744  _ingame->setPartyLeader(creature);
745  else if (_party.size() == 2)
746  _ingame->setPartyMember1(creature);
747  else if (_party.size() == 3)
748  _ingame->setPartyMember2(creature);
749 
750  // TODO: The character is in the original game placed on a position somewhere near theplayer character.
751  float x, y, z;
752  _pc->getPosition(x, y, z);
753  creature->show();
754  creature->setPosition(x, y, z);
755  addObject(*creature);
756 
757  // TODO: If the party size increases over 3 show the character selection screen.
758 }
759 
761  return std::find(_party.begin(), _party.end(), creature) != _party.end();
762 }
763 
765  if (index >= static_cast<int>(_party.size()) || index < 0)
766  throw Common::Exception("Module::getPartyMember() Invalid index");
767 
768  std::list<Creature *>::iterator iter = _party.begin();
769  std::advance(iter, index);
770  return *iter;
771 }
772 
774  std::list<Creature *>::iterator iter = _party.begin();
775  if (npc != -1)
776  std::advance(iter, npc);
777  _pc.release();
778  _pc.reset(*iter);
779 
780  Creature *pc = *iter;
781  _party.erase(iter);
782  _party.push_front(pc);
783 
784  _ingame->setPartyLeader(pc);
785 
786  if (_party.size() > 1)
787  _ingame->setPartyMember1(*++_party.begin());
788  if (_party.size() > 2)
789  _ingame->setPartyMember2(_party.back());
790 
791  float x, y, z;
792  _pc->getPosition(x, y, z);
793 
794  SatelliteCam.setTarget(x, y, z + _cameraHeight);
795 
796  if (_freeCamEnabled) {
797  CameraMan.setPosition(x, y, z + _cameraHeight);
798  CameraMan.update();
799  }
800 }
801 
802 void Module::showPartySelectionGUI(int forceNPC1, int forceNPC2) {
803  if (_inDialog)
804  _dialog->hide();
805  else
806  _ingame->hide();
807 
808  PartyConfiguration config;
809 
810  for (std::map<int, Common::UString>::iterator i = _availableParty.begin();
811  i != _availableParty.end(); ++i) {
812  config.slotTemplate[i->first] = i->second;
813  }
814 
815  config.forceNPC1 = forceNPC1;
816  config.forceNPC2 = forceNPC2;
817  config.canCancel = false;
818 
819  _partySelection->loadConfiguration(config);
820 
821  _partySelection->show();
822  _partySelection->run();
823  _partySelection->hide();
824 
825  if (_inDialog)
826  _dialog->show();
827  else
828  _ingame->show();
829 
830  int npc1 = config.forceNPC1;
831  int npc2 = config.forceNPC2;
832 
833  if (npc1 == -1)
834  for (int i = 0; i < 10; ++i)
835  if (config.slotSelected[i]) {
836  config.slotSelected[i] = false;
837  npc1 = i;
838  }
839 
840  if (npc2 == -1)
841  for (int i = 0; i < 10; ++i)
842  if (config.slotSelected[i]) {
843  config.slotSelected[i] = false;
844  npc2 = i;
845  }
846 
847  if (npc1 != -1)
848  addToParty(new Creature(_availableParty[npc1]));
849 }
850 
851 void Module::addAvailablePartyMember(int slot, const Common::UString &templ) {
852  std::map<int, Common::UString>::iterator i = _availableParty.find(slot);
853  if (i != _availableParty.end())
854  _availableParty.erase(i);
855 
856  _availableParty.insert(std::pair<int, Common::UString>(slot, templ));
857 }
858 
860  return _availableParty.find(slot) != _availableParty.end();
861 }
862 
864  _ingame->setReturnStrref(id);
865 }
866 
868  _ingame->setReturnQueryStrref(id);
869 }
870 
871 void Module::setReturnEnabled(bool enabled) {
872  _ingame->setReturnEnabled(enabled);
873 }
874 
875 void Module::setGlobalBoolean(const Common::UString &id, bool value) {
876  _globalBooleans[id] = value;
877 }
878 
880  std::map<Common::UString, bool>::const_iterator iter = _globalBooleans.find(id);
881  if (iter != _globalBooleans.end())
882  return iter->second;
883  else
884  return false;
885 }
886 
887 void Module::setGlobalNumber(const Common::UString &id, int value) {
888  _globalNumbers[id] = value;
889 }
890 
892  std::map<Common::UString, int>::const_iterator iter = _globalNumbers.find(id);
893  if (iter != _globalNumbers.end())
894  return iter->second;
895  else
896  return 0;
897 }
898 
900  return _ifo;
901 }
902 
904  return KotOR::Object::getName();
905 }
906 
908  return _area.get();
909 }
910 
912  const Aurora::NWScript::ScriptState &state,
914  Aurora::NWScript::Object *triggerer, uint32 delay) {
915  Action action;
916 
917  action.type = kActionScript;
918  action.script = script;
919  action.state = state;
920  action.owner = owner;
921  action.triggerer = triggerer;
922  action.timestamp = EventMan.getTimestamp() + delay;
923 
924  _delayedActions.insert(action);
925 }
926 
928  /* Return the localized name of the first (and only) area of the module,
929  * which is the closest thing to the name of the module.
930  *
931  * To do that, if looks through the module directory for a matching RIM file
932  * (case-insensitively) and opens it without indexing into the ResourceManager.
933  * It then opens the module.ifo, grabs the name of the area, opens its ARE file
934  * and returns the localized "Name" field.
935  *
936  * If there's any error while doing all this, an empty string is returned.
937  */
938 
939  try {
940  const Common::FileList modules(ConfigMan.getString("KOTOR_moduleDir"));
941 
942  const Aurora::RIMFile rim(new Common::ReadFile(modules.findFirst(module + ".rim", true)));
943  const uint32 ifoIndex = rim.findResource("module", Aurora::kFileTypeIFO);
944 
945  const Aurora::GFF3File ifo(rim.getResource(ifoIndex), MKTAG('I', 'F', 'O', ' '));
946 
947  const Aurora::GFF3List &areas = ifo.getTopLevel().getList("Mod_Area_list");
948  if (areas.empty())
949  return "";
950 
951  const uint32 areIndex = rim.findResource((*areas.begin())->getString("Area_Name"), Aurora::kFileTypeARE);
952 
953  const Aurora::GFF3File are(rim.getResource(areIndex), MKTAG('A', 'R', 'E', ' '));
954 
955  return are.getTopLevel().getString("Name");
956 
957  } catch (...) {
958  }
959 
960  return "";
961 }
962 
965  if (_freeCamEnabled && ConfigMan.getBool("flycamallrooms"))
966  _area->showAllRooms();
967 }
968 
970  _area->toggleWalkmesh();
971 }
972 
974  _area->toggleTriggers();
975 }
976 
978  try {
979  usePC(save->getPC());
980  load(save->getModuleName());
981  _pcPositionLoaded = save->isPCLoaded();
982  } catch (...) {
984  }
985 }
986 
988  if (_inDialog)
989  return;
990 
991  Common::UString finalName(name);
992 
993  if (finalName.empty() && owner) {
994  Creature *creature = ObjectContainer::toCreature(owner);
995  if (creature)
996  finalName = creature->getConversation();
997  }
998 
999  if (finalName.empty())
1000  return;
1001 
1002  _dialog->startConversation(finalName, owner);
1003 
1004  if (_dialog->isConversationActive()) {
1006  stopPCMovement();
1007 
1008  _ingame->hide();
1009  _dialog->show();
1010  _inDialog = true;
1011  }
1012 }
1013 
1015  const Common::UString &headAnim) {
1016  KotOR::Object *o = _area->getActiveObject();
1017  if (!o)
1018  return;
1019 
1020  o->playAnimation(baseAnim, true, -1.0f);
1021 
1022  Creature *creature = ObjectContainer::toCreature(o);
1023  if (creature) {
1024  if (headAnim.empty())
1025  creature->playDefaultHeadAnimation();
1026  else
1027  creature->playHeadAnimation(headAnim, true, -1.0f, 0.25f);
1028  }
1029 }
1030 
1031 void Module::addItemToActiveObject(const Common::UString &item, int count) {
1032  Inventory *inv = 0;
1033 
1034  KotOR::Object *o = _area->getActiveObject();
1035  if (!o) {
1036  if (_pc)
1037  inv = &_pc->getInventory();
1038  } else {
1039  Placeable *placeable = ObjectContainer::toPlaceable(o);
1040  if (placeable && placeable->hasInventory())
1041  inv = &placeable->getInventory();
1042 
1043  if (!inv) {
1044  Creature *creature = ObjectContainer::toCreature(o);
1045  if (creature)
1046  inv = &creature->getInventory();
1047  }
1048  }
1049 
1050  if (!inv)
1051  return;
1052 
1053  if (count > 0)
1054  inv->addItem(item, count);
1055  else if (count < 0)
1056  inv->removeItem(item, -count);
1057 }
1058 
1060  SatelliteCam.clearInput();
1061 }
1062 
1064  _forwardBtnPressed = false;
1065  _backwardsBtnPressed = false;
1066  _pc->playDefaultAnimation();
1067  _pcRunning = false;
1068 }
1069 
1070 } // End of namespace KotOR
1071 
1072 } // End of namespace Engines
A creature in a Star Wars: Knights of the Old Republic area.
void show()
Show the creature&#39;s model.
Definition: creature.cpp:101
Handling version V3.2/V3.3 of BioWare&#39;s GFFs (generic file format).
void addToParty(Creature *creature)
Add a creature to the party.
Definition: module.cpp:740
#define MKTAG(a0, a1, a2, a3)
A wrapper macro used around four character constants, like &#39;DATA&#39;, to ensure portability.
Definition: endianness.h:140
void delayScript(const Common::UString &script, const Aurora::NWScript::ScriptState &state, Aurora::NWScript::Object *owner, Aurora::NWScript::Object *triggerer, uint32 delay)
Definition: module.cpp:911
void playVideo(const Common::UString &video)
Play this video resource.
Definition: util.cpp:54
Generic Aurora engines resource utility functions.
void add(const char *s,...) GCC_PRINTF(2
Definition: error.cpp:58
bool isVisible() const
Definition: console.cpp:797
std::map< Common::UString, int > _globalNumbers
Definition: module.h:254
virtual Object * next()=0
Move to the next object in the search context and return the previous one.
void setGlobalNumber(const Common::UString &id, int value)
Get a global number.
Definition: module.cpp:887
void loadSavedGame(SavedGame *save)
Definition: module.cpp:977
A class holding an UTF-8 string.
Definition: ustring.h:48
The loading screen gui.
Common::UString _module
The current module&#39;s name.
Definition: module.h:234
#define TextureMan
Shortcut for accessing the texture manager.
Definition: textureman.h:127
std::list< Common::ChangeID > _resources
Resources added by the current module.
Definition: module.h:220
void enter()
Enter the loaded module, starting it.
Definition: module.cpp:365
The global config manager.
void addItemToActiveObject(const Common::UString &item, int count)
Definition: module.cpp:1031
Handling BioWare&#39;s RIMs (resource archives).
void unload()
Unload a currently loaded IFO.
Definition: ifofile.cpp:97
bool isRunning() const
Is a module currently running?
Definition: module.cpp:193
bool indexOptionalArchive(const Common::UString &file, uint32 priority, const std::vector< byte > &password, Common::ChangeID *changeID)
Definition: resources.cpp:69
The Aurora texture manager.
Mathematical helpers.
Camera management.
const Common::UString & getConversation() const
Definition: creature.cpp:597
bool _running
Are we currently running a module?
Definition: module.h:217
A simple streaming file reading class.
Definition: readfile.h:40
bool operator<(const Action &s) const
Definition: module.cpp:70
iterator getPosition(size_t n) const
Convert a numerical position into an iterator.
Definition: ustring.cpp:501
Module(::Engines::Console &console)
Definition: module.cpp:75
Engine utility class for camera handling where camera rotates around PC.
virtual void playAnimation(const Common::UString &anim, bool restart=true, float length=0.0f, float speed=1.0f)
Definition: object.cpp:208
const GFF3Struct & getTopLevel() const
Returns the top-level struct.
Definition: gff3file.cpp:91
ObjectType
Object type, matches the bitfield in nwscript.nss.
Definition: types.h:33
void getEntryDirection(float &x, float &y) const
Return the entry direction.
Definition: ifofile.cpp:302
void processEventQueue()
Process the current event queue.
Definition: module.cpp:529
void setReturnQueryStrref(uint32 id)
Set the string for the return dialog.
Definition: module.cpp:867
virtual void hide()
Hide the GUI.
Definition: gui.cpp:75
void showMenu()
Show the ingame main menu.
Definition: module.cpp:201
Inventory & getInventory()
Definition: creature.cpp:643
iterator findFirst(uint32 c) const
Definition: ustring.cpp:261
void playHeadAnimation(const Common::UString &anim, bool restart=true, float length=0.0f, float speed=1.0f)
Definition: creature.cpp:679
ObjectType getType() const
Return the exact type of the object.
Definition: object.cpp:65
const Common::UString & getString(Language language, LanguageGender gender=kLanguageGenderCurrent) const
Get the string of that language.
Definition: locstring.cpp:82
Common::UString _entryLocation
The tag of the object in the start location for this module.
Definition: module.h:238
static const char *const texturePacks[3]
Definition: module.cpp:254
Exception that provides a stack of explanations.
Definition: error.h:36
std::list< Creature * > _party
Definition: module.h:258
#define FreeRoamCam
SDL_Event Event
Definition: types.h:42
void changeModule(const Common::UString &module, const Common::UString &entryLocation, ObjectType entryLocationType)
Schedule a change to a new module.
Definition: module.cpp:338
void deindexResources(Common::ChangeID &changeID)
Remove previously added resources from the ResourceManager.
Definition: resources.cpp:164
const Aurora::IFOFile & getIFO() const
Return the IFO of the currently loaded module.
Definition: module.cpp:899
void exceptionDispatcherWarning(const char *s,...)
Exception dispatcher that prints the exception as a warning, and adds another reason on top...
Definition: error.cpp:158
void setReturnStrref(uint32 id)
Set the return string for the &#39;Return to Ebon Hawk&#39; button.
Definition: module.cpp:863
EventQueue _eventQueue
Definition: module.h:262
std::map< Common::UString, bool > _globalBooleans
Definition: module.h:253
Keyboard key was pressed.
Definition: types.h:46
void loadModule(const Common::UString &module, const Common::UString &entryLocation, ObjectType entryLocationType)
Load the actual module.
Definition: module.cpp:124
bool close(Object *closer)
The closer object closes this placeable.
Definition: placeable.cpp:195
Basic exceptions to throw.
void load(Common::SeekableReadStream *stream, bool repairNWNPremium=false)
Take over this stream and load an IFO out of it.
Definition: ifofile.cpp:101
Common::ChangeID _textures
Resources added by the current texture pack.
Definition: module.h:230
bool contains(const UString &what) const
Definition: ustring.cpp:335
UString substr(iterator from, iterator to) const
Definition: ustring.cpp:706
void indexMandatoryArchive(const Common::UString &file, uint32 priority, const std::vector< byte > &password, Common::ChangeID *changeID)
Definition: resources.cpp:36
const char * c_str() const
Return the (utf8 encoded) string data.
Definition: ustring.cpp:249
Aurora::NWScript::ObjectReference triggerer
Definition: module.h:203
void replaceModule()
Actually replace the currently running module.
Definition: module.cpp:347
void toggleFreeRoamCamera()
Definition: module.cpp:963
const Common::UString & getName() const
Return the object&#39;s name.
Definition: object.cpp:83
#define ConfigMan
Shortcut for accessing the config manager.
Definition: configman.h:176
Common::UString slotTemplate[10]
Definition: partyconfig.h:37
Common::UString script
Definition: module.h:199
Common::ScopedPtr< DialogGUI > _dialog
Conversation/cutscene GUI.
Definition: module.h:248
Utility templates and functions.
void switchPlayerCharacter(int npc)
Switch the player character.
Definition: module.cpp:773
Common::UString _name
The object&#39;s display name.
Definition: object.h:142
An IFO (module information) file, describing global module properties in many Aurora games...
Definition: ifofile.h:69
Common::ScopedPtr< Graphics::Aurora::FadeQuad > _fade
Definition: module.h:244
const Common::UString & getConversation() const
Get the conversation for this object.
Definition: situated.cpp:117
Aurora::NWScript::ScriptState state
Definition: module.h:201
The global events manager.
A GFF (generic file format) V3.2/V3.3 file, found in all Aurora games except Sonic Chronicles: The Da...
Definition: gff3file.h:85
A 3D model of an object.
const Common::UString & getName() const
Return the module&#39;s name.
Definition: module.cpp:903
ObjectSearch * findObjectsByTag(const Common::UString &tag) const
Return a search context to iterate over all objects with this tag.
The global sound manager, handling all sound output.
bool empty() const
Is the string empty?
Definition: ustring.cpp:245
bool runScript(Script script, const Aurora::NWScript::ObjectReference owner=Aurora::NWScript::ObjectReference(), const Aurora::NWScript::ObjectReference triggerer=Aurora::NWScript::ObjectReference())
Definition: container.cpp:158
Generic Aurora engines (debug) console.
ObjectType _entryLocationType
The type(s) of the object in the start location for this module.
Definition: module.h:240
#define SoundMan
Shortcut for accessing the sound manager.
Definition: sound.h:293
void unload(bool completeUnload=true)
Unload the whole shebang.
Definition: module.cpp:280
StackException Exception
Definition: error.h:59
A scoped plain pointer, allowing pointer-y access and normal deletion.
Definition: scopedptr.h:120
Aurora::NWScript::ObjectReference owner
Definition: module.h:202
An area in Star Wars: Knights of the Old Republic, holding all objects and rooms within, as well as general area properties like the current background music and ambient sounds.
Definition: area.h:65
void startConversation(const Common::UString &name, Aurora::NWScript::Object *owner=0)
Definition: module.cpp:987
Graphics::Aurora::FadeQuad & getFadeQuad()
Return the fade quad.
Definition: module.cpp:185
Aurora::IFOFile _ifo
The current module&#39;s IFO.
Definition: module.h:223
Module information, GFF.
Definition: types.h:83
void getEntryIFOLocation(float &entryX, float &entryY, float &entryZ, float &entryAngle)
Definition: module.cpp:456
The context holding a Star Wars: Knights of the Old Republic area.
std::vector< const GFF3Struct * > GFF3List
Definition: types.h:449
virtual void show()
Show the GUI.
Definition: gui.cpp:69
Inventory & getInventory()
Definition: placeable.cpp:256
#define EventMan
Shortcut for accessing the events manager.
Definition: events.h:210
A placeable in a Star Wars: Knights of the Old Republic area.
void setReturnEnabled(bool enabled)
Enable or disable the &#39;Return to Ebon Hawk&#39; button.
Definition: module.cpp:871
void addEvent(const Events::Event &event)
Add a single event for consideration into the event queue.
Definition: module.cpp:525
Implementing the stream reading interfaces for files.
void addItem(const Common::UString &tag, int count=1)
Definition: inventory.cpp:31
Unicode string handling.
bool getEntryObjectLocation(float &entryX, float &entryY, float &entryZ, float &entryAngle)
Definition: module.cpp:452
static KotOR::Object * toObject(::Aurora::NWScript::Object *object)
void movePC(float x, float y, float z)
Move the player character to this position within the current area.
Definition: module.cpp:695
Basic type definitions to handle files used in BioWare&#39;s Aurora engine.
void addAvailablePartyMember(int slot, const Common::UString &templ)
Add available party member by template.
Definition: module.cpp:851
void clear()
Clear the whole context.
Definition: module.cpp:106
const GFF3List & getList(const Common::UString &field) const
Definition: gff3file.cpp:741
static Placeable * toPlaceable(Aurora::NWScript::Object *object)
void loadTexturePack()
Load texture pack used by the module.
Definition: module.cpp:260
std::map< int, Common::UString > _availableParty
Definition: module.h:259
bool isAvailableCreature(int slot)
Check if there is a party member available for this id.
Definition: module.cpp:859
Common::ScopedPtr< IngameGUI > _ingame
The ingame ui.
Definition: module.h:246
A class representing an undoable change.
Definition: changeid.h:35
bool getGlobalBoolean(const Common::UString &id) const
Get a global boolean.
Definition: module.cpp:879
const GFF3Struct * getGFF() const
Return the IFO&#39;s GFF struct.
Definition: ifofile.cpp:244
uint32_t uint32
Definition: types.h:204
A list of files.
Definition: filelist.h:35
const LocString & getName() const
Return the name of the module.
Definition: ifofile.cpp:267
Common::UString _tag
Definition: object.h:56
Static area data, GFF.
Definition: types.h:81
static Creature * toCreature(Aurora::NWScript::Object *object)
Party selection GUI for Star Wars: Knights of the Old Republic.
void playAnimationOnActiveObject(const Common::UString &baseAnim, const Common::UString &headAnim)
Definition: module.cpp:1014
void setPosition(float x, float y, float z)
Set the creature&#39;s position.
Definition: creature.cpp:176
const Common::UString & getModuleName() const
Definition: savedgame.cpp:127
void status(const char *s,...)
Definition: util.cpp:52
void printf(const char *s,...) GCC_PRINTF(2
Definition: console.cpp:1093
#define FLT_MIN
Definition: maths.h:43
void setGlobalBoolean(const Common::UString &id, bool value)
Set a global boolean.
Definition: module.cpp:875
bool processEvent(const Events::Event &event)
Definition: console.cpp:817
bool isLoaded() const
Is a module currently loaded and ready to run?
Definition: module.cpp:189
#define CameraMan
Shortcut for accessing the camera manager.
Definition: camera.h:83
Common::UString getString(const Common::UString &field, const Common::UString &def="") const
Definition: gff3file.cpp:527
static Situated * toSituated(Aurora::NWScript::Object *object)
Class to hold resource data of a RIM archive file.
Definition: rimfile.h:61
static float rad2deg(float rad)
Definition: maths.h:93
bool _hasModule
Do we have a module?
Definition: module.h:216
Generic Aurora engines utility functions.
Conversation/cutscene GUI for Star Wars: Knights of the Old Republic.
A list of files.
void readScripts(const Aurora::GFF3Struct &gff, bool clear=true)
Definition: container.cpp:134
void usePC(Creature *pc)
Use this character as the player character.
Definition: module.cpp:177
float _forwardBtnPressed
Definition: module.h:268
The context needed to run a Star Wars: Knights of the Old Republic module.
bool isObjectPartyMember(Creature *creature)
Check if the specified creature is a party member.
Definition: module.cpp:760
const Common::UString & getTag() const
Return the module&#39;s tag.
Definition: ifofile.cpp:263
iterator end() const
Definition: ustring.cpp:257
virtual void getPosition(float &x, float &y, float &z) const
Return the object&#39;s position within its area.
Definition: object.cpp:138
Common::ScopedPtr< PartySelectionGUI > _partySelection
Definition: module.h:250
void getEntryPosition(float &x, float &y, float &z) const
Return the entry position.
Definition: ifofile.cpp:296
const Common::UString & getEntryArea() const
Return the entry area.
Definition: ifofile.cpp:292
ActionQueue _delayedActions
Definition: module.h:263
Common::UString _newModule
The module we should change to.
Definition: module.h:235
Keyboard key was released.
Definition: types.h:47
Area * getCurrentArea()
Return the area the PC is currently in.
Definition: module.cpp:907
Creature * getPartyMember(int index)
Get a party member by index.
Definition: module.cpp:764
int getGlobalNumber(const Common::UString &id) const
Set a global number.
Definition: module.cpp:891
Fake value for a module object.
Definition: types.h:51
bool _exit
Should we exit the module?
Definition: module.h:232
void movedPC()
Notify the module that the PC was moved.
Definition: module.cpp:716
void leave()
Leave the running module, quitting it.
Definition: module.cpp:465
Engine utility class for free-roam camera handling.
#define SatelliteCam
void clickObject(Object *object)
Open the inventory of a container.
Definition: module.cpp:498
Handling BioWare&#39;s DLGs (dialog / conversation files).
virtual Object * get()=0
Return the current object in the search context.
void clear()
Clear the string&#39;s contents.
Definition: ustring.cpp:236
Common::ScopedPtr< Creature > _pc
The player character we use.
Definition: module.h:225
const Common::UString & getStartMovie() const
Return the starting movie.
Definition: ifofile.cpp:288
::Engines::Console * _console
Definition: module.h:214
void addObject(KotOR::Object &object)
Add an object to this container.
#define GfxMan
Shortcut for accessing the graphics manager.
Definition: graphics.h:299
void removeItem(const Common::UString &tag, int count=1)
Definition: inventory.cpp:47
Utility class for manipulating file paths.
Common::ScopedPtr< Area > _area
The current module&#39;s area.
Definition: module.h:242
bool getObjectLocation(const Common::UString &object, ObjectType location, float &entryX, float &entryY, float &entryZ, float &entryAngle)
Definition: module.cpp:425
void showPartySelectionGUI(int forceNPC1, int forceNPC2)
Show the party selection GUI.
Definition: module.cpp:802
void exit()
Exit the currently running module.
Definition: module.cpp:197
The ingame GUI.
size_t getPartyMemberCount()
Get the count of party members.
Definition: module.cpp:736
int _currentTexturePack
The current texture pack.
Definition: module.h:228
Creature * getPC()
Return the currently playing PC.
Definition: module.cpp:181
float _backwardsBtnPressed
Definition: module.h:269