Skip to content

Commit

Permalink
NWN: Add back loading of waypoints, doors and placeables
Browse files Browse the repository at this point in the history
  • Loading branch information
DrMcCoy committed Jan 29, 2014
1 parent c680aa4 commit 27d1e49
Show file tree
Hide file tree
Showing 15 changed files with 1,665 additions and 0 deletions.
12 changes: 12 additions & 0 deletions src/engines/nwn/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ noinst_HEADERS = \
tileset.h \
area.h \
module.h \
location.h \
object.h \
waypoint.h \
situated.h \
door.h \
placeable.h \
$(EMPTY)

libnwn_la_SOURCES = \
Expand All @@ -21,4 +27,10 @@ libnwn_la_SOURCES = \
ifofile.cpp \
area.cpp \
module.cpp \
location.cpp \
object.cpp \
waypoint.cpp \
situated.cpp \
door.cpp \
placeable.cpp \
$(EMPTY)
66 changes: 66 additions & 0 deletions src/engines/nwn/area.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@

#include "engines/nwn/area.h"
#include "engines/nwn/module.h"
#include "engines/nwn/object.h"
#include "engines/nwn/waypoint.h"
#include "engines/nwn/door.h"
#include "engines/nwn/placeable.h"

namespace Engines {

Expand Down Expand Up @@ -73,6 +77,10 @@ Area::~Area() {

setVisible(false);

// Delete objects
for (ObjectList::iterator o = _objects.begin(); o != _objects.end(); ++o)
delete *o;

// Delete tiles and tileset
for (std::vector<Tile>::iterator t = _tiles.begin(); t != _tiles.end(); ++t)
destroyModel(t->model);
Expand Down Expand Up @@ -205,6 +213,10 @@ void Area::setVisible(bool visible) {
// Show tiles
for (std::vector<Tile>::iterator t = _tiles.begin(); t != _tiles.end(); ++t)
t->model->setVisible(true);

// Show objects
for (ObjectList::iterator o = _objects.begin(); o != _objects.end(); ++o)
(*o)->setVisible(true);
}

// Play music and sound
Expand All @@ -216,6 +228,10 @@ void Area::setVisible(bool visible) {
{
LOCK_FRAME();

// Hide objects
for (ObjectList::iterator o = _objects.begin(); o != _objects.end(); ++o)
(*o)->setVisible(false);

// Hide tiles
for (std::vector<Tile>::iterator t = _tiles.begin(); t != _tiles.end(); ++t)
t->model->setVisible(false);
Expand Down Expand Up @@ -259,6 +275,18 @@ void Area::loadGIT(const Aurora::GFFStruct &git) {
// Generic properties
if (git.hasField("AreaProperties"))
loadProperties(git.getStruct("AreaProperties"));

// Waypoints
if (git.hasField("WaypointList"))
loadWaypoints(git.getList("WaypointList"));

// Placeables
if (git.hasField("Placeable List"))
loadPlaceables(git.getList("Placeable List"));

// Doors
if (git.hasField("Door List"))
loadDoors(git.getList("Door List"));
}

void Area::loadProperties(const Aurora::GFFStruct &props) {
Expand Down Expand Up @@ -332,9 +360,15 @@ void Area::loadTile(const Aurora::GFFStruct &t, Tile &tile) {

void Area::loadModels() {
loadTileModels();

for (ObjectList::iterator o = _objects.begin(); o != _objects.end(); ++o)
(*o)->loadModel();
}

void Area::unloadModels() {
for (ObjectList::iterator o = _objects.begin(); o != _objects.end(); ++o)
(*o)->unloadModel();

unloadTileModels();
}

Expand Down Expand Up @@ -412,6 +446,38 @@ void Area::unloadTiles() {
}
}

void Area::loadObject(Engines::NWN::Object &object) {
object.setArea(this);

_objects.push_back(&object);
if (!object.isStatic())
_module->addObject(object);
}

void Area::loadWaypoints(const Aurora::GFFList &list) {
for (Aurora::GFFList::const_iterator d = list.begin(); d != list.end(); ++d) {
Waypoint *waypoint = new Waypoint(**d);

loadObject(*waypoint);
}
}

void Area::loadPlaceables(const Aurora::GFFList &list) {
for (Aurora::GFFList::const_iterator p = list.begin(); p != list.end(); ++p) {
Placeable *placeable = new Placeable(**p);

loadObject(*placeable);
}
}

void Area::loadDoors(const Aurora::GFFList &list) {
for (Aurora::GFFList::const_iterator d = list.begin(); d != list.end(); ++d) {
Door *door = new Door(*_module, **d);

loadObject(*door);
}
}

void Area::addEvent(const Events::Event &event) {
_eventQueue.push_back(event);
}
Expand Down
10 changes: 10 additions & 0 deletions src/engines/nwn/area.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ namespace Engines {
namespace NWN {

class Module;
class Object;

class Area : public Aurora::NWScript::Object, public Events::Notifyable {
public:
Expand Down Expand Up @@ -136,6 +137,8 @@ class Area : public Aurora::NWScript::Object, public Events::Notifyable {
Graphics::Aurora::Model_NWN *model; ///< The tile's model.
};

typedef std::list<Engines::NWN::Object *> ObjectList;


Module *_module;

Expand Down Expand Up @@ -176,6 +179,8 @@ class Area : public Aurora::NWScript::Object, public Events::Notifyable {

std::vector<Tile> _tiles; ///< The area's tiles.

ObjectList _objects; ///< List of all objects in the area.

std::list<Events::Event> _eventQueue; ///< The event queue.

Common::Mutex _mutex; ///< Mutex securing access to the area.
Expand All @@ -191,6 +196,11 @@ class Area : public Aurora::NWScript::Object, public Events::Notifyable {
void loadTiles(const Aurora::GFFList &tiles);
void loadTile(const Aurora::GFFStruct &t, Tile &tile);

void loadObject(Engines::NWN::Object &object);
void loadWaypoints (const Aurora::GFFList &list);
void loadPlaceables(const Aurora::GFFList &list);
void loadDoors (const Aurora::GFFList &list);

// Model loading/unloading helpers

void loadModels();
Expand Down
193 changes: 193 additions & 0 deletions src/engines/nwn/door.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
/* 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.
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*
* The Infinity, Aurora, Odyssey, Eclipse and Lycium engines, Copyright (c) BioWare corp.
* The Electron engine, Copyright (c) Obsidian Entertainment and BioWare corp.
*/

/** @file engines/nwn/door.cpp
* NWN door.
*/

#include "common/util.h"
#include "common/error.h"

#include "aurora/gfffile.h"
#include "aurora/2dafile.h"
#include "aurora/2dareg.h"

#include "graphics/aurora/model_nwn.h"

#include "engines/aurora/util.h"

#include "engines/nwn/door.h"
#include "engines/nwn/waypoint.h"
#include "engines/nwn/module.h"

namespace Engines {

namespace NWN {

Door::Door(Module &module, const Aurora::GFFStruct &door) : Situated(kObjectTypeDoor),
_module(&module), _invisible(false), _genericType(Aurora::kFieldIDInvalid),
_state(kStateClosed), _linkedToFlag(kLinkedToNothing), _evaluatedLink(false),
_link(0), _linkedDoor(0), _linkedWaypoint(0) {

load(door);
}

Door::~Door() {
}

void Door::load(const Aurora::GFFStruct &door) {
Common::UString temp = door.getString("TemplateResRef");

Aurora::GFFFile *utd = 0;
if (!temp.empty()) {
try {
utd = new Aurora::GFFFile(temp, Aurora::kFileTypeUTD, MKTAG('U', 'T', 'D', ' '));
} catch (...) {
delete utd;
}
}

Situated::load(door, utd ? &utd->getTopLevel() : 0);

delete utd;
}

void Door::loadObject(const Aurora::GFFStruct &gff) {
// Generic type

_genericType = gff.getUint("GenericType", _genericType);

// State

_state = (State) gff.getUint("AnimationState", (uint) _state);

// Linked to

_linkedToFlag = (LinkedToFlag) gff.getUint("LinkedToFlags", (uint) _linkedToFlag);
_linkedTo = gff.getString("LinkedTo");
}

void Door::loadAppearance() {
if (_appearanceID == 0) {
if (_genericType == Aurora::kFieldIDInvalid)
_invisible = true;
else
loadAppearance(TwoDAReg.get("genericdoors"), _genericType);
} else
loadAppearance(TwoDAReg.get("doortypes"), _appearanceID);

// Invisible doors have no model and are always open
if (_invisible) {
_modelName.clear();
_state = kStateOpened1;
}
}

void Door::loadAppearance(const Aurora::TwoDAFile &twoda, uint32 id) {
uint32 modelColumn = twoda.headerToColumn("ModelName");
if (modelColumn == Aurora::kFieldIDInvalid)
modelColumn = twoda.headerToColumn("Model");

_invisible = twoda.getRow(id).getInt("VisibleModel") == 0;
_modelName = twoda.getRow(id).getString(modelColumn);
_soundAppType = twoda.getRow(id).getInt("SoundAppType");
}

void Door::setLocked(bool locked) {
if (isLocked() == locked)
return;

Situated::setLocked(locked);
// Also lock/unlock the linked door
evaluateLink();
if (_linkedDoor)
_linkedDoor->setLocked(locked);
}

bool Door::open(Object *opener) {
// TODO: Door::open(): Open in direction of the opener

if (isOpen())
return true;

if (isLocked()) {
playSound(_soundLocked);
return false;
}

_state = kStateOpened1;

playSound(_soundOpened);

// Also open the linked door
evaluateLink();
if (_linkedDoor)
_linkedDoor->open(opener);

return true;
}

bool Door::close(Object *closer) {
if (!isOpen())
return true;

if (_invisible)
return false;

_state = kStateClosed;

playSound(_soundClosed);

// Also close the linked door
evaluateLink();
if (_linkedDoor)
_linkedDoor->close(closer);

return true;
}

bool Door::isOpen() const {
return (_state == kStateOpened1) || (_state == kStateOpened2);
}

void Door::evaluateLink() {
if (_evaluatedLink)
return;

if ((_linkedToFlag != 0) && !_linkedTo.empty()) {
Aurora::NWScript::Object *object = _module->findObject(_linkedTo);

if (_linkedToFlag == kLinkedToDoor)
_link = _linkedDoor = dynamic_cast<Door *>(object);
else if (_linkedToFlag == kLinkedToWaypoint)
_link = _linkedWaypoint = dynamic_cast<Waypoint *>(object);
}

_evaluatedLink = true;
}

} // End of namespace NWN

} // End of namespace Engines

0 comments on commit 27d1e49

Please sign in to comment.