mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-30 19:15:41 +00:00
Savegame: store projectiles
This commit is contained in:
parent
15368188dc
commit
e266aff561
13 changed files with 343 additions and 38 deletions
|
@ -255,7 +255,8 @@ namespace MWBase
|
|||
virtual void changeToExteriorCell (const ESM::Position& position) = 0;
|
||||
///< Move to exterior cell.
|
||||
|
||||
virtual void changeToCell (const ESM::CellId& cellId, const ESM::Position& position) = 0;
|
||||
virtual void changeToCell (const ESM::CellId& cellId, const ESM::Position& position, bool detectWorldSpaceChange=true) = 0;
|
||||
///< @param detectWorldSpaceChange if true, clean up worldspace-specific data when the world space changes
|
||||
|
||||
virtual const ESM::Cell *getExterior (const std::string& cellName) const = 0;
|
||||
///< Return a cell matching the given name or a 0-pointer, if there is no such cell.
|
||||
|
|
|
@ -785,7 +785,7 @@ namespace MWMechanics
|
|||
// Update witness crime id
|
||||
npcStats.setCrimeId(-1);
|
||||
}
|
||||
else if (!creatureStats.isHostile())
|
||||
else if (!creatureStats.isHostile() && creatureStats.getAiSequence().getTypeId() != AiPackage::TypeIdPursue)
|
||||
{
|
||||
if (ptr.getClass().isClass(ptr, "Guard"))
|
||||
creatureStats.getAiSequence().stack(AiPursue(player.getClass().getId(player)), ptr);
|
||||
|
|
|
@ -694,15 +694,8 @@ Shadows* RenderingManager::getShadows()
|
|||
return mShadows;
|
||||
}
|
||||
|
||||
void RenderingManager::switchToInterior()
|
||||
void RenderingManager::notifyWorldSpaceChanged()
|
||||
{
|
||||
// TODO: also do this when switching worldspace
|
||||
mEffectManager->clear();
|
||||
}
|
||||
|
||||
void RenderingManager::switchToExterior()
|
||||
{
|
||||
// TODO: also do this when switching worldspace
|
||||
mEffectManager->clear();
|
||||
}
|
||||
|
||||
|
@ -1061,6 +1054,7 @@ void RenderingManager::spawnEffect(const std::string &model, const std::string &
|
|||
void RenderingManager::clear()
|
||||
{
|
||||
mLocalMap->clear();
|
||||
notifyWorldSpaceChanged();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -163,8 +163,7 @@ public:
|
|||
|
||||
Shadows* getShadows();
|
||||
|
||||
void switchToInterior();
|
||||
void switchToExterior();
|
||||
void notifyWorldSpaceChanged();
|
||||
|
||||
void getTriangleBatchCount(unsigned int &triangles, unsigned int &batches);
|
||||
|
||||
|
|
|
@ -319,6 +319,8 @@ void MWState::StateManager::loadGame (const Character *character, const Slot *sl
|
|||
case ESM::REC_WTHR:
|
||||
case ESM::REC_DYNA:
|
||||
case ESM::REC_ACTC:
|
||||
case ESM::REC_PROJ:
|
||||
case ESM::REC_MPRJ:
|
||||
|
||||
MWBase::Environment::get().getWorld()->readRecord (reader, n.val, contentFileMap);
|
||||
break;
|
||||
|
@ -361,7 +363,11 @@ void MWState::StateManager::loadGame (const Character *character, const Slot *sl
|
|||
|
||||
ESM::CellId cellId = ptr.getCell()->getCell()->getCellId();
|
||||
|
||||
MWBase::Environment::get().getWorld()->changeToCell (cellId, ptr.getRefData().getPosition());
|
||||
// Use detectWorldSpaceChange=false, otherwise some of the data we just loaded would be cleared again
|
||||
MWBase::Environment::get().getWorld()->changeToCell (cellId, ptr.getRefData().getPosition(), false);
|
||||
|
||||
// Do not trigger erroneous cellChanged events
|
||||
MWBase::Environment::get().getWorld()->markCellAsUnchanged();
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
#include <libs/openengine/bullet/physic.hpp>
|
||||
|
||||
#include <components/esm/projectilestate.hpp>
|
||||
|
||||
#include "../mwworld/manualref.hpp"
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwworld/inventorystore.hpp"
|
||||
|
@ -67,10 +69,12 @@ namespace MWWorld
|
|||
|
||||
MagicBoltState state;
|
||||
state.mSourceName = sourceName;
|
||||
state.mId = spellId;
|
||||
state.mId = model;
|
||||
state.mSpellId = spellId;
|
||||
state.mActorId = actor.getClass().getCreatureStats(actor).getActorId();
|
||||
state.mSpeed = speed;
|
||||
state.mStack = stack;
|
||||
state.mSoundId = sound;
|
||||
|
||||
// Only interested in "on target" effects
|
||||
for (std::vector<ESM::ENAMstruct>::const_iterator iter (effects.mList.begin());
|
||||
|
@ -99,7 +103,7 @@ namespace MWWorld
|
|||
state.mActorId = actor.getClass().getCreatureStats(actor).getActorId();
|
||||
state.mBowId = bow.getCellRef().mRefID;
|
||||
state.mVelocity = orient.yAxis() * speed;
|
||||
state.mProjectileId = projectile.getCellRef().mRefID;
|
||||
state.mId = projectile.getCellRef().mRefID;
|
||||
|
||||
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), projectile.getCellRef().mRefID);
|
||||
MWWorld::Ptr ptr = ref.getPtr();
|
||||
|
@ -159,7 +163,7 @@ namespace MWWorld
|
|||
{
|
||||
MWMechanics::CastSpell cast(caster, obstacle);
|
||||
cast.mHitPosition = pos;
|
||||
cast.mId = it->mId;
|
||||
cast.mId = it->mSpellId;
|
||||
cast.mSourceName = it->mSourceName;
|
||||
cast.mStack = it->mStack;
|
||||
cast.inflict(obstacle, caster, it->mEffects, ESM::RT_Target, false, true);
|
||||
|
@ -170,7 +174,7 @@ namespace MWWorld
|
|||
if (hit)
|
||||
{
|
||||
MWWorld::Ptr caster = MWBase::Environment::get().getWorld()->searchPtrViaActorId(it->mActorId);
|
||||
MWBase::Environment::get().getWorld()->explodeSpell(pos, it->mEffects, caster, it->mId, it->mSourceName);
|
||||
MWBase::Environment::get().getWorld()->explodeSpell(pos, it->mEffects, caster, it->mSpellId, it->mSourceName);
|
||||
|
||||
MWBase::Environment::get().getSoundManager()->stopSound(it->mSound);
|
||||
|
||||
|
@ -224,7 +228,7 @@ namespace MWWorld
|
|||
}
|
||||
else if (obstacle.getClass().isActor())
|
||||
{
|
||||
MWWorld::ManualRef projectileRef(MWBase::Environment::get().getWorld()->getStore(), it->mProjectileId);
|
||||
MWWorld::ManualRef projectileRef(MWBase::Environment::get().getWorld()->getStore(), it->mId);
|
||||
|
||||
// Try to get a Ptr to the bow that was used. It might no longer exist.
|
||||
MWWorld::Ptr bow = projectileRef.getPtr();
|
||||
|
@ -270,4 +274,127 @@ namespace MWWorld
|
|||
mMagicBolts.clear();
|
||||
}
|
||||
|
||||
void ProjectileManager::write(ESM::ESMWriter &writer, Loading::Listener &progress) const
|
||||
{
|
||||
for (std::vector<ProjectileState>::const_iterator it = mProjectiles.begin(); it != mProjectiles.end(); ++it)
|
||||
{
|
||||
writer.startRecord(ESM::REC_PROJ);
|
||||
|
||||
ESM::ProjectileState state;
|
||||
state.mId = it->mId;
|
||||
state.mPosition = it->mNode->getPosition();
|
||||
state.mOrientation = it->mNode->getOrientation();
|
||||
state.mActorId = it->mActorId;
|
||||
|
||||
state.mBowId = it->mBowId;
|
||||
state.mVelocity = it->mVelocity;
|
||||
|
||||
state.save(writer);
|
||||
|
||||
writer.endRecord(ESM::REC_PROJ);
|
||||
|
||||
progress.increaseProgress();
|
||||
}
|
||||
|
||||
for (std::vector<MagicBoltState>::const_iterator it = mMagicBolts.begin(); it != mMagicBolts.end(); ++it)
|
||||
{
|
||||
writer.startRecord(ESM::REC_MPRJ);
|
||||
|
||||
ESM::MagicBoltState state;
|
||||
state.mId = it->mId;
|
||||
state.mPosition = it->mNode->getPosition();
|
||||
state.mOrientation = it->mNode->getOrientation();
|
||||
state.mActorId = it->mActorId;
|
||||
|
||||
state.mSpellId = it->mSpellId;
|
||||
state.mEffects = it->mEffects;
|
||||
state.mSound = it->mSoundId;
|
||||
state.mSourceName = it->mSourceName;
|
||||
state.mSpeed = it->mSpeed;
|
||||
state.mStack = it->mStack;
|
||||
|
||||
state.save(writer);
|
||||
|
||||
writer.endRecord(ESM::REC_MPRJ);
|
||||
|
||||
progress.increaseProgress();
|
||||
}
|
||||
}
|
||||
|
||||
bool ProjectileManager::readRecord(ESM::ESMReader &reader, int32_t type)
|
||||
{
|
||||
if (type == ESM::REC_PROJ)
|
||||
{
|
||||
ESM::ProjectileState esm;
|
||||
esm.load(reader);
|
||||
|
||||
ProjectileState state;
|
||||
state.mActorId = esm.mActorId;
|
||||
state.mBowId = esm.mBowId;
|
||||
state.mVelocity = esm.mVelocity;
|
||||
state.mId = esm.mId;
|
||||
|
||||
std::string model;
|
||||
try
|
||||
{
|
||||
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), esm.mId);
|
||||
MWWorld::Ptr ptr = ref.getPtr();
|
||||
model = ptr.getClass().getModel(ptr);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
state.mNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(esm.mPosition, esm.mOrientation);
|
||||
createModel(state, model);
|
||||
|
||||
mProjectiles.push_back(state);
|
||||
return true;
|
||||
}
|
||||
else if (type == ESM::REC_MPRJ)
|
||||
{
|
||||
ESM::MagicBoltState esm;
|
||||
esm.load(reader);
|
||||
|
||||
MagicBoltState state;
|
||||
state.mSourceName = esm.mSourceName;
|
||||
state.mId = esm.mId;
|
||||
state.mSpellId = esm.mSpellId;
|
||||
state.mActorId = esm.mActorId;
|
||||
state.mSpeed = esm.mSpeed;
|
||||
state.mStack = esm.mStack;
|
||||
state.mEffects = esm.mEffects;
|
||||
|
||||
std::string model;
|
||||
try
|
||||
{
|
||||
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), esm.mId);
|
||||
MWWorld::Ptr ptr = ref.getPtr();
|
||||
model = ptr.getClass().getModel(ptr);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
state.mNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(esm.mPosition, esm.mOrientation);
|
||||
createModel(state, model);
|
||||
|
||||
MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager();
|
||||
state.mSound = sndMgr->playManualSound3D(esm.mPosition, esm.mSound, 1.0f, 1.0f,
|
||||
MWBase::SoundManager::Play_TypeSfx, MWBase::SoundManager::Play_Loop);
|
||||
|
||||
mMagicBolts.push_back(state);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int ProjectileManager::countSavedGameRecords() const
|
||||
{
|
||||
return mMagicBolts.size() + mProjectiles.size();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,6 +20,11 @@ namespace Physic
|
|||
}
|
||||
}
|
||||
|
||||
namespace Loading
|
||||
{
|
||||
class Listener;
|
||||
}
|
||||
|
||||
namespace Ogre
|
||||
{
|
||||
class SceneManager;
|
||||
|
@ -46,6 +51,10 @@ namespace MWWorld
|
|||
/// Removes all current projectiles. Should be called when switching to a new worldspace.
|
||||
void clear();
|
||||
|
||||
void write (ESM::ESMWriter& writer, Loading::Listener& progress) const;
|
||||
bool readRecord (ESM::ESMReader& reader, int32_t type);
|
||||
int countSavedGameRecords() const;
|
||||
|
||||
private:
|
||||
OEngine::Physic::PhysicEngine& mPhysEngine;
|
||||
Ogre::SceneManager* mSceneMgr;
|
||||
|
@ -54,15 +63,17 @@ namespace MWWorld
|
|||
{
|
||||
NifOgre::ObjectScenePtr mObject;
|
||||
Ogre::SceneNode* mNode;
|
||||
|
||||
// Actor who shot this projectile
|
||||
int mActorId;
|
||||
|
||||
// MW-id of this projectile
|
||||
std::string mId;
|
||||
};
|
||||
|
||||
struct MagicBoltState : public State
|
||||
{
|
||||
// Id of spell or enchantment to apply when it hits
|
||||
std::string mId;
|
||||
|
||||
// Actor who casted this projectile
|
||||
int mActorId;
|
||||
std::string mSpellId;
|
||||
|
||||
// Name of item to display as effect source in magic menu (in case we casted an enchantment)
|
||||
std::string mSourceName;
|
||||
|
@ -74,16 +85,11 @@ namespace MWWorld
|
|||
bool mStack;
|
||||
|
||||
MWBase::SoundPtr mSound;
|
||||
std::string mSoundId;
|
||||
};
|
||||
|
||||
struct ProjectileState : public State
|
||||
{
|
||||
// Actor who shot this projectile
|
||||
int mActorId;
|
||||
|
||||
// RefID of the projectile
|
||||
std::string mProjectileId;
|
||||
|
||||
// RefID of the bow or crossbow the actor was using when this projectile was fired (may be empty)
|
||||
std::string mBowId;
|
||||
|
||||
|
|
|
@ -237,6 +237,8 @@ namespace MWWorld
|
|||
{
|
||||
mRendering->clear();
|
||||
|
||||
mProjectileManager->clear();
|
||||
|
||||
mLocalScripts.clear();
|
||||
mPlayer->clear();
|
||||
|
||||
|
@ -275,6 +277,7 @@ namespace MWWorld
|
|||
mCells.countSavedGameRecords()
|
||||
+mStore.countSavedGameRecords()
|
||||
+mGlobalVariables.countSavedGameRecords()
|
||||
+mProjectileManager->countSavedGameRecords()
|
||||
+1 // player record
|
||||
+1 // weather record
|
||||
+1; // actorId counter
|
||||
|
@ -298,6 +301,7 @@ namespace MWWorld
|
|||
mGlobalVariables.write (writer, progress);
|
||||
mPlayer->write (writer, progress);
|
||||
mWeatherManager->write (writer, progress);
|
||||
mProjectileManager->write (writer, progress);
|
||||
}
|
||||
|
||||
void World::readRecord (ESM::ESMReader& reader, int32_t type,
|
||||
|
@ -313,7 +317,8 @@ namespace MWWorld
|
|||
!mGlobalVariables.readRecord (reader, type) &&
|
||||
!mPlayer->readRecord (reader, type) &&
|
||||
!mWeatherManager->readRecord (reader, type) &&
|
||||
!mCells.readRecord (reader, type, contentFileMap))
|
||||
!mCells.readRecord (reader, type, contentFileMap) &&
|
||||
!mProjectileManager->readRecord (reader, type))
|
||||
{
|
||||
throw std::runtime_error ("unknown record in saved game");
|
||||
}
|
||||
|
@ -808,9 +813,13 @@ namespace MWWorld
|
|||
|
||||
void World::changeToInteriorCell (const std::string& cellName, const ESM::Position& position)
|
||||
{
|
||||
// changed worldspace
|
||||
mProjectileManager->clear();
|
||||
mRendering->switchToInterior();
|
||||
if (mCurrentWorldSpace != cellName)
|
||||
{
|
||||
// changed worldspace
|
||||
mProjectileManager->clear();
|
||||
mRendering->notifyWorldSpaceChanged();
|
||||
mCurrentWorldSpace = cellName;
|
||||
}
|
||||
|
||||
removeContainerScripts(getPlayerPtr());
|
||||
mWorldScene->changeToInteriorCell(cellName, position);
|
||||
|
@ -819,19 +828,22 @@ namespace MWWorld
|
|||
|
||||
void World::changeToExteriorCell (const ESM::Position& position)
|
||||
{
|
||||
if (!getPlayerPtr().getCell()->getCell()->isExterior())
|
||||
if (mCurrentWorldSpace != "sys::default") // FIXME
|
||||
{
|
||||
// changed worldspace
|
||||
mProjectileManager->clear();
|
||||
mRendering->switchToExterior();
|
||||
mRendering->notifyWorldSpaceChanged();
|
||||
}
|
||||
removeContainerScripts(getPlayerPtr());
|
||||
mWorldScene->changeToExteriorCell(position);
|
||||
addContainerScripts(getPlayerPtr(), getPlayerPtr().getCell());
|
||||
}
|
||||
|
||||
void World::changeToCell (const ESM::CellId& cellId, const ESM::Position& position)
|
||||
void World::changeToCell (const ESM::CellId& cellId, const ESM::Position& position, bool detectWorldSpaceChange)
|
||||
{
|
||||
if (!detectWorldSpaceChange)
|
||||
mCurrentWorldSpace = cellId.mWorldspace;
|
||||
|
||||
if (cellId.mPaged)
|
||||
changeToExteriorCell (position);
|
||||
else
|
||||
|
|
|
@ -75,6 +75,8 @@ namespace MWWorld
|
|||
|
||||
Cells mCells;
|
||||
|
||||
std::string mCurrentWorldSpace;
|
||||
|
||||
OEngine::Physic::PhysicEngine* mPhysEngine;
|
||||
|
||||
boost::shared_ptr<ProjectileManager> mProjectileManager;
|
||||
|
@ -311,7 +313,8 @@ namespace MWWorld
|
|||
virtual void changeToExteriorCell (const ESM::Position& position);
|
||||
///< Move to exterior cell.
|
||||
|
||||
virtual void changeToCell (const ESM::CellId& cellId, const ESM::Position& position);
|
||||
virtual void changeToCell (const ESM::CellId& cellId, const ESM::Position& position, bool detectWorldSpaceChange=true);
|
||||
///< @param detectWorldSpaceChange if true, clean up worldspace-specific data when the world space changes
|
||||
|
||||
virtual const ESM::Cell *getExterior (const std::string& cellName) const;
|
||||
///< Return a cell matching the given name or a 0-pointer, if there is no such cell.
|
||||
|
|
|
@ -41,7 +41,7 @@ add_component_dir (esm
|
|||
loadnpc loadpgrd loadrace loadregn loadscpt loadskil loadsndg loadsoun loadspel loadsscr loadstat
|
||||
loadweap records aipackage effectlist spelllist variant variantimp loadtes3 cellref filter
|
||||
savedgame journalentry queststate locals globalscript player objectstate cellid cellstate globalmap lightstate inventorystate containerstate npcstate creaturestate dialoguestate statstate
|
||||
npcstats creaturestats weatherstate quickkeys fogstate spellstate activespells creaturelevliststate doorstate
|
||||
npcstats creaturestats weatherstate quickkeys fogstate spellstate activespells creaturelevliststate doorstate projectilestate
|
||||
)
|
||||
|
||||
add_component_dir (misc
|
||||
|
|
|
@ -109,6 +109,8 @@ enum RecNameInts
|
|||
REC_DYNA = FourCC<'D','Y','N','A'>::value,
|
||||
REC_ASPL = FourCC<'A','S','P','L'>::value,
|
||||
REC_ACTC = FourCC<'A','C','T','C'>::value,
|
||||
REC_MPRJ = FourCC<'M','P','R','J'>::value,
|
||||
REC_PROJ = FourCC<'P','R','O','J'>::value,
|
||||
|
||||
// format 1
|
||||
REC_FILT = 0x544C4946
|
||||
|
|
65
components/esm/projectilestate.cpp
Normal file
65
components/esm/projectilestate.cpp
Normal file
|
@ -0,0 +1,65 @@
|
|||
#include "projectilestate.hpp"
|
||||
|
||||
#include "esmwriter.hpp"
|
||||
#include "esmreader.hpp"
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
|
||||
void BaseProjectileState::save(ESMWriter &esm) const
|
||||
{
|
||||
esm.writeHNString ("ID__", mId);
|
||||
esm.writeHNT ("VEC3", mPosition);
|
||||
esm.writeHNT ("QUAT", mOrientation);
|
||||
esm.writeHNT ("ACTO", mActorId);
|
||||
}
|
||||
|
||||
void BaseProjectileState::load(ESMReader &esm)
|
||||
{
|
||||
mId = esm.getHNString("ID__");
|
||||
esm.getHNT (mPosition, "VEC3");
|
||||
esm.getHNT (mOrientation, "QUAT");
|
||||
esm.getHNT (mActorId, "ACTO");
|
||||
}
|
||||
|
||||
void MagicBoltState::save(ESMWriter &esm) const
|
||||
{
|
||||
BaseProjectileState::save(esm);
|
||||
|
||||
esm.writeHNString ("SPEL", mSpellId);
|
||||
esm.writeHNString ("SRCN", mSourceName);
|
||||
mEffects.save(esm);
|
||||
esm.writeHNT ("SPED", mSpeed);
|
||||
esm.writeHNT ("STCK", mStack);
|
||||
esm.writeHNString ("SOUN", mSound);
|
||||
}
|
||||
|
||||
void MagicBoltState::load(ESMReader &esm)
|
||||
{
|
||||
BaseProjectileState::load(esm);
|
||||
|
||||
mSpellId = esm.getHNString("SPEL");
|
||||
mSourceName = esm.getHNString ("SRCN");
|
||||
mEffects.load(esm);
|
||||
esm.getHNT (mSpeed, "SPED");
|
||||
esm.getHNT (mStack, "STCK");
|
||||
mSound = esm.getHNString ("SOUN");
|
||||
}
|
||||
|
||||
void ProjectileState::save(ESMWriter &esm) const
|
||||
{
|
||||
BaseProjectileState::save(esm);
|
||||
|
||||
esm.writeHNString ("BOW_", mBowId);
|
||||
esm.writeHNT ("VEL_", mVelocity);
|
||||
}
|
||||
|
||||
void ProjectileState::load(ESMReader &esm)
|
||||
{
|
||||
BaseProjectileState::load(esm);
|
||||
|
||||
mBowId = esm.getHNString ("BOW_");
|
||||
esm.getHNT (mVelocity, "VEL_");
|
||||
}
|
||||
|
||||
}
|
90
components/esm/projectilestate.hpp
Normal file
90
components/esm/projectilestate.hpp
Normal file
|
@ -0,0 +1,90 @@
|
|||
#ifndef OPENMW_ESM_PROJECTILESTATE_H
|
||||
#define OPENMW_ESM_PROJECTILESTATE_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <OgreVector3.h>
|
||||
#include <OgreQuaternion.h>
|
||||
|
||||
#include "effectlist.hpp"
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
|
||||
// format 0, savegames only
|
||||
|
||||
struct Quaternion
|
||||
{
|
||||
float mValues[4];
|
||||
|
||||
Quaternion() {}
|
||||
Quaternion (Ogre::Quaternion q)
|
||||
{
|
||||
mValues[0] = q.w;
|
||||
mValues[1] = q.x;
|
||||
mValues[2] = q.y;
|
||||
mValues[3] = q.z;
|
||||
}
|
||||
|
||||
operator Ogre::Quaternion () const
|
||||
{
|
||||
return Ogre::Quaternion(mValues[0], mValues[1], mValues[2], mValues[3]);
|
||||
}
|
||||
};
|
||||
|
||||
struct Vector3
|
||||
{
|
||||
float mValues[3];
|
||||
|
||||
Vector3() {}
|
||||
Vector3 (Ogre::Vector3 v)
|
||||
{
|
||||
mValues[0] = v.x;
|
||||
mValues[1] = v.y;
|
||||
mValues[2] = v.z;
|
||||
}
|
||||
|
||||
operator Ogre::Vector3 () const
|
||||
{
|
||||
return Ogre::Vector3(&mValues[0]);
|
||||
}
|
||||
};
|
||||
|
||||
struct BaseProjectileState
|
||||
{
|
||||
std::string mId;
|
||||
|
||||
Vector3 mPosition;
|
||||
Quaternion mOrientation;
|
||||
|
||||
int mActorId;
|
||||
|
||||
void load (ESMReader &esm);
|
||||
void save (ESMWriter &esm) const;
|
||||
};
|
||||
|
||||
struct MagicBoltState : public BaseProjectileState
|
||||
{
|
||||
std::string mSpellId;
|
||||
std::string mSourceName;
|
||||
ESM::EffectList mEffects;
|
||||
float mSpeed;
|
||||
bool mStack;
|
||||
std::string mSound;
|
||||
|
||||
void load (ESMReader &esm);
|
||||
void save (ESMWriter &esm) const;
|
||||
};
|
||||
|
||||
struct ProjectileState : public BaseProjectileState
|
||||
{
|
||||
std::string mBowId;
|
||||
Vector3 mVelocity;
|
||||
|
||||
void load (ESMReader &esm);
|
||||
void save (ESMWriter &esm) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue