Commit 9b32b140 authored by scrawl's avatar scrawl

Feature #960: Implement Creature::hit

parent 228254c8
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment