Skip to content

Commit

Permalink
NWN2: Implement Journal class
Browse files Browse the repository at this point in the history
When loading the Campaign journal for the NWN2 OC, running getString()
for ResRef #180942 results in the following error:

  WARNING: iconv() failed: Illegal byte sequence!

See issue 10 on xoreos/xoreos-tools for more information.
  • Loading branch information
rjshae committed Mar 28, 2019
1 parent 1b3ee95 commit e1e674b
Show file tree
Hide file tree
Showing 6 changed files with 200 additions and 0 deletions.
8 changes: 8 additions & 0 deletions src/engines/nwn2/campaign.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,14 @@ void Campaign::loadCampaignResource(const Common::UString &campaign) {
_name = gff->getTopLevel().getString("DisplayName");
_description = gff->getTopLevel().getString("Description");

try {
// Load the campaign journal into the module
gff.reset(new Aurora::GFF3File("module", Aurora::kFileTypeJRL, MKTAG('J', 'R', 'L', ' ')));
if (_module)
_module->loadCampaignJournal(gff->getTopLevel());
} catch (...) {
}

success = true;
}

Expand Down
83 changes: 83 additions & 0 deletions src/engines/nwn2/journal.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/* xoreos - A reimplementation of BioWare's Aurora engine
*
* xoreos is the legal property of its developers, whose names
* can be found in the AUTHORS file distributed with this source
* distribution.
*
* xoreos is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 3
* of the License, or (at your option) any later version.
*
* xoreos is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with xoreos. If not, see <http://www.gnu.org/licenses/>.
*/

/** @file
* A journal in a Neverwinter Nights 2 module.
*/

#include <algorithm>

#include "src/aurora/gff3file.h"

#include "src/engines/nwn2/journal.h"

namespace Engines {

namespace NWN2 {

Journal::Journal(const Aurora::GFF3Struct &journal) {

load(journal);
}

uint32 Journal::getJournalQuestExperience(const Common::UString &plotID) const {
auto category = std::find_if(_categories.begin(), _categories.end(), [&](const Category &c) {
return c.name == plotID;
});

return (category != _categories.end()) ? category->XP : 0;
}

void Journal::load(const Aurora::GFF3Struct &journal) {
if (!journal.hasField("Categories"))
return;

const Aurora::GFF3List &categories = journal.getList("Categories");
for (const Aurora::GFF3Struct *c : categories) {
Category category;

category.name = c->getString("Name");
category.identifier = c->getString("Tag");
category.comment = c->getString("Comment");
category.priority = c->getUint("Priority");
category.XP = c->getUint("XP");

category.entries.clear();
if (c->hasField("EntryList")) {
const Aurora::GFF3List &entries = c->getList("EntryList");
for (const Aurora::GFF3Struct *e : entries) {
Entry entry;

entry.text = e->getString("Text");
entry.comment = e->getString("Comment");
entry.id = e->getUint("ID");
entry.end = (e->getUint("End") != 0);

category.entries.push_back(entry);
}
}

_categories.push_back(category);
}
}

} // End of namespace NWN2

} // End of namespace Engines
72 changes: 72 additions & 0 deletions src/engines/nwn2/journal.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/* xoreos - A reimplementation of BioWare's Aurora engine
*
* xoreos is the legal property of its developers, whose names
* can be found in the AUTHORS file distributed with this source
* distribution.
*
* xoreos is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 3
* of the License, or (at your option) any later version.
*
* xoreos is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with xoreos. If not, see <http://www.gnu.org/licenses/>.
*/

/** @file
* A journal in a Neverwinter Nights 2 module or campaign.
*/

#ifndef ENGINES_NWN2_JOURNAL_H
#define ENGINES_NWN2_JOURNAL_H

#include <vector>

#include "src/common/ustring.h"

namespace Engines {

namespace NWN2 {

class Journal {
public:
Journal(const Aurora::GFF3Struct &journal);
~Journal() = default;

/** Get the XP awarded for completing the quest with the matching tag. */
uint32 getJournalQuestExperience(const Common::UString &plotID) const;

private:

struct Entry {
Common::UString text;
Common::UString comment;
uint32 id;
bool end;
};

struct Category {
Common::UString identifier;
Common::UString name;
Common::UString comment;
uint32 priority;
uint32 XP;
std::vector<Entry> entries;
};

std::vector<Category> _categories;

/** Load from a journal instance. */
void load(const Aurora::GFF3Struct &journal);
};

} // End of namespace NWN2

} // End of namespace Engines

#endif // ENGINES_NWN2_JOURNAL_H
26 changes: 26 additions & 0 deletions src/engines/nwn2/module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
#include "src/engines/nwn2/creature.h"
#include "src/engines/nwn2/faction.h"
#include "src/engines/nwn2/roster.h"
#include "src/engines/nwn2/journal.h"

