mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-21 09:23:53 +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), "",
|
||||
MWBase::Environment::get().getWorld()->getStore());
|
||||
|
||||
// Relates to NPC gold reset delay
|
||||
data->mNpcStats.setTradeTime(MWWorld::TimeStamp(0.0, 0));
|
||||
|
||||
data->mNpcStats.setGoldPool(gold);
|
||||
|
||||
// store
|
||||
|
|
|
@ -233,6 +233,9 @@ namespace MWGui
|
|||
|
||||
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::IntPoint cursorPosition = MyGUI::InputManager::getInstance().getMousePosition();
|
||||
float mouseX = cursorPosition.left / float(viewSize.width);
|
||||
|
|
|
@ -541,9 +541,11 @@ namespace MWGui
|
|||
|
||||
int count = object.getRefData().getCount();
|
||||
|
||||
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
||||
MWBase::Environment::get().getWorld()->breakInvisibility(player);
|
||||
|
||||
// add to player inventory
|
||||
// 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);
|
||||
// remove from world
|
||||
MWBase::Environment::get().getWorld()->deleteObject (object);
|
||||
|
|
|
@ -465,7 +465,18 @@ namespace MWGui
|
|||
|
||||
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)
|
||||
|
|
|
@ -97,14 +97,17 @@ namespace MWGui
|
|||
|
||||
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 setGlobalMapPlayerPosition (float worldX, float worldY);
|
||||
|
||||
virtual void open();
|
||||
|
||||
void onFrame(float dt) { NoDrop::onFrame(dt); }
|
||||
void onFrame(float dt);
|
||||
|
||||
/// Clear all savegame-specific data
|
||||
void clear();
|
||||
|
@ -132,6 +135,10 @@ namespace MWGui
|
|||
typedef std::pair<int, int> CellId;
|
||||
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* mEventBoxLocal;
|
||||
|
||||
|
|
|
@ -1326,9 +1326,6 @@ namespace MWGui
|
|||
|
||||
void WindowManager::updatePlayer()
|
||||
{
|
||||
unsetSelectedSpell();
|
||||
unsetSelectedWeapon();
|
||||
|
||||
mInventoryWindow->updatePlayer();
|
||||
}
|
||||
|
||||
|
@ -1425,6 +1422,14 @@ namespace MWGui
|
|||
|
||||
mQuickKeysMenu->write(writer);
|
||||
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)
|
||||
|
@ -1433,12 +1438,18 @@ namespace MWGui
|
|||
mMap->readRecord(reader, type);
|
||||
else if (type == ESM::REC_KEYS)
|
||||
mQuickKeysMenu->readRecord(reader, type);
|
||||
else if (type == ESM::REC_ASPL)
|
||||
{
|
||||
reader.getSubNameIs("ID__");
|
||||
mSelectedSpell = reader.getHString();
|
||||
}
|
||||
}
|
||||
|
||||
int WindowManager::countSavedGameRecords() const
|
||||
{
|
||||
return 1 // Global map
|
||||
+ 1; // QuickKeysMenu
|
||||
+ 1 // QuickKeysMenu
|
||||
+ (!mSelectedSpell.empty() ? 1 : 0);
|
||||
}
|
||||
|
||||
bool WindowManager::isSavingAllowed() const
|
||||
|
|
|
@ -920,9 +920,6 @@ namespace MWMechanics
|
|||
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())
|
||||
{
|
||||
++mDeathCount[cls.getId(iter->first)];
|
||||
|
@ -939,6 +936,8 @@ namespace MWMechanics
|
|||
stats.setMagicEffects(MWMechanics::MagicEffects());
|
||||
calculateCreatureStatModifiers(iter->first, 0);
|
||||
|
||||
MWBase::Environment::get().getWorld()->enableActorCollision(iter->first, false);
|
||||
|
||||
if (cls.isEssential(iter->first))
|
||||
MWBase::Environment::get().getWindowManager()->messageBox("#{sKilledEssential}");
|
||||
}
|
||||
|
|
|
@ -17,8 +17,10 @@ namespace MWMechanics
|
|||
mAttacked (false), mHostile (false),
|
||||
mAttackingOrSpell(false),
|
||||
mIsWerewolf(false),
|
||||
mFallHeight(0), mRecalcDynamicStats(false), mKnockdown(false), mKnockdownOneFrame(false), mKnockdownOverOneFrame(false), mHitRecovery(false), mBlock(false),
|
||||
mMovementFlags(0), mDrawState (DrawState_Nothing), mAttackStrength(0.f)
|
||||
mFallHeight(0), mRecalcDynamicStats(false), mKnockdown(false), mKnockdownOneFrame(false),
|
||||
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)
|
||||
mAiSettings[i] = 0;
|
||||
|
@ -348,20 +350,6 @@ namespace MWMechanics
|
|||
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)
|
||||
{
|
||||
mFallHeight += height;
|
||||
|
@ -481,20 +469,75 @@ namespace MWMechanics
|
|||
|
||||
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]);
|
||||
|
||||
for (int i=0; i<3; ++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)
|
||||
{
|
||||
for (int i=0; i<8; ++i)
|
||||
for (int i=0; i<ESM::Attribute::Length; ++i)
|
||||
mAttributes[i].readState (state.mAttributes[i]);
|
||||
|
||||
for (int i=0; i<3; ++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
|
||||
|
|
|
@ -55,15 +55,15 @@ namespace MWMechanics
|
|||
// Do we need to recalculate stats derived from attributes or other factors?
|
||||
bool mRecalcDynamicStats;
|
||||
|
||||
std::map<std::string, MWWorld::TimeStamp> mUsedPowers;
|
||||
|
||||
MWWorld::TimeStamp mTradeTime; // Relates to NPC gold reset delay
|
||||
|
||||
int mGoldPool; // the pool of merchant gold not in inventory
|
||||
|
||||
protected:
|
||||
// These two are only set by NpcStats, but they are declared in CreatureStats to prevent using virtual methods.
|
||||
bool mIsWerewolf;
|
||||
AttributeValue mWerewolfAttributes[8];
|
||||
|
||||
int mLevel;
|
||||
|
||||
public:
|
||||
|
@ -84,9 +84,6 @@ namespace MWMechanics
|
|||
/// @return total fall height
|
||||
float land();
|
||||
|
||||
bool canUsePower (const std::string& power) const;
|
||||
void usePower (const std::string& power);
|
||||
|
||||
const AttributeValue & getAttribute(int index) 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!
|
||||
enum DrawState_
|
||||
{
|
||||
DrawState_Weapon = 0,
|
||||
DrawState_Spell = 1,
|
||||
DrawState_Nothing = 2
|
||||
DrawState_Nothing = 0,
|
||||
DrawState_Weapon = 1,
|
||||
DrawState_Spell = 2
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -342,7 +342,9 @@ namespace MWMechanics
|
|||
MWWorld::ContainerStoreIterator enchantItem = inv.getSelectedEnchantItem();
|
||||
if (enchantItem != inv.end())
|
||||
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();
|
||||
}
|
||||
|
||||
|
|
|
@ -432,9 +432,9 @@ float MWMechanics::NpcStats::getTimeToStartDrowning() const
|
|||
{
|
||||
return mTimeToStartDrowning;
|
||||
}
|
||||
|
||||
void MWMechanics::NpcStats::setTimeToStartDrowning(float time)
|
||||
{
|
||||
assert(time>=0 && time<=20);
|
||||
mTimeToStartDrowning=time;
|
||||
}
|
||||
|
||||
|
@ -446,11 +446,16 @@ void MWMechanics::NpcStats::writeState (ESM::NpcStats& state) const
|
|||
|
||||
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);
|
||||
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;
|
||||
|
||||
|
@ -467,10 +472,9 @@ void MWMechanics::NpcStats::writeState (ESM::NpcStats& state) const
|
|||
state.mReputation = mReputation;
|
||||
state.mWerewolfKills = mWerewolfKills;
|
||||
state.mProfit = mProfit;
|
||||
state.mAttackStrength = mAttackStrength;
|
||||
state.mLevelProgress = mLevelProgress;
|
||||
|
||||
for (int i=0; i<8; ++i)
|
||||
for (int i=0; i<ESM::Attribute::Length; ++i)
|
||||
state.mSkillIncrease[i] = mSkillIncreases[i];
|
||||
|
||||
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;
|
||||
|
||||
for (int i=0; i<27; ++i)
|
||||
for (int i=0; i<ESM::Skill::Length; ++i)
|
||||
{
|
||||
mSkill[i].readState (state.mSkills[i].mRegular);
|
||||
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;
|
||||
mBounty = state.mBounty;
|
||||
mReputation = state.mReputation;
|
||||
mWerewolfKills = state.mWerewolfKills;
|
||||
mProfit = state.mProfit;
|
||||
mAttackStrength = state.mAttackStrength;
|
||||
mLevelProgress = state.mLevelProgress;
|
||||
|
||||
for (int i=0; i<8; ++i)
|
||||
for (int i=0; i<ESM::Attribute::Length; ++i)
|
||||
mSkillIncreases[i] = state.mSkillIncrease[i];
|
||||
|
||||
for (std::vector<std::string>::const_iterator iter (state.mUsedIds.begin());
|
||||
|
|
|
@ -31,8 +31,8 @@ namespace MWMechanics
|
|||
std::map<std::string, int> mFactionRank;
|
||||
|
||||
int mDisposition;
|
||||
SkillValue mSkill[27];
|
||||
SkillValue mWerewolfSkill[27];
|
||||
SkillValue mSkill[ESM::Skill::Length];
|
||||
SkillValue mWerewolfSkill[ESM::Skill::Length];
|
||||
int mBounty;
|
||||
std::set<std::string> mExpelled;
|
||||
std::map<std::string, int> mFactionReputation;
|
||||
|
@ -40,7 +40,6 @@ namespace MWMechanics
|
|||
int mCrimeId;
|
||||
int mWerewolfKills;
|
||||
int mProfit;
|
||||
float mAttackStrength;
|
||||
|
||||
int mLevelProgress; // 0-10
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <cstdlib>
|
||||
|
||||
#include <components/esm/loadspel.hpp>
|
||||
#include <components/esm/spellstate.hpp>
|
||||
|
||||
#include "../mwbase/environment.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);
|
||||
|
||||
std::vector<float> random;
|
||||
random.resize(spell->mEffects.mList.size());
|
||||
for (unsigned int i=0; i<random.size();++i)
|
||||
random[i] = static_cast<float> (std::rand()) / RAND_MAX;
|
||||
std::map<const int, float> random;
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
mSpells.insert (std::make_pair (Misc::StringUtils::lowerCase(spellId), random));
|
||||
}
|
||||
}
|
||||
|
@ -67,7 +77,11 @@ namespace MWMechanics
|
|||
int i=0;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -192,9 +206,60 @@ namespace MWMechanics
|
|||
for (std::vector<ESM::ENAMstruct>::const_iterator effectIt = list.mList.begin();
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 "../mwworld/ptr.hpp"
|
||||
#include "../mwworld/timestamp.hpp"
|
||||
|
||||
#include "magiceffects.hpp"
|
||||
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
struct Spell;
|
||||
|
||||
struct SpellState;
|
||||
}
|
||||
|
||||
namespace MWMechanics
|
||||
|
@ -22,21 +26,29 @@ namespace MWMechanics
|
|||
/// \brief Spell list
|
||||
///
|
||||
/// 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
|
||||
{
|
||||
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;
|
||||
|
||||
private:
|
||||
|
||||
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::map<std::string, MWWorld::TimeStamp> mUsedPowers;
|
||||
|
||||
public:
|
||||
|
||||
bool canUsePower (const std::string& power) const;
|
||||
void usePower (const std::string& power);
|
||||
|
||||
void purgeCommonDisease();
|
||||
void purgeBlightDisease();
|
||||
void purgeCorprusDisease();
|
||||
|
@ -72,6 +84,9 @@ namespace MWMechanics
|
|||
bool hasBlightDisease() 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));
|
||||
|
||||
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())
|
||||
{
|
||||
|
@ -296,7 +299,8 @@ void LocalMap::requestMap(MWWorld::CellStore* cell,
|
|||
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.
|
||||
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];
|
||||
loadFogOfWar(texturePrefix, esm);
|
||||
|
@ -338,8 +342,6 @@ Ogre::TexturePtr LocalMap::createFogOfWarTexture(const std::string &texName)
|
|||
PF_A8R8G8B8,
|
||||
TU_DYNAMIC_WRITE_ONLY);
|
||||
}
|
||||
else
|
||||
tex->unload();
|
||||
|
||||
return tex;
|
||||
}
|
||||
|
@ -351,12 +353,14 @@ void LocalMap::loadFogOfWar (const std::string& texturePrefix, ESM::FogTexture&
|
|||
Ogre::Image image;
|
||||
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";
|
||||
|
||||
Ogre::TexturePtr tex = createFogOfWarTexture(texName);
|
||||
|
||||
tex->unload();
|
||||
tex->loadImage(image);
|
||||
|
||||
// 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,
|
||||
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->setNearClipDistance(50);
|
||||
|
@ -408,6 +412,11 @@ void LocalMap::render(const float x, const float y,
|
|||
PF_R8G8B8);
|
||||
tex->getBuffer()->blit(mRenderTexture->getBuffer());
|
||||
}
|
||||
else if (force)
|
||||
{
|
||||
mRenderTarget->update();
|
||||
tex->getBuffer()->blit(mRenderTexture->getBuffer());
|
||||
}
|
||||
|
||||
mRenderingManager->enableLights(true);
|
||||
mLight->setVisible(false);
|
||||
|
|
|
@ -106,10 +106,11 @@ namespace MWRender
|
|||
float mAngle;
|
||||
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,
|
||||
const float zlow, const float zhigh,
|
||||
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
|
||||
void createFogOfWar(const std::string& texturePrefix);
|
||||
|
|
|
@ -380,6 +380,10 @@ void RenderingManager::update (float duration, bool paused)
|
|||
|
||||
mCamera->update(duration, paused);
|
||||
|
||||
Ogre::SceneNode *node = data.getBaseNode();
|
||||
Ogre::Quaternion orient = node->_getDerivedOrientation();
|
||||
mLocalMap->updatePlayer(playerPos, orient);
|
||||
|
||||
if(paused)
|
||||
return;
|
||||
|
||||
|
@ -393,10 +397,6 @@ void RenderingManager::update (float duration, bool paused)
|
|||
|
||||
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));
|
||||
|
||||
|
|
|
@ -326,6 +326,8 @@ void MWState::StateManager::loadGame (const Character *character, const Slot *sl
|
|||
|
||||
case ESM::REC_GMAP:
|
||||
case ESM::REC_KEYS:
|
||||
case ESM::REC_ASPL:
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->readRecord(reader, n.val);
|
||||
break;
|
||||
|
||||
|
|
|
@ -3,6 +3,9 @@
|
|||
|
||||
#include "class.hpp"
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/world.hpp"
|
||||
|
||||
namespace MWWorld
|
||||
{
|
||||
ActionApply::ActionApply (const Ptr& target, const std::string& id)
|
||||
|
@ -11,6 +14,8 @@ namespace MWWorld
|
|||
|
||||
void ActionApply::executeImp (const Ptr& actor)
|
||||
{
|
||||
MWBase::Environment::get().getWorld()->breakInvisibility(actor);
|
||||
|
||||
MWWorld::Class::get (getTarget()).apply (getTarget(), mId, actor);
|
||||
}
|
||||
|
||||
|
@ -22,6 +27,8 @@ namespace MWWorld
|
|||
|
||||
void ActionApplyWithSkill::executeImp (const Ptr& actor)
|
||||
{
|
||||
MWBase::Environment::get().getWorld()->breakInvisibility(actor);
|
||||
|
||||
if (MWWorld::Class::get (getTarget()).apply (getTarget(), mId, actor) && mUsageType!=-1)
|
||||
MWWorld::Class::get (getTarget()).skillUsageSucceeded (actor, mSkillIndex, mUsageType);
|
||||
}
|
||||
|
|
|
@ -199,7 +199,7 @@ void ESMStore::setUp()
|
|||
|
||||
if (!mRaces.find (player->mRace) ||
|
||||
!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;
|
||||
|
|
|
@ -87,6 +87,7 @@ namespace MWWorld
|
|||
float mMultiplier;
|
||||
};
|
||||
|
||||
// TODO: store in savegame
|
||||
typedef std::map<std::string, std::vector<EffectParams> > TEffectMagnitudes;
|
||||
TEffectMagnitudes mPermanentMagicEffectMagnitudes;
|
||||
|
||||
|
|
|
@ -626,12 +626,12 @@ namespace MWWorld
|
|||
bool cmode = act->getCollisionMode();
|
||||
if(cmode)
|
||||
{
|
||||
act->enableCollisions(false);
|
||||
act->enableCollisionMode(false);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
act->enableCollisions(true);
|
||||
act->enableCollisionMode(true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -85,7 +85,17 @@ namespace
|
|||
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);
|
||||
}
|
||||
|
||||
|
@ -197,8 +207,9 @@ namespace MWWorld
|
|||
|
||||
mRendering.updateTerrain();
|
||||
|
||||
for (CellStoreCollection::iterator active = mActiveCells.begin(); active!=mActiveCells.end(); ++active)
|
||||
mRendering.requestMap(*active);
|
||||
// Delay the map update until scripts have been given a chance to run.
|
||||
// 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);
|
||||
}
|
||||
|
@ -342,7 +353,7 @@ namespace MWWorld
|
|||
|
||||
//We need the ogre renderer and a scene node.
|
||||
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;
|
||||
MWRender::RenderingManager& mRendering;
|
||||
|
||||
bool mNeedMapUpdate;
|
||||
|
||||
void playerCellChange (CellStore *cell, const ESM::Position& position,
|
||||
bool adjustPlayerPos = true);
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
|
||||
#include "timestamp.hpp"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include <components/esm/defs.hpp>
|
||||
|
||||
namespace MWWorld
|
||||
{
|
||||
TimeStamp::TimeStamp (float hour, int day)
|
||||
|
@ -105,4 +105,18 @@ namespace MWWorld
|
|||
|
||||
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
|
||||
#define GAME_MWWORLD_TIMESTAMP_H
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
class TimeStamp;
|
||||
}
|
||||
|
||||
namespace MWWorld
|
||||
{
|
||||
/// \brief In-game time stamp
|
||||
|
@ -14,9 +19,12 @@ namespace MWWorld
|
|||
public:
|
||||
|
||||
explicit TimeStamp (float hour = 0, int day = 0);
|
||||
///< \oaram hour [0, 23)
|
||||
///< \param hour [0, 23)
|
||||
/// \param day >=0
|
||||
|
||||
explicit TimeStamp (const ESM::TimeStamp& esm);
|
||||
ESM::TimeStamp toEsm () const;
|
||||
|
||||
float getHour() const;
|
||||
|
||||
int getDay() const;
|
||||
|
|
|
@ -1491,6 +1491,9 @@ namespace MWWorld
|
|||
{
|
||||
MWWorld::LiveCellRef<ESM::Door>& ref = *it;
|
||||
|
||||
if (!ref.mData.isEnabled())
|
||||
continue;
|
||||
|
||||
if (ref.mRef.mTeleport)
|
||||
{
|
||||
World::DoorMarker newMarker;
|
||||
|
@ -1954,7 +1957,7 @@ namespace MWWorld
|
|||
{
|
||||
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)
|
||||
|
@ -2161,8 +2164,8 @@ namespace MWWorld
|
|||
// 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 (stats.canUsePower(spell->mId))
|
||||
stats.usePower(spell->mId);
|
||||
if (stats.getSpells().canUsePower(spell->mId))
|
||||
stats.getSpells().usePower(spell->mId);
|
||||
else
|
||||
{
|
||||
message = "#{sPowerAlreadyUsed}";
|
||||
|
|
|
@ -45,7 +45,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
|
||||
npcstats creaturestats weatherstate quickkeys fogstate spellstate
|
||||
)
|
||||
|
||||
add_component_dir (misc
|
||||
|
|
|
@ -8,13 +8,143 @@ void ESM::CreatureStats::load (ESMReader &esm)
|
|||
|
||||
for (int i=0; i<3; ++i)
|
||||
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
|
||||
{
|
||||
|
||||
for (int i=0; i<8; ++i)
|
||||
mAttributes[i].save (esm);
|
||||
|
||||
for (int i=0; i<3; ++i)
|
||||
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,21 +7,51 @@
|
|||
|
||||
#include "statstate.hpp"
|
||||
|
||||
#include "defs.hpp"
|
||||
|
||||
#include "spellstate.hpp"
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
class ESMReader;
|
||||
class ESMWriter;
|
||||
|
||||
// format 0, saved games only
|
||||
|
||||
struct CreatureStats
|
||||
{
|
||||
StatState<int> mAttributes[8];
|
||||
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 save (ESMWriter &esm) const;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -6,6 +6,12 @@
|
|||
namespace ESM
|
||||
{
|
||||
|
||||
struct TimeStamp
|
||||
{
|
||||
float mHour;
|
||||
int mDay;
|
||||
};
|
||||
|
||||
// Pixel color value. Standard four-byte rr,gg,bb,aa format.
|
||||
typedef int32_t Color;
|
||||
|
||||
|
@ -101,6 +107,7 @@ enum RecNameInts
|
|||
REC_WTHR = 0x52485457,
|
||||
REC_KEYS = FourCC<'K','E','Y','S'>::value,
|
||||
REC_DYNA = FourCC<'D','Y','N','A'>::value,
|
||||
REC_ASPL = FourCC<'A','S','P','L'>::value,
|
||||
|
||||
// format 1
|
||||
REC_FILT = 0x544C4946
|
||||
|
|
|
@ -100,6 +100,9 @@ namespace ESM
|
|||
|
||||
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);
|
||||
RecordData rec;
|
||||
rec.name = name;
|
||||
|
|
|
@ -96,6 +96,7 @@ class ESMWriter
|
|||
|
||||
void startRecord(const std::string& 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 endRecord(const std::string& name);
|
||||
void endRecord(uint32_t name);
|
||||
|
|
|
@ -36,6 +36,18 @@ void ESM::NpcStats::load (ESMReader &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;
|
||||
esm.getHNOT (mBounty, "BOUN");
|
||||
|
||||
|
@ -48,8 +60,9 @@ void ESM::NpcStats::load (ESMReader &esm)
|
|||
mProfit = 0;
|
||||
esm.getHNOT (mProfit, "PROF");
|
||||
|
||||
mAttackStrength = 0;
|
||||
esm.getHNOT (mAttackStrength, "ASTR");
|
||||
// No longer used. Now part of CreatureStats.
|
||||
float attackStrength = 0;
|
||||
esm.getHNOT (attackStrength, "ASTR");
|
||||
|
||||
mLevelProgress = 0;
|
||||
esm.getHNOT (mLevelProgress, "LPRO");
|
||||
|
@ -101,6 +114,13 @@ void ESM::NpcStats::save (ESMWriter &esm) const
|
|||
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)
|
||||
esm.writeHNT ("BOUN", mBounty);
|
||||
|
||||
|
@ -113,9 +133,6 @@ void ESM::NpcStats::save (ESMWriter &esm) const
|
|||
if (mProfit)
|
||||
esm.writeHNT ("PROF", mProfit);
|
||||
|
||||
if (mAttackStrength)
|
||||
esm.writeHNT ("ASTR", mAttackStrength);
|
||||
|
||||
if (mLevelProgress)
|
||||
esm.writeHNT ("LPRO", mLevelProgress);
|
||||
|
||||
|
@ -136,4 +153,4 @@ void ESM::NpcStats::save (ESMWriter &esm) const
|
|||
|
||||
if (mCrimeId != -1)
|
||||
esm.writeHNT ("CRID", mCrimeId);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,6 +31,9 @@ namespace ESM
|
|||
Faction();
|
||||
};
|
||||
|
||||
StatState<int> mWerewolfAttributes[8];
|
||||
bool mIsWerewolf;
|
||||
|
||||
std::map<std::string, Faction> mFactions;
|
||||
int mDisposition;
|
||||
Skill mSkills[27];
|
||||
|
@ -38,7 +41,6 @@ namespace ESM
|
|||
int mReputation;
|
||||
int mWerewolfKills;
|
||||
int mProfit;
|
||||
float mAttackStrength;
|
||||
int mLevelProgress;
|
||||
int mSkillIncrease[8];
|
||||
std::vector<std::string> mUsedIds;
|
||||
|
@ -52,4 +54,4 @@ namespace ESM
|
|||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -8,11 +8,13 @@ namespace 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;
|
||||
esm.getHNT(keyType, "TYPE");
|
||||
esm.getHT(keyType);
|
||||
std::string id;
|
||||
id = esm.getHNString("ID__");
|
||||
|
||||
|
@ -21,21 +23,18 @@ namespace ESM
|
|||
key.mId = id;
|
||||
|
||||
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
|
||||
{
|
||||
const std::string recKey = "KEY_";
|
||||
|
||||
for (std::vector<QuickKey>::const_iterator it = mKeys.begin(); it != mKeys.end(); ++it)
|
||||
{
|
||||
esm.startSubRecord(recKey);
|
||||
|
||||
esm.writeHNT("TYPE", it->mType);
|
||||
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);
|
||||
if(collision && !mCollisionMode) enableCollisionBody();
|
||||
if(!collision && mCollisionMode) disableCollisionBody();
|
||||
mCollisionMode = collision;
|
||||
}
|
||||
|
||||
|
||||
void PhysicActor::setPosition(const Ogre::Vector3 &pos)
|
||||
{
|
||||
assert(mBody);
|
||||
|
|
|
@ -99,7 +99,15 @@ namespace Physic
|
|||
*/
|
||||
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
|
||||
{
|
||||
|
|
|
@ -116,7 +116,7 @@ void ActorTracer::findGround(btCollisionObject *actor, const Ogre::Vector3 &star
|
|||
mFraction = newTraceCallback.m_closestHitFraction;
|
||||
mPlaneNormal = Ogre::Vector3(tracehitnormal.x(), tracehitnormal.y(), tracehitnormal.z());
|
||||
mEndPos = (end-start)*mFraction + start;
|
||||
mEndPos[2] -= 1.0f;
|
||||
mEndPos[2] += 1.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue