space-game001/src/Character.h
Vladislav Khorev 2bb7da2e37 Added hp
2026-04-24 18:40:51 +03:00

134 lines
4.8 KiB
C++

#pragma once
#include "BoneAnimatedModelNew.h"
#include "render/Renderer.h"
#include "render/TextureManager.h"
#include "items/Item.h"
#include <functional>
#include <memory>
#include <map>
#include <string>
#include <cstdint>
#include <vector>
#include <unordered_map>
namespace ZL {
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,
};
class Character {
public:
using PathPlanner = std::function<std::vector<Eigen::Vector3f>(
const Eigen::Vector3f& start,
const Eigen::Vector3f& end)>;
void loadAnimation(AnimationState state, const std::string& filename, const std::string& zipFile = "");
void loadBinaryAnimation(AnimationState state, const std::string& filename, const std::string& zipFile = "");
// Assigns the given texture to a specific mesh (by name, as defined in the animation file).
void setTexture(const std::string& meshName, std::shared_ptr<Texture> texture);
// Assigns the given texture to every mesh in every loaded animation.
// Call AFTER loading animations so the mesh names are known.
void setTexture(std::shared_ptr<ZL::Texture> texture);
void update(int64_t deltaMs);
// onArrived is called once when the character reaches this target.
// From Python you can chain further commands (walk, wait, trigger others).
void setTarget(const Eigen::Vector3f& target,
std::function<void()> onArrived = nullptr);
void setPathPlanner(PathPlanner planner);
void draw(Renderer& renderer);
void drawShadowDepth(Renderer& renderer);
void drawWithShadow(Renderer& renderer, const Eigen::Matrix4f& lightFromCamera, GLuint shadowMapTex, const Eigen::Vector3f& lightDirCamera);
void applyDamage(float damageAmount);
// Public: read by Game for camera tracking and ray-cast origin
Eigen::Vector3f position = Eigen::Vector3f(0.f, 0.f, 0.f);
float facingAngle = 0.0f;
// Per-character tuning — set after construction, before first update
float walkSpeed = 3.0f;
float rotationSpeed = 4.0f;
float modelScale = 0.12f;
// Applied after scale, fixes model-space orientation (e.g. Blender Z-up exports)
Eigen::Quaternionf modelCorrectionRotation = Eigen::Quaternionf::Identity();
// NPC Gift
Item giftItem;
std::string npcId;
std::string npcName;
bool giftReceived = false;
float hp = 100.f;
int battle_state = 0;
bool resetAnim = false;
int attack = 0;
AnimationState currentState = AnimationState::STAND;
float attack_cooldown = 0.f;
bool canAttack = false;
Character* attackTarget = nullptr;
bool isPlayer = false;
bool useGpuSkinning = true;
//bool useGpuSkinning = false;
float interactionRadius = 0.0f;
VertexRenderStruct weaponMesh;
std::shared_ptr<Texture> weaponTexture;
Eigen::Matrix3f weaponInitialRotation = Eigen::Matrix3f::Identity();
Eigen::Vector3f weaponInitialPosition = Eigen::Vector3f::Zero();
std::string weaponAttachBoneName = "RightHand";
bool showWeapon = true;
private:
std::map<AnimationState, BoneAnimationDataNew> animations;
VertexRenderStruct modelMutable;
std::unordered_map<std::string, std::shared_ptr<Texture>> meshTextures;
Eigen::Vector3f walkTarget = Eigen::Vector3f(0.f, 0.f, 0.f);
Eigen::Vector3f requestedWalkTarget = Eigen::Vector3f(0.f, 0.f, 0.f);
std::vector<Eigen::Vector3f> pathWaypoints;
size_t currentWaypointIndex = 0;
PathPlanner pathPlanner;
float targetFacingAngle = 0.0f;
std::function<void()> onArrivedCallback;
static constexpr float WALK_THRESHOLD = 0.05f;
static constexpr float TARGET_REPLAN_THRESHOLD = 0.25f;
// Returns the animation state to actually play/draw, falling back to IDLE
// if the requested state has no loaded animation.
AnimationState resolveActiveState() const;
bool prepareGpuSkinning();
// Draws the weapon mesh attached to weaponAttachBoneName.
// Caller must ensure the right shader is active with matching uniforms.
void drawAttachedWeapon(Renderer& renderer);
// GPU skinning: draw using shader-based skinning
void drawGpuSkinning(Renderer& renderer);
// Shadow: draw into depth map (no texture, no projection push)
void drawShadowDepthGpuSkinning(Renderer& renderer);
void drawShadowDepthCpu(Renderer& renderer);
// Shadow: draw with shadow-aware shaders
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);
};
} // namespace ZL