namespace Engines {

Expand Down Expand Up @@ -206,6 +207,7 @@ void Module::enter(Creature &pc, bool isNewCampaign) {
loadAreas();
loadFactions();
loadRoster();
loadJournal();

} catch (Common::Exception &e) {
e.add("Can't initialize module \"%s\"", _name.c_str());
Expand Down Expand Up @@ -365,6 +367,7 @@ void Module::unload() {
unloadAreas();
unloadFactions();
unloadRoster();
unloadJournal();
unloadHAKs();
unloadTLK();
unloadModule();
Expand Down Expand Up @@ -424,6 +427,25 @@ void Module::loadRoster() {
_roster.reset(new Roster());
}

void Module::loadJournal() {
if (_campaignJournal) {
// Copy the campaign journal
_moduleJournal.reset(new Journal(*_campaignJournal));
} else {
// Load the module journal
std::unique_ptr<Aurora::GFF3File> jrl;
jrl.reset(loadOptionalGFF3("module", Aurora::kFileTypeJRL, MKTAG('J', 'R', 'L', ' ')));
if (jrl) {
const Aurora::GFF3Struct &top = jrl->getTopLevel();
_moduleJournal.reset(new Journal(top));
}
}
}

void Module::loadCampaignJournal(const Aurora::GFF3Struct &journal) {
_campaignJournal.reset(new Journal(journal));
}

void Module::loadAreas() {
status("Loading areas...");

Expand Down Expand Up @@ -471,6 +493,10 @@ void Module::unloadRoster() {
_roster.reset();
}

void Module::unloadJournal() {
_moduleJournal.reset();
}

void Module::movePC(const Common::UString &area) {
if (!_pc)
return;
Expand Down
9 changes: 9 additions & 0 deletions src/engines/nwn2/module.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include "src/common/changeid.h"

#include "src/aurora/ifofile.h"
#include "src/aurora/gff3file.h"

#include "src/aurora/nwscript/objectref.h"

Expand All @@ -54,6 +55,7 @@ class Area;
class Creature;
class Factions;
class Roster;
class Journal;

class Module : public NWN2::Object, public NWN2::ObjectContainer {
public:
Expand Down Expand Up @@ -87,6 +89,8 @@ class Module : public NWN2::Object, public NWN2::ObjectContainer {
Factions &getFactions();
/** Return the module's roster. */
Roster &getRoster();
/** Load the campaign journal. */
void loadCampaignJournal(const Aurora::GFF3Struct &gff);
// '---

void delayScript(const Common::UString &script,
Expand Down Expand Up @@ -184,6 +188,9 @@ class Module : public NWN2::Object, public NWN2::ObjectContainer {
Common::ScopedPtr<Factions> _factions; ///< The factions in the current module.
Common::ScopedPtr<Roster> _roster; ///< The roster for the current module.

std::unique_ptr<Journal> _moduleJournal; ///< The current module's journal.
std::unique_ptr<Journal> _campaignJournal; ///< The campaign journal.

bool _ranPCSpawn; ///< Did we run the PC spawn script?

Common::UString _newModule; ///< The module we should change to.
Expand All @@ -202,6 +209,7 @@ class Module : public NWN2::Object, public NWN2::ObjectContainer {
void unloadAreas(); ///< Unload the areas.
void unloadFactions(); ///< Unload the factions.
void unloadRoster(); ///< Unload the roster.
void unloadJournal(); ///< Unload the journal.
// '---

// .--- Loading
Expand All @@ -213,6 +221,7 @@ class Module : public NWN2::Object, public NWN2::ObjectContainer {
void loadAreas(); ///< Load the areas.
void loadFactions(); ///< Load the factions.
void loadRoster(); ///< Load the roster.
void loadJournal(); ///< Load the journal.
// '---

void enterArea(); ///< Enter a new area.
Expand Down
2 changes: 2 additions & 0 deletions src/engines/nwn2/rules.mk
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ src_engines_nwn2_libnwn2_la_SOURCES += \
src/engines/nwn2/itemproperty.h \
src/engines/nwn2/inventory.h \
src/engines/nwn2/store.h \
src/engines/nwn2/journal.h \
$(EMPTY)

src_engines_nwn2_libnwn2_la_SOURCES += \
Expand Down Expand Up @@ -82,6 +83,7 @@ src_engines_nwn2_libnwn2_la_SOURCES += \
src/engines/nwn2/itemproperty.cpp \
src/engines/nwn2/inventory.cpp \
src/engines/nwn2/store.cpp \
src/engines/nwn2/journal.cpp \
$(EMPTY)

include src/engines/nwn2/script/rules.mk

0 comments on commit e1e674b

Please sign in to comment.