Skip to content

Commit

Permalink
Load dungeon object actions
Browse files Browse the repository at this point in the history
  • Loading branch information
kcat committed Jul 24, 2015
1 parent d08c79c commit abe748b
Show file tree
Hide file tree
Showing 2 changed files with 225 additions and 5 deletions.
144 changes: 142 additions & 2 deletions src/world/dblocks.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@

#include "dblocks.hpp"

#include <algorithm>
#include <iomanip>

#include <osg/MatrixTransform>
Expand All @@ -15,11 +16,105 @@
namespace DF
{

void ActionMovable::load(DBlockHeader &block, const std::array<uint8_t,5> &data)
{
mAxis = (Axis)data[0];
mDuration = data[1] | (data[2]<<8);
mMagnitude = data[3] | (data[4]<<8);
}

bool ActionTranslate::update(ObjectBase *target, float timediff)
{
mTimeAccum = std::min<float>(mTimeAccum+timediff, mDuration);

if(mAxis == Axis_NegX)
target->setPos(target->mXPos - (mMagnitude*(mTimeAccum/mDuration)), target->mYPos, target->mZPos);
else if(mAxis == Axis_X)
target->setPos(target->mXPos + (mMagnitude*(mTimeAccum/mDuration)), target->mYPos, target->mZPos);
else if(mAxis == Axis_NegY)
target->setPos(target->mXPos, target->mYPos - (mMagnitude*(mTimeAccum/mDuration)), target->mZPos);
else if(mAxis == Axis_Y)
target->setPos(target->mXPos, target->mYPos + (mMagnitude*(mTimeAccum/mDuration)), target->mZPos);
else if(mAxis == Axis_NegZ)
target->setPos(target->mXPos, target->mYPos, target->mZPos - (mMagnitude*(mTimeAccum/mDuration)));
else if(mAxis == Axis_Z)
target->setPos(target->mXPos, target->mYPos, target->mZPos + (mMagnitude*(mTimeAccum/mDuration)));

return mTimeAccum >= mDuration;
}

bool ActionRotate::update(ObjectBase* target, float timediff)
{
mTimeAccum = std::min<float>(mTimeAccum+timediff, mDuration);

// FIXME: Rotate

return mTimeAccum >= mDuration;
}

bool ActionTranslateRotate::update(ObjectBase* target, float timediff)
{
mTimeAccum = std::min<float>(mTimeAccum+timediff, mDuration);

// FIXME: Rotate too
if(mAxis == Axis_NegX)
target->setPos(target->mXPos - (mMagnitude*(mTimeAccum/mDuration)), target->mYPos, target->mZPos);
else if(mAxis == Axis_X)
target->setPos(target->mXPos + (mMagnitude*(mTimeAccum/mDuration)), target->mYPos, target->mZPos);
else if(mAxis == Axis_NegY)
target->setPos(target->mXPos, target->mYPos - (mMagnitude*(mTimeAccum/mDuration)), target->mZPos);
else if(mAxis == Axis_Y)
target->setPos(target->mXPos, target->mYPos + (mMagnitude*(mTimeAccum/mDuration)), target->mZPos);
else if(mAxis == Axis_NegZ)
target->setPos(target->mXPos, target->mYPos, target->mZPos - (mMagnitude*(mTimeAccum/mDuration)));
else if(mAxis == Axis_Z)
target->setPos(target->mXPos, target->mYPos, target->mZPos + (mMagnitude*(mTimeAccum/mDuration)));

return mTimeAccum >= mDuration;
}


ObjectBase::ObjectBase(uint8_t type, int x, int y, int z)
: mType(type), mXPos(x), mYPos(y), mZPos(z)
: mType(type), mParentLink(nullptr), mActive(false), mXPos(x), mYPos(y), mZPos(z), mActionOffset(0)
{
}
ObjectBase::~ObjectBase()
{
}

void ObjectBase::loadAction(std::istream &stream, DBlockHeader &block)
{
if(mActionOffset <= 0)
return;

std::array<uint8_t,5> adata;
stream.seekg(mActionOffset);
stream.read(reinterpret_cast<char*>(adata.data()), adata.size());
int32_t target = VFS::read_le32(stream);
uint8_t type = stream.get();

ObjectBase *link = nullptr;
if(target > 0)
{
link = block.getObject(target);
if(link) link->mParentLink = this;
}
if(type == Action_Translate)
mAction = new ActionTranslate(link);
else if(type == Action_Rotate)
mAction = new ActionRotate(link);
else if(type == Action_TranslateRotate)
mAction = new ActionTranslateRotate(link);
else if(type != Action_None)
Log::get().stream(Log::Level_Error)<< "Unhandled action type: 0x"<<std::hex<<std::setfill('0')<<std::setw(2)<<(int)type;
if(mAction) mAction->load(block, adata);
}

void ObjectBase::setPos(float x, float y, float z)
{
mBaseNode->setMatrix(osg::Matrix::translate(x, y, z));
}

void ObjectBase::print(LogStream &stream) const
{
stream<<std::setfill('0');
Expand Down Expand Up @@ -73,6 +168,18 @@ void ModelObject::buildNodes(osg::Group *root, size_t objid)
root->addChild(mBaseNode);
}

void ModelObject::setPos(float x, float y, float z)
{
osg::Matrix mat;
mat.makeRotate(
mXRot*3.14159f/1024.0f, osg::Vec3f(1.0f, 0.0f, 0.0f),
-mYRot*3.14159f/1024.0f, osg::Vec3f(0.0f, 1.0f, 0.0f),
mZRot*3.14159f/1024.0f, osg::Vec3f(0.0f, 0.0f, 1.0f)
);
mat.postMultTranslate(osg::Vec3(x, y, z));
mBaseNode->setMatrix(mat);
}

void ModelObject::print(LogStream &stream) const
{
ObjectBase::print(stream);
Expand Down Expand Up @@ -107,7 +214,7 @@ void FlatObject::load(std::istream &stream)
mGender = VFS::read_le16(stream);
mFactionId = VFS::read_le16(stream);
mActionOffset = VFS::read_le32(stream);
stream.read(reinterpret_cast<char*>(&mUnknown), sizeof(mUnknown));
mUnknown = stream.get();
}

void FlatObject::buildNodes(osg::Group *root, size_t objid)
Expand Down Expand Up @@ -213,6 +320,9 @@ void DBlockHeader::load(std::istream &stream)
offset = next;
}
}

