xoreos  0.0.5
campaigns.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/error.h"
26 #include "src/common/filepath.h"
27 #include "src/common/filelist.h"
28 
29 #include "src/aurora/resman.h"
30 
31 #include "src/graphics/camera.h"
32 
33 #include "src/events/events.h"
34 
37 
42 
43 namespace Engines {
44 
45 namespace DragonAge {
46 
47 Campaigns::Campaigns(::Engines::Console &console, Game &game) : _console(&console), _game(&game),
48  _hasCampaign(false), _running(false), _exit(true), _currentCampaign(0) {
49 
50  findCampaigns();
51 }
52 
54  try {
55  clean();
56  } catch (...) {
57  }
58 }
59 
61  if (_currentCampaign)
63 }
64 
66  return _campaigns;
67 }
68 
70  return _addins;
71 }
72 
74  for (PlayableCampaigns::const_iterator c = _campaigns.begin(); c != _campaigns.end(); ++c)
75  if ((*c)->getUID().equalsIgnoreCase(uid))
76  return *c;
77 
78  return 0;
79 }
80 
81 const Campaign *Campaigns::findAddin(const Common::UString &uid) const {
82  for (AddinContent::const_iterator a = _addins.begin(); a != _addins.end(); ++a)
83  if ((*a)->getUID().equalsIgnoreCase(uid))
84  return *a;
85 
86  return 0;
87 }
88 
90  for (PlayableCampaigns::iterator c = _campaigns.begin(); c != _campaigns.end(); ++c)
91  if ((*c)->getUID().equalsIgnoreCase(uid))
92  return *c;
93 
94  return 0;
95 }
96 
98  for (AddinContent::iterator a = _addins.begin(); a != _addins.end(); ++a)
99  if ((*a)->getUID().equalsIgnoreCase(uid))
100  return *a;
101 
102  return 0;
103 }
104 
105 bool Campaigns::isLoaded() const {
107 }
108 
109 bool Campaigns::isRunning() const {
110  return !EventMan.quitRequested() && _running && !_exit && _currentCampaign && _currentCampaign->isLoaded();
111 }
112 
114  status("Looking for campaigns...");
115 
116  const Common::UString baseDir = ResMan.getDataBase();
117 
118  // Single player
119 
120  const Common::UString spDir = Common::FilePath::findSubDirectory(baseDir, "modules/single player", true);
121  const Common::FileList spFiles(spDir, -1);
122  addCampaign(readCampaign(spFiles.findFirst("singleplayer.cif", true)));
123 
124  // DLCs
125 
126  const Common::UString dlcDir = Common::FilePath::findSubDirectory(baseDir, "addins", true);
127 
128  std::list<Common::UString> dlcDirs;
129  Common::FilePath::getSubDirectories(dlcDir, dlcDirs);
130 
131  for (std::list<Common::UString>::const_iterator d = dlcDirs.begin(); d != dlcDirs.end(); ++d) {
132  const Common::FileList dlcFiles(*d);
133  const Common::FileList moduleFiles(Common::FilePath::findSubDirectory(*d, "module", true));
134 
135  const Common::UString cifFile = moduleFiles.findFirstGlob(".*\\.cif", true);
136  const Common::UString manifestFile = dlcFiles.findFirst("/manifest.xml", true);
137 
138  const Common::UString addinBase = Common::FilePath::relativize(dlcDir, *d);
139 
140  addCampaign(readCampaign(cifFile, manifestFile, addinBase));
141  }
142 }
143 
145  if (!campaign || !campaign->isEnabled() || campaign->getUID().empty()) {
146  delete campaign;
147  return;
148  }
149 
150  if (campaign->getExtendsUID().empty())
151  _campaigns.push_back(campaign);
152  else
153  _addins.push_back(campaign);
154 }
155 
157  const Common::UString &addinBase) {
158  if (cifPath.empty())
159  return 0;
160 
161  Campaign *campaign = 0;
162 
163  try {
164 
165  campaign = new Campaign(*_game, cifPath, manifestPath, addinBase);
166 
167  } catch (...) {
168  Common::exceptionDispatcherWarning("Failed reading campaign \"%s\"",
169  Common::FilePath::getStem(cifPath).c_str());
170  }
171 
172  return campaign;
173 }
174 
175 void Campaigns::load(const Campaign &campaign) {
176  if (isRunning()) {
177  // We are currently running a campaign. Schedule a safe change instead
178 
179  changeCampaign(campaign);
180  return;
181  }
182 
183  // We are not currently running a campaign. Directly load the new campaign
184  loadCampaign(campaign);
185 }
186 
188  _exit = true;
189 }
190 
192  unload(true);
193 }
194 
195 void Campaigns::unload(bool completeUnload) {
196  if (_currentCampaign)
198 
199  _currentCampaign = 0;
200 
201  _hasCampaign = false;
202  _running = false;
203  _exit = true;
204 
206 
207  if (completeUnload)
208  unloadPC();
209 
210  _eventQueue.clear();
211 }
212 
214  _pc.reset();
215 }
216 
217 void Campaigns::loadCampaign(const Campaign &campaign) {
218  unload(false);
219 
220  try {
221  _currentCampaign = getCampaign(campaign.getUID());
222  if (!_currentCampaign)
223  throw Common::Exception("Campaign does not exist in this context");
224 
226 
227  } catch (Common::Exception &e) {
228  unload(false);
229 
230  e.add("Failed loading campaign \"%s\" (\"%s\")",
231  campaign.getUID().c_str(), campaign.getName().getString().c_str());
232  throw e;
233  }
234 
235  _hasCampaign = true;
236 }
237 
239  _pc.reset(pc);
240 }
241 
243  if (!_hasCampaign)
244  throw Common::Exception("Campaigns::enter(): Lacking a campaign?!?");
245 
246  if (!_pc)
247  throw Common::Exception("Campaigns::enter(): Lacking a PC?!?");
248 
250 
251  _running = true;
252  _exit = false;
253 }
254 
256  if (_currentCampaign)
258 
259  _running = false;
260  _exit = true;
261 }
262 
263 void Campaigns::addEvent(const Events::Event &event) {
264  _eventQueue.push_back(event);
265 }
266 
268  if (!isRunning())
269  return;
270 
271  replaceCampaign();
272 
273  if (!isRunning())
274  return;
275 
276  handleEvents();
277 }
278 
280  for (EventQueue::const_iterator event = _eventQueue.begin(); event != _eventQueue.end(); ++event) {
281  // Handle console
282  if (_console->isVisible()) {
283  _console->processEvent(*event);
284  continue;
285  }
286 
287  if (event->type == Events::kEventKeyDown) {
288  // Console
289  if ((event->key.keysym.sym == SDLK_d) && (event->key.keysym.mod & KMOD_CTRL)) {
290  _console->show();
291  continue;
292  }
293  }
294 
295  // Camera
296  if (FreeRoamCam.handleCameraInput(*event))
297  continue;
298 
299  if (_currentCampaign)
300  _currentCampaign->addEvent(*event);
301  }
302 
303  _eventQueue.clear();
304 
305  CameraMan.update();
306 
307  if (_currentCampaign)
309 }
310 
312  return _currentCampaign;
313 }
314 
316  return _pc.get();
317 }
318 
319 void Campaigns::changeCampaign(const Campaign &campaign) {
320  _newCampaign = campaign.getUID();
321 }
322 
324  if (_newCampaign.empty())
325  return;
326 
327  Campaign *campaign = getCampaign(_newCampaign);
329 
330  if (!campaign)
331  return;
332 
333  loadCampaign(*campaign);
334  enter();
335 }
336 
338 }
339 
340 } // End of namespace DragonAge
341 
342 } // End of namespace Engines
#define ResMan
Shortcut for accessing the sound manager.
Definition: resman.h:557
void changeCampaign(const Campaign &campaign)
Schedule a change to a new campaign.
Definition: campaigns.cpp:319
bool _exit
Should we exit the campaign?
Definition: campaigns.h:116
void add(const char *s,...) GCC_PRINTF(2
Definition: error.cpp:58
bool isVisible() const
Definition: console.cpp:797
A class holding an UTF-8 string.
Definition: ustring.h:48
void addCampaign(Campaign *campaign)
Definition: campaigns.cpp:144
The context holding a Dragon Age: Origins campaign.
bool isLoaded() const
Is a campaign currently loaded and ready to run?
Definition: campaigns.cpp:105
static bool getSubDirectories(const UString &directory, std::list< UString > &subDirectories)
Collect all direct subdirectories of a directory in a list.
Definition: filepath.cpp:234
bool isLoaded() const
Is this campaign currently loaded?
Definition: campaign.cpp:299
A creature in a Dragon Age: Origins area.
Camera management.
void unload()
Unload the campaign after playing.
Definition: campaign.cpp:356
const PlayableCampaigns & getCampaigns() const
Return all playable campaigns.
Definition: campaigns.cpp:65
void leave()
Leave the running campaign, quitting it.
Definition: campaigns.cpp:255
Campaigns(::Engines::Console &console, Game &game)
Definition: campaigns.cpp:47
bool isEnabled() const
Is this Campaign enabled?
Definition: campaign.cpp:265
const Common::UString & getString(Language language, LanguageGender gender=kLanguageGenderCurrent) const
Get the string of that language.
Definition: locstring.cpp:82
const Campaign * findAddin(const Common::UString &uid) const
Find a specific add-in by UID and return it, or 0 if not found.
Definition: campaigns.cpp:81
Exception that provides a stack of explanations.
Definition: error.h:36
#define FreeRoamCam
void unload()
Completely unload the currently loaded campaign.
Definition: campaigns.cpp:191
SDL_Event Event
Definition: types.h:42
Campaign * readCampaign(const Common::UString &cifPath="", const Common::UString &manifestPath="", const Common::UString &addinBase="")
Definition: campaigns.cpp:156
UString findFirst(const UString &str, bool caseInsensitive) const
Find the first file ending with the given string.
Definition: filelist.cpp:193
void exceptionDispatcherWarning(const char *s,...)
Exception dispatcher that prints the exception as a warning, and adds another reason on top...
Definition: error.cpp:158
const Aurora::LocString & getName() const
Definition: campaign.cpp:90
bool _running
Are we currently running a campaign?
Definition: campaigns.h:115
Keyboard key was pressed.
Definition: types.h:46
const AddinContent & getAddins() const
Return all add-in content for other campaigns.
Definition: campaigns.cpp:69
void exit()
Exit the currently running campaign.
Definition: campaigns.cpp:187
void leave()
Leave the campaign, ending it.
Definition: campaign.cpp:431
void addEvent(const Events::Event &event)
Add a single event for consideration into the event queue.
Definition: campaigns.cpp:263
Basic exceptions to throw.
const char * c_str() const
Return the (utf8 encoded) string data.
Definition: ustring.cpp:249
The context handling the gameplay in Dragon Age: Origins.
void load(const Campaign &campaign)
Load a campaign.
Definition: campaigns.cpp:175
Common::UString _newCampaign
The UID of the campaign we should change to.
Definition: campaigns.h:130
Campaign * getCampaign(const Common::UString &uid)
Definition: campaigns.cpp:89
Creature * getPC() const
Return the currently playing PC.
Definition: campaigns.cpp:315
Common::ScopedPtr< Creature > _pc
The player character we use.
Definition: campaigns.h:127
void load()
Load the campaign for playing.
Definition: campaign.cpp:344
void processEventQueue()
Process the current event queue.
Definition: campaign.cpp:486
The global events manager.
bool empty() const
Is the string empty?
Definition: ustring.cpp:245
Generic Aurora engines (debug) console.
void usePC(Creature *pc)
Use this character as the player character.
Definition: campaigns.cpp:238
StackException Exception
Definition: error.h:59
void refreshLocalized()
Refresh all localized strings.
Definition: campaigns.cpp:337
void enter()
Enter the loaded campaign, starting it.
Definition: campaigns.cpp:242
void replaceCampaign()
Actually replace the currently running campaign.
Definition: campaigns.cpp:323
Campaign * getAddin(const Common::UString &uid)
Definition: campaigns.cpp:97
void enter(Creature &pc)
Enter the campaign, starting it.
Definition: campaign.cpp:417
#define EventMan
Shortcut for accessing the events manager.
Definition: events.h:210
Campaign * getCurrentCampaign() const
Return the currently running campaign.
Definition: campaigns.cpp:311
PlayableCampaigns _campaigns
All campaigns we know about.
Definition: campaigns.h:119
static UString getStem(const UString &p)
Return a file name&#39;s stem.
Definition: filepath.cpp:87
bool _hasCampaign
Do we have a campaign?
Definition: campaigns.h:114
UString findFirstGlob(const UString &glob, bool caseInsensitive) const
Find the first file matching the given regex.
Definition: filelist.cpp:207
void loadCampaign(const Campaign &campaign)
Load a new campaign.
Definition: campaigns.cpp:217
static UString relativize(const UString &basePath, const UString &path)
Return the path relative to the base path.
Definition: filepath.cpp:142
AddinContent _addins
All add-in content we know about.
Definition: campaigns.h:121
A list of files.
Definition: filelist.h:35
void status(const char *s,...)
Definition: util.cpp:52
bool processEvent(const Events::Event &event)
Definition: console.cpp:817
#define CameraMan
Shortcut for accessing the camera manager.
Definition: camera.h:83
void addEvent(const Events::Event &event)
Add a single event for consideration into the area event queue.
Definition: campaign.cpp:482
A list of files.
Campaign * _currentCampaign
The currently loaded campaign.
Definition: campaigns.h:124
The context managing and running the Dragon Age: Origins campaigns.
Engine utility class for free-roam camera handling.
void processEventQueue()
Process the current event queue.
Definition: campaigns.cpp:267
const Campaign * findCampaign(const Common::UString &uid) const
Find a specific campaign by UID and return it, or 0 if not found.
Definition: campaigns.cpp:73
void clear()
Clear the string&#39;s contents.
Definition: ustring.cpp:236
const Common::UString & getExtendsUID() const
Return the UID of the campaign this campaign/content extends, if any.
Definition: campaign.cpp:98
::Engines::Console * _console
Definition: campaigns.h:111
The global resource manager for Aurora resources.
Utility class for manipulating file paths.
static UString findSubDirectory(const UString &directory, const UString &subDirectory, bool caseInsensitive=false)
Find a directory&#39;s subdirectory.
Definition: filepath.cpp:318
const Common::UString & getUID() const
Return the unique ID of this campaign.
Definition: campaign.cpp:86
bool isRunning() const
Is a campaign currently running?
Definition: campaigns.cpp:109