mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-19 22:23:51 +00:00
Merge remote-tracking branch 'potatoesmaster/acrobatics'
This commit is contained in:
commit
9c4d88cd76
9 changed files with 117 additions and 1 deletions
|
@ -324,6 +324,7 @@ namespace MWBase
|
||||||
virtual void processChangedSettings (const Settings::CategorySettingVector& settings) = 0;
|
virtual void processChangedSettings (const Settings::CategorySettingVector& settings) = 0;
|
||||||
|
|
||||||
virtual bool isFlying(const MWWorld::Ptr &ptr) const = 0;
|
virtual bool isFlying(const MWWorld::Ptr &ptr) const = 0;
|
||||||
|
virtual bool isSlowFalling(const MWWorld::Ptr &ptr) const = 0;
|
||||||
virtual bool isSwimming(const MWWorld::Ptr &object) const = 0;
|
virtual bool isSwimming(const MWWorld::Ptr &object) const = 0;
|
||||||
///Is the head of the creature underwater?
|
///Is the head of the creature underwater?
|
||||||
virtual bool isSubmerged(const MWWorld::Ptr &object) const = 0;
|
virtual bool isSubmerged(const MWWorld::Ptr &object) const = 0;
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
#include <OgreSceneNode.h>
|
#include <OgreSceneNode.h>
|
||||||
|
|
||||||
|
#include <components/esm/loadmgef.hpp>
|
||||||
#include <components/esm/loadnpc.hpp>
|
#include <components/esm/loadnpc.hpp>
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
|
@ -769,6 +770,37 @@ namespace MWClass
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float Npc::getFallDamage(const MWWorld::Ptr &ptr, float fallHeight) const
|
||||||
|
{
|
||||||
|
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||||
|
const MWWorld::Store<ESM::GameSetting> &gmst = world->getStore().get<ESM::GameSetting>();
|
||||||
|
|
||||||
|
const float fallDistanceMin = gmst.find("fFallDamageDistanceMin")->getFloat();
|
||||||
|
|
||||||
|
if (fallHeight >= fallDistanceMin)
|
||||||
|
{
|
||||||
|
const float acrobaticsSkill = MWWorld::Class::get(ptr).getNpcStats (ptr).getSkill(ESM::Skill::Acrobatics).getModified();
|
||||||
|
const CustomData *npcdata = static_cast<const CustomData*>(ptr.getRefData().getCustomData());
|
||||||
|
const float jumpSpellBonus = npcdata->mNpcStats.getMagicEffects().get(MWMechanics::EffectKey(ESM::MagicEffect::Jump)).mMagnitude;
|
||||||
|
const float fallAcroBase = gmst.find("fFallAcroBase")->getFloat();
|
||||||
|
const float fallAcroMult = gmst.find("fFallAcroMult")->getFloat();
|
||||||
|
const float fallDistanceBase = gmst.find("fFallDistanceBase")->getFloat();
|
||||||
|
const float fallDistanceMult = gmst.find("fFallDistanceMult")->getFloat();
|
||||||
|
|
||||||
|
float x = fallHeight - fallDistanceMin;
|
||||||
|
x -= (1.5 * acrobaticsSkill) + jumpSpellBonus;
|
||||||
|
x = std::max(0.0f, x);
|
||||||
|
|
||||||
|
float a = fallAcroBase + fallAcroMult * (100 - acrobaticsSkill);
|
||||||
|
x = fallDistanceBase + fallDistanceMult * x;
|
||||||
|
x *= a;
|
||||||
|
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
MWMechanics::Movement& Npc::getMovementSettings (const MWWorld::Ptr& ptr) const
|
MWMechanics::Movement& Npc::getMovementSettings (const MWWorld::Ptr& ptr) const
|
||||||
{
|
{
|
||||||
ensureCustomData (ptr);
|
ensureCustomData (ptr);
|
||||||
|
|
|
@ -97,6 +97,9 @@ namespace MWClass
|
||||||
virtual float getJump(const MWWorld::Ptr &ptr) const;
|
virtual float getJump(const MWWorld::Ptr &ptr) const;
|
||||||
///< Return jump velocity (not accounting for movement)
|
///< Return jump velocity (not accounting for movement)
|
||||||
|
|
||||||
|
virtual float getFallDamage(const MWWorld::Ptr &ptr, float fallHeight) const;
|
||||||
|
///< Return amount of health points lost when falling
|
||||||
|
|
||||||
virtual MWMechanics::Movement& getMovementSettings (const MWWorld::Ptr& ptr) const;
|
virtual MWMechanics::Movement& getMovementSettings (const MWWorld::Ptr& ptr) const;
|
||||||
///< Return desired movement.
|
///< Return desired movement.
|
||||||
|
|
||||||
|
|
|
@ -767,10 +767,25 @@ void CharacterController::update(float duration)
|
||||||
}
|
}
|
||||||
|
|
||||||
if(sneak || inwater || flying)
|
if(sneak || inwater || flying)
|
||||||
|
{
|
||||||
vec.z = 0.0f;
|
vec.z = 0.0f;
|
||||||
|
mFallHeight = mPtr.getRefData().getPosition().pos[2];
|
||||||
|
}
|
||||||
|
|
||||||
if(!onground && !flying && !inwater)
|
if(!onground && !flying && !inwater)
|
||||||
{
|
{
|
||||||
|
// The player is in the air (either getting up —ascending part of jump— or falling).
|
||||||
|
|
||||||
|
if (world->isSlowFalling(mPtr))
|
||||||
|
{
|
||||||
|
// SlowFalling spell effect is active, do not keep previous fall height
|
||||||
|
mFallHeight = mPtr.getRefData().getPosition().pos[2];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mFallHeight = std::max(mFallHeight, mPtr.getRefData().getPosition().pos[2]);
|
||||||
|
}
|
||||||
|
|
||||||
const MWWorld::Store<ESM::GameSetting> &gmst = world->getStore().get<ESM::GameSetting>();
|
const MWWorld::Store<ESM::GameSetting> &gmst = world->getStore().get<ESM::GameSetting>();
|
||||||
|
|
||||||
forcestateupdate = (mJumpState != JumpState_Falling);
|
forcestateupdate = (mJumpState != JumpState_Falling);
|
||||||
|
@ -794,6 +809,8 @@ void CharacterController::update(float duration)
|
||||||
}
|
}
|
||||||
else if(vec.z > 0.0f && mJumpState == JumpState_None)
|
else if(vec.z > 0.0f && mJumpState == JumpState_None)
|
||||||
{
|
{
|
||||||
|
// The player has started a jump.
|
||||||
|
|
||||||
float z = cls.getJump(mPtr);
|
float z = cls.getJump(mPtr);
|
||||||
if(vec.x == 0 && vec.y == 0)
|
if(vec.x == 0 && vec.y == 0)
|
||||||
vec = Ogre::Vector3(0.0f, 0.0f, z);
|
vec = Ogre::Vector3(0.0f, 0.0f, z);
|
||||||
|
@ -803,13 +820,49 @@ void CharacterController::update(float duration)
|
||||||
vec = Ogre::Vector3(lat.x, lat.y, 1.0f) * z * 0.707f;
|
vec = Ogre::Vector3(lat.x, lat.y, 1.0f) * z * 0.707f;
|
||||||
}
|
}
|
||||||
|
|
||||||
//decrease fatigue by fFatigueJumpBase + (1 - normalizedEncumbrance) * fFatigueJumpMult;
|
// advance acrobatics
|
||||||
|
cls.skillUsageSucceeded(mPtr, ESM::Skill::Acrobatics, 0);
|
||||||
|
|
||||||
|
// decrease fatigue
|
||||||
|
const MWWorld::Store<ESM::GameSetting> &gmst = world->getStore().get<ESM::GameSetting>();
|
||||||
|
const float fatigueJumpBase = gmst.find("fFatigueJumpBase")->getFloat();
|
||||||
|
const float fatigueJumpMult = gmst.find("fFatigueJumpMult")->getFloat();
|
||||||
|
const float normalizedEncumbrance = cls.getEncumbrance(mPtr) / cls.getCapacity(mPtr);
|
||||||
|
const int fatigueDecrease = fatigueJumpBase + (1 - normalizedEncumbrance) * fatigueJumpMult;
|
||||||
|
DynamicStat<float> fatigue = cls.getCreatureStats(mPtr).getFatigue();
|
||||||
|
fatigue.setCurrent(fatigue.getCurrent() - fatigueDecrease);
|
||||||
|
cls.getCreatureStats(mPtr).setFatigue(fatigue);
|
||||||
}
|
}
|
||||||
else if(mJumpState == JumpState_Falling)
|
else if(mJumpState == JumpState_Falling)
|
||||||
{
|
{
|
||||||
|
// The player is landing.
|
||||||
|
|
||||||
forcestateupdate = true;
|
forcestateupdate = true;
|
||||||
mJumpState = JumpState_Landing;
|
mJumpState = JumpState_Landing;
|
||||||
vec.z = 0.0f;
|
vec.z = 0.0f;
|
||||||
|
|
||||||
|
float healthLost = cls.getFallDamage(mPtr, mFallHeight - mPtr.getRefData().getPosition().pos[2]);
|
||||||
|
if (healthLost > 0.0f)
|
||||||
|
{
|
||||||
|
const float fatigueTerm = cls.getCreatureStats(mPtr).getFatigueTerm();
|
||||||
|
|
||||||
|
// inflict fall damages
|
||||||
|
DynamicStat<float> health = cls.getCreatureStats(mPtr).getHealth();
|
||||||
|
int realHealthLost = healthLost * (1.0f - 0.25 * fatigueTerm);
|
||||||
|
health.setCurrent(health.getCurrent() - realHealthLost);
|
||||||
|
cls.getCreatureStats(mPtr).setHealth(health);
|
||||||
|
|
||||||
|
// report acrobatics progression
|
||||||
|
cls.skillUsageSucceeded(mPtr, ESM::Skill::Acrobatics, 1);
|
||||||
|
|
||||||
|
const float acrobaticsSkill = cls.getNpcStats(mPtr).getSkill(ESM::Skill::Acrobatics).getModified();
|
||||||
|
if (healthLost > (acrobaticsSkill * fatigueTerm))
|
||||||
|
{
|
||||||
|
//TODO: actor falls over
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mFallHeight = mPtr.getRefData().getPosition().pos[2];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
#include <OgreVector3.h>
|
#include <OgreVector3.h>
|
||||||
|
|
||||||
|
#include <components/esm/loadmgef.hpp>
|
||||||
|
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
|
|
||||||
namespace MWWorld
|
namespace MWWorld
|
||||||
|
@ -154,6 +156,9 @@ class CharacterController
|
||||||
float mSecondsOfSwimming;
|
float mSecondsOfSwimming;
|
||||||
float mSecondsOfRunning;
|
float mSecondsOfRunning;
|
||||||
|
|
||||||
|
// used for acrobatics progress and fall damages
|
||||||
|
float mFallHeight;
|
||||||
|
|
||||||
std::string mAttackType; // slash, chop or thrust
|
std::string mAttackType; // slash, chop or thrust
|
||||||
|
|
||||||
void refreshCurrentAnims(CharacterState idle, CharacterState movement, bool force=false);
|
void refreshCurrentAnims(CharacterState idle, CharacterState movement, bool force=false);
|
||||||
|
|
|
@ -167,6 +167,11 @@ namespace MWWorld
|
||||||
throw std::runtime_error ("class does not support enchanting");
|
throw std::runtime_error ("class does not support enchanting");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float Class::getFallDamage(const MWWorld::Ptr &ptr, float fallHeight) const
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
MWMechanics::Movement& Class::getMovementSettings (const Ptr& ptr) const
|
MWMechanics::Movement& Class::getMovementSettings (const Ptr& ptr) const
|
||||||
{
|
{
|
||||||
throw std::runtime_error ("movement settings not supported by class");
|
throw std::runtime_error ("movement settings not supported by class");
|
||||||
|
|
|
@ -175,6 +175,9 @@ namespace MWWorld
|
||||||
virtual float getJump(const MWWorld::Ptr &ptr) const;
|
virtual float getJump(const MWWorld::Ptr &ptr) const;
|
||||||
///< Return jump velocity (not accounting for movement)
|
///< Return jump velocity (not accounting for movement)
|
||||||
|
|
||||||
|
virtual float getFallDamage(const MWWorld::Ptr &ptr, float fallHeight) const;
|
||||||
|
///< Return amount of health points lost when falling
|
||||||
|
|
||||||
virtual MWMechanics::Movement& getMovementSettings (const Ptr& ptr) const;
|
virtual MWMechanics::Movement& getMovementSettings (const Ptr& ptr) const;
|
||||||
///< Return desired movement.
|
///< Return desired movement.
|
||||||
|
|
||||||
|
|
|
@ -1582,6 +1582,19 @@ namespace MWWorld
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
World::isSlowFalling(const MWWorld::Ptr &ptr) const
|
||||||
|
{
|
||||||
|
if(!ptr.getClass().isActor())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const MWMechanics::CreatureStats &stats = ptr.getClass().getCreatureStats(ptr);
|
||||||
|
if(stats.getMagicEffects().get(MWMechanics::EffectKey(ESM::MagicEffect::SlowFall)).mMagnitude > 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool World::isSubmerged(const MWWorld::Ptr &object) const
|
bool World::isSubmerged(const MWWorld::Ptr &object) const
|
||||||
{
|
{
|
||||||
float *fpos = object.getRefData().getPosition().pos;
|
float *fpos = object.getRefData().getPosition().pos;
|
||||||
|
|
|
@ -355,6 +355,7 @@ namespace MWWorld
|
||||||
virtual void processChangedSettings(const Settings::CategorySettingVector& settings);
|
virtual void processChangedSettings(const Settings::CategorySettingVector& settings);
|
||||||
|
|
||||||
virtual bool isFlying(const MWWorld::Ptr &ptr) const;
|
virtual bool isFlying(const MWWorld::Ptr &ptr) const;
|
||||||
|
virtual bool isSlowFalling(const MWWorld::Ptr &ptr) const;
|
||||||
///Is the head of the creature underwater?
|
///Is the head of the creature underwater?
|
||||||
virtual bool isSubmerged(const MWWorld::Ptr &object) const;
|
virtual bool isSubmerged(const MWWorld::Ptr &object) const;
|
||||||
virtual bool isSwimming(const MWWorld::Ptr &object) const;
|
virtual bool isSwimming(const MWWorld::Ptr &object) const;
|
||||||
|
|
Loading…
Reference in a new issue