From add3cd6456c07fc149bfc5e3aefdfd6507bca7e1 Mon Sep 17 00:00:00 2001 From: Glorf Date: Tue, 30 Apr 2013 18:22:59 +0200 Subject: [PATCH 1/5] Advance acrobatics on jump --- apps/openmw/mwmechanics/character.cpp | 13 ++++++++++--- apps/openmw/mwmechanics/character.hpp | 1 + 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index b82fc4dc56..c762e6d14d 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -104,7 +104,8 @@ static void getStateInfo(CharacterState state, std::string *group) CharacterController::CharacterController(const MWWorld::Ptr &ptr, MWRender::Animation *anim, CharacterState state, bool loop) - : mPtr(ptr), mAnimation(anim), mCharState(state), mSkipAnim(false), mMovingAnim(false), mSecondsOfRunning(0), mSecondsOfSwimming(0) + : mPtr(ptr), mAnimation(anim), mCharState(state), mSkipAnim(false), mMovingAnim(false), + mSecondsOfRunning(0), mSecondsOfSwimming(0), mSecondsOfFalling(0) { if(!mAnimation) return; @@ -176,10 +177,16 @@ void CharacterController::update(float duration, Movement &movement) } } - /* FIXME: The state should be set to Jump, and X/Y movement should be disallowed except - * for the initial thrust (which would be carried by "physics" until landing). */ + // FIXME: X/Y movement should be disallowed except for the initial thrust (which would be carried by "physics" until landing). if(onground && vec.z > 0.0f) { + //Advance acrobatics on jump + if(getState()!=CharState_Jump) + { + setState(CharState_Jump, true); + MWWorld::Class::get(mPtr).skillUsageSucceeded(mPtr, ESM::Skill::Acrobatics, 0); + } + float x = cls.getJump(mPtr); if(vec.x == 0 && vec.y == 0) diff --git a/apps/openmw/mwmechanics/character.hpp b/apps/openmw/mwmechanics/character.hpp index 4ee217d119..7dfd5d0042 100644 --- a/apps/openmw/mwmechanics/character.hpp +++ b/apps/openmw/mwmechanics/character.hpp @@ -82,6 +82,7 @@ class CharacterController // counted for skill increase float mSecondsOfSwimming; float mSecondsOfRunning; + float mSecondsOfFalling; bool mMovingAnim; From 5a8c1661be8d688c6fcd7bd6cb65c85dbbe7eee4 Mon Sep 17 00:00:00 2001 From: Glorf Date: Tue, 30 Apr 2013 20:42:02 +0200 Subject: [PATCH 2/5] Jump acrobatics working, started falling acrobatics implementation --- apps/openmw/mwclass/npc.cpp | 28 +++++++++++++++++++++++++++ apps/openmw/mwclass/npc.hpp | 3 +++ apps/openmw/mwmechanics/character.cpp | 25 +++++++++++++++++++++++- apps/openmw/mwmechanics/character.hpp | 3 ++- apps/openmw/mwworld/class.cpp | 5 +++++ apps/openmw/mwworld/class.hpp | 3 +++ 6 files changed, 65 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index ea49ae4a4c..a90b859558 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -470,6 +470,34 @@ namespace MWClass return x; } + float Npc::getFallDamage(const MWWorld::Ptr &ptr, float fallHeight) const + { + const float fallDistanceMin = MWBase::Environment::get().getWorld()->getStore().get().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(ptr.getRefData().getCustomData()); + const float jumpSpellBonus = npcdata->mCreatureStats.getMagicEffects().get(MWMechanics::EffectKey(9/*jump*/)).mMagnitude; + const float fallAcroBase = MWBase::Environment::get().getWorld()->getStore().get().find ("fFallAcroBase")->getFloat(); + const float fallAcroMult = MWBase::Environment::get().getWorld()->getStore().get().find ("fFallAcroMult")->getFloat(); + const float fallDistanceBase = MWBase::Environment::get().getWorld()->getStore().get().find ("fFallDistanceBase")->getFloat(); + const float fallDistanceMult = MWBase::Environment::get().getWorld()->getStore().get().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); diff --git a/apps/openmw/mwclass/npc.hpp b/apps/openmw/mwclass/npc.hpp index d1a9158fdf..47d32d88f6 100644 --- a/apps/openmw/mwclass/npc.hpp +++ b/apps/openmw/mwclass/npc.hpp @@ -91,6 +91,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. diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index c762e6d14d..9a8e34bb73 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -31,6 +31,8 @@ #include "../mwworld/player.hpp" #include "../mwworld/class.hpp" +#include "../mwmechanics/stat.hpp" +#include "../mwmechanics/creaturestats.hpp" namespace MWMechanics { @@ -105,7 +107,7 @@ static void getStateInfo(CharacterState state, std::string *group) CharacterController::CharacterController(const MWWorld::Ptr &ptr, MWRender::Animation *anim, CharacterState state, bool loop) : mPtr(ptr), mAnimation(anim), mCharState(state), mSkipAnim(false), mMovingAnim(false), - mSecondsOfRunning(0), mSecondsOfSwimming(0), mSecondsOfFalling(0) + mSecondsOfRunning(0), mSecondsOfSwimming(0), mHighestPosition(0) { if(!mAnimation) return; @@ -200,8 +202,29 @@ void CharacterController::update(float duration, Movement &movement) movement.mPosition[2] += x * 0.707f * duration; } + //To calculate how much player will fall down + if(movement.mPosition[2] > mHighestPosition) + mHighestPosition = movement.mPosition[2]; + //decrease fatigue by fFatigueJumpBase + (1 - normalizedEncumbrance) * fFatigueJumpMult; } + else if(vec.z==0.0f && getState()==CharState_Jump) + { + float healthLost = cls.getFallDamage(mPtr, mHighestPosition); + + if(healthLost>0.0f) + { + DynamicStat health = cls.getCreatureStats(mPtr).getHealth(); + int fatigue = MWWorld::Class::get (mPtr).getCreatureStats (mPtr).getFatigue().getBase(); + int iHealth = health.getBase(); + health.setBase (iHealth-(healthLost * (1 - (0.25 * fatigue)))); + cls.getCreatureStats(mPtr).setHealth (health); + MWWorld::Class::get(mPtr).skillUsageSucceeded(mPtr, ESM::Skill::Acrobatics, 1); + } + + setState(CharState_Idle, true); + mHighestPosition=0; + } if(std::abs(vec.x/2.0f) > std::abs(vec.y) && speed > 0.0f) { diff --git a/apps/openmw/mwmechanics/character.hpp b/apps/openmw/mwmechanics/character.hpp index 7dfd5d0042..460141880c 100644 --- a/apps/openmw/mwmechanics/character.hpp +++ b/apps/openmw/mwmechanics/character.hpp @@ -82,7 +82,8 @@ class CharacterController // counted for skill increase float mSecondsOfSwimming; float mSecondsOfRunning; - float mSecondsOfFalling; + + float mHighestPosition; bool mMovingAnim; diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index 03a55c7f05..db798537ee 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -132,6 +132,11 @@ namespace MWWorld return 0; } + float Class::getFallDamage(const MWWorld::Ptr &ptr, float fallHeight) const + { + return 0; + } + float Class::getEnchantmentPoints (const MWWorld::Ptr& ptr) const { throw std::runtime_error ("class does not support enchanting"); diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index e203fedc3a..3901ea830f 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -146,6 +146,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. From d30e43784aab1d202c3a9457150b705a8ee84cda Mon Sep 17 00:00:00 2001 From: Glorf Date: Tue, 30 Apr 2013 23:39:56 +0200 Subject: [PATCH 3/5] Fatigue decrease when jumping, live decrease when falling --- apps/openmw/mwmechanics/character.cpp | 29 ++++++++++++++++++--------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 9a8e34bb73..1b8ed08686 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -156,6 +156,10 @@ void CharacterController::update(float duration, Movement &movement) const Ogre::Vector3 &rot = cls.getRotationVector(mPtr); speed = cls.getSpeed(mPtr); + //To calculate how much player will fall down + if(movement.mPosition[2] > mHighestPosition) + mHighestPosition = movement.mPosition[2]; + // advance athletics if (vec.squaredLength() > 0 && mPtr == MWBase::Environment::get().getWorld()->getPlayer().getPlayer()) { @@ -182,11 +186,20 @@ void CharacterController::update(float duration, Movement &movement) // FIXME: X/Y movement should be disallowed except for the initial thrust (which would be carried by "physics" until landing). if(onground && vec.z > 0.0f) { - //Advance acrobatics on jump + //Advance acrobatics on jump, decrease fatigue if(getState()!=CharState_Jump) { setState(CharState_Jump, true); MWWorld::Class::get(mPtr).skillUsageSucceeded(mPtr, ESM::Skill::Acrobatics, 0); + + const float normalizedEncumbrance = cls.getEncumbrance(mPtr) / cls.getCapacity(mPtr); + const float fatigueJumpBase = MWBase::Environment::get().getWorld()->getStore().get().find ("fFatigueJumpBase")->getFloat(); + const float fatigueJumpMult = MWBase::Environment::get().getWorld()->getStore().get().find ("fFatigueJumpMult")->getFloat(); + DynamicStat fatigue = cls.getCreatureStats(mPtr).getDynamic(2); + int current = fatigue.getCurrent(); + fatigue.setModified(fatigue.getModified()-(fatigueJumpBase + ((1 - normalizedEncumbrance) * fatigueJumpMult)), 0); + fatigue.setCurrent(current-(fatigueJumpBase + ((1 - normalizedEncumbrance) * fatigueJumpMult))); + cls.getCreatureStats(mPtr).setDynamic (2, fatigue); } float x = cls.getJump(mPtr); @@ -201,14 +214,9 @@ void CharacterController::update(float duration, Movement &movement) //movement += Ogre::Vector3(lat.x, lat.y, 1.0f) * x * 0.707f * duration; movement.mPosition[2] += x * 0.707f * duration; } - - //To calculate how much player will fall down - if(movement.mPosition[2] > mHighestPosition) - mHighestPosition = movement.mPosition[2]; - - //decrease fatigue by fFatigueJumpBase + (1 - normalizedEncumbrance) * fFatigueJumpMult; } - else if(vec.z==0.0f && getState()==CharState_Jump) + + if(vec.z<=0.0f && getState()==CharState_Jump) { float healthLost = cls.getFallDamage(mPtr, mHighestPosition); @@ -216,8 +224,9 @@ void CharacterController::update(float duration, Movement &movement) { DynamicStat health = cls.getCreatureStats(mPtr).getHealth(); int fatigue = MWWorld::Class::get (mPtr).getCreatureStats (mPtr).getFatigue().getBase(); - int iHealth = health.getBase(); - health.setBase (iHealth-(healthLost * (1 - (0.25 * fatigue)))); + int current = health.getCurrent(); + health.setModified (health.getModified()-(healthLost * (1 - (0.25 * fatigue))), 0); + health.setCurrent (current-(healthLost * (1 - (0.25 * fatigue)))); cls.getCreatureStats(mPtr).setHealth (health); MWWorld::Class::get(mPtr).skillUsageSucceeded(mPtr, ESM::Skill::Acrobatics, 1); } From 236ec3409fc02a187830c2f4ae9b1cd664d9b991 Mon Sep 17 00:00:00 2001 From: Glorf Date: Wed, 1 May 2013 12:21:59 +0200 Subject: [PATCH 4/5] Finished acrobatics --- apps/openmw/mwbase/world.hpp | 1 + apps/openmw/mwmechanics/character.cpp | 64 ++++++++++++++++----------- apps/openmw/mwmechanics/character.hpp | 3 +- apps/openmw/mwworld/worldimp.cpp | 7 +++ apps/openmw/mwworld/worldimp.hpp | 1 + libs/openengine/bullet/physic.cpp | 2 +- 6 files changed, 50 insertions(+), 28 deletions(-) diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index a3b9d2cf2b..0cf71ed8eb 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -314,6 +314,7 @@ namespace MWBase virtual bool isSwimming(const MWWorld::Ptr &object) const = 0; virtual bool isUnderwater(const MWWorld::Ptr::CellStore* cell, const Ogre::Vector3 &pos) const = 0; virtual bool isOnGround(const MWWorld::Ptr &ptr) const = 0; + virtual bool isGravity(const MWWorld::Ptr &ptr) const = 0; virtual void togglePOV() = 0; virtual void togglePreviewMode(bool enable) = 0; diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 1b8ed08686..a24d7daebc 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -33,6 +33,7 @@ #include "../mwmechanics/stat.hpp" #include "../mwmechanics/creaturestats.hpp" +#include "../mwmechanics/npcstats.hpp" namespace MWMechanics { @@ -107,7 +108,7 @@ static void getStateInfo(CharacterState state, std::string *group) CharacterController::CharacterController(const MWWorld::Ptr &ptr, MWRender::Animation *anim, CharacterState state, bool loop) : mPtr(ptr), mAnimation(anim), mCharState(state), mSkipAnim(false), mMovingAnim(false), - mSecondsOfRunning(0), mSecondsOfSwimming(0), mHighestPosition(0) + mSecondsOfRunning(0), mSecondsOfSwimming(0), mFallDistance(0), mLastHeight(0) { if(!mAnimation) return; @@ -149,6 +150,7 @@ void CharacterController::update(float duration, Movement &movement) const MWWorld::Class &cls = MWWorld::Class::get(mPtr); bool onground = world->isOnGround(mPtr); + bool gravity = world->isGravity(mPtr); bool inwater = world->isSwimming(mPtr); bool isrunning = cls.getStance(mPtr, MWWorld::Class::Run); bool sneak = cls.getStance(mPtr, MWWorld::Class::Sneak); @@ -156,9 +158,36 @@ void CharacterController::update(float duration, Movement &movement) const Ogre::Vector3 &rot = cls.getRotationVector(mPtr); speed = cls.getSpeed(mPtr); - //To calculate how much player will fall down - if(movement.mPosition[2] > mHighestPosition) - mHighestPosition = movement.mPosition[2]; + //player is falling down + if(!onground && gravity && mLastHeight>mPtr.getRefData().getPosition().pos[2]) + mFallDistance+=(mLastHeight-mPtr.getRefData().getPosition().pos[2]); + + //player just finished falling + if(onground && gravity && mFallDistance>0) + { + float healthLost = cls.getFallDamage(mPtr, mFallDistance); + + if(healthLost>0.0f) + { + DynamicStat health = cls.getCreatureStats(mPtr).getHealth(); + int current = health.getCurrent(); + float realHealthLost = healthLost * (1.0f - (0.25 * 1.25f/*fatigueTerm*/)); + health.setModified (health.getModified()-static_cast(realHealthLost), 0); + health.setCurrent (current-static_cast(realHealthLost)); + cls.getCreatureStats(mPtr).setHealth (health); + MWWorld::Class::get(mPtr).skillUsageSucceeded(mPtr, ESM::Skill::Acrobatics, 1); + std::cout< 0 && mPtr == MWBase::Environment::get().getWorld()->getPlayer().getPlayer()) @@ -184,7 +213,7 @@ void CharacterController::update(float duration, Movement &movement) } // FIXME: X/Y movement should be disallowed except for the initial thrust (which would be carried by "physics" until landing). - if(onground && vec.z > 0.0f) + if(onground && gravity && vec.z > 0.0f) { //Advance acrobatics on jump, decrease fatigue if(getState()!=CharState_Jump) @@ -197,8 +226,8 @@ void CharacterController::update(float duration, Movement &movement) const float fatigueJumpMult = MWBase::Environment::get().getWorld()->getStore().get().find ("fFatigueJumpMult")->getFloat(); DynamicStat fatigue = cls.getCreatureStats(mPtr).getDynamic(2); int current = fatigue.getCurrent(); - fatigue.setModified(fatigue.getModified()-(fatigueJumpBase + ((1 - normalizedEncumbrance) * fatigueJumpMult)), 0); - fatigue.setCurrent(current-(fatigueJumpBase + ((1 - normalizedEncumbrance) * fatigueJumpMult))); + fatigue.setModified(fatigue.getModified()-static_cast(fatigueJumpBase + ((1 - normalizedEncumbrance) * fatigueJumpMult)), 0); + fatigue.setCurrent(current-static_cast(fatigueJumpBase + ((1 - normalizedEncumbrance) * fatigueJumpMult))); cls.getCreatureStats(mPtr).setDynamic (2, fatigue); } @@ -216,25 +245,6 @@ void CharacterController::update(float duration, Movement &movement) } } - if(vec.z<=0.0f && getState()==CharState_Jump) - { - float healthLost = cls.getFallDamage(mPtr, mHighestPosition); - - if(healthLost>0.0f) - { - DynamicStat health = cls.getCreatureStats(mPtr).getHealth(); - int fatigue = MWWorld::Class::get (mPtr).getCreatureStats (mPtr).getFatigue().getBase(); - int current = health.getCurrent(); - health.setModified (health.getModified()-(healthLost * (1 - (0.25 * fatigue))), 0); - health.setCurrent (current-(healthLost * (1 - (0.25 * fatigue)))); - cls.getCreatureStats(mPtr).setHealth (health); - MWWorld::Class::get(mPtr).skillUsageSucceeded(mPtr, ESM::Skill::Acrobatics, 1); - } - - setState(CharState_Idle, true); - mHighestPosition=0; - } - if(std::abs(vec.x/2.0f) > std::abs(vec.y) && speed > 0.0f) { if(vec.x > 0.0f) @@ -299,6 +309,8 @@ void CharacterController::update(float duration, Movement &movement) movement.mPosition[2] += moved.z; } mSkipAnim = false; + + mLastHeight = mPtr.getRefData().getPosition().pos[2]; } diff --git a/apps/openmw/mwmechanics/character.hpp b/apps/openmw/mwmechanics/character.hpp index 460141880c..ffe4077310 100644 --- a/apps/openmw/mwmechanics/character.hpp +++ b/apps/openmw/mwmechanics/character.hpp @@ -83,7 +83,8 @@ class CharacterController float mSecondsOfSwimming; float mSecondsOfRunning; - float mHighestPosition; + float mFallDistance; + float mLastHeight; bool mMovingAnim; diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index a903369eec..6b8a225bba 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1492,6 +1492,13 @@ namespace MWWorld return physactor && physactor->getOnGround(); } + bool World::isGravity(const MWWorld::Ptr &ptr) const + { + RefData &refdata = ptr.getRefData(); + const OEngine::Physic::PhysicActor *physactor = mPhysEngine->getCharacter(refdata.getHandle()); + return physactor && physactor->getCollisionMode(); + } + bool World::vanityRotateCamera(float * rot) { return mRendering->vanityRotateCamera(rot); diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index f61f67062f..5932b54781 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -346,6 +346,7 @@ namespace MWWorld virtual bool isSwimming(const MWWorld::Ptr &object) const; virtual bool isUnderwater(const MWWorld::Ptr::CellStore* cell, const Ogre::Vector3 &pos) const; virtual bool isOnGround(const MWWorld::Ptr &ptr) const; + virtual bool isGravity(const MWWorld::Ptr &ptr) const; virtual void togglePOV() { mRendering->togglePOV(); diff --git a/libs/openengine/bullet/physic.cpp b/libs/openengine/bullet/physic.cpp index dbb42a6456..9c1d3a5302 100644 --- a/libs/openengine/bullet/physic.cpp +++ b/libs/openengine/bullet/physic.cpp @@ -143,7 +143,7 @@ namespace Physic bool PhysicActor::getOnGround() const { - return collisionMode && onGround; + return onGround; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////// From b8630239d74e8495ba5945b127a410e142a92a12 Mon Sep 17 00:00:00 2001 From: Glorf Date: Wed, 1 May 2013 12:25:02 +0200 Subject: [PATCH 5/5] Code cleanup --- apps/openmw/mwmechanics/character.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index a24d7daebc..f3c8629474 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -176,7 +176,6 @@ void CharacterController::update(float duration, Movement &movement) health.setCurrent (current-static_cast(realHealthLost)); cls.getCreatureStats(mPtr).setHealth (health); MWWorld::Class::get(mPtr).skillUsageSucceeded(mPtr, ESM::Skill::Acrobatics, 1); - std::cout<