mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-29 17:15:34 +00:00
Filter evade directions by supported animations
To avoid trying those which will not lead to any actor movement due to absent animation.
This commit is contained in:
parent
80ae8ce116
commit
b4868c6094
19 changed files with 199 additions and 37 deletions
|
@ -9,6 +9,7 @@
|
|||
#include "../mwworld/class.hpp"
|
||||
|
||||
#include "aicombataction.hpp"
|
||||
#include "character.hpp"
|
||||
#include "steering.hpp"
|
||||
|
||||
namespace MWMechanics
|
||||
|
@ -48,7 +49,9 @@ bool MWMechanics::AiCast::execute(const MWWorld::Ptr& actor, MWMechanics::Charac
|
|||
if (target.isEmpty())
|
||||
return true;
|
||||
|
||||
if (!mManual && !pathTo(actor, target.getRefData().getPosition().asVec3(), duration, mDistance))
|
||||
if (!mManual
|
||||
&& !pathTo(actor, target.getRefData().getPosition().asVec3(), duration,
|
||||
characterController.getSupportedMovementDirections(), mDistance))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -134,7 +134,8 @@ namespace MWMechanics
|
|||
const osg::Vec3f destination = storage.mUseCustomDestination
|
||||
? storage.mCustomDestination
|
||||
: target.getRefData().getPosition().asVec3();
|
||||
const bool is_target_reached = pathTo(actor, destination, duration, targetReachedTolerance);
|
||||
const bool is_target_reached = pathTo(actor, destination, duration,
|
||||
characterController.getSupportedMovementDirections(), targetReachedTolerance);
|
||||
if (is_target_reached)
|
||||
storage.mReadyToAttack = true;
|
||||
}
|
||||
|
@ -149,7 +150,7 @@ namespace MWMechanics
|
|||
}
|
||||
else
|
||||
{
|
||||
updateFleeing(actor, target, duration, storage);
|
||||
updateFleeing(actor, target, duration, characterController.getSupportedMovementDirections(), storage);
|
||||
}
|
||||
storage.mActionCooldown -= duration;
|
||||
|
||||
|
@ -342,8 +343,8 @@ namespace MWMechanics
|
|||
storage.mUpdateLOSTimer -= duration;
|
||||
}
|
||||
|
||||
void MWMechanics::AiCombat::updateFleeing(
|
||||
const MWWorld::Ptr& actor, const MWWorld::Ptr& target, float duration, MWMechanics::AiCombatStorage& storage)
|
||||
void MWMechanics::AiCombat::updateFleeing(const MWWorld::Ptr& actor, const MWWorld::Ptr& target, float duration,
|
||||
MWWorld::MovementDirectionFlags supportedMovementDirections, AiCombatStorage& storage)
|
||||
{
|
||||
static const float BLIND_RUN_DURATION = 1.0f;
|
||||
|
||||
|
@ -437,7 +438,7 @@ namespace MWMechanics
|
|||
float dist
|
||||
= (actor.getRefData().getPosition().asVec3() - target.getRefData().getPosition().asVec3()).length();
|
||||
if ((dist > fFleeDistance && !storage.mLOS)
|
||||
|| pathTo(actor, PathFinder::makeOsgVec3(storage.mFleeDest), duration))
|
||||
|| pathTo(actor, PathFinder::makeOsgVec3(storage.mFleeDest), duration, supportedMovementDirections))
|
||||
{
|
||||
state = AiCombatStorage::FleeState_Idle;
|
||||
}
|
||||
|
|
|
@ -111,8 +111,8 @@ namespace MWMechanics
|
|||
|
||||
void updateLOS(const MWWorld::Ptr& actor, const MWWorld::Ptr& target, float duration, AiCombatStorage& storage);
|
||||
|
||||
void updateFleeing(
|
||||
const MWWorld::Ptr& actor, const MWWorld::Ptr& target, float duration, AiCombatStorage& storage);
|
||||
void updateFleeing(const MWWorld::Ptr& actor, const MWWorld::Ptr& target, float duration,
|
||||
MWWorld::MovementDirectionFlags supportedMovementDirections, AiCombatStorage& storage);
|
||||
|
||||
/// Transfer desired movement (from AiCombatStorage) to Actor
|
||||
void updateActorsMovement(const MWWorld::Ptr& actor, float duration, AiCombatStorage& storage);
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "../mwworld/cellstore.hpp"
|
||||
#include "../mwworld/class.hpp"
|
||||
|
||||
#include "character.hpp"
|
||||
#include "creaturestats.hpp"
|
||||
#include "movement.hpp"
|
||||
|
||||
|
@ -94,7 +95,7 @@ namespace MWMechanics
|
|||
if ((leaderPos - followerPos).length2() <= mMaxDist * mMaxDist)
|
||||
{
|
||||
const osg::Vec3f dest(mX, mY, mZ);
|
||||
if (pathTo(actor, dest, duration, maxHalfExtent)) // Returns true on path complete
|
||||
if (pathTo(actor, dest, duration, characterController.getSupportedMovementDirections(), maxHalfExtent))
|
||||
{
|
||||
mRemainingDuration = mDuration;
|
||||
return true;
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "../mwworld/cellstore.hpp"
|
||||
#include "../mwworld/class.hpp"
|
||||
|
||||
#include "character.hpp"
|
||||
#include "creaturestats.hpp"
|
||||
#include "steering.hpp"
|
||||
|
||||
|
@ -202,7 +203,9 @@ namespace MWMechanics
|
|||
return false;
|
||||
}
|
||||
|
||||
storage.mMoving = !pathTo(actor, targetPos, duration, baseFollowDistance); // Go to the destination
|
||||
// Go to the destination
|
||||
storage.mMoving = !pathTo(
|
||||
actor, targetPos, duration, characterController.getSupportedMovementDirections(), baseFollowDistance);
|
||||
|
||||
if (storage.mMoving)
|
||||
{
|
||||
|
|
|
@ -110,7 +110,8 @@ void MWMechanics::AiPackage::reset()
|
|||
}
|
||||
|
||||
bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, const osg::Vec3f& dest, float duration,
|
||||
float destTolerance, float endTolerance, PathType pathType)
|
||||
MWWorld::MovementDirectionFlags supportedMovementDirections, float destTolerance, float endTolerance,
|
||||
PathType pathType)
|
||||
{
|
||||
const Misc::TimerStatus timerStatus = mReaction.update(duration);
|
||||
|
||||
|
@ -230,7 +231,7 @@ bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, const osg::Vec3f&
|
|||
smoothTurn(actor, mPathFinder.getXAngleToNext(position.x(), position.y(), position.z()), 0);
|
||||
|
||||
const auto destination = getNextPathPoint(dest);
|
||||
mObstacleCheck.update(actor, destination, duration);
|
||||
mObstacleCheck.update(actor, destination, duration, supportedMovementDirections);
|
||||
|
||||
if (smoothMovement)
|
||||
{
|
||||
|
|
|
@ -125,7 +125,8 @@ namespace MWMechanics
|
|||
protected:
|
||||
/// Handles path building and shortcutting with obstacles avoiding
|
||||
/** \return If the actor has arrived at his destination **/
|
||||
bool pathTo(const MWWorld::Ptr& actor, const osg::Vec3f& dest, float duration, float destTolerance = 0.0f,
|
||||
bool pathTo(const MWWorld::Ptr& actor, const osg::Vec3f& dest, float duration,
|
||||
MWWorld::MovementDirectionFlags supportedMovementDirections, float destTolerance = 0.0f,
|
||||
float endTolerance = 0.0f, PathType pathType = PathType::Full);
|
||||
|
||||
/// Check if there aren't any obstacles along the path to make shortcut possible
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "../mwworld/class.hpp"
|
||||
|
||||
#include "actorutil.hpp"
|
||||
#include "character.hpp"
|
||||
#include "creaturestats.hpp"
|
||||
|
||||
namespace MWMechanics
|
||||
|
@ -55,7 +56,8 @@ namespace MWMechanics
|
|||
const float pathTolerance = 100.f;
|
||||
|
||||
// check the true distance in case the target is far away in Z-direction
|
||||
bool reached = pathTo(actor, dest, duration, pathTolerance, (actorPos - dest).length(), PathType::Partial)
|
||||
bool reached = pathTo(actor, dest, duration, characterController.getSupportedMovementDirections(),
|
||||
pathTolerance, (actorPos - dest).length(), PathType::Partial)
|
||||
&& std::abs(dest.z() - actorPos.z()) < pathTolerance;
|
||||
|
||||
if (reached)
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include "../mwworld/class.hpp"
|
||||
|
||||
#include "character.hpp"
|
||||
#include "creaturestats.hpp"
|
||||
#include "movement.hpp"
|
||||
|
||||
|
@ -89,7 +90,7 @@ namespace MWMechanics
|
|||
if (!isWithinMaxRange(targetPos, actorPos))
|
||||
return mHidden;
|
||||
|
||||
if (pathTo(actor, targetPos, duration))
|
||||
if (pathTo(actor, targetPos, duration, characterController.getSupportedMovementDirections()))
|
||||
{
|
||||
actor.getClass().getMovementSettings(actor).mPosition[1] = 0;
|
||||
return true;
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "../mwphysics/raycasting.hpp"
|
||||
|
||||
#include "actorutil.hpp"
|
||||
#include "character.hpp"
|
||||
#include "creaturestats.hpp"
|
||||
#include "movement.hpp"
|
||||
#include "pathgrid.hpp"
|
||||
|
@ -190,7 +191,7 @@ namespace MWMechanics
|
|||
* will kick in.
|
||||
*/
|
||||
bool AiWander::execute(
|
||||
const MWWorld::Ptr& actor, CharacterController& /*characterController*/, AiState& state, float duration)
|
||||
const MWWorld::Ptr& actor, CharacterController& characterController, AiState& state, float duration)
|
||||
{
|
||||
MWMechanics::CreatureStats& cStats = actor.getClass().getCreatureStats(actor);
|
||||
if (cStats.isDead() || cStats.getHealth().getCurrent() <= 0)
|
||||
|
@ -244,7 +245,7 @@ namespace MWMechanics
|
|||
}
|
||||
}
|
||||
|
||||
doPerFrameActionsForState(actor, duration, storage);
|
||||
doPerFrameActionsForState(actor, duration, characterController.getSupportedMovementDirections(), storage);
|
||||
|
||||
if (storage.mReaction.update(duration) == Misc::TimerStatus::Waiting)
|
||||
return false;
|
||||
|
@ -454,7 +455,8 @@ namespace MWMechanics
|
|||
storage.setState(AiWanderStorage::Wander_IdleNow);
|
||||
}
|
||||
|
||||
void AiWander::doPerFrameActionsForState(const MWWorld::Ptr& actor, float duration, AiWanderStorage& storage)
|
||||
void AiWander::doPerFrameActionsForState(const MWWorld::Ptr& actor, float duration,
|
||||
MWWorld::MovementDirectionFlags supportedMovementDirections, AiWanderStorage& storage)
|
||||
{
|
||||
switch (storage.mState)
|
||||
{
|
||||
|
@ -463,7 +465,7 @@ namespace MWMechanics
|
|||
break;
|
||||
|
||||
case AiWanderStorage::Wander_Walking:
|
||||
onWalkingStatePerFrameActions(actor, duration, storage);
|
||||
onWalkingStatePerFrameActions(actor, duration, supportedMovementDirections, storage);
|
||||
break;
|
||||
|
||||
case AiWanderStorage::Wander_ChooseAction:
|
||||
|
@ -520,11 +522,13 @@ namespace MWMechanics
|
|||
return false;
|
||||
}
|
||||
|
||||
void AiWander::onWalkingStatePerFrameActions(const MWWorld::Ptr& actor, float duration, AiWanderStorage& storage)
|
||||
void AiWander::onWalkingStatePerFrameActions(const MWWorld::Ptr& actor, float duration,
|
||||
MWWorld::MovementDirectionFlags supportedMovementDirections, AiWanderStorage& storage)
|
||||
{
|
||||
// Is there no destination or are we there yet?
|
||||
if ((!mPathFinder.isPathConstructed())
|
||||
|| pathTo(actor, osg::Vec3f(mPathFinder.getPath().back()), duration, DESTINATION_TOLERANCE))
|
||||
|| pathTo(actor, osg::Vec3f(mPathFinder.getPath().back()), duration, supportedMovementDirections,
|
||||
DESTINATION_TOLERANCE))
|
||||
{
|
||||
stopWalking(actor);
|
||||
storage.setState(AiWanderStorage::Wander_ChooseAction);
|
||||
|
|
|
@ -123,9 +123,11 @@ namespace MWMechanics
|
|||
int getRandomIdle() const;
|
||||
void setPathToAnAllowedNode(const MWWorld::Ptr& actor, AiWanderStorage& storage, const ESM::Position& actorPos);
|
||||
void evadeObstacles(const MWWorld::Ptr& actor, AiWanderStorage& storage);
|
||||
void doPerFrameActionsForState(const MWWorld::Ptr& actor, float duration, AiWanderStorage& storage);
|
||||
void doPerFrameActionsForState(const MWWorld::Ptr& actor, float duration,
|
||||
MWWorld::MovementDirectionFlags supportedMovementDirections, AiWanderStorage& storage);
|
||||
void onIdleStatePerFrameActions(const MWWorld::Ptr& actor, float duration, AiWanderStorage& storage);
|
||||
void onWalkingStatePerFrameActions(const MWWorld::Ptr& actor, float duration, AiWanderStorage& storage);
|
||||
void onWalkingStatePerFrameActions(const MWWorld::Ptr& actor, float duration,
|
||||
MWWorld::MovementDirectionFlags supportedMovementDirections, AiWanderStorage& storage);
|
||||
void onChooseActionStatePerFrameActions(const MWWorld::Ptr& actor, AiWanderStorage& storage);
|
||||
bool reactionTimeActions(const MWWorld::Ptr& actor, AiWanderStorage& storage, ESM::Position& pos);
|
||||
inline bool isPackageCompleted() const;
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
#include "character.hpp"
|
||||
|
||||
#include <array>
|
||||
|
||||
#include <components/esm/records.hpp>
|
||||
#include <components/misc/mathutil.hpp>
|
||||
#include <components/misc/resourcehelpers.hpp>
|
||||
|
@ -2926,4 +2928,77 @@ namespace MWMechanics
|
|||
mAnimation->setHeadYaw(zAngleRadians);
|
||||
}
|
||||
|
||||
MWWorld::MovementDirectionFlags CharacterController::getSupportedMovementDirections() const
|
||||
{
|
||||
using namespace std::string_view_literals;
|
||||
// There are fallbacks in the CharacterController::refreshMovementAnims for certain animations. Arrays below
|
||||
// represent them.
|
||||
constexpr std::array all = { ""sv };
|
||||
constexpr std::array walk = { "walk"sv };
|
||||
constexpr std::array swimWalk = { "swimwalk"sv, "walk"sv };
|
||||
constexpr std::array sneak = { "sneak"sv };
|
||||
constexpr std::array run = { "run"sv, "walk"sv };
|
||||
constexpr std::array swimRun = { "swimrun"sv, "run"sv, "walk"sv };
|
||||
constexpr std::array swim = { "swim"sv };
|
||||
switch (mMovementState)
|
||||
{
|
||||
case CharState_None:
|
||||
case CharState_SpecialIdle:
|
||||
case CharState_Idle:
|
||||
case CharState_IdleSwim:
|
||||
case CharState_IdleSneak:
|
||||
return mAnimation->getSupportedMovementDirections(all);
|
||||
case CharState_WalkForward:
|
||||
case CharState_WalkBack:
|
||||
case CharState_WalkLeft:
|
||||
case CharState_WalkRight:
|
||||
return mAnimation->getSupportedMovementDirections(walk);
|
||||
case CharState_SwimWalkForward:
|
||||
case CharState_SwimWalkBack:
|
||||
case CharState_SwimWalkLeft:
|
||||
case CharState_SwimWalkRight:
|
||||
return mAnimation->getSupportedMovementDirections(swimWalk);
|
||||
case CharState_RunForward:
|
||||
case CharState_RunBack:
|
||||
case CharState_RunLeft:
|
||||
case CharState_RunRight:
|
||||
return mAnimation->getSupportedMovementDirections(run);
|
||||
case CharState_SwimRunForward:
|
||||
case CharState_SwimRunBack:
|
||||
case CharState_SwimRunLeft:
|
||||
case CharState_SwimRunRight:
|
||||
return mAnimation->getSupportedMovementDirections(swimRun);
|
||||
case CharState_SneakForward:
|
||||
case CharState_SneakBack:
|
||||
case CharState_SneakLeft:
|
||||
case CharState_SneakRight:
|
||||
return mAnimation->getSupportedMovementDirections(sneak);
|
||||
case CharState_TurnLeft:
|
||||
case CharState_TurnRight:
|
||||
return mAnimation->getSupportedMovementDirections(all);
|
||||
case CharState_SwimTurnLeft:
|
||||
case CharState_SwimTurnRight:
|
||||
return mAnimation->getSupportedMovementDirections(swim);
|
||||
case CharState_Death1:
|
||||
case CharState_Death2:
|
||||
case CharState_Death3:
|
||||
case CharState_Death4:
|
||||
case CharState_Death5:
|
||||
case CharState_SwimDeath:
|
||||
case CharState_SwimDeathKnockDown:
|
||||
case CharState_SwimDeathKnockOut:
|
||||
case CharState_DeathKnockDown:
|
||||
case CharState_DeathKnockOut:
|
||||
case CharState_Hit:
|
||||
case CharState_SwimHit:
|
||||
case CharState_KnockDown:
|
||||
case CharState_KnockOut:
|
||||
case CharState_SwimKnockDown:
|
||||
case CharState_SwimKnockOut:
|
||||
case CharState_Block:
|
||||
return mAnimation->getSupportedMovementDirections(all);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -315,6 +315,8 @@ namespace MWMechanics
|
|||
void setHeadTrackTarget(const MWWorld::ConstPtr& target);
|
||||
|
||||
void playSwishSound() const;
|
||||
|
||||
MWWorld::MovementDirectionFlags getSupportedMovementDirections() const;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "obstacle.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <span>
|
||||
|
||||
#include <components/detournavigator/agentbounds.hpp>
|
||||
#include <components/esm3/loaddoor.hpp>
|
||||
|
@ -22,14 +23,21 @@ namespace MWMechanics
|
|||
constexpr float durationSameSpot = 1.5f;
|
||||
constexpr float durationToEvade = 1;
|
||||
|
||||
constexpr float evadeDirections[][2] = {
|
||||
{ 1.0f, 1.0f }, // move to side and forward
|
||||
{ 1.0f, 0.0f }, // move to side
|
||||
{ 1.0f, -1.0f }, // move to side and backwards
|
||||
{ 0.0f, -1.0f }, // move backwards
|
||||
{ -1.0f, -1.0f }, // move to other side and backwards
|
||||
{ -1.0f, 0.0f }, // move to other side
|
||||
{ -1.0f, 1.0f }, // move to other side and forward
|
||||
struct EvadeDirection
|
||||
{
|
||||
float mMovementX;
|
||||
float mMovementY;
|
||||
MWWorld::MovementDirectionFlag mRequiredAnimation;
|
||||
};
|
||||
|
||||
constexpr EvadeDirection evadeDirections[] = {
|
||||
{ 1.0f, 1.0f, MWWorld::MovementDirectionFlag_Forward }, // move to right and forward
|
||||
{ 1.0f, 0.0f, MWWorld::MovementDirectionFlag_Right }, // move to right
|
||||
{ 1.0f, -1.0f, MWWorld::MovementDirectionFlag_Back }, // move to right and backwards
|
||||
{ 0.0f, -1.0f, MWWorld::MovementDirectionFlag_Back }, // move backwards
|
||||
{ -1.0f, -1.0f, MWWorld::MovementDirectionFlag_Back }, // move to left and backwards
|
||||
{ -1.0f, 0.0f, MWWorld::MovementDirectionFlag_Left }, // move to left
|
||||
{ -1.0f, 1.0f, MWWorld::MovementDirectionFlag_Forward }, // move to left and forward
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -132,7 +140,8 @@ namespace MWMechanics
|
|||
* u = how long to move sideways
|
||||
*
|
||||
*/
|
||||
void ObstacleCheck::update(const MWWorld::Ptr& actor, const osg::Vec3f& destination, float duration)
|
||||
void ObstacleCheck::update(const MWWorld::Ptr& actor, const osg::Vec3f& destination, float duration,
|
||||
MWWorld::MovementDirectionFlags supportedMovementDirection)
|
||||
{
|
||||
const auto position = actor.getRefData().getPosition().asVec3();
|
||||
|
||||
|
@ -185,8 +194,15 @@ namespace MWMechanics
|
|||
|
||||
mWalkState = WalkState::Evade;
|
||||
mStateDuration = 0;
|
||||
if (++mEvadeDirectionIndex == std::size(evadeDirections))
|
||||
mEvadeDirectionIndex = 0;
|
||||
std::size_t newEvadeDirectionIndex = mEvadeDirectionIndex;
|
||||
do
|
||||
{
|
||||
++newEvadeDirectionIndex;
|
||||
if (newEvadeDirectionIndex == std::size(evadeDirections))
|
||||
newEvadeDirectionIndex = 0;
|
||||
if ((evadeDirections[newEvadeDirectionIndex].mRequiredAnimation & supportedMovementDirection) != 0)
|
||||
break;
|
||||
} while (mEvadeDirectionIndex != newEvadeDirectionIndex);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -202,7 +218,7 @@ namespace MWMechanics
|
|||
|
||||
void ObstacleCheck::takeEvasiveAction(MWMechanics::Movement& actorMovement) const
|
||||
{
|
||||
actorMovement.mPosition[0] = evadeDirections[mEvadeDirectionIndex][0];
|
||||
actorMovement.mPosition[1] = evadeDirections[mEvadeDirectionIndex][1];
|
||||
actorMovement.mPosition[0] = evadeDirections[mEvadeDirectionIndex].mMovementX;
|
||||
actorMovement.mPosition[1] = evadeDirections[mEvadeDirectionIndex].mMovementY;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#ifndef OPENMW_MECHANICS_OBSTACLE_H
|
||||
#define OPENMW_MECHANICS_OBSTACLE_H
|
||||
|
||||
#include "apps/openmw/mwworld/movementdirection.hpp"
|
||||
|
||||
#include <osg/Vec3f>
|
||||
|
||||
#include <vector>
|
||||
|
@ -36,7 +38,8 @@ namespace MWMechanics
|
|||
bool isEvading() const;
|
||||
|
||||
// Updates internal state, call each frame for moving actor
|
||||
void update(const MWWorld::Ptr& actor, const osg::Vec3f& destination, float duration);
|
||||
void update(const MWWorld::Ptr& actor, const osg::Vec3f& destination, float duration,
|
||||
MWWorld::MovementDirectionFlags supportedMovementDirection);
|
||||
|
||||
// change direction to try to fix "stuck" actor
|
||||
void takeEvasiveAction(Movement& actorMovement) const;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "animation.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iomanip>
|
||||
#include <limits>
|
||||
|
||||
|
@ -1800,6 +1801,28 @@ namespace MWRender
|
|||
mInsert->removeChild(mObjectRoot);
|
||||
}
|
||||
|
||||
MWWorld::MovementDirectionFlags Animation::getSupportedMovementDirections(
|
||||
std::span<const std::string_view> prefixes) const
|
||||
{
|
||||
MWWorld::MovementDirectionFlags result = 0;
|
||||
for (const std::string_view animation : mSupportedAnimations)
|
||||
{
|
||||
if (std::find_if(
|
||||
prefixes.begin(), prefixes.end(), [&](std::string_view v) { return animation.starts_with(v); })
|
||||
== prefixes.end())
|
||||
continue;
|
||||
if (animation.ends_with("forward"))
|
||||
result |= MWWorld::MovementDirectionFlag_Forward;
|
||||
else if (animation.ends_with("back"))
|
||||
result |= MWWorld::MovementDirectionFlag_Back;
|
||||
else if (animation.ends_with("left"))
|
||||
result |= MWWorld::MovementDirectionFlag_Left;
|
||||
else if (animation.ends_with("right"))
|
||||
result |= MWWorld::MovementDirectionFlag_Right;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------
|
||||
|
||||
float Animation::AnimationTime::getValue(osg::NodeVisitor*)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#ifndef GAME_RENDER_ANIMATION_H
|
||||
#define GAME_RENDER_ANIMATION_H
|
||||
|
||||
#include "../mwworld/movementdirection.hpp"
|
||||
#include "../mwworld/ptr.hpp"
|
||||
|
||||
#include <components/misc/strings/algorithm.hpp>
|
||||
|
@ -9,6 +10,7 @@
|
|||
#include <components/sceneutil/textkeymap.hpp>
|
||||
#include <components/sceneutil/util.hpp>
|
||||
|
||||
#include <span>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
@ -472,6 +474,9 @@ namespace MWRender
|
|||
/// @note The matching is case-insensitive.
|
||||
const osg::Node* getNode(std::string_view name) const;
|
||||
|
||||
MWWorld::MovementDirectionFlags getSupportedMovementDirections(
|
||||
std::span<const std::string_view> prefixes) const;
|
||||
|
||||
virtual bool useShieldAnimations() const { return false; }
|
||||
virtual bool getWeaponsShown() const { return false; }
|
||||
virtual void showWeapons(bool showWeapon) {}
|
||||
|
|
17
apps/openmw/mwworld/movementdirection.hpp
Normal file
17
apps/openmw/mwworld/movementdirection.hpp
Normal file
|
@ -0,0 +1,17 @@
|
|||
#ifndef OPENMW_APPS_OPENMW_MWWORLD_MOVEMENTDIRECTION_H
|
||||
#define OPENMW_APPS_OPENMW_MWWORLD_MOVEMENTDIRECTION_H
|
||||
|
||||
namespace MWWorld
|
||||
{
|
||||
using MovementDirectionFlags = unsigned char;
|
||||
|
||||
enum MovementDirectionFlag : MovementDirectionFlags
|
||||
{
|
||||
MovementDirectionFlag_Forward = 1 << 0,
|
||||
MovementDirectionFlag_Back = 1 << 1,
|
||||
MovementDirectionFlag_Left = 1 << 2,
|
||||
MovementDirectionFlag_Right = 1 << 3,
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -44,6 +44,8 @@ namespace SceneUtil
|
|||
|
||||
bool hasGroupStart(std::string_view groupName) const { return mGroups.count(groupName) > 0; }
|
||||
|
||||
const std::set<std::string, std::less<>>& getGroups() const { return mGroups; }
|
||||
|
||||
private:
|
||||
struct IsGroupStart
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue