1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-02-21 06:09:42 +00:00

Account for Hrnchamd's research in touch effect hit position calculation

This commit is contained in:
Alexei Kotov 2024-03-03 22:06:39 +03:00
parent 7a84f27eeb
commit 1f629b1368

View file

@ -2939,11 +2939,12 @@ namespace MWWorld
{
MWMechanics::CreatureStats& stats = actor.getClass().getCreatureStats(actor);
const bool casterIsPlayer = actor == MWMechanics::getPlayer();
MWWorld::Ptr target;
// For scripted spells we should not use hit contact
if (manualSpell)
{
if (actor != MWMechanics::getPlayer())
if (!casterIsPlayer)
{
for (const auto& package : stats.getAiSequence())
{
@ -2957,7 +2958,7 @@ namespace MWWorld
}
else
{
if (actor == MWMechanics::getPlayer())
if (casterIsPlayer)
target = getFacedObject();
if (target.isEmpty() || !target.getClass().hasToolTip(target))
@ -2990,12 +2991,21 @@ namespace MWWorld
if (!target.isEmpty())
{
// Touch explosion placement doesn't depend on where the target was "touched".
// For NPC targets, it also doesn't depend on the height.
// Using 0.75 of the collision box height seems accurate for actors and looks decent for non-actors.
// In Morrowind, touch explosion placement for non-actors is inexplicable,
// often putting the explosion way above the object.
// In Morrowind, it's at 0.7 of the actor's AABB height for actors
// or at 0.7 of the player's height for non-actors if the player is the caster
// This is probably meant to prevent the explosion from being too far above on large objects
// but it often puts the explosions way above small objects, so we'll deviate here
// and use the object's bounds when reasonable (it's $CURRENT_YEAR, we can afford that)
// Note collision object origin is intentionally not used
hitPosition = target.getRefData().getPosition().asVec3();
hitPosition.z() += mPhysics->getHalfExtents(target).z() * 2.f * Constants::TorsoHeight;
constexpr float explosionHeight = 0.7f;
float targetHeight = getHalfExtents(target).z() * 2.f;
if (!target.getClass().isActor() && casterIsPlayer)
{
const float playerHeight = getHalfExtents(actor).z() * 2.f;
targetHeight = std::min(targetHeight, playerHeight);
}
hitPosition.z() += targetHeight * explosionHeight;
}
const ESM::RefId& selectedSpell = stats.getSpells().getSelectedSpell();