#pragma once #include #include #include #include #include #include #include "external/nlohmann/json.hpp" #include "ISaveable.h" namespace FRG { constexpr float VISIBLE_RANGE = 6.f; enum class AnimationState { STAND = 0, WALK = 1, STAND_TO_ACTION = 2, ACTION_ATTACK = 3, ACTION_ATTACK_2 = 4, ACTION_IDLE = 5, ACTION_TO_STAND = 6, ACTION_TO_DEATH = 7, 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 { // Each entry is (AnimationState, filepath). Binary .anim format is auto-detected. std::vector> animationPaths; // Per-mesh texture paths (mesh name → path); takes priority over singleTexturePath. std::unordered_map meshTexturePaths; // Single shared texture path (used when setTexture(shared_ptr) was called on all meshes). std::string singleTexturePath; // Weapon asset paths and attachment setup std::string weaponMeshPath; std::string weaponTexturePath; std::string weaponAttachBoneName = "RightHand"; Eigen::Vector3f weaponInitialPosition = Eigen::Vector3f::Zero(); // Weapon orientation stored as a quaternion (serializable as 4 floats). Eigen::Quaternionf weaponInitialRotation = Eigen::Quaternionf::Identity(); // Optional mesh-space transformations applied after loading the weapon mesh. Eigen::Vector3f weaponMeshMove = Eigen::Vector3f::Zero(); float weaponMeshScale = 1.0f; }; // All serializable game state for a character. // This is a member of Character; rendering-only data lives in Character itself. 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; bool canAttack = false; // --- Position / orientation --- Eigen::Vector3f position = Eigen::Vector3f::Zero(); float facingAngle = 0.0f; float targetFacingAngle = 0.0f; // --- Health --- float hp = 200.f; float initialHp = 200.f; float visibleRange = VISIBLE_RANGE; // --- Combat flags --- int battle_state = 0; bool resetAnim = false; int attack = 0; AnimationState currentState = AnimationState::STAND; float attack_cooldown = 0.f; // Weapon visibility toggle (changes during animation) bool showWeapon = true; // --- Index-based character references (replace raw pointers) --- int attackTargetIndex = kNoTarget; int faceTargetIndex = kNoTarget; // --- Home position for drift recovery --- Eigen::Vector3f homePosition = Eigen::Vector3f::Zero(); float maxHomeDrift = 3.0f; // --- Slow-motion effect --- float slowMoTimeRemaining = 0.0f; float slowMoActiveTime = 6.0f; float slowMoTransitionTime = 0.5f; // --- Movement / visual parameters --- float walkSpeed = 3.0f; float rotationSpeed = 4.0f; float modelScale = 0.12f; Eigen::Quaternionf modelCorrectionRotation = Eigen::Quaternionf::Identity(); bool useGpuSkinning = true; float collisionRadius = 0.45f; float interactionRadius = 0.0f; // --- Pathfinding data (serializable parts) --- Eigen::Vector3f walkTarget = Eigen::Vector3f::Zero(); Eigen::Vector3f requestedWalkTarget = Eigen::Vector3f::Zero(); std::vector pathWaypoints; size_t currentWaypointIndex = 0; // Internal drift-check timer (serializable so it survives save/load). float homeDriftCheckTimer = 5.0f; // --- Non-serializable callbacks (re-wired after each load) --- std::function onArrivedCallback; std::function onDeathAnimComplete; std::function 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. std::string onArrivedCallbackName; // --- Asset / creation info (used to reload visuals from a saved state) --- CharacterCreationInfo creationInfo; // --- Pure-state methods --- bool isMoving() const; const Eigen::Vector3f& getRequestedWalkTarget() const { return requestedWalkTarget; } Eigen::Vector3f getCurrentNavigationTarget() const; void stopInPlace(); float getHp() const { return hp; } void setHp(float newHp); // --- 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; }; } // namespace FRG