mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-04-07 21:53:51 +00:00
Replace the 2,200-line monolithic AnimationController (goto-driven, single class, untestable) with a composed FSM architecture per refactor.md. New subsystem (src/rendering/animation/ — 16 headers, 10 sources): - CharacterAnimator: FSM composer implementing ICharacterAnimator - LocomotionFSM: idle/walk/run/sprint/jump/swim/strafe - CombatFSM: melee/ranged/spell cast/stun/hit reaction/charge - ActivityFSM: emote/loot/sit-down/sitting/sit-up - MountFSM: idle/run/flight/taxi/fidget/rear-up (per-instance RNG) - AnimCapabilitySet + AnimCapabilityProbe: probe once at model load, eliminate per-frame hasAnimation() linear search - AnimationManager: registry of CharacterAnimator by GUID - EmoteRegistry: DBC-backed emote command → animId singleton - FootstepDriver, SfxStateDriver: extracted from AnimationController animation_ids.hpp/.cpp moved to animation/ subdirectory (452 named constants); all include paths updated. AnimationController retained as thin adapter (~400 LOC): collects FrameInput, delegates to CharacterAnimator, applies AnimOutput. Priority order: Mount > Stun > HitReaction > Spell > Charge > Melee/Ranged > CombatIdle > Emote > Loot > Sit > Locomotion. STAY_IN_STATE policy when all FSMs return valid=false. Bugs fixed: - Remove static mt19937 in mount fidget (shared state across all mounted units) — replaced with per-instance seeded RNG - Remove goto from mounted animation branch (skipped init) - Remove per-frame hasAnimation() calls (now one probe at load) - Fix VK_INDEX_TYPE_UINT16 → UINT32 in shadow pass Tests (4 new suites, all ASAN+UBSan clean): - test_locomotion_fsm: 167 assertions - test_combat_fsm: 125 cases - test_activity_fsm: 112 cases - test_anim_capability: 56 cases docs/ANIMATION_SYSTEM.md added (architecture reference).
142 lines
4.3 KiB
C++
142 lines
4.3 KiB
C++
#pragma once
|
|
|
|
#include "rendering/animation/anim_capability_set.hpp"
|
|
#include "rendering/animation/anim_event.hpp"
|
|
#include <cstdint>
|
|
#include <vector>
|
|
#include <random>
|
|
#include <glm/glm.hpp>
|
|
|
|
namespace wowee {
|
|
namespace rendering {
|
|
|
|
// ============================================================================
|
|
// MountFSM
|
|
//
|
|
// Self-contained mount animation state machine. Replaces the ~400-line
|
|
// mounted branch of updateCharacterAnimation() and eliminates the `goto`.
|
|
//
|
|
// Owns: fidget timer, RNG, idle sound timer, mount action state.
|
|
// All static RNG replaced with per-instance members.
|
|
// ============================================================================
|
|
class MountFSM {
|
|
public:
|
|
// Animation set discovered at mount time (property-based, not hardcoded)
|
|
struct MountAnimSet {
|
|
uint32_t jumpStart = 0;
|
|
uint32_t jumpLoop = 0;
|
|
uint32_t jumpEnd = 0;
|
|
uint32_t rearUp = 0;
|
|
uint32_t run = 0;
|
|
uint32_t stand = 0;
|
|
// Flight animations
|
|
uint32_t flyIdle = 0;
|
|
uint32_t flyForward = 0;
|
|
uint32_t flyBackwards = 0;
|
|
uint32_t flyLeft = 0;
|
|
uint32_t flyRight = 0;
|
|
uint32_t flyUp = 0;
|
|
uint32_t flyDown = 0;
|
|
std::vector<uint32_t> fidgets;
|
|
};
|
|
|
|
enum class MountState : uint8_t {
|
|
IDLE, RUN, JUMP_START, JUMP_LOOP, JUMP_LAND, REAR_UP, FLY,
|
|
};
|
|
|
|
enum class MountAction : uint8_t { None, Jump, RearUp };
|
|
|
|
struct Input {
|
|
bool moving = false;
|
|
bool movingBackward = false;
|
|
bool strafeLeft = false;
|
|
bool strafeRight = false;
|
|
bool grounded = true;
|
|
bool jumpKeyPressed = false;
|
|
bool flying = false;
|
|
bool swimming = false;
|
|
bool ascending = false;
|
|
bool descending = false;
|
|
bool taxiFlight = false;
|
|
float deltaTime = 0.0f;
|
|
float characterYaw = 0.0f;
|
|
// Mount anim state query
|
|
uint32_t curMountAnim = 0;
|
|
float curMountTime = 0.0f;
|
|
float curMountDuration = 0.0f;
|
|
bool haveMountState = false;
|
|
};
|
|
|
|
/// Output from evaluate(): what to play on rider + mount, and positioning data.
|
|
struct Output {
|
|
// Mount animation
|
|
uint32_t mountAnimId = 0;
|
|
bool mountAnimLoop = true;
|
|
bool mountAnimChanged = false; // true = should call playAnimation
|
|
|
|
// Rider animation
|
|
uint32_t riderAnimId = 0;
|
|
bool riderAnimLoop = true;
|
|
bool riderAnimChanged = false;
|
|
|
|
// Mount procedural motion
|
|
float mountBob = 0.0f; // Vertical bob offset
|
|
float mountPitch = 0.0f; // Pitch (forward lean)
|
|
float mountRoll = 0.0f; // Roll (banking)
|
|
|
|
// Signals
|
|
bool playJumpSound = false;
|
|
bool playLandSound = false;
|
|
bool playRearUpSound = false;
|
|
bool playIdleSound = false;
|
|
bool triggerMountJump = false; // Tell camera controller to jump
|
|
bool fidgetStarted = false;
|
|
};
|
|
|
|
void configure(const MountAnimSet& anims, bool taxiFlight);
|
|
void clear();
|
|
void onEvent(AnimEvent event);
|
|
|
|
/// Main evaluation: produces Output describing what to play.
|
|
Output evaluate(const Input& in);
|
|
|
|
bool isActive() const { return active_; }
|
|
MountState getState() const { return state_; }
|
|
MountAction getAction() const { return action_; }
|
|
const MountAnimSet& getAnims() const { return anims_; }
|
|
|
|
private:
|
|
bool active_ = false;
|
|
MountState state_ = MountState::IDLE;
|
|
MountAction action_ = MountAction::None;
|
|
uint32_t actionPhase_ = 0;
|
|
|
|
MountAnimSet anims_;
|
|
bool taxiFlight_ = false;
|
|
|
|
// Fidget system — per-instance, not static
|
|
float fidgetTimer_ = 0.0f;
|
|
float nextFidgetTime_ = 8.0f;
|
|
uint32_t activeFidget_ = 0;
|
|
std::mt19937 rng_;
|
|
|
|
// Idle ambient sound timer
|
|
float idleSoundTimer_ = 0.0f;
|
|
float nextIdleSoundTime_ = 60.0f;
|
|
|
|
// Procedural lean
|
|
float prevYaw_ = 0.0f;
|
|
float roll_ = 0.0f;
|
|
|
|
// Last mount animation for change detection
|
|
uint32_t lastMountAnim_ = 0;
|
|
|
|
/// Resolve the mount animation for the given input (non-taxi).
|
|
uint32_t resolveGroundOrFlyAnim(const Input& in) const;
|
|
|
|
/// Check if an action animation has completed.
|
|
bool actionAnimComplete(const Input& in) const;
|
|
};
|
|
|
|
} // namespace rendering
|
|
} // namespace wowee
|