Major refactoring - internal server state machine implemented
This commit is contained in:
1 parent
71c654e5b6
commit
66e93d46f4
48 files changed
+3948
-3696
No files matched your search
+59
-20
@@ -2,7 +2,9 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <functional>
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <Eigen/Core>
|
||||
#include <Eigen/Geometry>
|
||||
#include "external/nlohmann/json.hpp"
|
||||
@@ -12,6 +14,10 @@ namespace FRG {
|
||||
|
||||
constexpr float VISIBLE_RANGE = 6.f;
|
||||
|
||||
struct CharacterUpdateContext;
|
||||
struct CharacterUpdateEvents;
|
||||
struct LocationState;
|
||||
|
||||
enum class AnimationState {
|
||||
STAND = 0,
|
||||
WALK = 1,
|
||||
@@ -24,6 +30,8 @@ enum class AnimationState {
|
||||
DEATH_IDLE = 8,
|
||||
};
|
||||
|
||||
|
||||
|
||||
// Paths and fixed parameters needed to recreate a Character's visual assets
|
||||
// from scratch (e.g. after loading a saved game).
|
||||
struct CharacterCreationInfo {
|
||||
@@ -45,19 +53,14 @@ struct CharacterCreationInfo {
|
||||
float weaponMeshScale = 1.0f;
|
||||
};
|
||||
|
||||
// All serializable game state for a character.
|
||||
// This is a member of Character; rendering-only data lives in Character itself.
|
||||
// All serializable authoritative state for a character. GameState or
|
||||
// LocationGameState owns it; rendering-only data lives in Character.
|
||||
class CharacterState : public ISaveable {
|
||||
public:
|
||||
// Special index values for attackTargetIndex / faceTargetIndex
|
||||
static constexpr int kNoTarget = -1; // no target (was nullptr)
|
||||
static constexpr int kPlayerIndex = -2; // refers to Location::player
|
||||
|
||||
// Distance below which the character is considered to have reached its target.
|
||||
static constexpr float kWalkThreshold = 0.05f;
|
||||
|
||||
// --- Identity ---
|
||||
std::string npcId;
|
||||
std::string npcName;
|
||||
bool isPlayer = false;
|
||||
bool enabled = true;
|
||||
@@ -84,9 +87,11 @@ public:
|
||||
// Weapon visibility toggle (changes during animation)
|
||||
bool showWeapon = true;
|
||||
|
||||
// --- Index-based character references (replace raw pointers) ---
|
||||
int attackTargetIndex = kNoTarget;
|
||||
int faceTargetIndex = kNoTarget;
|
||||
// --- Stable character references ---
|
||||
// Empty means no target. "player" is the campaign player; NPC IDs are
|
||||
// location-local and validated while loading location content.
|
||||
std::string attackTargetId;
|
||||
std::string faceTargetId;
|
||||
|
||||
// --- Home position for drift recovery ---
|
||||
Eigen::Vector3f homePosition = Eigen::Vector3f::Zero();
|
||||
@@ -97,6 +102,13 @@ public:
|
||||
float slowMoActiveTime = 6.0f;
|
||||
float slowMoTransitionTime = 0.5f;
|
||||
|
||||
// --- Authoritative logical animation clock ---
|
||||
// Frame counts are immutable metadata copied from loaded clips during
|
||||
// character construction. Simulation advances animationFrame itself.
|
||||
float animationFrame = 0.0f;
|
||||
std::array<int, 9> animationStartFrames = {{0, 0, 0, 0, 0, 0, 0, 0, 0}};
|
||||
std::array<int, 9> animationFrameCounts = {{1, 1, 1, 1, 1, 1, 1, 1, 1}};
|
||||
|
||||
// --- Movement / visual parameters ---
|
||||
float walkSpeed = 3.0f;
|
||||
float rotationSpeed = 4.0f;
|
||||
@@ -115,14 +127,8 @@ public:
|
||||
// Internal drift-check timer (serializable so it survives save/load).
|
||||
float homeDriftCheckTimer = 5.0f;
|
||||
|
||||
// --- Non-serializable callbacks (re-wired after each load) ---
|
||||
std::function<void()> onArrivedCallback;
|
||||
std::function<void()> onDeathAnimComplete;
|
||||
std::function<void(float, float, int)> onHpChanged;
|
||||
|
||||
// Global Lua function name backing onArrivedCallback, if it was sourced from a
|
||||
// script (see ScriptEngine::rehydrateNamedCallback). Serialized so the callback
|
||||
// can be re-looked-up by name after a save/load; empty if none or non-Lua.
|
||||
// Global Lua function called when the character reaches the final waypoint.
|
||||
// The name is serialized, so no runtime callback needs to be rehydrated.
|
||||
std::string onArrivedCallbackName;
|
||||
|
||||
// --- Asset / creation info (used to reload visuals from a saved state) ---
|
||||
@@ -133,12 +139,45 @@ public:
|
||||
const Eigen::Vector3f& getRequestedWalkTarget() const { return requestedWalkTarget; }
|
||||
Eigen::Vector3f getCurrentNavigationTarget() const;
|
||||
void stopInPlace();
|
||||
void setTarget(const Eigen::Vector3f& target,
|
||||
std::string callbackName,
|
||||
const LocationState& location,
|
||||
const std::string& entityId);
|
||||
void forceReplan(const LocationState& location,
|
||||
const std::string& entityId);
|
||||
void stopAndRotateToTarget(std::string characterId);
|
||||
void resetPlayerAfterDeath();
|
||||
void tryAttackCombo();
|
||||
float getHp() const { return hp; }
|
||||
void setHp(float newHp);
|
||||
|
||||
CharacterUpdateEvents update(std::int64_t deltaMs, const CharacterUpdateContext& context);
|
||||
void setAnimationMetadata(AnimationState state, int startFrame, int frameCount);
|
||||
// --- Serialisation (runtime mutable fields only; creation info is reloaded from config) ---
|
||||
void save(nlohmann::json& out) const override;
|
||||
void load(const nlohmann::json& in) override;
|
||||
};
|
||||
|
||||
using PlayerStateMap =
|
||||
std::unordered_map<std::string, std::shared_ptr<CharacterState>>;
|
||||
|
||||
struct CharacterObservation {
|
||||
Eigen::Vector3f position = Eigen::Vector3f::Zero();
|
||||
float hp = 0.f;
|
||||
};
|
||||
|
||||
struct CharacterUpdateContext {
|
||||
const CharacterObservation* attackTarget = nullptr;
|
||||
const CharacterObservation* faceTarget = nullptr;
|
||||
};
|
||||
|
||||
struct CharacterUpdateEvents {
|
||||
bool attackImpact = false;
|
||||
bool deathAnimationComplete = false;
|
||||
bool navigationRequested = false;
|
||||
Eigen::Vector3f navigationTarget = Eigen::Vector3f::Zero();
|
||||
std::string arrivedCallbackName;
|
||||
std::string attackTargetId;
|
||||
Eigen::Vector3f attackDirection = Eigen::Vector3f::Zero();
|
||||
};
|
||||
|
||||
} // namespace FRG
|
||||
Reference in new issue
Block a user