mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-03-30 09:06:43 +00:00
Knockdown / hit recovery improvements. Use formula and GMSTs from research wiki for knockdown determination. Hand-to-hand automatically knocks out when fatigue empty.
This commit is contained in:
parent
3e58eb34e4
commit
83872f6bf5
5 changed files with 85 additions and 27 deletions
|
@ -242,6 +242,9 @@ namespace MWClass
|
||||||
fJumpAcroMultiplier = gmst.find("fJumpAcroMultiplier");
|
fJumpAcroMultiplier = gmst.find("fJumpAcroMultiplier");
|
||||||
fJumpRunMultiplier = gmst.find("fJumpRunMultiplier");
|
fJumpRunMultiplier = gmst.find("fJumpRunMultiplier");
|
||||||
fWereWolfRunMult = gmst.find("fWereWolfRunMult");
|
fWereWolfRunMult = gmst.find("fWereWolfRunMult");
|
||||||
|
fKnockDownMult = gmst.find("fKnockDownMult");
|
||||||
|
iKnockDownOddsMult = gmst.find("iKnockDownOddsMult");
|
||||||
|
iKnockDownOddsBase = gmst.find("iKnockDownOddsBase");
|
||||||
|
|
||||||
inited = true;
|
inited = true;
|
||||||
}
|
}
|
||||||
|
@ -651,7 +654,20 @@ namespace MWClass
|
||||||
{
|
{
|
||||||
MWBase::Environment::get().getDialogueManager()->say(ptr, "hit");
|
MWBase::Environment::get().getDialogueManager()->say(ptr, "hit");
|
||||||
}
|
}
|
||||||
getCreatureStats(ptr).setAttacked(true);//used in CharacterController
|
getCreatureStats(ptr).setAttacked(true);
|
||||||
|
|
||||||
|
// Check for knockdown
|
||||||
|
float agilityTerm = getCreatureStats(ptr).getAttribute(ESM::Attribute::Agility).getModified() * fKnockDownMult->getFloat();
|
||||||
|
float knockdownTerm = getCreatureStats(ptr).getAttribute(ESM::Attribute::Agility).getModified()
|
||||||
|
* iKnockDownOddsMult->getInt() * 0.01 + iKnockDownOddsBase->getInt();
|
||||||
|
roll = std::rand()/ (static_cast<double> (RAND_MAX) + 1) * 100; // [0, 99]
|
||||||
|
if (ishealth && agilityTerm <= damage && knockdownTerm <= roll)
|
||||||
|
{
|
||||||
|
getCreatureStats(ptr).setKnockedDown(true);
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
getCreatureStats(ptr).setHitRecovery(true); // Is this supposed to always occur?
|
||||||
|
|
||||||
if(object.isEmpty())
|
if(object.isEmpty())
|
||||||
{
|
{
|
||||||
|
@ -726,6 +742,15 @@ namespace MWClass
|
||||||
fatigue.setCurrent(fatigue.getCurrent() - damage, true);
|
fatigue.setCurrent(fatigue.getCurrent() - damage, true);
|
||||||
getCreatureStats(ptr).setFatigue(fatigue);
|
getCreatureStats(ptr).setFatigue(fatigue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (object.isEmpty())
|
||||||
|
{
|
||||||
|
// Hand-to-hand automatically knocks down when running out of fatigue
|
||||||
|
if (getCreatureStats(ptr).getFatigue().getCurrent() < 0)
|
||||||
|
{
|
||||||
|
getCreatureStats(ptr).setKnockedDown(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Npc::setActorHealth(const MWWorld::Ptr& ptr, float health, const MWWorld::Ptr& attacker) const
|
void Npc::setActorHealth(const MWWorld::Ptr& ptr, float health, const MWWorld::Ptr& attacker) const
|
||||||
|
@ -1286,4 +1311,7 @@ namespace MWClass
|
||||||
const ESM::GameSetting *Npc::fJumpAcroMultiplier;
|
const ESM::GameSetting *Npc::fJumpAcroMultiplier;
|
||||||
const ESM::GameSetting *Npc::fJumpRunMultiplier;
|
const ESM::GameSetting *Npc::fJumpRunMultiplier;
|
||||||
const ESM::GameSetting *Npc::fWereWolfRunMult;
|
const ESM::GameSetting *Npc::fWereWolfRunMult;
|
||||||
|
const ESM::GameSetting *Npc::fKnockDownMult;
|
||||||
|
const ESM::GameSetting *Npc::iKnockDownOddsMult;
|
||||||
|
const ESM::GameSetting *Npc::iKnockDownOddsBase;
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,9 @@ namespace MWClass
|
||||||
static const ESM::GameSetting *fJumpAcroMultiplier;
|
static const ESM::GameSetting *fJumpAcroMultiplier;
|
||||||
static const ESM::GameSetting *fJumpRunMultiplier;
|
static const ESM::GameSetting *fJumpRunMultiplier;
|
||||||
static const ESM::GameSetting *fWereWolfRunMult;
|
static const ESM::GameSetting *fWereWolfRunMult;
|
||||||
|
static const ESM::GameSetting *fKnockDownMult;
|
||||||
|
static const ESM::GameSetting *iKnockDownOddsMult;
|
||||||
|
static const ESM::GameSetting *iKnockDownOddsBase;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
|
@ -157,40 +157,40 @@ public:
|
||||||
|
|
||||||
void CharacterController::refreshCurrentAnims(CharacterState idle, CharacterState movement, bool force)
|
void CharacterController::refreshCurrentAnims(CharacterState idle, CharacterState movement, bool force)
|
||||||
{
|
{
|
||||||
//hit recoils/knockdown animations handling
|
// hit recoils/knockdown animations handling
|
||||||
if(MWWorld::Class::get(mPtr).isActor())
|
if(mPtr.getClass().isActor())
|
||||||
{
|
{
|
||||||
if(MWWorld::Class::get(mPtr).getCreatureStats(mPtr).getAttacked())
|
bool recovery = mPtr.getClass().getCreatureStats(mPtr).getHitRecovery();
|
||||||
|
bool knockdown = mPtr.getClass().getCreatureStats(mPtr).getKnockedDown();
|
||||||
|
if(mHitState == CharState_None)
|
||||||
{
|
{
|
||||||
MWWorld::Class::get(mPtr).getCreatureStats(mPtr).setAttacked(false);
|
if(knockdown)
|
||||||
|
|
||||||
if(mHitState == CharState_None)
|
|
||||||
{
|
{
|
||||||
if(mJumpState != JumpState_None && !MWBase::Environment::get().getWorld()->isFlying(mPtr)
|
mHitState = CharState_KnockDown;
|
||||||
&& !MWBase::Environment::get().getWorld()->isSwimming(mPtr) )
|
mCurrentHit = sHitList[sHitListSize-1];
|
||||||
|
mAnimation->play(mCurrentHit, Priority_Knockdown, MWRender::Animation::Group_All, true, 1, "start", "stop", 0.0f, 0);
|
||||||
|
}
|
||||||
|
else if (recovery)
|
||||||
|
{
|
||||||
|
mHitState = CharState_Hit;
|
||||||
|
int iHit = rand() % (sHitListSize-1);
|
||||||
|
mCurrentHit = sHitList[iHit];
|
||||||
|
if(mPtr.getRefData().getHandle()=="player" && !mAnimation->hasAnimation(mCurrentHit))
|
||||||
{
|
{
|
||||||
mHitState = CharState_KnockDown;
|
//only 3 different hit animations if player is in 1st person
|
||||||
mCurrentHit = sHitList[sHitListSize-1];
|
int iHit = rand() % (sHitListSize-3);
|
||||||
mAnimation->play(mCurrentHit, Priority_Knockdown, MWRender::Animation::Group_All, true, 1, "start", "stop", 0.0f, 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mHitState = CharState_Hit;
|
|
||||||
int iHit = rand() % (sHitListSize-1);
|
|
||||||
mCurrentHit = sHitList[iHit];
|
mCurrentHit = sHitList[iHit];
|
||||||
if(mPtr.getRefData().getHandle()=="player" && !mAnimation->hasAnimation(mCurrentHit))
|
|
||||||
{
|
|
||||||
//only 3 different hit animations if player is in 1st person
|
|
||||||
int iHit = rand() % (sHitListSize-3);
|
|
||||||
mCurrentHit = sHitList[iHit];
|
|
||||||
}
|
|
||||||
mAnimation->play(mCurrentHit, Priority_Hit, MWRender::Animation::Group_All, true, 1, "start", "stop", 0.0f, 0);
|
|
||||||
}
|
}
|
||||||
|
mAnimation->play(mCurrentHit, Priority_Hit, MWRender::Animation::Group_All, true, 1, "start", "stop", 0.0f, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(mHitState != CharState_None && !mAnimation->isPlaying(mCurrentHit))
|
else if(!mAnimation->isPlaying(mCurrentHit))
|
||||||
{
|
{
|
||||||
mCurrentHit.erase();
|
mCurrentHit.erase();
|
||||||
|
if (knockdown)
|
||||||
|
mPtr.getClass().getCreatureStats(mPtr).setKnockedDown(false);
|
||||||
|
if (recovery)
|
||||||
|
mPtr.getClass().getCreatureStats(mPtr).setHitRecovery(false);
|
||||||
mHitState = CharState_None;
|
mHitState = CharState_None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ namespace MWMechanics
|
||||||
mAttacked (false), mHostile (false),
|
mAttacked (false), mHostile (false),
|
||||||
mAttackingOrSpell(false), mAttackType(AT_Chop),
|
mAttackingOrSpell(false), mAttackType(AT_Chop),
|
||||||
mIsWerewolf(false),
|
mIsWerewolf(false),
|
||||||
mFallHeight(0), mRecalcDynamicStats(false)
|
mFallHeight(0), mRecalcDynamicStats(false), mKnockdown(false), mHitRecovery(false)
|
||||||
{
|
{
|
||||||
for (int i=0; i<4; ++i)
|
for (int i=0; i<4; ++i)
|
||||||
mAiSettings[i] = 0;
|
mAiSettings[i] = 0;
|
||||||
|
@ -402,4 +402,24 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CreatureStats::setKnockedDown(bool value)
|
||||||
|
{
|
||||||
|
mKnockdown = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CreatureStats::getKnockedDown() const
|
||||||
|
{
|
||||||
|
return mKnockdown;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CreatureStats::setHitRecovery(bool value)
|
||||||
|
{
|
||||||
|
mHitRecovery = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CreatureStats::getHitRecovery() const
|
||||||
|
{
|
||||||
|
return mHitRecovery;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,9 @@ namespace MWMechanics
|
||||||
bool mAlarmed;
|
bool mAlarmed;
|
||||||
bool mAttacked;
|
bool mAttacked;
|
||||||
bool mHostile;
|
bool mHostile;
|
||||||
bool mAttackingOrSpell;//for the player, this is true if the left mouse button is pressed, false if not.
|
bool mAttackingOrSpell;
|
||||||
|
bool mKnockdown;
|
||||||
|
bool mHitRecovery;
|
||||||
|
|
||||||
float mFallHeight;
|
float mFallHeight;
|
||||||
|
|
||||||
|
@ -186,6 +188,11 @@ namespace MWMechanics
|
||||||
|
|
||||||
float getEvasion() const;
|
float getEvasion() const;
|
||||||
|
|
||||||
|
void setKnockedDown(bool value);
|
||||||
|
bool getKnockedDown() const;
|
||||||
|
void setHitRecovery(bool value);
|
||||||
|
bool getHitRecovery() const;
|
||||||
|
|
||||||
void setLastHitObject(const std::string &objectid);
|
void setLastHitObject(const std::string &objectid);
|
||||||
const std::string &getLastHitObject() const;
|
const std::string &getLastHitObject() const;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue