Minor code change for CharacterState
This commit is contained in:
parent
0eb9d0be25
commit
0ca00f965d
@ -108,7 +108,7 @@ namespace ZL
|
||||
// Load NPCs from JSON. Aggressive (canAttack) NPCs need a player target
|
||||
// and hit sparks; peaceful NPCs don't take damage from the player so
|
||||
// they don't need either.
|
||||
npcs = GameObjectLoader::loadAndCreate_Npcs(params.npcsJsonPath, CONST_ZIP_FILE);
|
||||
npcs = GameObjectLoader::loadAndCreate_Npcs(params.npcsJsonPath, renderer, CONST_ZIP_FILE);
|
||||
for (auto& npc : npcs) {
|
||||
if (!npc) continue;
|
||||
npc->state.homePosition = Eigen::Vector3f(npc->state.position.x(), 0.f, npc->state.position.z());
|
||||
|
||||
@ -312,97 +312,73 @@ namespace ZL {
|
||||
return npcs;
|
||||
}
|
||||
|
||||
CharacterState NpcData::toCharacterState() const {
|
||||
CharacterState st;
|
||||
|
||||
// Identity + game state
|
||||
st.npcId = id;
|
||||
st.npcName = name;
|
||||
st.position = Eigen::Vector3f(positionX, positionY, positionZ);
|
||||
st.facingAngle = facingAngle;
|
||||
st.walkSpeed = walkSpeed;
|
||||
st.rotationSpeed = rotationSpeed;
|
||||
st.modelScale = modelScale;
|
||||
st.setHp(hp);
|
||||
st.initialHp = hp;
|
||||
st.canAttack = canAttack;
|
||||
st.enabled = enabled;
|
||||
st.interactionRadius = interactionRadius;
|
||||
|
||||
Eigen::Quaternionf corrRot = Eigen::Quaternionf::Identity();
|
||||
if (modelCorrectionRotX != 0.0f)
|
||||
corrRot = Eigen::Quaternionf(Eigen::AngleAxisf(modelCorrectionRotX, Eigen::Vector3f::UnitX())) * corrRot;
|
||||
if (modelCorrectionRotY != 0.0f)
|
||||
corrRot = Eigen::Quaternionf(Eigen::AngleAxisf(modelCorrectionRotY, Eigen::Vector3f::UnitY())) * corrRot;
|
||||
if (modelCorrectionRotZ != 0.0f)
|
||||
corrRot = Eigen::Quaternionf(Eigen::AngleAxisf(modelCorrectionRotZ, Eigen::Vector3f::UnitZ())) * corrRot;
|
||||
st.modelCorrectionRotation = corrRot;
|
||||
|
||||
// Creation info: animation paths
|
||||
CharacterCreationInfo& info = st.creationInfo;
|
||||
auto addAnim = [&](AnimationState animState, const std::string& path) {
|
||||
if (!path.empty())
|
||||
info.animationPaths.emplace_back(animState, path);
|
||||
};
|
||||
addAnim(AnimationState::STAND, animationIdlePath);
|
||||
addAnim(AnimationState::WALK, animationWalkPath);
|
||||
addAnim(AnimationState::ACTION_IDLE, animationActionIdlePath);
|
||||
addAnim(AnimationState::ACTION_ATTACK, animationActionAttackPath);
|
||||
addAnim(AnimationState::STAND_TO_ACTION, animationStandToActionPath);
|
||||
addAnim(AnimationState::ACTION_TO_STAND, animationActionToStandPath);
|
||||
addAnim(AnimationState::ACTION_TO_DEATH, animationActionToDeathPath);
|
||||
addAnim(AnimationState::DEATH_IDLE, animationDeathIdlePath);
|
||||
|
||||
// Creation info: textures
|
||||
info.meshTexturePaths = std::unordered_map<std::string, std::string>(meshTextures.begin(), meshTextures.end());
|
||||
info.singleTexturePath = texturePath;
|
||||
|
||||
return st;
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<Character>> GameObjectLoader::loadAndCreate_Npcs(
|
||||
const std::string& jsonPath,
|
||||
Renderer& renderer,
|
||||
const std::string& zipPath)
|
||||
{
|
||||
std::vector<std::unique_ptr<Character>> npcs;
|
||||
|
||||
for (const auto& npcData : loadNpcsFromJson(jsonPath, zipPath)) {
|
||||
std::cout << "Loading NPC: " << npcData.name << std::endl;
|
||||
|
||||
auto npc = std::make_unique<Character>();
|
||||
|
||||
try {
|
||||
if (npcData.animationIdlePath.substr(npcData.animationIdlePath.size() - 5) == ".anim")
|
||||
npc->loadBinaryAnimation(AnimationState::STAND, npcData.animationIdlePath, zipPath);
|
||||
else
|
||||
npc->loadAnimation(AnimationState::STAND, npcData.animationIdlePath, zipPath);
|
||||
std::cout << " Loaded IDLE animation: " << npcData.animationIdlePath << std::endl;
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << "GameObjectLoader: Failed to load IDLE animation for '" << npcData.name << "': " << e.what() << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
if (npcData.animationWalkPath.substr(npcData.animationWalkPath.size() - 5) == ".anim")
|
||||
npc->loadBinaryAnimation(AnimationState::WALK, npcData.animationWalkPath, zipPath);
|
||||
else
|
||||
npc->loadAnimation(AnimationState::WALK, npcData.animationWalkPath, zipPath);
|
||||
std::cout << " Loaded WALK animation: " << npcData.animationWalkPath << std::endl;
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << "GameObjectLoader: Failed to load WALK animation for '" << npcData.name << "': " << e.what() << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
auto loadOptionalAnim = [&](AnimationState animState, const std::string& path, const char* label) {
|
||||
if (path.empty()) return;
|
||||
try {
|
||||
if (path.size() >= 5 && path.substr(path.size() - 5) == ".anim")
|
||||
npc->loadBinaryAnimation(animState, path, zipPath);
|
||||
else
|
||||
npc->loadAnimation(animState, path, zipPath);
|
||||
std::cout << " Loaded " << label << " animation: " << path << std::endl;
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << "GameObjectLoader: Failed to load " << label
|
||||
<< " animation for '" << npcData.name << "': " << e.what() << std::endl;
|
||||
auto npc = Character::createFromState(npcData.toCharacterState(), renderer, zipPath.c_str());
|
||||
if (npc) {
|
||||
std::cout << "Successfully loaded NPC: " << npcData.name << " at ("
|
||||
<< npcData.positionX << ", " << npcData.positionY << ", " << npcData.positionZ << ")" << std::endl;
|
||||
npcs.push_back(std::move(npc));
|
||||
}
|
||||
};
|
||||
loadOptionalAnim(AnimationState::ACTION_IDLE, npcData.animationActionIdlePath, "ACTION_IDLE");
|
||||
loadOptionalAnim(AnimationState::ACTION_ATTACK, npcData.animationActionAttackPath, "ACTION_ATTACK");
|
||||
loadOptionalAnim(AnimationState::STAND_TO_ACTION, npcData.animationStandToActionPath, "STAND_TO_ACTION");
|
||||
loadOptionalAnim(AnimationState::ACTION_TO_STAND, npcData.animationActionToStandPath, "ACTION_TO_STAND");
|
||||
loadOptionalAnim(AnimationState::ACTION_TO_DEATH, npcData.animationActionToDeathPath, "ACTION_TO_DEATH");
|
||||
loadOptionalAnim(AnimationState::DEATH_IDLE, npcData.animationDeathIdlePath, "DEATH_IDLE");
|
||||
|
||||
try {
|
||||
|
||||
for (const auto& entry : npcData.meshTextures) {
|
||||
npc->setTexture(entry.first, std::make_shared<Texture>(CreateTextureDataFromPng(entry.second, zipPath.c_str())));
|
||||
std::cout << " -> mesh '" << entry.first << "'" << std::endl;
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << "GameObjectLoader: Failed to load texture for '" << npcData.name << "': " << e.what() << std::endl;
|
||||
continue;
|
||||
std::cerr << "GameObjectLoader: Failed to load NPC '" << npcData.name << "': " << e.what() << std::endl;
|
||||
}
|
||||
|
||||
npc->state.walkSpeed = npcData.walkSpeed;
|
||||
npc->state.rotationSpeed = npcData.rotationSpeed;
|
||||
npc->state.modelScale = npcData.modelScale;
|
||||
npc->state.position = Eigen::Vector3f(npcData.positionX, npcData.positionY, npcData.positionZ);
|
||||
npc->state.facingAngle = npcData.facingAngle;
|
||||
npc->state.setHp(npcData.hp);
|
||||
npc->state.initialHp = npcData.hp;
|
||||
npc->state.canAttack = npcData.canAttack;
|
||||
npc->state.enabled = npcData.enabled;
|
||||
npc->state.interactionRadius = npcData.interactionRadius;
|
||||
npc->state.npcId = npcData.id;
|
||||
npc->state.npcName = npcData.name;
|
||||
|
||||
Eigen::Quaternionf corrRot = Eigen::Quaternionf::Identity();
|
||||
if (npcData.modelCorrectionRotX != 0.0f)
|
||||
corrRot = Eigen::Quaternionf(Eigen::AngleAxisf(npcData.modelCorrectionRotX, Eigen::Vector3f::UnitX())) * corrRot;
|
||||
if (npcData.modelCorrectionRotY != 0.0f)
|
||||
corrRot = Eigen::Quaternionf(Eigen::AngleAxisf(npcData.modelCorrectionRotY, Eigen::Vector3f::UnitY())) * corrRot;
|
||||
if (npcData.modelCorrectionRotZ != 0.0f)
|
||||
corrRot = Eigen::Quaternionf(Eigen::AngleAxisf(npcData.modelCorrectionRotZ, Eigen::Vector3f::UnitZ())) * corrRot;
|
||||
npc->state.modelCorrectionRotation = corrRot;
|
||||
|
||||
npc->setTarget(npc->state.position);
|
||||
npcs.push_back(std::move(npc));
|
||||
|
||||
std::cout << "Successfully loaded NPC: " << npcData.name << " at ("
|
||||
<< npcData.positionX << ", " << npcData.positionY << ", " << npcData.positionZ << ")" << std::endl;
|
||||
}
|
||||
|
||||
std::cout << "Total NPCs loaded: " << npcs.size() << std::endl;
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
#include "external/nlohmann/json.hpp"
|
||||
#include "TextModel.h"
|
||||
#include "InteractiveObject.h"
|
||||
#include "../CharacterState.h"
|
||||
|
||||
namespace ZL {
|
||||
|
||||
@ -71,6 +72,10 @@ namespace ZL {
|
||||
bool canAttack = false;
|
||||
bool enabled = true;
|
||||
float interactionRadius = 0.0f;
|
||||
|
||||
// Converts this JSON-parsed descriptor into a fully-populated CharacterState
|
||||
// (including creationInfo) ready for Character::createFromState().
|
||||
CharacterState toCharacterState() const;
|
||||
};
|
||||
|
||||
class GameObjectLoader {
|
||||
@ -89,6 +94,7 @@ namespace ZL {
|
||||
|
||||
static std::vector<std::unique_ptr<ZL::Character>> loadAndCreate_Npcs(
|
||||
const std::string& jsonPath,
|
||||
Renderer& renderer,
|
||||
const std::string& zipPath = ""
|
||||
);
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user