From e1a1530774bdb21bd2314b9bd2e48947cf198933 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Fri, 15 Feb 2013 01:27:57 -0800 Subject: [PATCH] Better implement Npc::getSpeed --- apps/openmw/mwclass/npc.cpp | 84 +++++++++++++++++++++++++++++++++++-- apps/openmw/mwclass/npc.hpp | 17 ++++++++ 2 files changed, 98 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 3666d9d6b..d135d2683 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -55,9 +55,30 @@ namespace MWClass { void Npc::ensureCustomData (const MWWorld::Ptr& ptr) const { + static bool inited = false; + if(!inited) + { + const MWBase::World *world = MWBase::Environment::get().getWorld(); + const MWWorld::Store &gmst = world->getStore().get(); + + fMinWalkSpeed = gmst.find("fMinWalkSpeed"); + fMaxWalkSpeed = gmst.find("fMaxWalkSpeed"); + fEncumberedMoveEffect = gmst.find("fEncumberedMoveEffect"); + fSneakSpeedMultiplier = gmst.find("fSneakSpeedMultiplier"); + fAthleticsRunBonus = gmst.find("fAthleticsRunBonus"); + fBaseRunMultiplier = gmst.find("fBaseRunMultiplier"); + fMinFlySpeed = gmst.find("fMinFlySpeed"); + fMaxFlySpeed = gmst.find("fMaxFlySpeed"); + fSwimRunBase = gmst.find("fSwimRunBase"); + fSwimRunAthleticsMult = gmst.find("fSwimRunAthleticsMult"); + // Added in Tribunal/Bloodmoon, may not exist + fWereWolfRunMult = gmst.search("fWereWolfRunMult"); + + inited = true; + } if (!ptr.getRefData().getCustomData()) { - std::auto_ptr data (new CustomData); + std::auto_ptr data(new CustomData); MWWorld::LiveCellRef *ref = ptr.get(); @@ -297,9 +318,54 @@ namespace MWClass return false; } - float Npc::getSpeed (const MWWorld::Ptr& ptr) const + float Npc::getSpeed(const MWWorld::Ptr& ptr) const { - return getStance (ptr, Run) ? 600 : 300; // TODO calculate these values from stats + const MWBase::World *world = MWBase::Environment::get().getWorld(); + const CustomData *npcdata = static_cast(ptr.getRefData().getCustomData()); + const float normalizedEncumbrance = Npc::getEncumbrance(ptr) / Npc::getCapacity(ptr); + + float walkSpeed = fMinWalkSpeed->getFloat() + 0.01f*npcdata->mCreatureStats.getAttribute(ESM::Attribute::Speed).getModified()* + (fMaxWalkSpeed->getFloat() - fMinWalkSpeed->getFloat()); + walkSpeed *= 1.0f - fEncumberedMoveEffect->getFloat()*normalizedEncumbrance; + walkSpeed = std::max(0.0f, walkSpeed); + if(Npc::getStance(ptr, Sneak, false)) + walkSpeed *= fSneakSpeedMultiplier->getFloat(); + float runSpeed = walkSpeed*(0.01f * npcdata->mNpcStats.getSkill(ESM::Skill::Athletics).getModified() * + fAthleticsRunBonus->getFloat() + fBaseRunMultiplier->getFloat()); + + float moveSpeed; + if(normalizedEncumbrance > 1.0f) + moveSpeed = 0.0f; + else if(0/*world->isFlying(ptr)*/) + { + float flySpeed = 0.01f*(npcdata->mCreatureStats.getAttribute(ESM::Attribute::Speed).getModified() + + 0.0f/*levitationBonus*/); + flySpeed = fMinFlySpeed->getFloat() + flySpeed*(fMaxFlySpeed->getFloat() - fMinFlySpeed->getFloat()); + flySpeed *= 1.0f - fEncumberedMoveEffect->getFloat() * normalizedEncumbrance; + flySpeed = std::max(0.0f, flySpeed); + moveSpeed = flySpeed; + } + else if(world->isSwimming(ptr)) + { + float swimSpeed = walkSpeed; + if(Npc::getStance(ptr, Run, false)) + swimSpeed = runSpeed; + swimSpeed *= 1.0f + 0.01f * 0.0f/*swiftSwimBonus*/; + swimSpeed *= fSwimRunBase->getFloat() + 0.01f*npcdata->mNpcStats.getSkill(ESM::Skill::Athletics).getModified()* + fSwimRunAthleticsMult->getFloat(); + moveSpeed = swimSpeed; + } + else if(Npc::getStance(ptr, Run, false)) + moveSpeed = runSpeed; + else + moveSpeed = walkSpeed; + + if(getMovementSettings(ptr).mLeftRight != 0 && getMovementSettings(ptr).mForwardBackward == 0) + moveSpeed *= 0.75f; + if(npcdata->mNpcStats.isWerewolf() && Npc::getStance(ptr, Run, false)) + moveSpeed *= fWereWolfRunMult->getFloat(); + + return moveSpeed; } MWMechanics::Movement& Npc::getMovementSettings (const MWWorld::Ptr& ptr) const @@ -416,4 +482,16 @@ namespace MWClass return MWWorld::Ptr(&cell.mNpcs.insert(*ref), &cell); } + + const ESM::GameSetting *Npc::fMinWalkSpeed; + const ESM::GameSetting *Npc::fMaxWalkSpeed; + const ESM::GameSetting *Npc::fEncumberedMoveEffect; + const ESM::GameSetting *Npc::fSneakSpeedMultiplier; + const ESM::GameSetting *Npc::fAthleticsRunBonus; + const ESM::GameSetting *Npc::fBaseRunMultiplier; + const ESM::GameSetting *Npc::fMinFlySpeed; + const ESM::GameSetting *Npc::fMaxFlySpeed; + const ESM::GameSetting *Npc::fSwimRunBase; + const ESM::GameSetting *Npc::fSwimRunAthleticsMult; + const ESM::GameSetting *Npc::fWereWolfRunMult; } diff --git a/apps/openmw/mwclass/npc.hpp b/apps/openmw/mwclass/npc.hpp index 20c2da4b1..a97e4c42e 100644 --- a/apps/openmw/mwclass/npc.hpp +++ b/apps/openmw/mwclass/npc.hpp @@ -3,6 +3,11 @@ #include "../mwworld/class.hpp" +namespace ESM +{ + class GameSetting; +} + namespace MWClass { class Npc : public MWWorld::Class @@ -12,6 +17,18 @@ namespace MWClass virtual MWWorld::Ptr copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const; + static const ESM::GameSetting *fMinWalkSpeed; + static const ESM::GameSetting *fMaxWalkSpeed; + static const ESM::GameSetting *fEncumberedMoveEffect; + static const ESM::GameSetting *fSneakSpeedMultiplier; + static const ESM::GameSetting *fAthleticsRunBonus; + static const ESM::GameSetting *fBaseRunMultiplier; + static const ESM::GameSetting *fMinFlySpeed; + static const ESM::GameSetting *fMaxFlySpeed; + static const ESM::GameSetting *fSwimRunBase; + static const ESM::GameSetting *fSwimRunAthleticsMult; + static const ESM::GameSetting *fWereWolfRunMult; + public: virtual std::string getId (const MWWorld::Ptr& ptr) const;