mirror of
https://github.com/OpenMW/openmw.git
synced 2025-05-07 15:11:25 +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
4 changed files with 34 additions and 11 deletions
|
@ -236,11 +236,8 @@ namespace MWClass
|
||||||
}
|
}
|
||||||
|
|
||||||
MWBase::World* world = MWBase::Environment::get().getWorld();
|
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);
|
const std::pair<MWWorld::Ptr, osg::Vec3f> result = MWMechanics::getHitContact(ptr, dist);
|
||||||
if (result.first.isEmpty()) // Didn't hit anything
|
if (result.first.isEmpty()) // Didn't hit anything
|
||||||
return true;
|
return true;
|
||||||
|
@ -281,6 +278,9 @@ namespace MWClass
|
||||||
if (otherstats.isDead()) // Can't hit dead actors
|
if (otherstats.isDead()) // Can't hit dead actors
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!MWMechanics::isInMeleeReach(ptr, victim, MWMechanics::getMeleeWeaponReach(ptr, weapon)))
|
||||||
|
return;
|
||||||
|
|
||||||
if (!success)
|
if (!success)
|
||||||
{
|
{
|
||||||
victim.getClass().onHit(
|
victim.getClass().onHit(
|
||||||
|
|
|
@ -572,12 +572,8 @@ namespace MWClass
|
||||||
weapon = *weaponslot;
|
weapon = *weaponslot;
|
||||||
|
|
||||||
MWBase::World* world = MWBase::Environment::get().getWorld();
|
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);
|
const std::pair<MWWorld::Ptr, osg::Vec3f> result = MWMechanics::getHitContact(ptr, dist);
|
||||||
if (result.first.isEmpty()) // Didn't hit anything
|
if (result.first.isEmpty()) // Didn't hit anything
|
||||||
return true;
|
return true;
|
||||||
|
@ -615,6 +611,9 @@ namespace MWClass
|
||||||
if (otherstats.isDead()) // Can't hit dead actors
|
if (otherstats.isDead()) // Can't hit dead actors
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!MWMechanics::isInMeleeReach(ptr, victim, MWMechanics::getMeleeWeaponReach(ptr, weapon)))
|
||||||
|
return;
|
||||||
|
|
||||||
if (ptr == MWMechanics::getPlayer())
|
if (ptr == MWMechanics::getPlayer())
|
||||||
MWBase::Environment::get().getWindowManager()->setEnemy(victim);
|
MWBase::Environment::get().getWindowManager()->setEnemy(victim);
|
||||||
|
|
||||||
|
|
|
@ -578,6 +578,24 @@ namespace MWMechanics
|
||||||
return dist;
|
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)
|
std::pair<MWWorld::Ptr, osg::Vec3f> getHitContact(const MWWorld::Ptr& actor, float reach)
|
||||||
{
|
{
|
||||||
// Lasciate ogne speranza, voi ch'entrate
|
// Lasciate ogne speranza, voi ch'entrate
|
||||||
|
@ -614,11 +632,13 @@ namespace MWMechanics
|
||||||
{
|
{
|
||||||
if (actor == target || target.getClass().getCreatureStats(target).isDead())
|
if (actor == target || target.getClass().getCreatureStats(target).isDead())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const float dist = getDistanceToBounds(actor, target);
|
const float dist = getDistanceToBounds(actor, target);
|
||||||
const osg::Vec3f targetPos(target.getRefData().getPosition().asVec3());
|
if (dist >= minDist || !isInMeleeReach(actor, target, reach))
|
||||||
if (dist >= reach || dist >= minDist || std::abs(targetPos.z() - actorPos.z()) >= reach)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
const osg::Vec3f targetPos(target.getRefData().getPosition().asVec3());
|
||||||
|
|
||||||
// Horizontal angle checks.
|
// Horizontal angle checks.
|
||||||
osg::Vec2f actorToTargetXY{ targetPos.x() - actorPos.x(), targetPos.y() - actorPos.y() };
|
osg::Vec2f actorToTargetXY{ targetPos.x() - actorPos.x(), targetPos.y() - actorPos.y() };
|
||||||
actorToTargetXY.normalize();
|
actorToTargetXY.normalize();
|
||||||
|
|
|
@ -64,6 +64,10 @@ namespace MWMechanics
|
||||||
// Cursed distance calculation used for combat proximity and hit checks in Morrowind
|
// Cursed distance calculation used for combat proximity and hit checks in Morrowind
|
||||||
float getDistanceToBounds(const MWWorld::Ptr& actor, const MWWorld::Ptr& target);
|
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
|
// Similarly cursed hit target selection
|
||||||
std::pair<MWWorld::Ptr, osg::Vec3f> getHitContact(const MWWorld::Ptr& actor, float reach);
|
std::pair<MWWorld::Ptr, osg::Vec3f> getHitContact(const MWWorld::Ptr& actor, float reach);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue