mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-02-04 12:39:55 +00:00
Merge branch 'nooneactuallyknowshowmorrowindcombatworks' into 'master'
Check if the victim is within weapon reach upon hit (#8280) See merge request OpenMW/openmw!4518
This commit is contained in:
commit
c16064e6f3
@ -236,11 +236,8 @@ namespace MWClass
|
||||
}
|
||||
|
||||
MWBase::World* world = MWBase::Environment::get().getWorld();
|
||||
const MWWorld::Store<ESM::GameSetting>& store = world->getStore().get<ESM::GameSetting>();
|
||||
float dist = store.find("fCombatDistance")->mValue.getFloat();
|
||||
if (!weapon.isEmpty())
|
||||
dist *= weapon.get<ESM::Weapon>()->mBase->mData.mReach;
|
||||
|
||||
const float dist = MWMechanics::getMeleeWeaponReach(ptr, weapon);
|
||||
const std::pair<MWWorld::Ptr, osg::Vec3f> result = MWMechanics::getHitContact(ptr, dist);
|
||||
if (result.first.isEmpty()) // Didn't hit anything
|
||||
return true;
|
||||
@ -281,6 +278,9 @@ namespace MWClass
|
||||
if (otherstats.isDead()) // Can't hit dead actors
|
||||
return;
|
||||
|
||||
if (!MWMechanics::isInMeleeReach(ptr, victim, MWMechanics::getMeleeWeaponReach(ptr, weapon)))
|
||||
return;
|
||||
|
||||
if (!success)
|
||||
{
|
||||
victim.getClass().onHit(
|
||||
|
@ -572,12 +572,8 @@ namespace MWClass
|
||||
weapon = *weaponslot;
|
||||
|
||||
MWBase::World* world = MWBase::Environment::get().getWorld();
|
||||
const MWWorld::Store<ESM::GameSetting>& store = world->getStore().get<ESM::GameSetting>();
|
||||
const float fCombatDistance = store.find("fCombatDistance")->mValue.getFloat();
|
||||
float dist = fCombatDistance
|
||||
* (!weapon.isEmpty() ? weapon.get<ESM::Weapon>()->mBase->mData.mReach
|
||||
: store.find("fHandToHandReach")->mValue.getFloat());
|
||||
|
||||
const float dist = MWMechanics::getMeleeWeaponReach(ptr, weapon);
|
||||
const std::pair<MWWorld::Ptr, osg::Vec3f> result = MWMechanics::getHitContact(ptr, dist);
|
||||
if (result.first.isEmpty()) // Didn't hit anything
|
||||
return true;
|
||||
@ -615,6 +611,9 @@ namespace MWClass
|
||||
if (otherstats.isDead()) // Can't hit dead actors
|
||||
return;
|
||||
|
||||
if (!MWMechanics::isInMeleeReach(ptr, victim, MWMechanics::getMeleeWeaponReach(ptr, weapon)))
|
||||
return;
|
||||
|
||||
if (ptr == MWMechanics::getPlayer())
|
||||
MWBase::Environment::get().getWindowManager()->setEnemy(victim);
|
||||
|
||||
|
@ -578,6 +578,24 @@ namespace MWMechanics
|
||||
return dist;
|
||||
}
|
||||
|
||||
float getMeleeWeaponReach(const MWWorld::Ptr& actor, const MWWorld::Ptr& weapon)
|
||||
{
|
||||
MWBase::World* world = MWBase::Environment::get().getWorld();
|
||||
const MWWorld::Store<ESM::GameSetting>& store = world->getStore().get<ESM::GameSetting>();
|
||||
const float fCombatDistance = store.find("fCombatDistance")->mValue.getFloat();
|
||||
if (!weapon.isEmpty())
|
||||
return fCombatDistance * weapon.get<ESM::Weapon>()->mBase->mData.mReach;
|
||||
if (actor.getClass().isNpc())
|
||||
return fCombatDistance * store.find("fHandToHandReach")->mValue.getFloat();
|
||||
return fCombatDistance;
|
||||
}
|
||||
|
||||
bool isInMeleeReach(const MWWorld::Ptr& actor, const MWWorld::Ptr& target, const float reach)
|
||||
{
|
||||
const float heightDiff = actor.getRefData().getPosition().pos[2] - target.getRefData().getPosition().pos[2];
|
||||
return std::abs(heightDiff) < reach && getDistanceToBounds(actor, target) < reach;
|
||||
}
|
||||
|
||||
std::pair<MWWorld::Ptr, osg::Vec3f> getHitContact(const MWWorld::Ptr& actor, float reach)
|
||||
{
|
||||
// Lasciate ogne speranza, voi ch'entrate
|
||||
@ -614,11 +632,13 @@ namespace MWMechanics
|
||||
{
|
||||
if (actor == target || target.getClass().getCreatureStats(target).isDead())
|
||||
continue;
|
||||
|
||||
const float dist = getDistanceToBounds(actor, target);
|
||||
const osg::Vec3f targetPos(target.getRefData().getPosition().asVec3());
|
||||
if (dist >= reach || dist >= minDist || std::abs(targetPos.z() - actorPos.z()) >= reach)
|
||||
if (dist >= minDist || !isInMeleeReach(actor, target, reach))
|
||||
continue;
|
||||
|
||||
const osg::Vec3f targetPos(target.getRefData().getPosition().asVec3());
|
||||
|
||||
// Horizontal angle checks.
|
||||
osg::Vec2f actorToTargetXY{ targetPos.x() - actorPos.x(), targetPos.y() - actorPos.y() };
|
||||
actorToTargetXY.normalize();
|
||||
|
@ -64,6 +64,10 @@ namespace MWMechanics
|
||||
// Cursed distance calculation used for combat proximity and hit checks in Morrowind
|
||||
float getDistanceToBounds(const MWWorld::Ptr& actor, const MWWorld::Ptr& target);
|
||||
|
||||
float getMeleeWeaponReach(const MWWorld::Ptr& actor, const MWWorld::Ptr& weapon);
|
||||
|
||||
bool isInMeleeReach(const MWWorld::Ptr& actor, const MWWorld::Ptr& target, const float reach);
|
||||
|
||||
// Similarly cursed hit target selection
|
||||
std::pair<MWWorld::Ptr, osg::Vec3f> getHitContact(const MWWorld::Ptr& actor, float reach);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user