Reintroduce Acrobatics changes made by Glorf

Advance Acrobatics skill on jump and on landing,
apply fall damage on landing.
This commit is contained in:
Emanuel Guevel 2013-10-01 23:35:34 +02:00
parent 1363e86828
commit b8c60dabb3
6 changed files with 88 additions and 1 deletions

View file

@ -769,6 +769,34 @@ namespace MWClass
return x;
}
float Npc::getFallDamage(const MWWorld::Ptr &ptr, float fallHeight) const
{
const float fallDistanceMin = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().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(9/*jump*/)).mMagnitude;
const float fallAcroBase = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fFallAcroBase")->getFloat();
const float fallAcroMult = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fFallAcroMult")->getFloat();
const float fallDistanceBase = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fFallDistanceBase")->getFloat();
const float fallDistanceMult = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().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
{
ensureCustomData (ptr);

View file

@ -97,6 +97,9 @@ namespace MWClass
virtual float getJump(const MWWorld::Ptr &ptr) const;
///< 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;
///< Return desired movement.

View file

@ -767,10 +767,17 @@ void CharacterController::update(float duration)
}
if(sneak || inwater || flying)
{
vec.z = 0.0f;
mFallHeight = 0.0f;
}
if(!onground && !flying && !inwater)
{
// The player is in the air (either getting up —ascending part of jump— or falling).
mFallHeight = std::max(mFallHeight, mPtr.getRefData().getPosition().pos[2]);
const MWWorld::Store<ESM::GameSetting> &gmst = world->getStore().get<ESM::GameSetting>();
forcestateupdate = (mJumpState != JumpState_Falling);
@ -794,6 +801,8 @@ void CharacterController::update(float duration)
}
else if(vec.z > 0.0f && mJumpState == JumpState_None)
{
// The player has started a jump.
float z = cls.getJump(mPtr);
if(vec.x == 0 && vec.y == 0)
vec = Ogre::Vector3(0.0f, 0.0f, z);
@ -803,13 +812,49 @@ void CharacterController::update(float duration)
vec = Ogre::Vector3(lat.x, lat.y, 1.0f) * z * 0.707f;
}
//decrease fatigue by fFatigueJumpBase + (1 - normalizedEncumbrance) * fFatigueJumpMult;
// advance acrobatics
MWWorld::Class::get(mPtr).skillUsageSucceeded(mPtr, ESM::Skill::Acrobatics, 0);
// decrease fatigue
const float fatigueJumpBase = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fFatigueJumpBase")->getFloat();
const float fatigueJumpMult = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().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).getDynamic(2);
fatigue.setModified(fatigue.getModified() - fatigueDecrease, 0);
fatigue.setCurrent(fatigue.getCurrent() - fatigueDecrease);
cls.getCreatureStats(mPtr).setDynamic(2, fatigue);
}
else if(mJumpState == JumpState_Falling)
{
// The player is landing.
forcestateupdate = true;
mJumpState = JumpState_Landing;
vec.z = 0.0f;
float healthLost = cls.getFallDamage(mPtr, mFallHeight - mPtr.getRefData().getPosition().pos[2]);
if (healthLost > 0.0f)
{
// inflict fall damages
DynamicStat<float> health = cls.getCreatureStats(mPtr).getHealth();
int current = health.getCurrent();
int realHealthLost = healthLost * (1.0f - 0.25 * 1.25f /* * fatigueTerm */);
health.setModified(health.getModified() - realHealthLost, 0);
health.setCurrent(current - 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 * 1.25f /* * fatigueTerm */))
{
//TODO: actor falls over
}
}
mFallHeight = 0;
}
else
{

View file

@ -154,6 +154,9 @@ class CharacterController
float mSecondsOfSwimming;
float mSecondsOfRunning;
// used for acrobatics progress and fall damages
float mFallHeight;
std::string mAttackType; // slash, chop or thrust
void refreshCurrentAnims(CharacterState idle, CharacterState movement, bool force=false);

View file

@ -167,6 +167,11 @@ namespace MWWorld
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
{
throw std::runtime_error ("movement settings not supported by class");

View file

@ -175,6 +175,9 @@ namespace MWWorld
virtual float getJump(const MWWorld::Ptr &ptr) const;
///< 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;
///< Return desired movement.