for(ref_ptr<ObjectBase> &obj : mObjects)
obj->loadAction(stream, *this);
}


Expand Down Expand Up @@ -268,6 +378,36 @@ FlatObject *DBlockHeader::getFlatByTexture(size_t texid) const
}


void DBlockHeader::activate(size_t id)
{
ObjectBase *base = getObject(id);
if(!base || base->mParentLink)
return;

while(base != nullptr && base->mAction)
{
auto iter = std::find(mActiveObjects.begin(), mActiveObjects.end(), base);
if(iter != mActiveObjects.end()) return;

mActiveObjects.push_back(base);
base = base->mAction->mLink;
}
}


void DBlockHeader::update(float timediff)
{
auto iter = mActiveObjects.begin();
while(iter != mActiveObjects.end())
{
if(!(*iter)->updateAction(timediff))
iter = mActiveObjects.erase(iter);
else
++iter;
}
}


void DBlockHeader::print(LogStream &stream, int objtype) const
{
stream<<std::setfill('0');
Expand Down
86 changes: 83 additions & 3 deletions src/world/dblocks.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,28 +15,98 @@ namespace osg
{
class Node;
class Group;
class MatrixTransform;
}

namespace DF
{

class LogStream;

struct ObjectBase;
struct DBlockHeader;


enum ActionType {
// Maybe flags?
Action_None = 0,
Action_Translate = 1<<0,
Action_Rotate = 1<<7,
Action_TranslateRotate = Action_Translate | Action_Rotate
};

struct ActionBase : public Referenceable {
ActionType mType;
ObjectBase *mLink; // Linked object's action updates with this action

float mTimeAccum;

ActionBase(ActionType type, ObjectBase *link) : mType(type), mLink(link), mTimeAccum(0.0f) { }

virtual void load(DBlockHeader &block, const std::array<uint8_t,5> &data) = 0;
virtual bool update(ObjectBase *target, float timediff) = 0;
};

struct ActionMovable : public ActionBase {
enum Axis {
Axis_NegX = 0x01,
Axis_X = 0x02,
Axis_NegY = 0x03,
Axis_Y = 0x04,
Axis_NegZ = 0x05,
Axis_Z = 0x06
};

Axis mAxis;
uint16_t mDuration;
uint16_t mMagnitude;

ActionMovable(ActionType type, ObjectBase *link) : ActionBase(type, link) { }
virtual void load(DBlockHeader &block, const std::array<uint8_t,5> &data) final;
};

struct ActionTranslate : public ActionMovable {
ActionTranslate(ObjectBase *link) : ActionMovable(Action_Translate, link) { }
virtual bool update(ObjectBase *target, float timediff) final;
};
struct ActionRotate : public ActionMovable {
ActionRotate(ObjectBase *link) : ActionMovable(Action_Rotate, link) { }
virtual bool update(ObjectBase *target, float timediff) final;
};
struct ActionTranslateRotate : public ActionMovable {
ActionTranslateRotate(ObjectBase *link) : ActionMovable(Action_TranslateRotate, link) { }
virtual bool update(ObjectBase *target, float timediff) final;
};


enum ObjectType {
ObjectType_Model = 0x01,
ObjectType_Light = 0x02,
ObjectType_Flat = 0x03,
};

struct ObjectBase : public Referenceable {
osg::ref_ptr<osg::Group> mBaseNode;
osg::ref_ptr<osg::MatrixTransform> mBaseNode;

uint8_t mType;

ref_ptr<ActionBase> mAction;
ObjectBase *mParentLink;
bool mActive;

int32_t mXPos, mYPos, mZPos;
int32_t mActionOffset;

ObjectBase(uint8_t type, int x, int y, int z);
virtual ~ObjectBase();

void loadAction(std::istream &stream, DBlockHeader &block);
bool updateAction(float timediff) { return mAction->update(this, timediff); }

virtual void buildNodes(osg::Group *root, size_t objid) = 0;

virtual void setPos(float x, float y, float z);

virtual void print(LogStream &stream) const;
virtual void print(std::ostream &stream) const;
};
Expand All @@ -47,14 +117,17 @@ struct ModelObject : public ObjectBase {
uint16_t mModelIdx;
uint32_t mUnknown1;
uint8_t mUnknown2;
int32_t mActionOffset;
//int32_t mActionOffset;

std::array<char,8> mModelData;

ModelObject(int x, int y, int z) : ObjectBase(ObjectType_Model, x, y, z) { }
void load(std::istream &stream, const std::array<std::array<char,8>,750> &mdldata);

virtual void buildNodes(osg::Group *root, size_t objid) final;

virtual void setPos(float x, float y, float z) final;

virtual void print(LogStream &stream) const final;
virtual void print(std::ostream &stream) const final;
};
Expand All @@ -63,13 +136,14 @@ struct FlatObject : public ObjectBase {
uint16_t mTexture;
uint16_t mGender; // Flags?
uint16_t mFactionId;
uint32_t mActionOffset; // Maybe?
//int32_t mActionOffset; // Maybe?
uint8_t mUnknown;

FlatObject(int x, int y, int z) : ObjectBase(ObjectType_Flat, x, y, z) { }
void load(std::istream &stream);

virtual void buildNodes(osg::Group *root, size_t objid) final;

virtual void print(LogStream &stream) const final;
virtual void print(std::ostream &stream) const final;
};
Expand Down Expand Up @@ -99,6 +173,8 @@ struct DBlockHeader {

osg::ref_ptr<osg::Group> mBaseNode;

std::vector<ObjectBase*> mActiveObjects;

~DBlockHeader();

void load(std::istream &stream);
Expand All @@ -114,6 +190,10 @@ struct DBlockHeader {
*/
FlatObject *getFlatByTexture(size_t texid) const;

void activate(size_t id);

void update(float timediff);

void print(LogStream &stream, int objtype=0) const;
};

Expand Down

0 comments on commit abe748b

Please sign in to comment.