162 lines
7.7 KiB
C++
162 lines
7.7 KiB
C++
#pragma once
|
|
#include "CharacterState.h"
|
|
#include "BoneAnimatedModelNew.h"
|
|
#include "render/Renderer.h"
|
|
#include "render/TextureManager.h"
|
|
#include "SparkEmitter.h"
|
|
#include <functional>
|
|
#include <memory>
|
|
#include <map>
|
|
#include <string>
|
|
#include <cstdint>
|
|
#include <vector>
|
|
#include <unordered_map>
|
|
#include "dialogue/TranslationDatabase.h"
|
|
#include "AudioPlayerAsync.h"
|
|
|
|
namespace ZL {
|
|
|
|
class TextRenderer;
|
|
|
|
class Character {
|
|
public:
|
|
// Resolves a character index to a live Character pointer.
|
|
// kNoTarget (-1) → nullptr, kPlayerIndex (-2) → Location::player, 0..n → npcs[n].
|
|
using CharacterResolver = std::function<Character*(int index)>;
|
|
|
|
using PathPlanner = std::function<std::vector<Eigen::Vector3f>(
|
|
const Eigen::Vector3f& start,
|
|
const Eigen::Vector3f& end)>;
|
|
|
|
// All serializable game state (position, hp, flags, pathfinding, etc.)
|
|
CharacterState state;
|
|
|
|
int index = CharacterState::kNoTarget;
|
|
|
|
// ---- Asset loading ----
|
|
void loadAnimation(AnimationState animState, const std::string& filename, const std::string& zipFile = "");
|
|
void loadBinaryAnimation(AnimationState animState, const std::string& filename, const std::string& zipFile = "");
|
|
|
|
// Assigns a texture to a specific mesh by name.
|
|
void setTexture(const std::string& meshName, std::shared_ptr<Texture> texture);
|
|
// Assigns one texture to every mesh in every loaded animation. Call AFTER loading animations.
|
|
void setTexture(std::shared_ptr<ZL::Texture> texture);
|
|
|
|
// Creates a fully-loaded Character from a CharacterState (including its creationInfo).
|
|
// Loads all animations, textures, and weapon mesh/texture from the paths stored in creationInfo.
|
|
static std::unique_ptr<Character> createFromState(CharacterState st, Renderer& renderer, const char* zipFile);
|
|
|
|
// ---- Per-frame update ----
|
|
// resolver maps character indices to live pointers so attackTargetIndex / faceTargetIndex
|
|
// can be dereferenced inside update(). Pass nullptr only if no targets are set.
|
|
void update(int64_t deltaMs, const CharacterResolver& resolver = nullptr);
|
|
|
|
void setPathPlanner(PathPlanner planner);
|
|
|
|
// ---- Navigation (path data lives in state; pathPlanner lives here) ----
|
|
// callbackName, if given, is the global Lua function name backing onArrived —
|
|
// stored in state.onArrivedCallbackName so it survives save/load (see ScriptEngine::rehydrateNamedCallback).
|
|
void setTarget(const Eigen::Vector3f& target, std::function<void()> onArrived = nullptr, std::string callbackName = "");
|
|
void stopAndRotateToTarget(int npcId);
|
|
|
|
void forceReplan();
|
|
void stopInPlace() { state.stopInPlace(); }
|
|
|
|
// ---- Reset ----
|
|
void resetPlayerAfterDeath();
|
|
|
|
void tryAttackCombo();
|
|
|
|
// ---- Damage ----
|
|
void applyDamage(float damageAmount, const Eigen::Vector3f& attackDirection = Eigen::Vector3f::Zero(), int attackerIndex = CharacterState::kNoTarget);
|
|
|
|
// ---- Spark setup ----
|
|
void setupHitSparks(std::shared_ptr<Texture> sparkTexture);
|
|
void prepareHitSparksForDraw(const Eigen::Matrix4f& cameraViewMatrix);
|
|
|
|
// ---- HUD overlays ----
|
|
void drawName(TextRenderer& textRenderer,
|
|
const Eigen::Matrix4f& cameraViewMatrix,
|
|
const Eigen::Matrix4f& projectionMatrix);
|
|
void drawHealthBar(Renderer& renderer,
|
|
const Eigen::Matrix4f& cameraViewMatrix,
|
|
const Eigen::Matrix4f& projectionMatrix);
|
|
|
|
// ---- Draw passes ----
|
|
void draw(Renderer& renderer);
|
|
void drawShadowDepth(Renderer& renderer);
|
|
void drawWithShadow(Renderer& renderer, const Eigen::Matrix4f& lightFromCamera, GLuint shadowMapTex, const Eigen::Vector3f& lightDirCamera);
|
|
void drawNight(Renderer& renderer,
|
|
const float* pointLightPosEye, const float* pointLightDirEye,
|
|
const float* pointLightColors, int pointLightCount,
|
|
const float* pointLightWorldXZ, const float* pointLightLimitXZ,
|
|
const Eigen::Matrix4f& cameraViewInverse,
|
|
const float* ambientColor, const float* fogColor);
|
|
void drawNightWithShadow(Renderer& renderer,
|
|
const float* plPosEye, const float* plDirEye, const float* plColors, int plCount,
|
|
const float* plWorldXZ, const float* plLimitXZ,
|
|
const Eigen::Matrix4f& cameraViewInverse,
|
|
const Eigen::Matrix4f& lightFromCamera, GLuint shadowMapTex,
|
|
const float* ambientColor, const float* fogColor);
|
|
|
|
// ---- Query helpers (delegate to state) ----
|
|
bool isMoving() const { return state.isMoving(); }
|
|
const Eigen::Vector3f& getRequestedWalkTarget() const { return state.getRequestedWalkTarget(); }
|
|
Eigen::Vector3f getCurrentNavigationTarget() const { return state.getCurrentNavigationTarget(); }
|
|
float getHp() const { return state.getHp(); }
|
|
void setHp(float newHp) { state.setHp(newHp); }
|
|
|
|
float getSpeedMultiplier(float transitionProgress) const;
|
|
|
|
// ---- Weapon rendering data (initialized from state.creationInfo by createFromState) ----
|
|
VertexRenderStruct weaponMesh;
|
|
std::shared_ptr<Texture> weaponTexture;
|
|
Eigen::Matrix3f weaponInitialRotation = Eigen::Matrix3f::Identity();
|
|
Eigen::Vector3f weaponInitialPosition = Eigen::Vector3f::Zero();
|
|
std::string weaponAttachBoneName = "RightHand";
|
|
|
|
SparkEmitter hitSparkEmitter;
|
|
AudioPlayerAsync* audioPlayer;
|
|
|
|
static Dialogue::TranslationDatabase nameTranslations;
|
|
|
|
private:
|
|
std::map<AnimationState, BoneAnimationDataNew> animations;
|
|
VertexRenderStruct modelMutable;
|
|
VertexRenderStruct healthBarMesh;
|
|
std::unordered_map<std::string, std::shared_ptr<Texture>> meshTextures;
|
|
|
|
PathPlanner pathPlanner;
|
|
|
|
static constexpr float TARGET_REPLAN_THRESHOLD = 0.25f;
|
|
static constexpr float HOME_DRIFT_CHECK_INTERVAL = 5.0f;
|
|
|
|
AnimationState resolveActiveState() const;
|
|
bool prepareGpuSkinning();
|
|
void drawAttachedWeapon(Renderer& renderer);
|
|
|
|
void drawGpuSkinning(Renderer& renderer);
|
|
void drawShadowDepthGpuSkinning(Renderer& renderer);
|
|
void drawShadowDepthCpu(Renderer& renderer);
|
|
void drawGpuSkinningWithShadow(Renderer& renderer, const Eigen::Matrix4f& lightFromCamera, GLuint shadowMapTex, const Eigen::Vector3f& lightDirCamera);
|
|
void drawCpuWithShadow(Renderer& renderer, const Eigen::Matrix4f& lightFromCamera, GLuint shadowMapTex, const Eigen::Vector3f& lightDirCamera);
|
|
void drawNightGpuSkinning(Renderer& renderer,
|
|
const float* plPosEye, const float* plDirEye, const float* plColors, int plCount,
|
|
const float* plWorldXZ, const float* plLimitXZ, const Eigen::Matrix4f& cameraViewInverse,
|
|
const float* ambientColor, const float* fogColor);
|
|
void drawNightCpu(Renderer& renderer,
|
|
const float* plPosEye, const float* plDirEye, const float* plColors, int plCount,
|
|
const float* plWorldXZ, const float* plLimitXZ, const Eigen::Matrix4f& cameraViewInverse,
|
|
const float* ambientColor, const float* fogColor);
|
|
void drawNightGpuSkinningWithShadow(Renderer& renderer,
|
|
const float* plPosEye, const float* plDirEye, const float* plColors, int plCount,
|
|
const float* plWorldXZ, const float* plLimitXZ, const Eigen::Matrix4f& cameraViewInverse,
|
|
const Eigen::Matrix4f& lightFromCamera, GLuint shadowMapTex, const float* ambientColor, const float* fogColor);
|
|
void drawNightCpuWithShadow(Renderer& renderer,
|
|
const float* plPosEye, const float* plDirEye, const float* plColors, int plCount,
|
|
const float* plWorldXZ, const float* plLimitXZ, const Eigen::Matrix4f& cameraViewInverse,
|
|
const Eigen::Matrix4f& lightFromCamera, GLuint shadowMapTex, const float* ambientColor, const float* fogColor);
|
|
};
|
|
|
|
} // namespace ZL
|