xoreos  0.0.5
ifofile.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 /* See BioWare's own specs released for Neverwinter Nights modding
26  * (<https://github.com/xoreos/xoreos-docs/tree/master/specs/bioware>)
27  */
28 
29 #include <cassert>
30 #include <cstdio>
31 #include <cstring>
32 
33 #include <algorithm>
34 
35 #include "src/common/error.h"
36 #include "src/common/readstream.h"
37 
38 #include "src/aurora/ifofile.h"
39 #include "src/aurora/gff3file.h"
40 #include "src/aurora/resman.h"
41 
42 namespace Aurora {
43 
45  clear();
46 }
47 
49 }
50 
52  _gff.reset();
53 
54  std::memset(_id, 0, sizeof(_id));
55 
56  _tag.clear();
57 
58  _name.clear();
60 
61  _minVersionMajor = 0;
62  _minVersionMinor = 0;
63 
64  _expansions = 0;
65 
66  _isSave = false;
67 
68  _customTLK.clear();
69 
71 
72  _entryArea.clear();
73 
74  _entryX = 0.0f;
75  _entryY = 0.0f;
76  _entryZ = 0.0f;
77  _entryDirX = 0.0f;
78  _entryDirY = 0.0f;
79 
80  _haks.clear();
81  _areas.clear();
82  _nssCache.clear();
83 
84  _hourDawn = 0;
85  _hourDusk = 0;
86 
87  _minutesPerHour = 1;
88 
89  _startHour = 0;
90  _startDay = 1;
91  _startMonth = 1;
92  _startYear = 0;
93 
94  _xpScale = 1.0f;
95 }
96 
98  clear();
99 }
100 
101 void IFOFile::load(Common::SeekableReadStream *stream, bool repairNWNPremium) {
102  unload();
103 
104  assert(stream);
105  _gff.reset(new GFF3File(stream, MKTAG('I', 'F', 'O', ' '), repairNWNPremium));
106 
107  const GFF3Struct &ifoTop = _gff->getTopLevel();
108 
109  // IFO version
110  _version = ifoTop.getUint("Mod_Version");
111  _creatorID = ifoTop.getUint("Mod_Creator_ID");
112 
113  // Game version
114  Common::UString version = ifoTop.getString("Mod_MinGameVer");
115  parseVersion(version);
116 
117  // Expansions
118  _expansions = ifoTop.getUint("Expansion_Pack");
119 
120  // Is Save?
121  _isSave = ifoTop.getUint("Mod_IsSaveGame") == 1;
122 
123  // Tag
124  _tag = ifoTop.getString("Mod_Tag");
125 
126  // Name and description
127  ifoTop.getLocString("Mod_Name" , _name);
128  ifoTop.getLocString("Mod_Description", _description);
129 
130  // ID
131  const size_t idSize = _isSave ? 32 : 16;
133 
134  if (id && (id->read(_id, idSize) != idSize))
135  throw Common::Exception("Can't read MOD ID");
136 
137  // TLK
138  _customTLK = ifoTop.getString("Mod_CustomTlk");
139 
140  // Starting movie
141  _startMovie = ifoTop.getString("Mod_StartMovie");
142 
143  // HAK List
144  if (ifoTop.hasField("Mod_HakList")) {
145  const GFF3List &haks = ifoTop.getList("Mod_HakList");
146 
147  for (GFF3List::const_iterator h = haks.begin(); h != haks.end(); ++h)
148  _haks.insert(_haks.begin(), (*h)->getString("Mod_Hak"));
149  }
150 
151  // Singular HAK
152  Common::UString hak = ifoTop.getString("Mod_Hak");
153  if (!hak.empty())
154  _haks.insert(_haks.begin(), hak);
155 
156  // Areas
157  if (ifoTop.hasField("Mod_Area_list")) {
158  const GFF3List &areas = ifoTop.getList("Mod_Area_list");
159 
160  for (GFF3List::const_iterator a = areas.begin(); a != areas.end(); ++a)
161  _areas.push_back((*a)->getString("Area_Name"));
162  }
163 
164  std::sort(_areas.begin(), _areas.end(), Common::UString::iless());
165 
166  // NSS files that should be cached
167  if (ifoTop.hasField("Mod_CacheNSSList")) {
168  const GFF3List &nss = ifoTop.getList("Mod_CacheNSSList");
169 
170  for (GFF3List::const_iterator n = nss.begin(); n != nss.end(); ++n)
171  _nssCache.push_back((*n)->getString("ResRef"));
172  }
173 
174  // Quests
175  if (ifoTop.hasField("Quest_list")) {
176  const GFF3List &quests = ifoTop.getList("Quest_list");
177 
178  for (GFF3List::const_iterator q = quests.begin(); q != quests.end(); ++q)
179  _quests.push_back((*q)->getString("Quest"));
180  }
181  if (ifoTop.hasField("QuestBase_list")) {
182  const GFF3List &quests = ifoTop.getList("QuestBase_list");
183 
184  for (GFF3List::const_iterator q = quests.begin(); q != quests.end(); ++q)
185  _questDBs.push_back((*q)->getString("QuestBase"));
186  }
187 
188  // NPCs
189  if (ifoTop.hasField("StoryNPC_list")) {
190  const GFF3List &npcs = ifoTop.getList("StoryNPC_list");
191 
192  for (GFF3List::const_iterator n = npcs.begin(); n != npcs.end(); ++n)
193  _storyNPCs.push_back((*n)->getString("StoryNPC"));
194  }
195  if (ifoTop.hasField("MonsterNPC_list")) {
196  const GFF3List &npcs = ifoTop.getList("MonsterNPC_list");
197 
198  for (GFF3List::const_iterator n = npcs.begin(); n != npcs.end(); ++n)
199  _monsterNPCs.push_back((*n)->getString("MonsterNPC"));
200  }
201 
202  // Entry
203  _entryArea = ifoTop.getString("Mod_Entry_Area");
204  _entryX = ifoTop.getDouble("Mod_Entry_X");
205  _entryY = ifoTop.getDouble("Mod_Entry_Y");
206  _entryZ = ifoTop.getDouble("Mod_Entry_Z");
207  _entryDirX = ifoTop.getDouble("Mod_Entry_Dir_X");
208  _entryDirY = ifoTop.getDouble("Mod_Entry_Dir_Y");
209 
210  // Time settings
211  _hourDawn = ifoTop.getUint("Mod_DawnHour" , 0);
212  _hourDusk = ifoTop.getUint("Mod_DuskHour" , 0);
213  _minutesPerHour = ifoTop.getUint("Mod_MinPerHour", 1);
214  _startHour = ifoTop.getUint("Mod_StartHour" , 0);
215  _startDay = ifoTop.getUint("Mod_StartDay" , 1);
216  _startMonth = ifoTop.getUint("Mod_StartMonth", 1);
217  _startYear = ifoTop.getUint("Mod_StartYear" , 0);
218 
219  // Weather
220  _minWeatherIntensity = ifoTop.getSint("Mod_MinWeatInt", 0);
221  _maxWeatherIntensity = ifoTop.getSint("Mod_MaxWeatInt", 100);
222  _rainChance = ifoTop.getSint("Mod_RainChance", 0);
223  _snowChance = ifoTop.getSint("Mod_SnowChance", 0);
224 
225  // XP Scale
226  _xpScale = ifoTop.getUint("Mod_XPScale", 100) / 100.0f;
227 }
228 
229 void IFOFile::load(bool repairNWNPremium) {
230  unload();
231 
232  Common::SeekableReadStream *stream = ResMan.getResource("module", kFileTypeIFO);
233  if (!stream)
234  throw Common::Exception("No module.ifo available");
235 
236  load(stream, repairNWNPremium);
237 }
238 
240  if (std::sscanf(version.c_str(), "%d.%d", &_minVersionMajor, &_minVersionMinor) != 2)
242 }
243 
244 const GFF3Struct *IFOFile::getGFF() const {
245  if (!_gff)
246  return 0;
247 
248  return &_gff->getTopLevel();
249 }
250 
252  return _version;
253 }
254 
256  return _creatorID;
257 }
258 
259 bool IFOFile::isSave() const {
260  return _isSave;
261 }
262 
264  return _tag;
265 }
266 
267 const LocString &IFOFile::getName() const {
268  return _name;
269 }
270 
272  return _description;
273 }
274 
276  return _customTLK;
277 }
278 
279 void IFOFile::getMinVersion(int &major, int &minor) const {
280  major = _minVersionMajor;
281  minor = _minVersionMinor;
282 }
283 
285  return _expansions;
286 }
287 
289  return _startMovie;
290 }
291 
293  return _entryArea;
294 }
295 
296 void IFOFile::getEntryPosition(float &x, float &y, float &z) const {
297  x = _entryX;
298  y = _entryY;
299  z = _entryZ;
300 }
301 
302 void IFOFile::getEntryDirection(float &x, float &y) const {
303  x = _entryDirX;
304  y = _entryDirY;
305 }
306 
307 const std::vector<Common::UString> &IFOFile::getHAKs() const {
308  return _haks;
309 }
310 
311 const std::vector<Common::UString> &IFOFile::getAreas() const {
312  return _areas;
313 }
314 
315 const std::vector<Common::UString> &IFOFile::getNSSCache() const {
316  return _nssCache;
317 }
318 
319 const std::vector<Common::UString> &IFOFile::getQuests() const {
320  return _quests;
321 }
322 
323 const std::vector<Common::UString> &IFOFile::getQuestDBs() const {
324  return _questDBs;
325 }
326 
327 const std::vector<Common::UString> &IFOFile::getStoryNPCs() const {
328  return _storyNPCs;
329 }
330 
331 const std::vector<Common::UString> &IFOFile::getMonsterNPCs() const {
332  return _monsterNPCs;
333 }
334 
335 void IFOFile::getStartTime(uint8 &hour, uint8 &day, uint8 &month, uint32 &year) const {
336  hour = _startHour;
337  day = _startDay;
338  month = _startMonth;
339  year = _startYear;
340 }
341 
343  return _hourDawn;
344 }
345 
347  return _hourDusk;
348 }
349 
351  return _minutesPerHour;
352 }
353 
355  return _minWeatherIntensity;
356 }
357 
359  return _maxWeatherIntensity;
360 }
361 
363  return _rainChance;
364 }
365 
367  return _snowChance;
368 }
369 
370 float IFOFile::getXPScale() const {
371  return _xpScale;
372 }
373 
374 } // End of namespace Aurora
int64 getSint(const Common::UString &field, int64 def=0) const
Definition: gff3file.cpp:473
Handling version V3.2/V3.3 of BioWare&#39;s GFFs (generic file format).
uint8 _hourDawn
The hour dawn starts.
Definition: ifofile.h:234
#define ResMan
Shortcut for accessing the sound manager.
Definition: resman.h:557
#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
bool isSave() const
Is the module a save file?
Definition: ifofile.cpp:259
int32 _maxWeatherIntensity
Maximum weather intensity.
Definition: ifofile.h:245
const Common::UString & getTLK() const
Return the custom TLK table this module uses.
Definition: ifofile.cpp:275
bool getLocString(const Common::UString &field, LocString &str) const
Definition: gff3file.cpp:614
uint32 getMinutesPerHour() const
Return the number of real time minutes per game hour.
Definition: ifofile.cpp:350
A class holding an UTF-8 string.
Definition: ustring.h:48
int32 getMaxWeatherIntensity() const
Return the maximum weather intensity.
Definition: ifofile.cpp:358
uint32 _creatorID
ID of the IFO file creator.
Definition: ifofile.h:203
A localized string.
Definition: locstring.h:43
std::vector< Common::UString > _storyNPCs
List of story NPCs used in the module.
Definition: ifofile.h:231
void unload()
Unload a currently loaded IFO.
Definition: ifofile.cpp:97
Common::UString _entryArea
The area the PC starts in.
Definition: ifofile.h:216
uint8_t uint8
Definition: types.h:200
uint32 getCreatorID() const
Return the ID of the IFO file creator.
Definition: ifofile.cpp:255
bool hasField(const Common::UString &field) const
Does this specific field exist?
Definition: gff3file.cpp:400
float _entryZ
The Z position the PC starts in.
Definition: ifofile.h:220
Common::UString _customTLK
The custom TLK the module uses.
Definition: ifofile.h:212
const LocString & getDescription() const
Return the description of the module.
Definition: ifofile.cpp:271
std::vector< Common::UString > _monsterNPCs
List of monster NPCs used in the module.
Definition: ifofile.h:232
int32 _snowChance
Chance for snow.
Definition: ifofile.h:247
void getEntryDirection(float &x, float &y) const
Return the entry direction.
Definition: ifofile.cpp:302
int _minVersionMajor
Minimum major game version this module needs.
Definition: ifofile.h:205
uint64 getUint(const Common::UString &field, uint64 def=0) const
Definition: gff3file.cpp:436
void getMinVersion(int &major, int &minor) const
Return the minimum game version the module needs to run.
Definition: ifofile.cpp:279
uint8 _minutesPerHour
Number of real time minutes per game hour.
Definition: ifofile.h:237
int _minVersionMinor
Minimum minor game version this module needs.
Definition: ifofile.h:206
std::vector< Common::UString > _nssCache
Scripts that should be cached.
Definition: ifofile.h:226
float _entryDirY
The Y orientation the PC starts in.
Definition: ifofile.h:222
Common::UString _tag
The module&#39;s tag.
Definition: ifofile.h:197
std::vector< Common::UString > _areas
Areas found in the module.
Definition: ifofile.h:225
const std::vector< Common::UString > & getHAKs() const
Return the list of required HAK files.
Definition: ifofile.cpp:307
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
const std::vector< Common::UString > & getQuestDBs() const
Returns the list of quest databases used in the module.
Definition: ifofile.cpp:323
std::vector< Common::UString > _questDBs
List of quest databases used in the module.
Definition: ifofile.h:229
const char * c_str() const
Return the (utf8 encoded) string data.
Definition: ustring.cpp:249
const std::vector< Common::UString > & getNSSCache() const
Return the list of NSS (script) files that should be cached.
Definition: ifofile.cpp:315
byte _id[32]
The module&#39;s unique ID.
Definition: ifofile.h:195
Common::UString _startMovie
The movie the module starts with.
Definition: ifofile.h:214
Loader for the module.ifo file.
float getXPScale() const
Get the number creature kill XP is multiplied by.
Definition: ifofile.cpp:370
uint16_t uint16
Definition: types.h:202
double getDouble(const Common::UString &field, double def=0.0) const
Definition: gff3file.cpp:514
const std::vector< Common::UString > & getStoryNPCs() const
Returns the list of story NPCs used in the module.
Definition: ifofile.cpp:327
float _entryX
The X position the PC starts in.
Definition: ifofile.h:218
A GFF (generic file format) V3.2/V3.3 file, found in all Aurora games except Sonic Chronicles: The Da...
Definition: gff3file.h:85
std::vector< Common::UString > _haks
HAKs required by the module.
Definition: ifofile.h:224
uint8 getDawnHour() const
Return the hour dawn starts.
Definition: ifofile.cpp:342
const std::vector< Common::UString > & getAreas() const
Return the list of areas in the module.
Definition: ifofile.cpp:311
float _entryDirX
The X orientation the PC starts in.
Definition: ifofile.h:221
uint8 _startDay
Day the module starts.
Definition: ifofile.h:240
bool empty() const
Is the string empty?
Definition: ustring.cpp:245
StackException Exception
Definition: error.h:59
uint8 _startMonth
Month the module starts.
Definition: ifofile.h:241
void parseVersion(const Common::UString &version)
Definition: ifofile.cpp:239
void getStartTime(uint8 &hour, uint8 &day, uint8 &month, uint32 &year) const
Return the module&#39;s starting time.
Definition: ifofile.cpp:335
Basic reading stream interfaces.
Module information, GFF.
Definition: types.h:83
std::vector< const GFF3Struct * > GFF3List
Definition: types.h:449
uint32 _startYear
Year the module starts.
Definition: ifofile.h:242
const GFF3List & getList(const Common::UString &field) const
Definition: gff3file.cpp:741
uint8 _hourDusk
The hour dusk starts.
Definition: ifofile.h:235
A struct within a GFF3.
Definition: gff3file.h:164
LocString _name
The module&#39;s localized name.
Definition: ifofile.h:199
const GFF3Struct * getGFF() const
Return the IFO&#39;s GFF struct.
Definition: ifofile.cpp:244
uint32_t uint32
Definition: types.h:204
const LocString & getName() const
Return the name of the module.
Definition: ifofile.cpp:267
float _xpScale
The number creature kill XP is multiplied by.
Definition: ifofile.h:249
const std::vector< Common::UString > & getQuests() const
Returns the list of quests used in the module.
Definition: ifofile.cpp:319
void clear()
Definition: ifofile.cpp:51
int32 getMinWeatherIntensity() const
Return the minimum weather intensity.
Definition: ifofile.cpp:354
Common::SeekableReadStream * getData(const Common::UString &field) const
Definition: gff3file.cpp:638
Common::UString getString(const Common::UString &field, const Common::UString &def="") const
Definition: gff3file.cpp:527
uint32 _version
Version of this IFO file.
Definition: ifofile.h:202
int32 getRainChance() const
Return the chance that it&#39;s going to rain.
Definition: ifofile.cpp:362
const std::vector< Common::UString > & getMonsterNPCs() const
Returns the list of monster NPCs used in the module.
Definition: ifofile.cpp:331
int32 _rainChance
Chance for rain.
Definition: ifofile.h:246
uint8 _startHour
Hour the module starts.
Definition: ifofile.h:239
uint16 _expansions
Bitfield of required expansions.
Definition: ifofile.h:208
const Common::UString & getTag() const
Return the module&#39;s tag.
Definition: ifofile.cpp:263
uint16 getExpansions() const
Return the list of required expansions.
Definition: ifofile.cpp:284
void getEntryPosition(float &x, float &y, float &z) const
Return the entry position.
Definition: ifofile.cpp:296
int32 _minWeatherIntensity
Minimum weather intensity.
Definition: ifofile.h:244
const Common::UString & getEntryArea() const
Return the entry area.
Definition: ifofile.cpp:292
float _entryY
The Y position the PC starts in.
Definition: ifofile.h:219
void clear()
Clear the string&#39;s contents.
Definition: ustring.cpp:236
Common::ScopedPtr< GFF3File > _gff
The module.ifo GFF.
Definition: ifofile.h:193
Interface for a seekable & readable data stream.
Definition: readstream.h:265
const Common::UString & getStartMovie() const
Return the starting movie.
Definition: ifofile.cpp:288
std::vector< Common::UString > _quests
List of quests used in the module.
Definition: ifofile.h:228
int32 getSnowChance() const
Return the chance that it&#39;s going to snow.
Definition: ifofile.cpp:366
LocString _description
The module&#39;s localized description.
Definition: ifofile.h:200
uint32 getVersion() const
Return the version of this IFO file.
Definition: ifofile.cpp:251
bool _isSave
Is this module a save?
Definition: ifofile.h:210
The global resource manager for Aurora resources.
uint8 getDuskHour() const
Return the hour dusk starts.
Definition: ifofile.cpp:346
int32_t int32
Definition: types.h:203