mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-22 04:53:52 +00:00
Merge remote-tracking branch 'scrawl/master'
This commit is contained in:
commit
6c8e4b27d3
42 changed files with 622 additions and 109 deletions
|
@ -357,9 +357,6 @@ namespace MWClass
|
||||||
data->mInventoryStore.fill(ref->mBase->mInventory, getId(ptr), "",
|
data->mInventoryStore.fill(ref->mBase->mInventory, getId(ptr), "",
|
||||||
MWBase::Environment::get().getWorld()->getStore());
|
MWBase::Environment::get().getWorld()->getStore());
|
||||||
|
|
||||||
// Relates to NPC gold reset delay
|
|
||||||
data->mNpcStats.setTradeTime(MWWorld::TimeStamp(0.0, 0));
|
|
||||||
|
|
||||||
data->mNpcStats.setGoldPool(gold);
|
data->mNpcStats.setGoldPool(gold);
|
||||||
|
|
||||||
// store
|
// store
|
||||||
|
|
|
@ -233,6 +233,9 @@ namespace MWGui
|
||||||
|
|
||||||
MWBase::World* world = MWBase::Environment::get().getWorld();
|
MWBase::World* world = MWBase::Environment::get().getWorld();
|
||||||
|
|
||||||
|
MWBase::Environment::get().getWorld()->breakInvisibility(
|
||||||
|
MWBase::Environment::get().getWorld()->getPlayerPtr());
|
||||||
|
|
||||||
MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize();
|
MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize();
|
||||||
MyGUI::IntPoint cursorPosition = MyGUI::InputManager::getInstance().getMousePosition();
|
MyGUI::IntPoint cursorPosition = MyGUI::InputManager::getInstance().getMousePosition();
|
||||||
float mouseX = cursorPosition.left / float(viewSize.width);
|
float mouseX = cursorPosition.left / float(viewSize.width);
|
||||||
|
|
|
@ -541,9 +541,11 @@ namespace MWGui
|
||||||
|
|
||||||
int count = object.getRefData().getCount();
|
int count = object.getRefData().getCount();
|
||||||
|
|
||||||
|
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
||||||
|
MWBase::Environment::get().getWorld()->breakInvisibility(player);
|
||||||
|
|
||||||
// add to player inventory
|
// add to player inventory
|
||||||
// can't use ActionTake here because we need an MWWorld::Ptr to the newly inserted object
|
// can't use ActionTake here because we need an MWWorld::Ptr to the newly inserted object
|
||||||
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
|
||||||
MWWorld::Ptr newObject = *player.getClass().getContainerStore (player).add (object, object.getRefData().getCount(), player);
|
MWWorld::Ptr newObject = *player.getClass().getContainerStore (player).add (object, object.getRefData().getCount(), player);
|
||||||
// remove from world
|
// remove from world
|
||||||
MWBase::Environment::get().getWorld()->deleteObject (object);
|
MWBase::Environment::get().getWorld()->deleteObject (object);
|
||||||
|
|
|
@ -465,7 +465,18 @@ namespace MWGui
|
||||||
|
|
||||||
void MapWindow::cellExplored(int x, int y)
|
void MapWindow::cellExplored(int x, int y)
|
||||||
{
|
{
|
||||||
mGlobalMapRender->exploreCell(x,y);
|
mQueuedToExplore.push_back(std::make_pair(x,y));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MapWindow::onFrame(float dt)
|
||||||
|
{
|
||||||
|
for (std::vector<CellId>::iterator it = mQueuedToExplore.begin(); it != mQueuedToExplore.end(); ++it)
|
||||||
|
{
|
||||||
|
mGlobalMapRender->exploreCell(it->first, it->second);
|
||||||
|
}
|
||||||
|
mQueuedToExplore.clear();
|
||||||
|
|
||||||
|
NoDrop::onFrame(dt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapWindow::onDragStart(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id)
|
void MapWindow::onDragStart(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id)
|
||||||
|
|
|
@ -97,14 +97,17 @@ namespace MWGui
|
||||||
|
|
||||||
void renderGlobalMap(Loading::Listener* loadingListener);
|
void renderGlobalMap(Loading::Listener* loadingListener);
|
||||||
|
|
||||||
void addVisitedLocation(const std::string& name, int x, int y); // adds the marker to the global map
|
// adds the marker to the global map
|
||||||
|
void addVisitedLocation(const std::string& name, int x, int y);
|
||||||
|
|
||||||
|
// reveals this cell's map on the global map
|
||||||
void cellExplored(int x, int y);
|
void cellExplored(int x, int y);
|
||||||
|
|
||||||
void setGlobalMapPlayerPosition (float worldX, float worldY);
|
void setGlobalMapPlayerPosition (float worldX, float worldY);
|
||||||
|
|
||||||
virtual void open();
|
virtual void open();
|
||||||
|
|
||||||
void onFrame(float dt) { NoDrop::onFrame(dt); }
|
void onFrame(float dt);
|
||||||
|
|
||||||
/// Clear all savegame-specific data
|
/// Clear all savegame-specific data
|
||||||
void clear();
|
void clear();
|
||||||
|
@ -132,6 +135,10 @@ namespace MWGui
|
||||||
typedef std::pair<int, int> CellId;
|
typedef std::pair<int, int> CellId;
|
||||||
std::vector<CellId> mMarkers;
|
std::vector<CellId> mMarkers;
|
||||||
|
|
||||||
|
// Cells that should be explored in the next frame (i.e. their map revealed on the global map)
|
||||||
|
// We can't do this immediately, because the map update is not immediate either (see mNeedMapUpdate in scene.cpp)
|
||||||
|
std::vector<CellId> mQueuedToExplore;
|
||||||
|
|
||||||
MyGUI::Button* mEventBoxGlobal;
|
MyGUI::Button* mEventBoxGlobal;
|
||||||
MyGUI::Button* mEventBoxLocal;
|
MyGUI::Button* mEventBoxLocal;
|
||||||
|
|
||||||
|
|
|
@ -1326,9 +1326,6 @@ namespace MWGui
|
||||||
|
|
||||||
void WindowManager::updatePlayer()
|
void WindowManager::updatePlayer()
|
||||||
{
|
{
|
||||||
unsetSelectedSpell();
|
|
||||||
unsetSelectedWeapon();
|
|
||||||
|
|
||||||
mInventoryWindow->updatePlayer();
|
mInventoryWindow->updatePlayer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1425,6 +1422,14 @@ namespace MWGui
|
||||||
|
|
||||||
mQuickKeysMenu->write(writer);
|
mQuickKeysMenu->write(writer);
|
||||||
progress.increaseProgress();
|
progress.increaseProgress();
|
||||||
|
|
||||||
|
if (!mSelectedSpell.empty())
|
||||||
|
{
|
||||||
|
writer.startRecord(ESM::REC_ASPL);
|
||||||
|
writer.writeHNString("ID__", mSelectedSpell);
|
||||||
|
writer.endRecord(ESM::REC_ASPL);
|
||||||
|
progress.increaseProgress();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowManager::readRecord(ESM::ESMReader &reader, int32_t type)
|
void WindowManager::readRecord(ESM::ESMReader &reader, int32_t type)
|
||||||
|
@ -1433,12 +1438,18 @@ namespace MWGui
|
||||||
mMap->readRecord(reader, type);
|
mMap->readRecord(reader, type);
|
||||||
else if (type == ESM::REC_KEYS)
|
else if (type == ESM::REC_KEYS)
|
||||||
mQuickKeysMenu->readRecord(reader, type);
|
mQuickKeysMenu->readRecord(reader, type);
|
||||||
|
else if (type == ESM::REC_ASPL)
|
||||||
|
{
|
||||||
|
reader.getSubNameIs("ID__");
|
||||||
|
mSelectedSpell = reader.getHString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int WindowManager::countSavedGameRecords() const
|
int WindowManager::countSavedGameRecords() const
|
||||||
{
|
{
|
||||||
return 1 // Global map
|
return 1 // Global map
|
||||||
+ 1; // QuickKeysMenu
|
+ 1 // QuickKeysMenu
|
||||||
|
+ (!mSelectedSpell.empty() ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WindowManager::isSavingAllowed() const
|
bool WindowManager::isSavingAllowed() const
|
||||||
|
|
|
@ -920,9 +920,6 @@ namespace MWMechanics
|
||||||
spells.purge(iter->first.getRefData().getHandle());
|
spells.purge(iter->first.getRefData().getHandle());
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: see http://bugs.openmw.org/issues/869
|
|
||||||
MWBase::Environment::get().getWorld()->enableActorCollision(iter->first, false);
|
|
||||||
|
|
||||||
if (iter->second->kill())
|
if (iter->second->kill())
|
||||||
{
|
{
|
||||||
++mDeathCount[cls.getId(iter->first)];
|
++mDeathCount[cls.getId(iter->first)];
|
||||||
|
@ -939,6 +936,8 @@ namespace MWMechanics
|
||||||
stats.setMagicEffects(MWMechanics::MagicEffects());
|
stats.setMagicEffects(MWMechanics::MagicEffects());
|
||||||
calculateCreatureStatModifiers(iter->first, 0);
|
calculateCreatureStatModifiers(iter->first, 0);
|
||||||
|
|
||||||
|
MWBase::Environment::get().getWorld()->enableActorCollision(iter->first, false);
|
||||||
|
|
||||||
if (cls.isEssential(iter->first))
|
if (cls.isEssential(iter->first))
|
||||||
MWBase::Environment::get().getWindowManager()->messageBox("#{sKilledEssential}");
|
MWBase::Environment::get().getWindowManager()->messageBox("#{sKilledEssential}");
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,8 +17,10 @@ namespace MWMechanics
|
||||||
mAttacked (false), mHostile (false),
|
mAttacked (false), mHostile (false),
|
||||||
mAttackingOrSpell(false),
|
mAttackingOrSpell(false),
|
||||||
mIsWerewolf(false),
|
mIsWerewolf(false),
|
||||||
mFallHeight(0), mRecalcDynamicStats(false), mKnockdown(false), mKnockdownOneFrame(false), mKnockdownOverOneFrame(false), mHitRecovery(false), mBlock(false),
|
mFallHeight(0), mRecalcDynamicStats(false), mKnockdown(false), mKnockdownOneFrame(false),
|
||||||
mMovementFlags(0), mDrawState (DrawState_Nothing), mAttackStrength(0.f)
|
mKnockdownOverOneFrame(false), mHitRecovery(false), mBlock(false),
|
||||||
|
mMovementFlags(0), mDrawState (DrawState_Nothing), mAttackStrength(0.f),
|
||||||
|
mTradeTime(0,0), mGoldPool(0)
|
||||||
{
|
{
|
||||||
for (int i=0; i<4; ++i)
|
for (int i=0; i<4; ++i)
|
||||||
mAiSettings[i] = 0;
|
mAiSettings[i] = 0;
|
||||||
|
@ -348,20 +350,6 @@ namespace MWMechanics
|
||||||
return mLastHitObject;
|
return mLastHitObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CreatureStats::canUsePower(const std::string &power) const
|
|
||||||
{
|
|
||||||
std::map<std::string, MWWorld::TimeStamp>::const_iterator it = mUsedPowers.find(power);
|
|
||||||
if (it == mUsedPowers.end() || it->second + 24 <= MWBase::Environment::get().getWorld()->getTimeStamp())
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CreatureStats::usePower(const std::string &power)
|
|
||||||
{
|
|
||||||
mUsedPowers[power] = MWBase::Environment::get().getWorld()->getTimeStamp();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CreatureStats::addToFallHeight(float height)
|
void CreatureStats::addToFallHeight(float height)
|
||||||
{
|
{
|
||||||
mFallHeight += height;
|
mFallHeight += height;
|
||||||
|
@ -481,20 +469,75 @@ namespace MWMechanics
|
||||||
|
|
||||||
void CreatureStats::writeState (ESM::CreatureStats& state) const
|
void CreatureStats::writeState (ESM::CreatureStats& state) const
|
||||||
{
|
{
|
||||||
for (int i=0; i<8; ++i)
|
for (int i=0; i<ESM::Attribute::Length; ++i)
|
||||||
mAttributes[i].writeState (state.mAttributes[i]);
|
mAttributes[i].writeState (state.mAttributes[i]);
|
||||||
|
|
||||||
for (int i=0; i<3; ++i)
|
for (int i=0; i<3; ++i)
|
||||||
mDynamic[i].writeState (state.mDynamic[i]);
|
mDynamic[i].writeState (state.mDynamic[i]);
|
||||||
|
|
||||||
|
state.mTradeTime = mTradeTime.toEsm();
|
||||||
|
state.mGoldPool = mGoldPool;
|
||||||
|
|
||||||
|
state.mDead = mDead;
|
||||||
|
state.mDied = mDied;
|
||||||
|
state.mFriendlyHits = mFriendlyHits;
|
||||||
|
state.mTalkedTo = mTalkedTo;
|
||||||
|
state.mAlarmed = mAlarmed;
|
||||||
|
state.mAttacked = mAttacked;
|
||||||
|
state.mHostile = mHostile;
|
||||||
|
state.mAttackingOrSpell = mAttackingOrSpell;
|
||||||
|
// TODO: rewrite. does this really need 3 separate bools?
|
||||||
|
state.mKnockdown = mKnockdown;
|
||||||
|
state.mKnockdownOneFrame = mKnockdownOneFrame;
|
||||||
|
state.mKnockdownOverOneFrame = mKnockdownOverOneFrame;
|
||||||
|
state.mHitRecovery = mHitRecovery;
|
||||||
|
state.mBlock = mBlock;
|
||||||
|
state.mMovementFlags = mMovementFlags;
|
||||||
|
state.mAttackStrength = mAttackStrength;
|
||||||
|
state.mFallHeight = mFallHeight;
|
||||||
|
state.mLastHitObject = mLastHitObject;
|
||||||
|
state.mRecalcDynamicStats = mRecalcDynamicStats;
|
||||||
|
state.mDrawState = mDrawState;
|
||||||
|
state.mLevel = mLevel;
|
||||||
|
|
||||||
|
mSpells.writeState(state.mSpells);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreatureStats::readState (const ESM::CreatureStats& state)
|
void CreatureStats::readState (const ESM::CreatureStats& state)
|
||||||
{
|
{
|
||||||
for (int i=0; i<8; ++i)
|
for (int i=0; i<ESM::Attribute::Length; ++i)
|
||||||
mAttributes[i].readState (state.mAttributes[i]);
|
mAttributes[i].readState (state.mAttributes[i]);
|
||||||
|
|
||||||
for (int i=0; i<3; ++i)
|
for (int i=0; i<3; ++i)
|
||||||
mDynamic[i].readState (state.mDynamic[i]);
|
mDynamic[i].readState (state.mDynamic[i]);
|
||||||
|
|
||||||
|
mTradeTime = MWWorld::TimeStamp(state.mTradeTime);
|
||||||
|
mGoldPool = state.mGoldPool;
|
||||||
|
mFallHeight = state.mFallHeight;
|
||||||
|
|
||||||
|
mDead = state.mDead;
|
||||||
|
mDied = state.mDied;
|
||||||
|
mFriendlyHits = state.mFriendlyHits;
|
||||||
|
mTalkedTo = state.mTalkedTo;
|
||||||
|
mAlarmed = state.mAlarmed;
|
||||||
|
mAttacked = state.mAttacked;
|
||||||
|
mHostile = state.mHostile;
|
||||||
|
mAttackingOrSpell = state.mAttackingOrSpell;
|
||||||
|
// TODO: rewrite. does this really need 3 separate bools?
|
||||||
|
mKnockdown = state.mKnockdown;
|
||||||
|
mKnockdownOneFrame = state.mKnockdownOneFrame;
|
||||||
|
mKnockdownOverOneFrame = state.mKnockdownOverOneFrame;
|
||||||
|
mHitRecovery = state.mHitRecovery;
|
||||||
|
mBlock = state.mBlock;
|
||||||
|
mMovementFlags = state.mMovementFlags;
|
||||||
|
mAttackStrength = state.mAttackStrength;
|
||||||
|
mFallHeight = state.mFallHeight;
|
||||||
|
mLastHitObject = state.mLastHitObject;
|
||||||
|
mRecalcDynamicStats = state.mRecalcDynamicStats;
|
||||||
|
mDrawState = DrawState_(state.mDrawState);
|
||||||
|
mLevel = state.mLevel;
|
||||||
|
|
||||||
|
mSpells.readState(state.mSpells);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Relates to NPC gold reset delay
|
// Relates to NPC gold reset delay
|
||||||
|
|
|
@ -55,15 +55,15 @@ namespace MWMechanics
|
||||||
// Do we need to recalculate stats derived from attributes or other factors?
|
// Do we need to recalculate stats derived from attributes or other factors?
|
||||||
bool mRecalcDynamicStats;
|
bool mRecalcDynamicStats;
|
||||||
|
|
||||||
std::map<std::string, MWWorld::TimeStamp> mUsedPowers;
|
|
||||||
|
|
||||||
MWWorld::TimeStamp mTradeTime; // Relates to NPC gold reset delay
|
MWWorld::TimeStamp mTradeTime; // Relates to NPC gold reset delay
|
||||||
|
|
||||||
int mGoldPool; // the pool of merchant gold not in inventory
|
int mGoldPool; // the pool of merchant gold not in inventory
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
// These two are only set by NpcStats, but they are declared in CreatureStats to prevent using virtual methods.
|
||||||
bool mIsWerewolf;
|
bool mIsWerewolf;
|
||||||
AttributeValue mWerewolfAttributes[8];
|
AttributeValue mWerewolfAttributes[8];
|
||||||
|
|
||||||
int mLevel;
|
int mLevel;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -84,9 +84,6 @@ namespace MWMechanics
|
||||||
/// @return total fall height
|
/// @return total fall height
|
||||||
float land();
|
float land();
|
||||||
|
|
||||||
bool canUsePower (const std::string& power) const;
|
|
||||||
void usePower (const std::string& power);
|
|
||||||
|
|
||||||
const AttributeValue & getAttribute(int index) const;
|
const AttributeValue & getAttribute(int index) const;
|
||||||
|
|
||||||
const DynamicStat<float> & getHealth() const;
|
const DynamicStat<float> & getHealth() const;
|
||||||
|
|
|
@ -6,9 +6,9 @@ namespace MWMechanics
|
||||||
/// \note The _ suffix is required to avoid a collision with a Windoze macro. Die, Microsoft! Die!
|
/// \note The _ suffix is required to avoid a collision with a Windoze macro. Die, Microsoft! Die!
|
||||||
enum DrawState_
|
enum DrawState_
|
||||||
{
|
{
|
||||||
DrawState_Weapon = 0,
|
DrawState_Nothing = 0,
|
||||||
DrawState_Spell = 1,
|
DrawState_Weapon = 1,
|
||||||
DrawState_Nothing = 2
|
DrawState_Spell = 2
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -342,7 +342,9 @@ namespace MWMechanics
|
||||||
MWWorld::ContainerStoreIterator enchantItem = inv.getSelectedEnchantItem();
|
MWWorld::ContainerStoreIterator enchantItem = inv.getSelectedEnchantItem();
|
||||||
if (enchantItem != inv.end())
|
if (enchantItem != inv.end())
|
||||||
winMgr->setSelectedEnchantItem(*enchantItem);
|
winMgr->setSelectedEnchantItem(*enchantItem);
|
||||||
else if (winMgr->getSelectedSpell() == "")
|
else if (!winMgr->getSelectedSpell().empty())
|
||||||
|
winMgr->setSelectedSpell(winMgr->getSelectedSpell(), int(MWMechanics::getSpellSuccessChance(winMgr->getSelectedSpell(), mWatched)));
|
||||||
|
else
|
||||||
winMgr->unsetSelectedSpell();
|
winMgr->unsetSelectedSpell();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -432,9 +432,9 @@ float MWMechanics::NpcStats::getTimeToStartDrowning() const
|
||||||
{
|
{
|
||||||
return mTimeToStartDrowning;
|
return mTimeToStartDrowning;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MWMechanics::NpcStats::setTimeToStartDrowning(float time)
|
void MWMechanics::NpcStats::setTimeToStartDrowning(float time)
|
||||||
{
|
{
|
||||||
assert(time>=0 && time<=20);
|
|
||||||
mTimeToStartDrowning=time;
|
mTimeToStartDrowning=time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -446,11 +446,16 @@ void MWMechanics::NpcStats::writeState (ESM::NpcStats& state) const
|
||||||
|
|
||||||
state.mDisposition = mDisposition;
|
state.mDisposition = mDisposition;
|
||||||
|
|
||||||
for (int i=0; i<27; ++i)
|
for (int i=0; i<ESM::Skill::Length; ++i)
|
||||||
{
|
{
|
||||||
mSkill[i].writeState (state.mSkills[i].mRegular);
|
mSkill[i].writeState (state.mSkills[i].mRegular);
|
||||||
mWerewolfSkill[i].writeState (state.mSkills[i].mWerewolf);
|
mWerewolfSkill[i].writeState (state.mSkills[i].mWerewolf);
|
||||||
}
|
}
|
||||||
|
for (int i=0; i<ESM::Attribute::Length; ++i)
|
||||||
|
{
|
||||||
|
mWerewolfAttributes[i].writeState (state.mWerewolfAttributes[i]);
|
||||||
|
}
|
||||||
|
state.mIsWerewolf = mIsWerewolf;
|
||||||
|
|
||||||
state.mCrimeId = mCrimeId;
|
state.mCrimeId = mCrimeId;
|
||||||
|
|
||||||
|
@ -467,10 +472,9 @@ void MWMechanics::NpcStats::writeState (ESM::NpcStats& state) const
|
||||||
state.mReputation = mReputation;
|
state.mReputation = mReputation;
|
||||||
state.mWerewolfKills = mWerewolfKills;
|
state.mWerewolfKills = mWerewolfKills;
|
||||||
state.mProfit = mProfit;
|
state.mProfit = mProfit;
|
||||||
state.mAttackStrength = mAttackStrength;
|
|
||||||
state.mLevelProgress = mLevelProgress;
|
state.mLevelProgress = mLevelProgress;
|
||||||
|
|
||||||
for (int i=0; i<8; ++i)
|
for (int i=0; i<ESM::Attribute::Length; ++i)
|
||||||
state.mSkillIncrease[i] = mSkillIncreases[i];
|
state.mSkillIncrease[i] = mSkillIncreases[i];
|
||||||
|
|
||||||
std::copy (mUsedIds.begin(), mUsedIds.end(), std::back_inserter (state.mUsedIds));
|
std::copy (mUsedIds.begin(), mUsedIds.end(), std::back_inserter (state.mUsedIds));
|
||||||
|
@ -500,21 +504,26 @@ void MWMechanics::NpcStats::readState (const ESM::NpcStats& state)
|
||||||
|
|
||||||
mDisposition = state.mDisposition;
|
mDisposition = state.mDisposition;
|
||||||
|
|
||||||
for (int i=0; i<27; ++i)
|
for (int i=0; i<ESM::Skill::Length; ++i)
|
||||||
{
|
{
|
||||||
mSkill[i].readState (state.mSkills[i].mRegular);
|
mSkill[i].readState (state.mSkills[i].mRegular);
|
||||||
mWerewolfSkill[i].readState (state.mSkills[i].mWerewolf);
|
mWerewolfSkill[i].readState (state.mSkills[i].mWerewolf);
|
||||||
}
|
}
|
||||||
|
for (int i=0; i<ESM::Attribute::Length; ++i)
|
||||||
|
{
|
||||||
|
mWerewolfAttributes[i].readState (state.mWerewolfAttributes[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
mIsWerewolf = state.mIsWerewolf;
|
||||||
|
|
||||||
mCrimeId = state.mCrimeId;
|
mCrimeId = state.mCrimeId;
|
||||||
mBounty = state.mBounty;
|
mBounty = state.mBounty;
|
||||||
mReputation = state.mReputation;
|
mReputation = state.mReputation;
|
||||||
mWerewolfKills = state.mWerewolfKills;
|
mWerewolfKills = state.mWerewolfKills;
|
||||||
mProfit = state.mProfit;
|
mProfit = state.mProfit;
|
||||||
mAttackStrength = state.mAttackStrength;
|
|
||||||
mLevelProgress = state.mLevelProgress;
|
mLevelProgress = state.mLevelProgress;
|
||||||
|
|
||||||
for (int i=0; i<8; ++i)
|
for (int i=0; i<ESM::Attribute::Length; ++i)
|
||||||
mSkillIncreases[i] = state.mSkillIncrease[i];
|
mSkillIncreases[i] = state.mSkillIncrease[i];
|
||||||
|
|
||||||
for (std::vector<std::string>::const_iterator iter (state.mUsedIds.begin());
|
for (std::vector<std::string>::const_iterator iter (state.mUsedIds.begin());
|
||||||
|
|
|
@ -31,8 +31,8 @@ namespace MWMechanics
|
||||||
std::map<std::string, int> mFactionRank;
|
std::map<std::string, int> mFactionRank;
|
||||||
|
|
||||||
int mDisposition;
|
int mDisposition;
|
||||||
SkillValue mSkill[27];
|
SkillValue mSkill[ESM::Skill::Length];
|
||||||
SkillValue mWerewolfSkill[27];
|
SkillValue mWerewolfSkill[ESM::Skill::Length];
|
||||||
int mBounty;
|
int mBounty;
|
||||||
std::set<std::string> mExpelled;
|
std::set<std::string> mExpelled;
|
||||||
std::map<std::string, int> mFactionReputation;
|
std::map<std::string, int> mFactionReputation;
|
||||||
|
@ -40,7 +40,6 @@ namespace MWMechanics
|
||||||
int mCrimeId;
|
int mCrimeId;
|
||||||
int mWerewolfKills;
|
int mWerewolfKills;
|
||||||
int mProfit;
|
int mProfit;
|
||||||
float mAttackStrength;
|
|
||||||
|
|
||||||
int mLevelProgress; // 0-10
|
int mLevelProgress; // 0-10
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
#include <components/esm/loadspel.hpp>
|
#include <components/esm/loadspel.hpp>
|
||||||
|
#include <components/esm/spellstate.hpp>
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
|
@ -30,10 +31,19 @@ namespace MWMechanics
|
||||||
{
|
{
|
||||||
const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().find(spellId);
|
const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().find(spellId);
|
||||||
|
|
||||||
std::vector<float> random;
|
std::map<const int, float> random;
|
||||||
random.resize(spell->mEffects.mList.size());
|
|
||||||
for (unsigned int i=0; i<random.size();++i)
|
// Determine the random magnitudes (unless this is a castable spell, in which case
|
||||||
|
// they will be determined when the spell is cast)
|
||||||
|
if (spell->mData.mType != ESM::Spell::ST_Power && spell->mData.mType != ESM::Spell::ST_Spell)
|
||||||
|
{
|
||||||
|
for (unsigned int i=0; i<spell->mEffects.mList.size();++i)
|
||||||
|
{
|
||||||
|
if (spell->mEffects.mList[i].mMagnMin != spell->mEffects.mList[i].mMagnMax)
|
||||||
random[i] = static_cast<float> (std::rand()) / RAND_MAX;
|
random[i] = static_cast<float> (std::rand()) / RAND_MAX;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mSpells.insert (std::make_pair (Misc::StringUtils::lowerCase(spellId), random));
|
mSpells.insert (std::make_pair (Misc::StringUtils::lowerCase(spellId), random));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,7 +77,11 @@ namespace MWMechanics
|
||||||
int i=0;
|
int i=0;
|
||||||
for (std::vector<ESM::ENAMstruct>::const_iterator it = spell->mEffects.mList.begin(); it != spell->mEffects.mList.end(); ++it)
|
for (std::vector<ESM::ENAMstruct>::const_iterator it = spell->mEffects.mList.begin(); it != spell->mEffects.mList.end(); ++it)
|
||||||
{
|
{
|
||||||
effects.add (*it, it->mMagnMin + (it->mMagnMax - it->mMagnMin) * iter->second[i]);
|
float random = 1.f;
|
||||||
|
if (iter->second.find(i) != iter->second.end())
|
||||||
|
random = iter->second.at(i);
|
||||||
|
|
||||||
|
effects.add (*it, it->mMagnMin + (it->mMagnMax - it->mMagnMin) * random);
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -192,9 +206,60 @@ namespace MWMechanics
|
||||||
for (std::vector<ESM::ENAMstruct>::const_iterator effectIt = list.mList.begin();
|
for (std::vector<ESM::ENAMstruct>::const_iterator effectIt = list.mList.begin();
|
||||||
effectIt != list.mList.end(); ++effectIt, ++i)
|
effectIt != list.mList.end(); ++effectIt, ++i)
|
||||||
{
|
{
|
||||||
float magnitude = effectIt->mMagnMin + (effectIt->mMagnMax - effectIt->mMagnMin) * it->second[i];
|
float random = 1.f;
|
||||||
|
if (it->second.find(i) != it->second.end())
|
||||||
|
random = it->second.at(i);
|
||||||
|
|
||||||
|
float magnitude = effectIt->mMagnMin + (effectIt->mMagnMax - effectIt->mMagnMin) * random;
|
||||||
visitor.visit(MWMechanics::EffectKey(*effectIt), spell->mName, "", magnitude);
|
visitor.visit(MWMechanics::EffectKey(*effectIt), spell->mName, "", magnitude);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Spells::canUsePower(const std::string &power) const
|
||||||
|
{
|
||||||
|
std::map<std::string, MWWorld::TimeStamp>::const_iterator it = mUsedPowers.find(power);
|
||||||
|
if (it == mUsedPowers.end() || it->second + 24 <= MWBase::Environment::get().getWorld()->getTimeStamp())
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Spells::usePower(const std::string &power)
|
||||||
|
{
|
||||||
|
mUsedPowers[power] = MWBase::Environment::get().getWorld()->getTimeStamp();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Spells::readState(const ESM::SpellState &state)
|
||||||
|
{
|
||||||
|
mSpells = state.mSpells;
|
||||||
|
mSelectedSpell = state.mSelectedSpell;
|
||||||
|
|
||||||
|
// Discard spells that are no longer available due to changed content files
|
||||||
|
for (TContainer::iterator iter = mSpells.begin(); iter!=mSpells.end();)
|
||||||
|
{
|
||||||
|
const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().search(iter->first);
|
||||||
|
if (!spell)
|
||||||
|
{
|
||||||
|
if (iter->first == mSelectedSpell)
|
||||||
|
mSelectedSpell = "";
|
||||||
|
mSpells.erase(iter++);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
++iter;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No need to discard spells here (doesn't really matter if non existent ids are kept)
|
||||||
|
for (std::map<std::string, ESM::TimeStamp>::const_iterator it = state.mUsedPowers.begin(); it != state.mUsedPowers.end(); ++it)
|
||||||
|
mUsedPowers[it->first] = MWWorld::TimeStamp(it->second);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Spells::writeState(ESM::SpellState &state) const
|
||||||
|
{
|
||||||
|
state.mSpells = mSpells;
|
||||||
|
state.mSelectedSpell = mSelectedSpell;
|
||||||
|
|
||||||
|
for (std::map<std::string, MWWorld::TimeStamp>::const_iterator it = mUsedPowers.begin(); it != mUsedPowers.end(); ++it)
|
||||||
|
state.mUsedPowers[it->first] = it->second.toEsm();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,12 +7,16 @@
|
||||||
#include <components/misc/stringops.hpp>
|
#include <components/misc/stringops.hpp>
|
||||||
|
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
|
#include "../mwworld/timestamp.hpp"
|
||||||
|
|
||||||
#include "magiceffects.hpp"
|
#include "magiceffects.hpp"
|
||||||
|
|
||||||
|
|
||||||
namespace ESM
|
namespace ESM
|
||||||
{
|
{
|
||||||
struct Spell;
|
struct Spell;
|
||||||
|
|
||||||
|
struct SpellState;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace MWMechanics
|
namespace MWMechanics
|
||||||
|
@ -22,21 +26,29 @@ namespace MWMechanics
|
||||||
/// \brief Spell list
|
/// \brief Spell list
|
||||||
///
|
///
|
||||||
/// This class manages known spells as well as abilities, powers and permanent negative effects like
|
/// This class manages known spells as well as abilities, powers and permanent negative effects like
|
||||||
/// diseases.
|
/// diseases. It also keeps track of used powers (which can only be used every 24h).
|
||||||
class Spells
|
class Spells
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
typedef std::map<std::string, std::vector<float> > TContainer; // ID, normalised magnitudes
|
|
||||||
|
typedef std::map<std::string, std::map<const int, float> > TContainer; // ID, <effect index, normalised random magnitude>
|
||||||
typedef TContainer::const_iterator TIterator;
|
typedef TContainer::const_iterator TIterator;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
TContainer mSpells;
|
TContainer mSpells;
|
||||||
|
|
||||||
|
// Note: this is the spell that's about to be cast, *not* the spell selected in the GUI (which may be different)
|
||||||
std::string mSelectedSpell;
|
std::string mSelectedSpell;
|
||||||
|
|
||||||
|
std::map<std::string, MWWorld::TimeStamp> mUsedPowers;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
bool canUsePower (const std::string& power) const;
|
||||||
|
void usePower (const std::string& power);
|
||||||
|
|
||||||
void purgeCommonDisease();
|
void purgeCommonDisease();
|
||||||
void purgeBlightDisease();
|
void purgeBlightDisease();
|
||||||
void purgeCorprusDisease();
|
void purgeCorprusDisease();
|
||||||
|
@ -72,6 +84,9 @@ namespace MWMechanics
|
||||||
bool hasBlightDisease() const;
|
bool hasBlightDisease() const;
|
||||||
|
|
||||||
void visitEffectSources (MWMechanics::EffectSourceVisitor& visitor) const;
|
void visitEffectSources (MWMechanics::EffectSourceVisitor& visitor) const;
|
||||||
|
|
||||||
|
void readState (const ESM::SpellState& state);
|
||||||
|
void writeState (ESM::SpellState& state) const;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -168,7 +168,10 @@ void LocalMap::requestMap(MWWorld::CellStore* cell, float zMin, float zMax)
|
||||||
|
|
||||||
mCameraPosNode->setPosition(Vector3(0,0,0));
|
mCameraPosNode->setPosition(Vector3(0,0,0));
|
||||||
|
|
||||||
render((x+0.5)*sSize, (y+0.5)*sSize, zMin, zMax, sSize, sSize, name);
|
// Note: using force=true for exterior cell maps.
|
||||||
|
// They must be updated even if they were visited before, because the set of surrounding active cells might be different
|
||||||
|
// (and objects in a different cell can "bleed" into another cell's map if they cross the border)
|
||||||
|
render((x+0.5)*sSize, (y+0.5)*sSize, zMin, zMax, sSize, sSize, name, true);
|
||||||
|
|
||||||
if (mBuffers.find(name) == mBuffers.end())
|
if (mBuffers.find(name) == mBuffers.end())
|
||||||
{
|
{
|
||||||
|
@ -296,7 +299,8 @@ void LocalMap::requestMap(MWWorld::CellStore* cell,
|
||||||
ESM::FogState* fog = cell->getFog();
|
ESM::FogState* fog = cell->getFog();
|
||||||
|
|
||||||
// We are using the same bounds and angle as we were using when the textures were originally made. Segments should come out the same.
|
// We are using the same bounds and angle as we were using when the textures were originally made. Segments should come out the same.
|
||||||
assert (i < int(fog->mFogTextures.size()));
|
if (i >= int(fog->mFogTextures.size()))
|
||||||
|
throw std::runtime_error("fog texture count mismatch");
|
||||||
|
|
||||||
ESM::FogTexture& esm = fog->mFogTextures[i];
|
ESM::FogTexture& esm = fog->mFogTextures[i];
|
||||||
loadFogOfWar(texturePrefix, esm);
|
loadFogOfWar(texturePrefix, esm);
|
||||||
|
@ -338,8 +342,6 @@ Ogre::TexturePtr LocalMap::createFogOfWarTexture(const std::string &texName)
|
||||||
PF_A8R8G8B8,
|
PF_A8R8G8B8,
|
||||||
TU_DYNAMIC_WRITE_ONLY);
|
TU_DYNAMIC_WRITE_ONLY);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
tex->unload();
|
|
||||||
|
|
||||||
return tex;
|
return tex;
|
||||||
}
|
}
|
||||||
|
@ -351,12 +353,14 @@ void LocalMap::loadFogOfWar (const std::string& texturePrefix, ESM::FogTexture&
|
||||||
Ogre::Image image;
|
Ogre::Image image;
|
||||||
image.load(stream, "tga");
|
image.load(stream, "tga");
|
||||||
|
|
||||||
assert (image.getWidth() == sFogOfWarResolution && image.getHeight() == sFogOfWarResolution);
|
if (image.getWidth() != sFogOfWarResolution || image.getHeight() != sFogOfWarResolution)
|
||||||
|
throw std::runtime_error("fog texture size mismatch");
|
||||||
|
|
||||||
std::string texName = texturePrefix + "_fog";
|
std::string texName = texturePrefix + "_fog";
|
||||||
|
|
||||||
Ogre::TexturePtr tex = createFogOfWarTexture(texName);
|
Ogre::TexturePtr tex = createFogOfWarTexture(texName);
|
||||||
|
|
||||||
|
tex->unload();
|
||||||
tex->loadImage(image);
|
tex->loadImage(image);
|
||||||
|
|
||||||
// create a buffer to use for dynamic operations
|
// create a buffer to use for dynamic operations
|
||||||
|
@ -369,7 +373,7 @@ void LocalMap::loadFogOfWar (const std::string& texturePrefix, ESM::FogTexture&
|
||||||
|
|
||||||
void LocalMap::render(const float x, const float y,
|
void LocalMap::render(const float x, const float y,
|
||||||
const float zlow, const float zhigh,
|
const float zlow, const float zhigh,
|
||||||
const float xw, const float yw, const std::string& texture)
|
const float xw, const float yw, const std::string& texture, bool force)
|
||||||
{
|
{
|
||||||
mCellCamera->setFarClipDistance( (zhigh-zlow) + 2000 );
|
mCellCamera->setFarClipDistance( (zhigh-zlow) + 2000 );
|
||||||
mCellCamera->setNearClipDistance(50);
|
mCellCamera->setNearClipDistance(50);
|
||||||
|
@ -408,6 +412,11 @@ void LocalMap::render(const float x, const float y,
|
||||||
PF_R8G8B8);
|
PF_R8G8B8);
|
||||||
tex->getBuffer()->blit(mRenderTexture->getBuffer());
|
tex->getBuffer()->blit(mRenderTexture->getBuffer());
|
||||||
}
|
}
|
||||||
|
else if (force)
|
||||||
|
{
|
||||||
|
mRenderTarget->update();
|
||||||
|
tex->getBuffer()->blit(mRenderTexture->getBuffer());
|
||||||
|
}
|
||||||
|
|
||||||
mRenderingManager->enableLights(true);
|
mRenderingManager->enableLights(true);
|
||||||
mLight->setVisible(false);
|
mLight->setVisible(false);
|
||||||
|
|
|
@ -106,10 +106,11 @@ namespace MWRender
|
||||||
float mAngle;
|
float mAngle;
|
||||||
const Ogre::Vector2 rotatePoint(const Ogre::Vector2& p, const Ogre::Vector2& c, const float angle);
|
const Ogre::Vector2 rotatePoint(const Ogre::Vector2& p, const Ogre::Vector2& c, const float angle);
|
||||||
|
|
||||||
|
/// @param force Always render, even if we already have a cached map
|
||||||
void render(const float x, const float y,
|
void render(const float x, const float y,
|
||||||
const float zlow, const float zhigh,
|
const float zlow, const float zhigh,
|
||||||
const float xw, const float yw,
|
const float xw, const float yw,
|
||||||
const std::string& texture);
|
const std::string& texture, bool force=false);
|
||||||
|
|
||||||
// Creates a fog of war texture and initializes it to full black
|
// Creates a fog of war texture and initializes it to full black
|
||||||
void createFogOfWar(const std::string& texturePrefix);
|
void createFogOfWar(const std::string& texturePrefix);
|
||||||
|
|
|
@ -380,6 +380,10 @@ void RenderingManager::update (float duration, bool paused)
|
||||||
|
|
||||||
mCamera->update(duration, paused);
|
mCamera->update(duration, paused);
|
||||||
|
|
||||||
|
Ogre::SceneNode *node = data.getBaseNode();
|
||||||
|
Ogre::Quaternion orient = node->_getDerivedOrientation();
|
||||||
|
mLocalMap->updatePlayer(playerPos, orient);
|
||||||
|
|
||||||
if(paused)
|
if(paused)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -393,10 +397,6 @@ void RenderingManager::update (float duration, bool paused)
|
||||||
|
|
||||||
mSkyManager->setGlare(mOcclusionQuery->getSunVisibility());
|
mSkyManager->setGlare(mOcclusionQuery->getSunVisibility());
|
||||||
|
|
||||||
Ogre::SceneNode *node = data.getBaseNode();
|
|
||||||
Ogre::Quaternion orient = node->_getDerivedOrientation();
|
|
||||||
|
|
||||||
mLocalMap->updatePlayer(playerPos, orient);
|
|
||||||
|
|
||||||
mWater->updateUnderwater(world->isUnderwater(player.getCell(), cam));
|
mWater->updateUnderwater(world->isUnderwater(player.getCell(), cam));
|
||||||
|
|
||||||
|
|
|
@ -326,6 +326,8 @@ void MWState::StateManager::loadGame (const Character *character, const Slot *sl
|
||||||
|
|
||||||
case ESM::REC_GMAP:
|
case ESM::REC_GMAP:
|
||||||
case ESM::REC_KEYS:
|
case ESM::REC_KEYS:
|
||||||
|
case ESM::REC_ASPL:
|
||||||
|
|
||||||
MWBase::Environment::get().getWindowManager()->readRecord(reader, n.val);
|
MWBase::Environment::get().getWindowManager()->readRecord(reader, n.val);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,9 @@
|
||||||
|
|
||||||
#include "class.hpp"
|
#include "class.hpp"
|
||||||
|
|
||||||
|
#include "../mwbase/environment.hpp"
|
||||||
|
#include "../mwbase/world.hpp"
|
||||||
|
|
||||||
namespace MWWorld
|
namespace MWWorld
|
||||||
{
|
{
|
||||||
ActionApply::ActionApply (const Ptr& target, const std::string& id)
|
ActionApply::ActionApply (const Ptr& target, const std::string& id)
|
||||||
|
@ -11,6 +14,8 @@ namespace MWWorld
|
||||||
|
|
||||||
void ActionApply::executeImp (const Ptr& actor)
|
void ActionApply::executeImp (const Ptr& actor)
|
||||||
{
|
{
|
||||||
|
MWBase::Environment::get().getWorld()->breakInvisibility(actor);
|
||||||
|
|
||||||
MWWorld::Class::get (getTarget()).apply (getTarget(), mId, actor);
|
MWWorld::Class::get (getTarget()).apply (getTarget(), mId, actor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +27,8 @@ namespace MWWorld
|
||||||
|
|
||||||
void ActionApplyWithSkill::executeImp (const Ptr& actor)
|
void ActionApplyWithSkill::executeImp (const Ptr& actor)
|
||||||
{
|
{
|
||||||
|
MWBase::Environment::get().getWorld()->breakInvisibility(actor);
|
||||||
|
|
||||||
if (MWWorld::Class::get (getTarget()).apply (getTarget(), mId, actor) && mUsageType!=-1)
|
if (MWWorld::Class::get (getTarget()).apply (getTarget(), mId, actor) && mUsageType!=-1)
|
||||||
MWWorld::Class::get (getTarget()).skillUsageSucceeded (actor, mSkillIndex, mUsageType);
|
MWWorld::Class::get (getTarget()).skillUsageSucceeded (actor, mSkillIndex, mUsageType);
|
||||||
}
|
}
|
||||||
|
|
|
@ -199,7 +199,7 @@ void ESMStore::setUp()
|
||||||
|
|
||||||
if (!mRaces.find (player->mRace) ||
|
if (!mRaces.find (player->mRace) ||
|
||||||
!mClasses.find (player->mClass))
|
!mClasses.find (player->mClass))
|
||||||
throw std::runtime_error ("Invalid player record (race or class unavilable");
|
throw std::runtime_error ("Invalid player record (race or class unavailable");
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -87,6 +87,7 @@ namespace MWWorld
|
||||||
float mMultiplier;
|
float mMultiplier;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO: store in savegame
|
||||||
typedef std::map<std::string, std::vector<EffectParams> > TEffectMagnitudes;
|
typedef std::map<std::string, std::vector<EffectParams> > TEffectMagnitudes;
|
||||||
TEffectMagnitudes mPermanentMagicEffectMagnitudes;
|
TEffectMagnitudes mPermanentMagicEffectMagnitudes;
|
||||||
|
|
||||||
|
|
|
@ -626,12 +626,12 @@ namespace MWWorld
|
||||||
bool cmode = act->getCollisionMode();
|
bool cmode = act->getCollisionMode();
|
||||||
if(cmode)
|
if(cmode)
|
||||||
{
|
{
|
||||||
act->enableCollisions(false);
|
act->enableCollisionMode(false);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
act->enableCollisions(true);
|
act->enableCollisionMode(true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,7 +85,17 @@ namespace
|
||||||
namespace MWWorld
|
namespace MWWorld
|
||||||
{
|
{
|
||||||
|
|
||||||
void Scene::update (float duration, bool paused){
|
void Scene::update (float duration, bool paused)
|
||||||
|
{
|
||||||
|
if (mNeedMapUpdate)
|
||||||
|
{
|
||||||
|
// Note: exterior cell maps must be updated, even if they were visited before, because the set of surrounding cells might be different
|
||||||
|
// (and objects in a different cell can "bleed" into another cells map if they cross the border)
|
||||||
|
for (CellStoreCollection::iterator active = mActiveCells.begin(); active!=mActiveCells.end(); ++active)
|
||||||
|
mRendering.requestMap(*active);
|
||||||
|
mNeedMapUpdate = false;
|
||||||
|
}
|
||||||
|
|
||||||
mRendering.update (duration, paused);
|
mRendering.update (duration, paused);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,8 +207,9 @@ namespace MWWorld
|
||||||
|
|
||||||
mRendering.updateTerrain();
|
mRendering.updateTerrain();
|
||||||
|
|
||||||
for (CellStoreCollection::iterator active = mActiveCells.begin(); active!=mActiveCells.end(); ++active)
|
// Delay the map update until scripts have been given a chance to run.
|
||||||
mRendering.requestMap(*active);
|
// If we don't do this, objects that should be disabled will still appear on the map.
|
||||||
|
mNeedMapUpdate = true;
|
||||||
|
|
||||||
MWBase::Environment::get().getWindowManager()->changeCell(mCurrentCell);
|
MWBase::Environment::get().getWindowManager()->changeCell(mCurrentCell);
|
||||||
}
|
}
|
||||||
|
@ -342,7 +353,7 @@ namespace MWWorld
|
||||||
|
|
||||||
//We need the ogre renderer and a scene node.
|
//We need the ogre renderer and a scene node.
|
||||||
Scene::Scene (MWRender::RenderingManager& rendering, PhysicsSystem *physics)
|
Scene::Scene (MWRender::RenderingManager& rendering, PhysicsSystem *physics)
|
||||||
: mCurrentCell (0), mCellChanged (false), mPhysics(physics), mRendering(rendering)
|
: mCurrentCell (0), mCellChanged (false), mPhysics(physics), mRendering(rendering), mNeedMapUpdate(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,8 @@ namespace MWWorld
|
||||||
PhysicsSystem *mPhysics;
|
PhysicsSystem *mPhysics;
|
||||||
MWRender::RenderingManager& mRendering;
|
MWRender::RenderingManager& mRendering;
|
||||||
|
|
||||||
|
bool mNeedMapUpdate;
|
||||||
|
|
||||||
void playerCellChange (CellStore *cell, const ESM::Position& position,
|
void playerCellChange (CellStore *cell, const ESM::Position& position,
|
||||||
bool adjustPlayerPos = true);
|
bool adjustPlayerPos = true);
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
|
|
||||||
#include "timestamp.hpp"
|
#include "timestamp.hpp"
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#include <components/esm/defs.hpp>
|
||||||
|
|
||||||
namespace MWWorld
|
namespace MWWorld
|
||||||
{
|
{
|
||||||
TimeStamp::TimeStamp (float hour, int day)
|
TimeStamp::TimeStamp (float hour, int day)
|
||||||
|
@ -105,4 +105,18 @@ namespace MWWorld
|
||||||
|
|
||||||
return hours + 24*days;
|
return hours + 24*days;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ESM::TimeStamp TimeStamp::toEsm() const
|
||||||
|
{
|
||||||
|
ESM::TimeStamp ret;
|
||||||
|
ret.mDay = mDay;
|
||||||
|
ret.mHour = mHour;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
TimeStamp::TimeStamp(const ESM::TimeStamp &esm)
|
||||||
|
{
|
||||||
|
mDay = esm.mDay;
|
||||||
|
mHour = esm.mHour;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
#ifndef GAME_MWWORLD_TIMESTAMP_H
|
#ifndef GAME_MWWORLD_TIMESTAMP_H
|
||||||
#define GAME_MWWORLD_TIMESTAMP_H
|
#define GAME_MWWORLD_TIMESTAMP_H
|
||||||
|
|
||||||
|
namespace ESM
|
||||||
|
{
|
||||||
|
class TimeStamp;
|
||||||
|
}
|
||||||
|
|
||||||
namespace MWWorld
|
namespace MWWorld
|
||||||
{
|
{
|
||||||
/// \brief In-game time stamp
|
/// \brief In-game time stamp
|
||||||
|
@ -14,9 +19,12 @@ namespace MWWorld
|
||||||
public:
|
public:
|
||||||
|
|
||||||
explicit TimeStamp (float hour = 0, int day = 0);
|
explicit TimeStamp (float hour = 0, int day = 0);
|
||||||
///< \oaram hour [0, 23)
|
///< \param hour [0, 23)
|
||||||
/// \param day >=0
|
/// \param day >=0
|
||||||
|
|
||||||
|
explicit TimeStamp (const ESM::TimeStamp& esm);
|
||||||
|
ESM::TimeStamp toEsm () const;
|
||||||
|
|
||||||
float getHour() const;
|
float getHour() const;
|
||||||
|
|
||||||
int getDay() const;
|
int getDay() const;
|
||||||
|
|
|
@ -1491,6 +1491,9 @@ namespace MWWorld
|
||||||
{
|
{
|
||||||
MWWorld::LiveCellRef<ESM::Door>& ref = *it;
|
MWWorld::LiveCellRef<ESM::Door>& ref = *it;
|
||||||
|
|
||||||
|
if (!ref.mData.isEnabled())
|
||||||
|
continue;
|
||||||
|
|
||||||
if (ref.mRef.mTeleport)
|
if (ref.mRef.mTeleport)
|
||||||
{
|
{
|
||||||
World::DoorMarker newMarker;
|
World::DoorMarker newMarker;
|
||||||
|
@ -1954,7 +1957,7 @@ namespace MWWorld
|
||||||
{
|
{
|
||||||
OEngine::Physic::PhysicActor *physicActor = mPhysEngine->getCharacter(actor.getRefData().getHandle());
|
OEngine::Physic::PhysicActor *physicActor = mPhysEngine->getCharacter(actor.getRefData().getHandle());
|
||||||
|
|
||||||
physicActor->enableCollisions(enable);
|
physicActor->enableCollisionBody(enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool World::findInteriorPosition(const std::string &name, ESM::Position &pos)
|
bool World::findInteriorPosition(const std::string &name, ESM::Position &pos)
|
||||||
|
@ -2161,8 +2164,8 @@ namespace MWWorld
|
||||||
// If this is a power, check if it was already used in the last 24h
|
// If this is a power, check if it was already used in the last 24h
|
||||||
if (!fail && spell->mData.mType == ESM::Spell::ST_Power)
|
if (!fail && spell->mData.mType == ESM::Spell::ST_Power)
|
||||||
{
|
{
|
||||||
if (stats.canUsePower(spell->mId))
|
if (stats.getSpells().canUsePower(spell->mId))
|
||||||
stats.usePower(spell->mId);
|
stats.getSpells().usePower(spell->mId);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
message = "#{sPowerAlreadyUsed}";
|
message = "#{sPowerAlreadyUsed}";
|
||||||
|
|
|
@ -45,7 +45,7 @@ add_component_dir (esm
|
||||||
loadnpc loadpgrd loadrace loadregn loadscpt loadskil loadsndg loadsoun loadspel loadsscr loadstat
|
loadnpc loadpgrd loadrace loadregn loadscpt loadskil loadsndg loadsoun loadspel loadsscr loadstat
|
||||||
loadweap records aipackage effectlist spelllist variant variantimp loadtes3 cellref filter
|
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
|
savedgame journalentry queststate locals globalscript player objectstate cellid cellstate globalmap lightstate inventorystate containerstate npcstate creaturestate dialoguestate statstate
|
||||||
npcstats creaturestats weatherstate quickkeys fogstate
|
npcstats creaturestats weatherstate quickkeys fogstate spellstate
|
||||||
)
|
)
|
||||||
|
|
||||||
add_component_dir (misc
|
add_component_dir (misc
|
||||||
|
|
|
@ -8,13 +8,143 @@ void ESM::CreatureStats::load (ESMReader &esm)
|
||||||
|
|
||||||
for (int i=0; i<3; ++i)
|
for (int i=0; i<3; ++i)
|
||||||
mDynamic[i].load (esm);
|
mDynamic[i].load (esm);
|
||||||
|
|
||||||
|
mGoldPool = 0;
|
||||||
|
esm.getHNOT (mGoldPool, "GOLD");
|
||||||
|
|
||||||
|
mTradeTime.mDay = 0;
|
||||||
|
mTradeTime.mHour = 0;
|
||||||
|
esm.getHNOT (mTradeTime, "TIME");
|
||||||
|
|
||||||
|
mDead = false;
|
||||||
|
esm.getHNOT (mDead, "DEAD");
|
||||||
|
|
||||||
|
mDied = false;
|
||||||
|
esm.getHNOT (mDied, "DIED");
|
||||||
|
|
||||||
|
mFriendlyHits = 0;
|
||||||
|
esm.getHNOT (mFriendlyHits, "FRHT");
|
||||||
|
|
||||||
|
mTalkedTo = false;
|
||||||
|
esm.getHNOT (mTalkedTo, "TALK");
|
||||||
|
|
||||||
|
mAlarmed = false;
|
||||||
|
esm.getHNOT (mAlarmed, "ALRM");
|
||||||
|
|
||||||
|
mHostile = false;
|
||||||
|
esm.getHNOT (mHostile, "HOST");
|
||||||
|
|
||||||
|
mAttackingOrSpell = false;
|
||||||
|
esm.getHNOT (mAttackingOrSpell, "ATCK");
|
||||||
|
|
||||||
|
mKnockdown = false;
|
||||||
|
esm.getHNOT (mKnockdown, "KNCK");
|
||||||
|
|
||||||
|
mKnockdownOneFrame = false;
|
||||||
|
esm.getHNOT (mKnockdownOneFrame, "KNC1");
|
||||||
|
|
||||||
|
mKnockdownOverOneFrame = false;
|
||||||
|
esm.getHNOT (mKnockdownOverOneFrame, "KNCO");
|
||||||
|
|
||||||
|
mHitRecovery = false;
|
||||||
|
esm.getHNOT (mHitRecovery, "HITR");
|
||||||
|
|
||||||
|
mBlock = false;
|
||||||
|
esm.getHNOT (mBlock, "BLCK");
|
||||||
|
|
||||||
|
mMovementFlags = 0;
|
||||||
|
esm.getHNOT (mMovementFlags, "MOVE");
|
||||||
|
|
||||||
|
mAttackStrength = 0;
|
||||||
|
esm.getHNOT (mAttackStrength, "ASTR");
|
||||||
|
|
||||||
|
mFallHeight = 0;
|
||||||
|
esm.getHNOT (mFallHeight, "FALL");
|
||||||
|
|
||||||
|
mLastHitObject = esm.getHNOString ("LHIT");
|
||||||
|
|
||||||
|
mRecalcDynamicStats = false;
|
||||||
|
esm.getHNOT (mRecalcDynamicStats, "CALC");
|
||||||
|
|
||||||
|
mDrawState = 0;
|
||||||
|
esm.getHNOT (mDrawState, "DRAW");
|
||||||
|
|
||||||
|
mLevel = 1;
|
||||||
|
esm.getHNOT (mLevel, "LEVL");
|
||||||
|
|
||||||
|
mSpells.load(esm);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ESM::CreatureStats::save (ESMWriter &esm) const
|
void ESM::CreatureStats::save (ESMWriter &esm) const
|
||||||
{
|
{
|
||||||
|
|
||||||
for (int i=0; i<8; ++i)
|
for (int i=0; i<8; ++i)
|
||||||
mAttributes[i].save (esm);
|
mAttributes[i].save (esm);
|
||||||
|
|
||||||
for (int i=0; i<3; ++i)
|
for (int i=0; i<3; ++i)
|
||||||
mDynamic[i].save (esm);
|
mDynamic[i].save (esm);
|
||||||
|
|
||||||
|
if (mGoldPool)
|
||||||
|
esm.writeHNT ("GOLD", mGoldPool);
|
||||||
|
|
||||||
|
esm.writeHNT ("TIME", mTradeTime);
|
||||||
|
|
||||||
|
if (mDead)
|
||||||
|
esm.writeHNT ("DEAD", mDead);
|
||||||
|
|
||||||
|
if (mDied)
|
||||||
|
esm.writeHNT ("DIED", mDied);
|
||||||
|
|
||||||
|
if (mFriendlyHits)
|
||||||
|
esm.writeHNT ("FRHT", mFriendlyHits);
|
||||||
|
|
||||||
|
if (mTalkedTo)
|
||||||
|
esm.writeHNT ("TALK", mTalkedTo);
|
||||||
|
|
||||||
|
if (mAlarmed)
|
||||||
|
esm.writeHNT ("ALRM", mAlarmed);
|
||||||
|
|
||||||
|
if (mHostile)
|
||||||
|
esm.writeHNT ("HOST", mHostile);
|
||||||
|
|
||||||
|
if (mAttackingOrSpell)
|
||||||
|
esm.writeHNT ("ATCK", mAttackingOrSpell);
|
||||||
|
|
||||||
|
if (mKnockdown)
|
||||||
|
esm.writeHNT ("KNCK", mKnockdown);
|
||||||
|
|
||||||
|
if (mKnockdownOneFrame)
|
||||||
|
esm.writeHNT ("KNC1", mKnockdownOneFrame);
|
||||||
|
|
||||||
|
if (mKnockdownOverOneFrame)
|
||||||
|
esm.writeHNT ("KNCO", mKnockdownOverOneFrame);
|
||||||
|
|
||||||
|
if (mHitRecovery)
|
||||||
|
esm.writeHNT ("HITR", mHitRecovery);
|
||||||
|
|
||||||
|
if (mBlock)
|
||||||
|
esm.writeHNT ("BLCK", mBlock);
|
||||||
|
|
||||||
|
if (mMovementFlags)
|
||||||
|
esm.writeHNT ("MOVE", mMovementFlags);
|
||||||
|
|
||||||
|
if (mAttackStrength)
|
||||||
|
esm.writeHNT ("ASTR", mAttackStrength);
|
||||||
|
|
||||||
|
if (mFallHeight)
|
||||||
|
esm.writeHNT ("FALL", mFallHeight);
|
||||||
|
|
||||||
|
if (!mLastHitObject.empty())
|
||||||
|
esm.writeHNString ("LHIT", mLastHitObject);
|
||||||
|
|
||||||
|
if (mRecalcDynamicStats)
|
||||||
|
esm.writeHNT ("CALC", mRecalcDynamicStats);
|
||||||
|
|
||||||
|
if (mDrawState)
|
||||||
|
esm.writeHNT ("DRAW", mDrawState);
|
||||||
|
|
||||||
|
if (mLevel != 1)
|
||||||
|
esm.writeHNT ("LEVL", mLevel);
|
||||||
|
|
||||||
|
mSpells.save(esm);
|
||||||
}
|
}
|
|
@ -7,18 +7,48 @@
|
||||||
|
|
||||||
#include "statstate.hpp"
|
#include "statstate.hpp"
|
||||||
|
|
||||||
|
#include "defs.hpp"
|
||||||
|
|
||||||
|
#include "spellstate.hpp"
|
||||||
|
|
||||||
namespace ESM
|
namespace ESM
|
||||||
{
|
{
|
||||||
class ESMReader;
|
class ESMReader;
|
||||||
class ESMWriter;
|
class ESMWriter;
|
||||||
|
|
||||||
// format 0, saved games only
|
// format 0, saved games only
|
||||||
|
|
||||||
struct CreatureStats
|
struct CreatureStats
|
||||||
{
|
{
|
||||||
StatState<int> mAttributes[8];
|
StatState<int> mAttributes[8];
|
||||||
StatState<float> mDynamic[3];
|
StatState<float> mDynamic[3];
|
||||||
|
|
||||||
|
ESM::TimeStamp mTradeTime;
|
||||||
|
int mGoldPool;
|
||||||
|
|
||||||
|
bool mDead;
|
||||||
|
bool mDied;
|
||||||
|
int mFriendlyHits;
|
||||||
|
bool mTalkedTo;
|
||||||
|
bool mAlarmed;
|
||||||
|
bool mAttacked;
|
||||||
|
bool mHostile;
|
||||||
|
bool mAttackingOrSpell;
|
||||||
|
bool mKnockdown;
|
||||||
|
bool mKnockdownOneFrame;
|
||||||
|
bool mKnockdownOverOneFrame;
|
||||||
|
bool mHitRecovery;
|
||||||
|
bool mBlock;
|
||||||
|
unsigned int mMovementFlags;
|
||||||
|
float mAttackStrength;
|
||||||
|
float mFallHeight;
|
||||||
|
std::string mLastHitObject;
|
||||||
|
bool mRecalcDynamicStats;
|
||||||
|
int mDrawState;
|
||||||
|
|
||||||
|
int mLevel;
|
||||||
|
|
||||||
|
SpellState mSpells;
|
||||||
|
|
||||||
void load (ESMReader &esm);
|
void load (ESMReader &esm);
|
||||||
void save (ESMWriter &esm) const;
|
void save (ESMWriter &esm) const;
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,6 +6,12 @@
|
||||||
namespace ESM
|
namespace ESM
|
||||||
{
|
{
|
||||||
|
|
||||||
|
struct TimeStamp
|
||||||
|
{
|
||||||
|
float mHour;
|
||||||
|
int mDay;
|
||||||
|
};
|
||||||
|
|
||||||
// Pixel color value. Standard four-byte rr,gg,bb,aa format.
|
// Pixel color value. Standard four-byte rr,gg,bb,aa format.
|
||||||
typedef int32_t Color;
|
typedef int32_t Color;
|
||||||
|
|
||||||
|
@ -101,6 +107,7 @@ enum RecNameInts
|
||||||
REC_WTHR = 0x52485457,
|
REC_WTHR = 0x52485457,
|
||||||
REC_KEYS = FourCC<'K','E','Y','S'>::value,
|
REC_KEYS = FourCC<'K','E','Y','S'>::value,
|
||||||
REC_DYNA = FourCC<'D','Y','N','A'>::value,
|
REC_DYNA = FourCC<'D','Y','N','A'>::value,
|
||||||
|
REC_ASPL = FourCC<'A','S','P','L'>::value,
|
||||||
|
|
||||||
// format 1
|
// format 1
|
||||||
REC_FILT = 0x544C4946
|
REC_FILT = 0x544C4946
|
||||||
|
|
|
@ -100,6 +100,9 @@ namespace ESM
|
||||||
|
|
||||||
void ESMWriter::startSubRecord(const std::string& name)
|
void ESMWriter::startSubRecord(const std::string& name)
|
||||||
{
|
{
|
||||||
|
// Sub-record hierarchies are not properly supported in ESMReader. This should be fixed later.
|
||||||
|
assert (mRecords.size() <= 1);
|
||||||
|
|
||||||
writeName(name);
|
writeName(name);
|
||||||
RecordData rec;
|
RecordData rec;
|
||||||
rec.name = name;
|
rec.name = name;
|
||||||
|
|
|
@ -96,6 +96,7 @@ class ESMWriter
|
||||||
|
|
||||||
void startRecord(const std::string& name, uint32_t flags = 0);
|
void startRecord(const std::string& name, uint32_t flags = 0);
|
||||||
void startRecord(uint32_t name, uint32_t flags = 0);
|
void startRecord(uint32_t name, uint32_t flags = 0);
|
||||||
|
/// @note Sub-record hierarchies are not properly supported in ESMReader. This should be fixed later.
|
||||||
void startSubRecord(const std::string& name);
|
void startSubRecord(const std::string& name);
|
||||||
void endRecord(const std::string& name);
|
void endRecord(const std::string& name);
|
||||||
void endRecord(uint32_t name);
|
void endRecord(uint32_t name);
|
||||||
|
|
|
@ -36,6 +36,18 @@ void ESM::NpcStats::load (ESMReader &esm)
|
||||||
mSkills[i].mWerewolf.load (esm);
|
mSkills[i].mWerewolf.load (esm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool hasWerewolfAttributes = false;
|
||||||
|
esm.getHNOT (hasWerewolfAttributes, "HWAT");
|
||||||
|
|
||||||
|
if (hasWerewolfAttributes)
|
||||||
|
{
|
||||||
|
for (int i=0; i<8; ++i)
|
||||||
|
mWerewolfAttributes[i].load (esm);
|
||||||
|
}
|
||||||
|
|
||||||
|
mIsWerewolf = false;
|
||||||
|
esm.getHNOT (mIsWerewolf, "WOLF");
|
||||||
|
|
||||||
mBounty = 0;
|
mBounty = 0;
|
||||||
esm.getHNOT (mBounty, "BOUN");
|
esm.getHNOT (mBounty, "BOUN");
|
||||||
|
|
||||||
|
@ -48,8 +60,9 @@ void ESM::NpcStats::load (ESMReader &esm)
|
||||||
mProfit = 0;
|
mProfit = 0;
|
||||||
esm.getHNOT (mProfit, "PROF");
|
esm.getHNOT (mProfit, "PROF");
|
||||||
|
|
||||||
mAttackStrength = 0;
|
// No longer used. Now part of CreatureStats.
|
||||||
esm.getHNOT (mAttackStrength, "ASTR");
|
float attackStrength = 0;
|
||||||
|
esm.getHNOT (attackStrength, "ASTR");
|
||||||
|
|
||||||
mLevelProgress = 0;
|
mLevelProgress = 0;
|
||||||
esm.getHNOT (mLevelProgress, "LPRO");
|
esm.getHNOT (mLevelProgress, "LPRO");
|
||||||
|
@ -101,6 +114,13 @@ void ESM::NpcStats::save (ESMWriter &esm) const
|
||||||
mSkills[i].mWerewolf.save (esm);
|
mSkills[i].mWerewolf.save (esm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
esm.writeHNT ("HWAT", true);
|
||||||
|
for (int i=0; i<8; ++i)
|
||||||
|
mWerewolfAttributes[i].save (esm);
|
||||||
|
|
||||||
|
if (mIsWerewolf)
|
||||||
|
esm.writeHNT ("WOLF", mIsWerewolf);
|
||||||
|
|
||||||
if (mBounty)
|
if (mBounty)
|
||||||
esm.writeHNT ("BOUN", mBounty);
|
esm.writeHNT ("BOUN", mBounty);
|
||||||
|
|
||||||
|
@ -113,9 +133,6 @@ void ESM::NpcStats::save (ESMWriter &esm) const
|
||||||
if (mProfit)
|
if (mProfit)
|
||||||
esm.writeHNT ("PROF", mProfit);
|
esm.writeHNT ("PROF", mProfit);
|
||||||
|
|
||||||
if (mAttackStrength)
|
|
||||||
esm.writeHNT ("ASTR", mAttackStrength);
|
|
||||||
|
|
||||||
if (mLevelProgress)
|
if (mLevelProgress)
|
||||||
esm.writeHNT ("LPRO", mLevelProgress);
|
esm.writeHNT ("LPRO", mLevelProgress);
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,9 @@ namespace ESM
|
||||||
Faction();
|
Faction();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
StatState<int> mWerewolfAttributes[8];
|
||||||
|
bool mIsWerewolf;
|
||||||
|
|
||||||
std::map<std::string, Faction> mFactions;
|
std::map<std::string, Faction> mFactions;
|
||||||
int mDisposition;
|
int mDisposition;
|
||||||
Skill mSkills[27];
|
Skill mSkills[27];
|
||||||
|
@ -38,7 +41,6 @@ namespace ESM
|
||||||
int mReputation;
|
int mReputation;
|
||||||
int mWerewolfKills;
|
int mWerewolfKills;
|
||||||
int mProfit;
|
int mProfit;
|
||||||
float mAttackStrength;
|
|
||||||
int mLevelProgress;
|
int mLevelProgress;
|
||||||
int mSkillIncrease[8];
|
int mSkillIncrease[8];
|
||||||
std::vector<std::string> mUsedIds;
|
std::vector<std::string> mUsedIds;
|
||||||
|
|
|
@ -8,11 +8,13 @@ namespace ESM
|
||||||
|
|
||||||
void QuickKeys::load(ESMReader &esm)
|
void QuickKeys::load(ESMReader &esm)
|
||||||
{
|
{
|
||||||
while (esm.isNextSub("KEY_"))
|
if (esm.isNextSub("KEY_"))
|
||||||
|
esm.getSubHeader(); // no longer used, because sub-record hierachies do not work properly in esmreader
|
||||||
|
|
||||||
|
while (esm.isNextSub("TYPE"))
|
||||||
{
|
{
|
||||||
esm.getSubHeader();
|
|
||||||
int keyType;
|
int keyType;
|
||||||
esm.getHNT(keyType, "TYPE");
|
esm.getHT(keyType);
|
||||||
std::string id;
|
std::string id;
|
||||||
id = esm.getHNString("ID__");
|
id = esm.getHNString("ID__");
|
||||||
|
|
||||||
|
@ -21,21 +23,18 @@ namespace ESM
|
||||||
key.mId = id;
|
key.mId = id;
|
||||||
|
|
||||||
mKeys.push_back(key);
|
mKeys.push_back(key);
|
||||||
|
|
||||||
|
if (esm.isNextSub("KEY_"))
|
||||||
|
esm.getSubHeader(); // no longer used, because sub-record hierachies do not work properly in esmreader
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QuickKeys::save(ESMWriter &esm) const
|
void QuickKeys::save(ESMWriter &esm) const
|
||||||
{
|
{
|
||||||
const std::string recKey = "KEY_";
|
|
||||||
|
|
||||||
for (std::vector<QuickKey>::const_iterator it = mKeys.begin(); it != mKeys.end(); ++it)
|
for (std::vector<QuickKey>::const_iterator it = mKeys.begin(); it != mKeys.end(); ++it)
|
||||||
{
|
{
|
||||||
esm.startSubRecord(recKey);
|
|
||||||
|
|
||||||
esm.writeHNT("TYPE", it->mType);
|
esm.writeHNT("TYPE", it->mType);
|
||||||
esm.writeHNString("ID__", it->mId);
|
esm.writeHNString("ID__", it->mId);
|
||||||
|
|
||||||
esm.endRecord(recKey);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
66
components/esm/spellstate.cpp
Normal file
66
components/esm/spellstate.cpp
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
#include "spellstate.hpp"
|
||||||
|
|
||||||
|
#include "esmreader.hpp"
|
||||||
|
#include "esmwriter.hpp"
|
||||||
|
|
||||||
|
namespace ESM
|
||||||
|
{
|
||||||
|
|
||||||
|
void SpellState::load(ESMReader &esm)
|
||||||
|
{
|
||||||
|
while (esm.isNextSub("SPEL"))
|
||||||
|
{
|
||||||
|
std::string id = esm.getHString();
|
||||||
|
|
||||||
|
std::map<const int, float> random;
|
||||||
|
while (esm.isNextSub("INDX"))
|
||||||
|
{
|
||||||
|
int index;
|
||||||
|
esm.getHT(index);
|
||||||
|
|
||||||
|
float magnitude;
|
||||||
|
esm.getHNT(magnitude, "RAND");
|
||||||
|
|
||||||
|
random[index] = magnitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
mSpells[id] = random;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (esm.isNextSub("USED"))
|
||||||
|
{
|
||||||
|
std::string id = esm.getHString();
|
||||||
|
TimeStamp time;
|
||||||
|
esm.getHNT(time, "TIME");
|
||||||
|
|
||||||
|
mUsedPowers[id] = time;
|
||||||
|
}
|
||||||
|
|
||||||
|
mSelectedSpell = esm.getHNOString("SLCT");
|
||||||
|
}
|
||||||
|
|
||||||
|
void SpellState::save(ESMWriter &esm) const
|
||||||
|
{
|
||||||
|
for (TContainer::const_iterator it = mSpells.begin(); it != mSpells.end(); ++it)
|
||||||
|
{
|
||||||
|
esm.writeHNString("SPEL", it->first);
|
||||||
|
|
||||||
|
const std::map<const int, float>& random = it->second;
|
||||||
|
for (std::map<const int, float>::const_iterator rIt = random.begin(); rIt != random.end(); ++rIt)
|
||||||
|
{
|
||||||
|
esm.writeHNT("INDX", rIt->first);
|
||||||
|
esm.writeHNT("RAND", rIt->second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::map<std::string, TimeStamp>::const_iterator it = mUsedPowers.begin(); it != mUsedPowers.end(); ++it)
|
||||||
|
{
|
||||||
|
esm.writeHNString("USED", it->first);
|
||||||
|
esm.writeHNT("TIME", it->second);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mSelectedSpell.empty())
|
||||||
|
esm.writeHNString("SLCT", mSelectedSpell);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
29
components/esm/spellstate.hpp
Normal file
29
components/esm/spellstate.hpp
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
#ifndef OPENMW_ESM_SPELLSTATE_H
|
||||||
|
#define OPENMW_ESM_SPELLSTATE_H
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "defs.hpp"
|
||||||
|
|
||||||
|
namespace ESM
|
||||||
|
{
|
||||||
|
class ESMReader;
|
||||||
|
class ESMWriter;
|
||||||
|
|
||||||
|
struct SpellState
|
||||||
|
{
|
||||||
|
typedef std::map<std::string, std::map<const int, float> > TContainer;
|
||||||
|
TContainer mSpells;
|
||||||
|
|
||||||
|
std::map<std::string, TimeStamp> mUsedPowers;
|
||||||
|
|
||||||
|
std::string mSelectedSpell;
|
||||||
|
|
||||||
|
void load (ESMReader &esm);
|
||||||
|
void save (ESMWriter &esm) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -41,15 +41,18 @@ namespace Physic
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhysicActor::enableCollisions(bool collision)
|
void PhysicActor::enableCollisionMode(bool collision)
|
||||||
|
{
|
||||||
|
mCollisionMode = collision;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PhysicActor::enableCollisionBody(bool collision)
|
||||||
{
|
{
|
||||||
assert(mBody);
|
assert(mBody);
|
||||||
if(collision && !mCollisionMode) enableCollisionBody();
|
if(collision && !mCollisionMode) enableCollisionBody();
|
||||||
if(!collision && mCollisionMode) disableCollisionBody();
|
if(!collision && mCollisionMode) disableCollisionBody();
|
||||||
mCollisionMode = collision;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PhysicActor::setPosition(const Ogre::Vector3 &pos)
|
void PhysicActor::setPosition(const Ogre::Vector3 &pos)
|
||||||
{
|
{
|
||||||
assert(mBody);
|
assert(mBody);
|
||||||
|
|
|
@ -99,7 +99,15 @@ namespace Physic
|
||||||
*/
|
*/
|
||||||
void setRotation(const Ogre::Quaternion &quat);
|
void setRotation(const Ogre::Quaternion &quat);
|
||||||
|
|
||||||
void enableCollisions(bool collision);
|
/**
|
||||||
|
* Sets the collisionMode for this actor. If disabled, the actor can fly and clip geometry.
|
||||||
|
*/
|
||||||
|
void enableCollisionMode(bool collision);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables or disables the *external* collision body. If disabled, other actors will not collide with this actor.
|
||||||
|
*/
|
||||||
|
void enableCollisionBody(bool collision);
|
||||||
|
|
||||||
bool getCollisionMode() const
|
bool getCollisionMode() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -116,7 +116,7 @@ void ActorTracer::findGround(btCollisionObject *actor, const Ogre::Vector3 &star
|
||||||
mFraction = newTraceCallback.m_closestHitFraction;
|
mFraction = newTraceCallback.m_closestHitFraction;
|
||||||
mPlaneNormal = Ogre::Vector3(tracehitnormal.x(), tracehitnormal.y(), tracehitnormal.z());
|
mPlaneNormal = Ogre::Vector3(tracehitnormal.x(), tracehitnormal.y(), tracehitnormal.z());
|
||||||
mEndPos = (end-start)*mFraction + start;
|
mEndPos = (end-start)*mFraction + start;
|
||||||
mEndPos[2] -= 1.0f;
|
mEndPos[2] += 1.0f;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue