forked from mirror/openmw-tes3mp
Feature #960: Implement Creature::hit
This commit is contained in:
parent
228254c890
commit
9b32b1403b
5 changed files with 75 additions and 9 deletions
|
@ -173,6 +173,62 @@ namespace MWClass
|
|||
|
||||
void Creature::hit(const MWWorld::Ptr& ptr, int type) const
|
||||
{
|
||||
MWWorld::LiveCellRef<ESM::Creature> *ref =
|
||||
ptr.get<ESM::Creature>();
|
||||
|
||||
// TODO: where is the distance defined?
|
||||
std::pair<MWWorld::Ptr, Ogre::Vector3> result = MWBase::Environment::get().getWorld()->getHitContact(ptr, 100);
|
||||
if (result.first.isEmpty())
|
||||
return; // Didn't hit anything
|
||||
|
||||
MWWorld::Ptr victim = result.first;
|
||||
|
||||
if (!victim.getClass().isActor())
|
||||
return; // Can't hit non-actors
|
||||
|
||||
Ogre::Vector3 hitPosition = result.second;
|
||||
|
||||
MWMechanics::CreatureStats &stats = getCreatureStats(ptr);
|
||||
MWMechanics::CreatureStats &otherstats = victim.getClass().getCreatureStats(victim);
|
||||
const MWMechanics::MagicEffects &mageffects = stats.getMagicEffects();
|
||||
float hitchance = ref->mBase->mData.mCombat +
|
||||
(stats.getAttribute(ESM::Attribute::Agility).getModified() / 5.0f) +
|
||||
(stats.getAttribute(ESM::Attribute::Luck).getModified() / 10.0f);
|
||||
hitchance *= stats.getFatigueTerm();
|
||||
hitchance += mageffects.get(ESM::MagicEffect::FortifyAttack).mMagnitude -
|
||||
mageffects.get(ESM::MagicEffect::Blind).mMagnitude;
|
||||
hitchance -= otherstats.getEvasion();
|
||||
|
||||
if((::rand()/(RAND_MAX+1.0)) > hitchance/100.0f)
|
||||
{
|
||||
victim.getClass().onHit(victim, 0.0f, false, MWWorld::Ptr(), ptr, false);
|
||||
return;
|
||||
}
|
||||
|
||||
int min,max;
|
||||
switch (type)
|
||||
{
|
||||
case 0:
|
||||
min = ref->mBase->mData.mAttack[0];
|
||||
max = ref->mBase->mData.mAttack[1];
|
||||
break;
|
||||
case 1:
|
||||
min = ref->mBase->mData.mAttack[2];
|
||||
max = ref->mBase->mData.mAttack[3];
|
||||
break;
|
||||
case 2:
|
||||
default:
|
||||
min = ref->mBase->mData.mAttack[4];
|
||||
max = ref->mBase->mData.mAttack[5];
|
||||
break;
|
||||
}
|
||||
|
||||
float damage = min + (max - min) * ::rand()/(RAND_MAX+1.0);
|
||||
|
||||
// TODO: do not do this if the attack is blocked
|
||||
MWBase::Environment::get().getWorld()->spawnBloodEffect(victim, hitPosition);
|
||||
|
||||
victim.getClass().onHit(victim, damage, true, MWWorld::Ptr(), ptr, true);
|
||||
}
|
||||
|
||||
void Creature::onHit(const MWWorld::Ptr &ptr, float damage, bool ishealth, const MWWorld::Ptr &object, const MWWorld::Ptr &attacker, bool successful) const
|
||||
|
|
|
@ -454,7 +454,7 @@ namespace MWClass
|
|||
float dist = 100.0f * (!weapon.isEmpty() ?
|
||||
weapon.get<ESM::Weapon>()->mBase->mData.mReach :
|
||||
gmst.find("fHandToHandReach")->getFloat());
|
||||
// TODO: Use second to work out the hit angle and where to spawn the blood effect
|
||||
// TODO: Use second to work out the hit angle
|
||||
std::pair<MWWorld::Ptr, Ogre::Vector3> result = world->getHitContact(ptr, dist);
|
||||
MWWorld::Ptr victim = result.first;
|
||||
Ogre::Vector3 hitPosition = result.second;
|
||||
|
@ -604,6 +604,7 @@ namespace MWClass
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: do not do this if the attack is blocked
|
||||
if (healthdmg)
|
||||
MWBase::Environment::get().getWorld()->spawnBloodEffect(victim, hitPosition);
|
||||
|
||||
|
|
|
@ -495,10 +495,10 @@ bool CharacterController::updateCreatureState()
|
|||
case CreatureStats::AT_Chop:
|
||||
mCurrentWeapon = "attack1";
|
||||
break;
|
||||
case CreatureStats::AT_Thrust:
|
||||
case CreatureStats::AT_Slash:
|
||||
mCurrentWeapon = "attack2";
|
||||
break;
|
||||
case CreatureStats::AT_Slash:
|
||||
case CreatureStats::AT_Thrust:
|
||||
mCurrentWeapon = "attack3";
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -116,9 +116,9 @@ namespace MWMechanics
|
|||
|
||||
enum AttackType
|
||||
{
|
||||
AT_Chop,
|
||||
AT_Slash,
|
||||
AT_Thrust,
|
||||
AT_Chop
|
||||
AT_Thrust
|
||||
};
|
||||
void setAttackType(int attackType) { mAttackType = attackType; }
|
||||
int getAttackType() { return mAttackType; }
|
||||
|
|
|
@ -660,13 +660,22 @@ void Animation::handleTextKey(AnimState &state, const std::string &groupname, co
|
|||
else if(evt.compare(off, len, "unequip detach") == 0)
|
||||
showWeapons(false);
|
||||
else if(evt.compare(off, len, "chop hit") == 0)
|
||||
MWWorld::Class::get(mPtr).hit(mPtr, MWMechanics::CreatureStats::AT_Chop);
|
||||
mPtr.getClass().hit(mPtr, MWMechanics::CreatureStats::AT_Chop);
|
||||
else if(evt.compare(off, len, "slash hit") == 0)
|
||||
MWWorld::Class::get(mPtr).hit(mPtr, MWMechanics::CreatureStats::AT_Slash);
|
||||
mPtr.getClass().hit(mPtr, MWMechanics::CreatureStats::AT_Slash);
|
||||
else if(evt.compare(off, len, "thrust hit") == 0)
|
||||
MWWorld::Class::get(mPtr).hit(mPtr, MWMechanics::CreatureStats::AT_Thrust);
|
||||
mPtr.getClass().hit(mPtr, MWMechanics::CreatureStats::AT_Thrust);
|
||||
else if(evt.compare(off, len, "hit") == 0)
|
||||
MWWorld::Class::get(mPtr).hit(mPtr);
|
||||
{
|
||||
if (groupname == "attack1")
|
||||
mPtr.getClass().hit(mPtr, MWMechanics::CreatureStats::AT_Chop);
|
||||
else if (groupname == "attack2")
|
||||
mPtr.getClass().hit(mPtr, MWMechanics::CreatureStats::AT_Slash);
|
||||
else if (groupname == "attack3")
|
||||
mPtr.getClass().hit(mPtr, MWMechanics::CreatureStats::AT_Thrust);
|
||||
else
|
||||
mPtr.getClass().hit(mPtr);
|
||||
}
|
||||
|
||||
else if (groupname == "spellcast" && evt.substr(evt.size()-7, 7) == "release")
|
||||
MWBase::Environment::get().getWorld()->castSpell(mPtr);
|
||||
|
|
Loading…
Reference in a new issue