More work on states, added bot
This commit is contained in:
1 parent
66e93d46f4
commit
5e9a663812
25 files changed
+1595
-740
No files matched your search
+235
-138
@@ -1,4 +1,4 @@
|
||||
#include "Character.h"
|
||||
#include "Character.h"
|
||||
#include "render/TextRenderer.h"
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
@@ -19,6 +19,44 @@ namespace FRG {
|
||||
|
||||
Dialogue::TranslationDatabase Character::nameTranslations;
|
||||
|
||||
std::shared_ptr<const CharacterState> Character::stateSnapshot() const {
|
||||
auto snapshot = gameServer_.snapshot();
|
||||
if (!snapshot) return {};
|
||||
|
||||
auto player = snapshot->players.find(entityId_);
|
||||
if (player != snapshot->players.end()) {
|
||||
return std::shared_ptr<const CharacterState>(
|
||||
std::move(snapshot), &player->second.state);
|
||||
}
|
||||
|
||||
auto location = snapshot->locations.find(locationId_);
|
||||
if (location == snapshot->locations.end()) return {};
|
||||
auto npc = location->second.npcs.find(entityId_);
|
||||
if (npc == location->second.npcs.end()) return {};
|
||||
return std::shared_ptr<const CharacterState>(
|
||||
std::move(snapshot), &npc->second.state);
|
||||
}
|
||||
|
||||
bool Character::isMoving() const {
|
||||
auto state = stateSnapshot();
|
||||
return state && state->isMoving();
|
||||
}
|
||||
|
||||
Eigen::Vector3f Character::getRequestedWalkTarget() const {
|
||||
auto state = stateSnapshot();
|
||||
return state ? state->getRequestedWalkTarget() : Eigen::Vector3f::Zero();
|
||||
}
|
||||
|
||||
Eigen::Vector3f Character::getCurrentNavigationTarget() const {
|
||||
auto state = stateSnapshot();
|
||||
return state ? state->getCurrentNavigationTarget() : Eigen::Vector3f::Zero();
|
||||
}
|
||||
|
||||
float Character::getHp() const {
|
||||
auto state = stateSnapshot();
|
||||
return state ? state->getHp() : 0.f;
|
||||
}
|
||||
|
||||
void Character::loadAnimation(AnimationState animState, const std::string& filename, const std::string& zipFile) {
|
||||
auto& data = animations[animState];
|
||||
data.model.LoadFromFile(filename, zipFile);
|
||||
@@ -46,7 +84,7 @@ void Character::loadBinaryAnimation(AnimationState animState, const std::string&
|
||||
std::unique_ptr<Character> Character::createFromState(const CharacterState& st, IGameServer& server,
|
||||
const std::string& locationId, const std::string& entityId,
|
||||
Renderer& renderer, const char* zipFile) {
|
||||
auto c = std::make_unique<Character>(st, server, locationId, entityId);
|
||||
auto c = std::make_unique<Character>(server, locationId, entityId);
|
||||
|
||||
const std::string zip = zipFile ? zipFile : "";
|
||||
|
||||
@@ -62,7 +100,7 @@ std::unique_ptr<Character> Character::createFromState(const CharacterState& st,
|
||||
}
|
||||
};
|
||||
|
||||
for (const auto& [animState, path] : c->characterState.creationInfo.animationPaths)
|
||||
for (const auto& [animState, path] : st.creationInfo.animationPaths)
|
||||
loadAnim(animState, path);
|
||||
|
||||
auto loadTex = [&](const std::string& path) -> std::shared_ptr<Texture> {
|
||||
@@ -76,27 +114,27 @@ std::unique_ptr<Character> Character::createFromState(const CharacterState& st,
|
||||
}
|
||||
};
|
||||
|
||||
if (!c->characterState.creationInfo.singleTexturePath.empty()) {
|
||||
auto tex = loadTex(c->characterState.creationInfo.singleTexturePath);
|
||||
if (!st.creationInfo.singleTexturePath.empty()) {
|
||||
auto tex = loadTex(st.creationInfo.singleTexturePath);
|
||||
if (tex) c->setTexture(tex);
|
||||
}
|
||||
for (const auto& [meshName, texPath] : c->characterState.creationInfo.meshTexturePaths) {
|
||||
for (const auto& [meshName, texPath] : st.creationInfo.meshTexturePaths) {
|
||||
auto tex = loadTex(texPath);
|
||||
if (tex) c->setTexture(meshName, tex);
|
||||
}
|
||||
|
||||
if (!c->characterState.creationInfo.weaponMeshPath.empty()) {
|
||||
const std::string& wp = c->characterState.creationInfo.weaponMeshPath;
|
||||
if (!st.creationInfo.weaponMeshPath.empty()) {
|
||||
const std::string& wp = st.creationInfo.weaponMeshPath;
|
||||
try {
|
||||
if (wp.size() >= 4 && wp.substr(wp.size() - 4) == ".bin")
|
||||
c->weaponMesh.data = LoadModelFromBinFile(wp, zip);
|
||||
else
|
||||
c->weaponMesh.data = LoadFromTextFile02(wp, zip);
|
||||
|
||||
if (c->characterState.creationInfo.weaponMeshMove != Eigen::Vector3f::Zero())
|
||||
c->weaponMesh.data.Move(c->characterState.creationInfo.weaponMeshMove);
|
||||
if (c->characterState.creationInfo.weaponMeshScale != 1.0f)
|
||||
c->weaponMesh.data.Scale(c->characterState.creationInfo.weaponMeshScale);
|
||||
if (st.creationInfo.weaponMeshMove != Eigen::Vector3f::Zero())
|
||||
c->weaponMesh.data.Move(st.creationInfo.weaponMeshMove);
|
||||
if (st.creationInfo.weaponMeshScale != 1.0f)
|
||||
c->weaponMesh.data.Scale(st.creationInfo.weaponMeshScale);
|
||||
|
||||
c->weaponMesh.RefreshVBO();
|
||||
} catch (const std::exception& e) {
|
||||
@@ -104,10 +142,10 @@ std::unique_ptr<Character> Character::createFromState(const CharacterState& st,
|
||||
}
|
||||
}
|
||||
|
||||
c->weaponTexture = loadTex(c->characterState.creationInfo.weaponTexturePath);
|
||||
c->weaponAttachBoneName = c->characterState.creationInfo.weaponAttachBoneName;
|
||||
c->weaponInitialPosition = c->characterState.creationInfo.weaponInitialPosition;
|
||||
c->weaponInitialRotation = c->characterState.creationInfo.weaponInitialRotation.toRotationMatrix();
|
||||
c->weaponTexture = loadTex(st.creationInfo.weaponTexturePath);
|
||||
c->weaponAttachBoneName = st.creationInfo.weaponAttachBoneName;
|
||||
c->weaponInitialPosition = st.creationInfo.weaponInitialPosition;
|
||||
c->weaponInitialRotation = st.creationInfo.weaponInitialRotation.toRotationMatrix();
|
||||
|
||||
return c;
|
||||
}
|
||||
@@ -124,8 +162,8 @@ void Character::setTexture(const std::string& meshName, std::shared_ptr<Texture>
|
||||
meshTextures[meshName] = std::move(tex);
|
||||
}
|
||||
|
||||
AnimationState Character::resolveActiveState() const {
|
||||
if (animations.count(characterState.currentState)) return characterState.currentState;
|
||||
AnimationState Character::resolveActiveState(const CharacterState& state) const {
|
||||
if (animations.count(state.currentState)) return state.currentState;
|
||||
return AnimationState::STAND;
|
||||
}
|
||||
|
||||
@@ -134,29 +172,33 @@ void Character::update(int64_t deltaMs, const CharacterUpdateEvents* events) {
|
||||
hitSparkEmitter.update(static_cast<float>(deltaMs));
|
||||
}
|
||||
|
||||
auto stateSnapshot = this->stateSnapshot();
|
||||
if (!stateSnapshot) return;
|
||||
const CharacterState& state = *stateSnapshot;
|
||||
|
||||
if (events) {
|
||||
if (events->deathAnimationComplete && onDeathAnimComplete)
|
||||
onDeathAnimComplete();
|
||||
if (events->attackImpact && audioPlayer) {
|
||||
audioPlayer->playSoundAsync(characterState.isPlayer
|
||||
audioPlayer->playSoundAsync(state.isPlayer
|
||||
? "resources/audio/547041__cogfirestudios__hit-swing-sword-small-3.ogg"
|
||||
: "resources/audio/13925__adcbicycle__21.ogg");
|
||||
}
|
||||
}
|
||||
|
||||
if (!characterState.enabled) return;
|
||||
auto it = animations.find(characterState.currentState);
|
||||
if (!state.enabled) return;
|
||||
auto it = animations.find(state.currentState);
|
||||
if (it == animations.end()) return;
|
||||
|
||||
auto& anim = it->second;
|
||||
anim.currentFrame = (std::min)(
|
||||
characterState.animationFrame, static_cast<float>((std::max)(0, anim.totalFrames - 1)));
|
||||
state.animationFrame, static_cast<float>((std::max)(0, anim.totalFrames - 1)));
|
||||
|
||||
if (static_cast<int>(anim.currentFrame) != anim.lastFrame) {
|
||||
anim.gpuSkinningShaderData.ComputeSkinningMatrices(
|
||||
anim.model.startBones, anim.model.animations[0].keyFrames,
|
||||
static_cast<int>(anim.currentFrame));
|
||||
if (!characterState.useGpuSkinning) {
|
||||
if (!state.useGpuSkinning) {
|
||||
anim.model.Interpolate(static_cast<int>(anim.currentFrame));
|
||||
}
|
||||
anim.lastFrame = static_cast<int>(anim.currentFrame);
|
||||
@@ -171,14 +213,17 @@ void Character::draw(Renderer& renderer) {
|
||||
renderer.RenderUniform1f("uAlpha", 1.0f);
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
if (!characterState.enabled) return;
|
||||
auto stateSnapshot = this->stateSnapshot();
|
||||
if (!stateSnapshot) return;
|
||||
const CharacterState& state = *stateSnapshot;
|
||||
if (!state.enabled) return;
|
||||
|
||||
if (characterState.useGpuSkinning) {
|
||||
drawGpuSkinning(renderer);
|
||||
if (state.useGpuSkinning) {
|
||||
drawGpuSkinning(renderer, state);
|
||||
return;
|
||||
}
|
||||
|
||||
AnimationState drawState = resolveActiveState();
|
||||
AnimationState drawState = resolveActiveState(state);
|
||||
auto it = animations.find(drawState);
|
||||
if (it == animations.end()) return;
|
||||
|
||||
@@ -192,10 +237,10 @@ void Character::draw(Renderer& renderer) {
|
||||
Environment::CONST_Z_NEAR, Environment::CONST_Z_FAR);
|
||||
|
||||
renderer.PushMatrix();
|
||||
renderer.TranslateMatrix({ characterState.position.x(), characterState.position.y(), characterState.position.z() });
|
||||
renderer.RotateMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(-characterState.facingAngle, Eigen::Vector3f::UnitY())).toRotationMatrix());
|
||||
renderer.ScaleMatrix(characterState.modelScale);
|
||||
renderer.RotateMatrix(characterState.modelCorrectionRotation.toRotationMatrix());
|
||||
renderer.TranslateMatrix({ state.position.x(), state.position.y(), state.position.z() });
|
||||
renderer.RotateMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(-state.facingAngle, Eigen::Vector3f::UnitY())).toRotationMatrix());
|
||||
renderer.ScaleMatrix(state.modelScale);
|
||||
renderer.RotateMatrix(state.modelCorrectionRotation.toRotationMatrix());
|
||||
|
||||
auto& anim = it->second;
|
||||
for (const auto& name : anim.model.meshNamesOrdered) {
|
||||
@@ -211,14 +256,14 @@ void Character::draw(Renderer& renderer) {
|
||||
|
||||
renderer.PopMatrix();
|
||||
|
||||
drawAttachedWeapon(renderer);
|
||||
drawAttachedWeapon(renderer, state);
|
||||
|
||||
renderer.PopProjectionMatrix();
|
||||
renderer.shaderManager.PopShader();
|
||||
}
|
||||
|
||||
void Character::drawGpuSkinning(Renderer& renderer) {
|
||||
AnimationState drawState = resolveActiveState();
|
||||
void Character::drawGpuSkinning(Renderer& renderer, const CharacterState& state) {
|
||||
AnimationState drawState = resolveActiveState(state);
|
||||
auto it = animations.find(drawState);
|
||||
if (it == animations.end()) return;
|
||||
|
||||
@@ -246,10 +291,10 @@ void Character::drawGpuSkinning(Renderer& renderer) {
|
||||
Environment::CONST_Z_NEAR, Environment::CONST_Z_FAR);
|
||||
|
||||
renderer.PushMatrix();
|
||||
renderer.TranslateMatrix({ characterState.position.x(), characterState.position.y(), characterState.position.z() });
|
||||
renderer.RotateMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(-characterState.facingAngle, Eigen::Vector3f::UnitY())).toRotationMatrix());
|
||||
renderer.ScaleMatrix(characterState.modelScale);
|
||||
renderer.RotateMatrix(characterState.modelCorrectionRotation.toRotationMatrix());
|
||||
renderer.TranslateMatrix({ state.position.x(), state.position.y(), state.position.z() });
|
||||
renderer.RotateMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(-state.facingAngle, Eigen::Vector3f::UnitY())).toRotationMatrix());
|
||||
renderer.ScaleMatrix(state.modelScale);
|
||||
renderer.RotateMatrix(state.modelCorrectionRotation.toRotationMatrix());
|
||||
|
||||
renderer.RenderUniformMatrix4fvArray(boneMatricesUniform,
|
||||
static_cast<int>(anim.gpuSkinningShaderData.skinningMatrices.size()), false,
|
||||
@@ -269,15 +314,15 @@ void Character::drawGpuSkinning(Renderer& renderer) {
|
||||
renderer.shaderManager.PushShader("fog");
|
||||
renderer.RenderUniform1i(textureUniformName, 0);
|
||||
renderer.RenderUniform3fv("uPlayerEyePos", playerEyePosSkin);
|
||||
drawAttachedWeapon(renderer);
|
||||
drawAttachedWeapon(renderer, state);
|
||||
renderer.shaderManager.PopShader();
|
||||
|
||||
renderer.PopProjectionMatrix();
|
||||
renderer.shaderManager.PopShader();
|
||||
}
|
||||
|
||||
bool Character::prepareGpuSkinning() {
|
||||
AnimationState drawState = resolveActiveState();
|
||||
bool Character::prepareGpuSkinning(const CharacterState& state) {
|
||||
AnimationState drawState = resolveActiveState(state);
|
||||
auto it = animations.find(drawState);
|
||||
if (it == animations.end()) return false;
|
||||
|
||||
@@ -293,11 +338,11 @@ bool Character::prepareGpuSkinning() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void Character::drawAttachedWeapon(Renderer& renderer) {
|
||||
if (!characterState.showWeapon) return;
|
||||
void Character::drawAttachedWeapon(Renderer& renderer, const CharacterState& state) {
|
||||
if (!state.showWeapon) return;
|
||||
if (weaponMesh.data.PositionData.size() == 0 || !weaponTexture) return;
|
||||
|
||||
auto it = animations.find(resolveActiveState());
|
||||
auto it = animations.find(resolveActiveState(state));
|
||||
if (it == animations.end()) return;
|
||||
|
||||
auto& anim = it->second;
|
||||
@@ -310,10 +355,10 @@ void Character::drawAttachedWeapon(Renderer& renderer) {
|
||||
Eigen::Matrix4f currentBone = anim.gpuSkinningShaderData.skinningMatrices[boneIdx] * bindBone;
|
||||
|
||||
renderer.PushMatrix();
|
||||
renderer.TranslateMatrix({ characterState.position.x(), characterState.position.y(), characterState.position.z() });
|
||||
renderer.RotateMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(-characterState.facingAngle, Eigen::Vector3f::UnitY())).toRotationMatrix());
|
||||
renderer.ScaleMatrix(characterState.modelScale);
|
||||
renderer.RotateMatrix(characterState.modelCorrectionRotation.toRotationMatrix());
|
||||
renderer.TranslateMatrix({ state.position.x(), state.position.y(), state.position.z() });
|
||||
renderer.RotateMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(-state.facingAngle, Eigen::Vector3f::UnitY())).toRotationMatrix());
|
||||
renderer.ScaleMatrix(state.modelScale);
|
||||
renderer.RotateMatrix(state.modelCorrectionRotation.toRotationMatrix());
|
||||
renderer.TranslateMatrix(Eigen::Vector3f(currentBone.block<3, 1>(0, 3)));
|
||||
renderer.RotateMatrix(Eigen::Matrix3f(currentBone.block<3, 3>(0, 0)));
|
||||
renderer.TranslateMatrix(weaponInitialPosition);
|
||||
@@ -327,24 +372,27 @@ void Character::drawAttachedWeapon(Renderer& renderer) {
|
||||
// ==================== Shadow depth pass ====================
|
||||
|
||||
void Character::drawShadowDepth(Renderer& renderer) {
|
||||
if (!characterState.enabled) return;
|
||||
if (characterState.useGpuSkinning) {
|
||||
drawShadowDepthGpuSkinning(renderer);
|
||||
auto stateSnapshot = this->stateSnapshot();
|
||||
if (!stateSnapshot) return;
|
||||
const CharacterState& state = *stateSnapshot;
|
||||
if (!state.enabled) return;
|
||||
if (state.useGpuSkinning) {
|
||||
drawShadowDepthGpuSkinning(renderer, state);
|
||||
} else {
|
||||
drawShadowDepthCpu(renderer);
|
||||
drawShadowDepthCpu(renderer, state);
|
||||
}
|
||||
}
|
||||
|
||||
void Character::drawShadowDepthCpu(Renderer& renderer) {
|
||||
AnimationState drawState = resolveActiveState();
|
||||
void Character::drawShadowDepthCpu(Renderer& renderer, const CharacterState& state) {
|
||||
AnimationState drawState = resolveActiveState(state);
|
||||
auto it = animations.find(drawState);
|
||||
if (it == animations.end()) return;
|
||||
|
||||
renderer.PushMatrix();
|
||||
renderer.TranslateMatrix({ characterState.position.x(), characterState.position.y(), characterState.position.z() });
|
||||
renderer.RotateMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(-characterState.facingAngle, Eigen::Vector3f::UnitY())).toRotationMatrix());
|
||||
renderer.ScaleMatrix(characterState.modelScale);
|
||||
renderer.RotateMatrix(characterState.modelCorrectionRotation.toRotationMatrix());
|
||||
renderer.TranslateMatrix({ state.position.x(), state.position.y(), state.position.z() });
|
||||
renderer.RotateMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(-state.facingAngle, Eigen::Vector3f::UnitY())).toRotationMatrix());
|
||||
renderer.ScaleMatrix(state.modelScale);
|
||||
renderer.RotateMatrix(state.modelCorrectionRotation.toRotationMatrix());
|
||||
|
||||
auto& anim = it->second;
|
||||
for (const auto& name : anim.model.meshNamesOrdered) {
|
||||
@@ -358,17 +406,17 @@ void Character::drawShadowDepthCpu(Renderer& renderer) {
|
||||
}
|
||||
renderer.PopMatrix();
|
||||
|
||||
drawAttachedWeapon(renderer);
|
||||
drawAttachedWeapon(renderer, state);
|
||||
}
|
||||
|
||||
void Character::drawShadowDepthGpuSkinning(Renderer& renderer) {
|
||||
void Character::drawShadowDepthGpuSkinning(Renderer& renderer, const CharacterState& state) {
|
||||
CheckGlError(__FILE__, __LINE__);
|
||||
AnimationState drawState = resolveActiveState();
|
||||
AnimationState drawState = resolveActiveState(state);
|
||||
auto it = animations.find(drawState);
|
||||
if (it == animations.end()) return;
|
||||
|
||||
CheckGlError(__FILE__, __LINE__);
|
||||
if (!prepareGpuSkinning()) return;
|
||||
if (!prepareGpuSkinning(state)) return;
|
||||
CheckGlError(__FILE__, __LINE__);
|
||||
|
||||
static const std::string shadowSkinningShader = "shadow_depth_skinning";
|
||||
@@ -377,10 +425,10 @@ void Character::drawShadowDepthGpuSkinning(Renderer& renderer) {
|
||||
renderer.shaderManager.PushShader(shadowSkinningShader);
|
||||
|
||||
renderer.PushMatrix();
|
||||
renderer.TranslateMatrix({ characterState.position.x(), characterState.position.y(), characterState.position.z() });
|
||||
renderer.RotateMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(-characterState.facingAngle, Eigen::Vector3f::UnitY())).toRotationMatrix());
|
||||
renderer.ScaleMatrix(characterState.modelScale);
|
||||
renderer.RotateMatrix(characterState.modelCorrectionRotation.toRotationMatrix());
|
||||
renderer.TranslateMatrix({ state.position.x(), state.position.y(), state.position.z() });
|
||||
renderer.RotateMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(-state.facingAngle, Eigen::Vector3f::UnitY())).toRotationMatrix());
|
||||
renderer.ScaleMatrix(state.modelScale);
|
||||
renderer.RotateMatrix(state.modelCorrectionRotation.toRotationMatrix());
|
||||
|
||||
CheckGlError(__FILE__, __LINE__);
|
||||
renderer.RenderUniformMatrix4fvArray(boneMatricesUniform,
|
||||
@@ -400,14 +448,17 @@ void Character::drawShadowDepthGpuSkinning(Renderer& renderer) {
|
||||
renderer.PopMatrix();
|
||||
renderer.shaderManager.PopShader();
|
||||
|
||||
drawAttachedWeapon(renderer);
|
||||
drawAttachedWeapon(renderer, state);
|
||||
CheckGlError(__FILE__, __LINE__);
|
||||
}
|
||||
|
||||
// ==================== Main pass with shadows ====================
|
||||
|
||||
void Character::drawWithShadow(Renderer& renderer, const Eigen::Matrix4f& lightFromCamera, GLuint shadowMapTex, const Eigen::Vector3f& lightDirCamera) {
|
||||
if (!characterState.enabled) return;
|
||||
auto stateSnapshot = this->stateSnapshot();
|
||||
if (!stateSnapshot) return;
|
||||
const CharacterState& state = *stateSnapshot;
|
||||
if (!state.enabled) return;
|
||||
if (hitSparkEmitter.isConfigured() && hitSparkEmitter.getActiveParticleCount() > 0) {
|
||||
hitSparkEmitter.draw(renderer, 1.0f, Environment::width, Environment::height, false);
|
||||
}
|
||||
@@ -415,15 +466,15 @@ void Character::drawWithShadow(Renderer& renderer, const Eigen::Matrix4f& lightF
|
||||
renderer.RenderUniform1f("uAlpha", 1.0f);
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
if (characterState.useGpuSkinning) {
|
||||
drawGpuSkinningWithShadow(renderer, lightFromCamera, shadowMapTex, lightDirCamera);
|
||||
if (state.useGpuSkinning) {
|
||||
drawGpuSkinningWithShadow(renderer, state, lightFromCamera, shadowMapTex, lightDirCamera);
|
||||
} else {
|
||||
drawCpuWithShadow(renderer, lightFromCamera, shadowMapTex, lightDirCamera);
|
||||
drawCpuWithShadow(renderer, state, lightFromCamera, shadowMapTex, lightDirCamera);
|
||||
}
|
||||
}
|
||||
|
||||
void Character::drawCpuWithShadow(Renderer& renderer, const Eigen::Matrix4f& lightFromCamera, GLuint shadowMapTex, const Eigen::Vector3f& lightDirCamera) {
|
||||
AnimationState drawState = resolveActiveState();
|
||||
void Character::drawCpuWithShadow(Renderer& renderer, const CharacterState& state, const Eigen::Matrix4f& lightFromCamera, GLuint shadowMapTex, const Eigen::Vector3f& lightDirCamera) {
|
||||
AnimationState drawState = resolveActiveState(state);
|
||||
auto it = animations.find(drawState);
|
||||
if (it == animations.end()) return;
|
||||
|
||||
@@ -446,10 +497,10 @@ void Character::drawCpuWithShadow(Renderer& renderer, const Eigen::Matrix4f& lig
|
||||
Environment::CONST_Z_NEAR, Environment::CONST_Z_FAR);
|
||||
|
||||
renderer.PushMatrix();
|
||||
renderer.TranslateMatrix({ characterState.position.x(), characterState.position.y(), characterState.position.z() });
|
||||
renderer.RotateMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(-characterState.facingAngle, Eigen::Vector3f::UnitY())).toRotationMatrix());
|
||||
renderer.ScaleMatrix(characterState.modelScale);
|
||||
renderer.RotateMatrix(characterState.modelCorrectionRotation.toRotationMatrix());
|
||||
renderer.TranslateMatrix({ state.position.x(), state.position.y(), state.position.z() });
|
||||
renderer.RotateMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(-state.facingAngle, Eigen::Vector3f::UnitY())).toRotationMatrix());
|
||||
renderer.ScaleMatrix(state.modelScale);
|
||||
renderer.RotateMatrix(state.modelCorrectionRotation.toRotationMatrix());
|
||||
|
||||
auto& anim = it->second;
|
||||
for (const auto& name : anim.model.meshNamesOrdered) {
|
||||
@@ -468,20 +519,20 @@ void Character::drawCpuWithShadow(Renderer& renderer, const Eigen::Matrix4f& lig
|
||||
renderer.shaderManager.PushShader("fog");
|
||||
renderer.RenderUniform1i(textureUniformName, 0);
|
||||
renderer.RenderUniform3fv("uPlayerEyePos", playerEyePosShadow);
|
||||
drawAttachedWeapon(renderer);
|
||||
drawAttachedWeapon(renderer, state);
|
||||
renderer.shaderManager.PopShader();
|
||||
|
||||
renderer.PopProjectionMatrix();
|
||||
renderer.shaderManager.PopShader();
|
||||
}
|
||||
|
||||
void Character::drawGpuSkinningWithShadow(Renderer& renderer, const Eigen::Matrix4f& lightFromCamera, GLuint shadowMapTex, const Eigen::Vector3f& lightDirCamera) {
|
||||
AnimationState drawState = resolveActiveState();
|
||||
void Character::drawGpuSkinningWithShadow(Renderer& renderer, const CharacterState& state, const Eigen::Matrix4f& lightFromCamera, GLuint shadowMapTex, const Eigen::Vector3f& lightDirCamera) {
|
||||
AnimationState drawState = resolveActiveState(state);
|
||||
auto it = animations.find(drawState);
|
||||
if (it == animations.end()) return;
|
||||
|
||||
CheckGlError(__FILE__, __LINE__);
|
||||
if (!prepareGpuSkinning()) return;
|
||||
if (!prepareGpuSkinning(state)) return;
|
||||
CheckGlError(__FILE__, __LINE__);
|
||||
|
||||
static const std::string skinningShadowShader = "fog_skinning_shadow";
|
||||
@@ -508,10 +559,10 @@ void Character::drawGpuSkinningWithShadow(Renderer& renderer, const Eigen::Matri
|
||||
Environment::CONST_Z_NEAR, Environment::CONST_Z_FAR);
|
||||
|
||||
renderer.PushMatrix();
|
||||
renderer.TranslateMatrix({ characterState.position.x(), characterState.position.y(), characterState.position.z() });
|
||||
renderer.RotateMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(-characterState.facingAngle, Eigen::Vector3f::UnitY())).toRotationMatrix());
|
||||
renderer.ScaleMatrix(characterState.modelScale);
|
||||
renderer.RotateMatrix(characterState.modelCorrectionRotation.toRotationMatrix());
|
||||
renderer.TranslateMatrix({ state.position.x(), state.position.y(), state.position.z() });
|
||||
renderer.RotateMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(-state.facingAngle, Eigen::Vector3f::UnitY())).toRotationMatrix());
|
||||
renderer.ScaleMatrix(state.modelScale);
|
||||
renderer.RotateMatrix(state.modelCorrectionRotation.toRotationMatrix());
|
||||
|
||||
CheckGlError(__FILE__, __LINE__);
|
||||
renderer.RenderUniformMatrix4fvArray(boneMatricesUniform,
|
||||
@@ -534,7 +585,7 @@ void Character::drawGpuSkinningWithShadow(Renderer& renderer, const Eigen::Matri
|
||||
renderer.shaderManager.PushShader("fog");
|
||||
renderer.RenderUniform1i(textureUniformName, 0);
|
||||
renderer.RenderUniform3fv("uPlayerEyePos", playerEyePosSkinShadow);
|
||||
drawAttachedWeapon(renderer);
|
||||
drawAttachedWeapon(renderer, state);
|
||||
renderer.shaderManager.PopShader();
|
||||
|
||||
CheckGlError(__FILE__, __LINE__);
|
||||
@@ -554,7 +605,10 @@ void Character::drawNight(Renderer& renderer,
|
||||
const Eigen::Matrix4f& cameraViewInverse,
|
||||
const float* ambientColor, const float* fogColor)
|
||||
{
|
||||
if (!characterState.enabled) return;
|
||||
auto stateSnapshot = this->stateSnapshot();
|
||||
if (!stateSnapshot) return;
|
||||
const CharacterState& state = *stateSnapshot;
|
||||
if (!state.enabled) return;
|
||||
if (hitSparkEmitter.isConfigured() && hitSparkEmitter.getActiveParticleCount() > 0) {
|
||||
hitSparkEmitter.draw(renderer, 1.0f, Environment::width, Environment::height, false);
|
||||
}
|
||||
@@ -562,25 +616,26 @@ void Character::drawNight(Renderer& renderer,
|
||||
renderer.RenderUniform1f("uAlpha", 1.0f);
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
if (characterState.useGpuSkinning) {
|
||||
drawNightGpuSkinning(renderer, pointLightPosEye, pointLightDirEye, pointLightColors, pointLightCount,
|
||||
if (state.useGpuSkinning) {
|
||||
drawNightGpuSkinning(renderer, state, pointLightPosEye, pointLightDirEye, pointLightColors, pointLightCount,
|
||||
pointLightWorldXZ, pointLightLimitXZ, cameraViewInverse, ambientColor, fogColor);
|
||||
} else {
|
||||
drawNightCpu(renderer, pointLightPosEye, pointLightDirEye, pointLightColors, pointLightCount,
|
||||
drawNightCpu(renderer, state, pointLightPosEye, pointLightDirEye, pointLightColors, pointLightCount,
|
||||
pointLightWorldXZ, pointLightLimitXZ, cameraViewInverse, ambientColor, fogColor);
|
||||
}
|
||||
}
|
||||
|
||||
void Character::drawNightGpuSkinning(Renderer& renderer,
|
||||
const CharacterState& state,
|
||||
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)
|
||||
{
|
||||
AnimationState drawState = resolveActiveState();
|
||||
AnimationState drawState = resolveActiveState(state);
|
||||
auto it = animations.find(drawState);
|
||||
if (it == animations.end()) return;
|
||||
|
||||
if (!prepareGpuSkinning()) return;
|
||||
if (!prepareGpuSkinning(state)) return;
|
||||
|
||||
static const std::string nightSkinningShader = "night_fog_skinning";
|
||||
static const std::string boneMatricesUniform = "uBoneMatrices[0]";
|
||||
@@ -606,10 +661,10 @@ void Character::drawNightGpuSkinning(Renderer& renderer,
|
||||
Environment::CONST_Z_NEAR, Environment::CONST_Z_FAR);
|
||||
|
||||
renderer.PushMatrix();
|
||||
renderer.TranslateMatrix({ characterState.position.x(), characterState.position.y(), characterState.position.z() });
|
||||
renderer.RotateMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(-characterState.facingAngle, Eigen::Vector3f::UnitY())).toRotationMatrix());
|
||||
renderer.ScaleMatrix(characterState.modelScale);
|
||||
renderer.RotateMatrix(characterState.modelCorrectionRotation.toRotationMatrix());
|
||||
renderer.TranslateMatrix({ state.position.x(), state.position.y(), state.position.z() });
|
||||
renderer.RotateMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(-state.facingAngle, Eigen::Vector3f::UnitY())).toRotationMatrix());
|
||||
renderer.ScaleMatrix(state.modelScale);
|
||||
renderer.RotateMatrix(state.modelCorrectionRotation.toRotationMatrix());
|
||||
|
||||
renderer.RenderUniformMatrix4fvArray(boneMatricesUniform,
|
||||
static_cast<int>(it->second.gpuSkinningShaderData.skinningMatrices.size()), false,
|
||||
@@ -639,7 +694,7 @@ void Character::drawNightGpuSkinning(Renderer& renderer,
|
||||
renderer.RenderUniform2fvArray("uPointLightWorldXZ[0]", plCount, plWorldXZ);
|
||||
renderer.RenderUniform2fvArray("uPointLightLimitXZ[0]", plCount, plLimitXZ);
|
||||
}
|
||||
drawAttachedWeapon(renderer);
|
||||
drawAttachedWeapon(renderer, state);
|
||||
renderer.shaderManager.PopShader();
|
||||
|
||||
renderer.PopProjectionMatrix();
|
||||
@@ -647,11 +702,12 @@ void Character::drawNightGpuSkinning(Renderer& renderer,
|
||||
}
|
||||
|
||||
void Character::drawNightCpu(Renderer& renderer,
|
||||
const CharacterState& state,
|
||||
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)
|
||||
{
|
||||
AnimationState drawState = resolveActiveState();
|
||||
AnimationState drawState = resolveActiveState(state);
|
||||
auto it = animations.find(drawState);
|
||||
if (it == animations.end()) return;
|
||||
|
||||
@@ -677,10 +733,10 @@ void Character::drawNightCpu(Renderer& renderer,
|
||||
Environment::CONST_Z_NEAR, Environment::CONST_Z_FAR);
|
||||
|
||||
renderer.PushMatrix();
|
||||
renderer.TranslateMatrix({ characterState.position.x(), characterState.position.y(), characterState.position.z() });
|
||||
renderer.RotateMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(-characterState.facingAngle, Eigen::Vector3f::UnitY())).toRotationMatrix());
|
||||
renderer.ScaleMatrix(characterState.modelScale);
|
||||
renderer.RotateMatrix(characterState.modelCorrectionRotation.toRotationMatrix());
|
||||
renderer.TranslateMatrix({ state.position.x(), state.position.y(), state.position.z() });
|
||||
renderer.RotateMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(-state.facingAngle, Eigen::Vector3f::UnitY())).toRotationMatrix());
|
||||
renderer.ScaleMatrix(state.modelScale);
|
||||
renderer.RotateMatrix(state.modelCorrectionRotation.toRotationMatrix());
|
||||
|
||||
auto& anim = it->second;
|
||||
for (const auto& name : anim.model.meshNamesOrdered) {
|
||||
@@ -697,7 +753,7 @@ void Character::drawNightCpu(Renderer& renderer,
|
||||
renderer.PopMatrix();
|
||||
|
||||
renderer.RenderUniform3fv("uPlayerEyePos", playerEyePosNight);
|
||||
drawAttachedWeapon(renderer);
|
||||
drawAttachedWeapon(renderer, state);
|
||||
|
||||
renderer.PopProjectionMatrix();
|
||||
renderer.shaderManager.PopShader();
|
||||
@@ -712,35 +768,39 @@ void Character::drawNightWithShadow(Renderer& renderer,
|
||||
const Eigen::Matrix4f& lightFromCamera, GLuint shadowMapTex,
|
||||
const float* ambientColor, const float* fogColor)
|
||||
{
|
||||
if (!characterState.enabled) return;
|
||||
auto stateSnapshot = this->stateSnapshot();
|
||||
if (!stateSnapshot) return;
|
||||
const CharacterState& state = *stateSnapshot;
|
||||
if (!state.enabled) return;
|
||||
if (hitSparkEmitter.isConfigured() && hitSparkEmitter.getActiveParticleCount() > 0) {
|
||||
hitSparkEmitter.draw(renderer, 1.0f, Environment::width, Environment::height, false);
|
||||
}
|
||||
renderer.RenderUniform1f("uAlpha", 1.0f);
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
if (characterState.useGpuSkinning) {
|
||||
drawNightGpuSkinningWithShadow(renderer, plPosEye, plDirEye, plColors, plCount,
|
||||
if (state.useGpuSkinning) {
|
||||
drawNightGpuSkinningWithShadow(renderer, state, plPosEye, plDirEye, plColors, plCount,
|
||||
plWorldXZ, plLimitXZ, cameraViewInverse,
|
||||
lightFromCamera, shadowMapTex, ambientColor, fogColor);
|
||||
} else {
|
||||
drawNightCpuWithShadow(renderer, plPosEye, plDirEye, plColors, plCount,
|
||||
drawNightCpuWithShadow(renderer, state, plPosEye, plDirEye, plColors, plCount,
|
||||
plWorldXZ, plLimitXZ, cameraViewInverse,
|
||||
lightFromCamera, shadowMapTex, ambientColor, fogColor);
|
||||
}
|
||||
}
|
||||
|
||||
void Character::drawNightGpuSkinningWithShadow(Renderer& renderer,
|
||||
const CharacterState& state,
|
||||
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)
|
||||
{
|
||||
AnimationState drawState = resolveActiveState();
|
||||
AnimationState drawState = resolveActiveState(state);
|
||||
auto it = animations.find(drawState);
|
||||
if (it == animations.end()) return;
|
||||
if (!prepareGpuSkinning()) return;
|
||||
if (!prepareGpuSkinning(state)) return;
|
||||
|
||||
static const std::string nightShadowSkinningShader = "night_fog_skinning_shadow";
|
||||
static const std::string boneMatricesUniform = "uBoneMatrices[0]";
|
||||
@@ -774,10 +834,10 @@ void Character::drawNightGpuSkinningWithShadow(Renderer& renderer,
|
||||
Environment::CONST_Z_NEAR, Environment::CONST_Z_FAR);
|
||||
|
||||
renderer.PushMatrix();
|
||||
renderer.TranslateMatrix({ characterState.position.x(), characterState.position.y(), characterState.position.z() });
|
||||
renderer.RotateMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(-characterState.facingAngle, Eigen::Vector3f::UnitY())).toRotationMatrix());
|
||||
renderer.ScaleMatrix(characterState.modelScale);
|
||||
renderer.RotateMatrix(characterState.modelCorrectionRotation.toRotationMatrix());
|
||||
renderer.TranslateMatrix({ state.position.x(), state.position.y(), state.position.z() });
|
||||
renderer.RotateMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(-state.facingAngle, Eigen::Vector3f::UnitY())).toRotationMatrix());
|
||||
renderer.ScaleMatrix(state.modelScale);
|
||||
renderer.RotateMatrix(state.modelCorrectionRotation.toRotationMatrix());
|
||||
|
||||
renderer.RenderUniformMatrix4fvArray(boneMatricesUniform,
|
||||
static_cast<int>(it->second.gpuSkinningShaderData.skinningMatrices.size()), false,
|
||||
@@ -810,7 +870,7 @@ void Character::drawNightGpuSkinningWithShadow(Renderer& renderer,
|
||||
}
|
||||
renderer.RenderUniform2fvArray("uPointLightWorldXZ[0]", plCount, plWorldXZ);
|
||||
renderer.RenderUniform2fvArray("uPointLightLimitXZ[0]", plCount, plLimitXZ);
|
||||
drawAttachedWeapon(renderer);
|
||||
drawAttachedWeapon(renderer, state);
|
||||
renderer.shaderManager.PopShader();
|
||||
|
||||
renderer.PopProjectionMatrix();
|
||||
@@ -818,13 +878,14 @@ void Character::drawNightGpuSkinningWithShadow(Renderer& renderer,
|
||||
}
|
||||
|
||||
void Character::drawNightCpuWithShadow(Renderer& renderer,
|
||||
const CharacterState& state,
|
||||
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)
|
||||
{
|
||||
AnimationState drawState = resolveActiveState();
|
||||
AnimationState drawState = resolveActiveState(state);
|
||||
auto it = animations.find(drawState);
|
||||
if (it == animations.end()) return;
|
||||
|
||||
@@ -858,10 +919,10 @@ void Character::drawNightCpuWithShadow(Renderer& renderer,
|
||||
Environment::CONST_Z_NEAR, Environment::CONST_Z_FAR);
|
||||
|
||||
renderer.PushMatrix();
|
||||
renderer.TranslateMatrix({ characterState.position.x(), characterState.position.y(), characterState.position.z() });
|
||||
renderer.RotateMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(-characterState.facingAngle, Eigen::Vector3f::UnitY())).toRotationMatrix());
|
||||
renderer.ScaleMatrix(characterState.modelScale);
|
||||
renderer.RotateMatrix(characterState.modelCorrectionRotation.toRotationMatrix());
|
||||
renderer.TranslateMatrix({ state.position.x(), state.position.y(), state.position.z() });
|
||||
renderer.RotateMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(-state.facingAngle, Eigen::Vector3f::UnitY())).toRotationMatrix());
|
||||
renderer.ScaleMatrix(state.modelScale);
|
||||
renderer.RotateMatrix(state.modelCorrectionRotation.toRotationMatrix());
|
||||
|
||||
auto& anim = it->second;
|
||||
for (const auto& name : anim.model.meshNamesOrdered) {
|
||||
@@ -878,7 +939,7 @@ void Character::drawNightCpuWithShadow(Renderer& renderer,
|
||||
renderer.PopMatrix();
|
||||
|
||||
renderer.RenderUniform3fv("uPlayerEyePos", playerEyePosNightShadow);
|
||||
drawAttachedWeapon(renderer);
|
||||
drawAttachedWeapon(renderer, state);
|
||||
|
||||
renderer.PopProjectionMatrix();
|
||||
renderer.shaderManager.PopShader();
|
||||
@@ -906,8 +967,11 @@ void Character::presentDamage(float hp, float maxHp,
|
||||
onHpChanged(hp, maxHp, attackerId);
|
||||
|
||||
if (!hitSparkEmitter.isConfigured()) return;
|
||||
auto stateSnapshot = this->stateSnapshot();
|
||||
if (!stateSnapshot) return;
|
||||
const CharacterState& state = *stateSnapshot;
|
||||
|
||||
Eigen::Vector3f emitPos = characterState.position + Eigen::Vector3f(0.f, 1.f, 0.f);
|
||||
Eigen::Vector3f emitPos = state.position + Eigen::Vector3f(0.f, 1.f, 0.f);
|
||||
hitSparkEmitter.resetEmissionPoints({ emitPos });
|
||||
hitSparkEmitter.setEmissionDirection(attackDirection);
|
||||
|
||||
@@ -924,16 +988,18 @@ void Character::prepareHitSparksForDraw(const Eigen::Matrix4f& cameraViewMatrix)
|
||||
hitSparkEmitter.prepareForDraw(cameraViewMatrix);
|
||||
}
|
||||
|
||||
void Character::drawName(TextRenderer& textRenderer,
|
||||
const Eigen::Matrix4f& cameraViewMatrix,
|
||||
const Eigen::Matrix4f& projectionMatrix)
|
||||
static void drawCharacterNameLabel(
|
||||
TextRenderer& textRenderer,
|
||||
const Eigen::Matrix4f& cameraViewMatrix,
|
||||
const Eigen::Matrix4f& projectionMatrix,
|
||||
const CharacterState& state,
|
||||
const std::string& displayName,
|
||||
const std::array<float, 4>& color)
|
||||
{
|
||||
if (characterState.isPlayer) return;
|
||||
if (!characterState.enabled) return;
|
||||
if (characterState.hp <= 0.f) return;
|
||||
if (characterState.npcName.empty()) return;
|
||||
if (!state.enabled || state.hp <= 0.f || displayName.empty()) return;
|
||||
|
||||
Eigen::Vector4f worldPos(characterState.position.x(), characterState.position.y() + 1.83f, characterState.position.z(), 1.f);
|
||||
Eigen::Vector4f worldPos(
|
||||
state.position.x(), state.position.y() + 1.83f, state.position.z(), 1.f);
|
||||
Eigen::Vector4f clip = projectionMatrix * cameraViewMatrix * worldPos;
|
||||
if (clip.w() <= 0.f) return;
|
||||
|
||||
@@ -943,26 +1009,57 @@ void Character::drawName(TextRenderer& textRenderer,
|
||||
|
||||
float screenX = (ndcX * 0.5f + 0.5f) * Environment::projectionWidth;
|
||||
float screenY = (ndcY * 0.5f + 0.5f) * Environment::projectionHeight;
|
||||
textRenderer.drawText(displayName, screenX, screenY, 1.0f, true, color);
|
||||
}
|
||||
|
||||
std::array<float, 4> color = characterState.canAttack
|
||||
void Character::drawName(TextRenderer& textRenderer,
|
||||
const Eigen::Matrix4f& cameraViewMatrix,
|
||||
const Eigen::Matrix4f& projectionMatrix)
|
||||
{
|
||||
auto stateSnapshot = this->stateSnapshot();
|
||||
if (!stateSnapshot) return;
|
||||
const CharacterState& state = *stateSnapshot;
|
||||
if (state.isPlayer) return;
|
||||
if (state.npcName.empty()) return;
|
||||
|
||||
std::array<float, 4> color = state.canAttack
|
||||
? std::array<float, 4>{ 1.f, 0.f, 0.f, 1.f }
|
||||
: std::array<float, 4>{ 0.f, 1.f, 0.f, 1.f };
|
||||
|
||||
const std::string& translatedName = Character::nameTranslations.translateRef(characterState.npcName, g_currentLanguage);
|
||||
const std::string& translatedName = Character::nameTranslations.translateRef(state.npcName, g_currentLanguage);
|
||||
|
||||
textRenderer.drawText(translatedName, screenX, screenY, 1.0f, true, color);
|
||||
drawCharacterNameLabel(
|
||||
textRenderer, cameraViewMatrix, projectionMatrix,
|
||||
state, translatedName, color);
|
||||
}
|
||||
|
||||
void Character::drawPlayerName(
|
||||
TextRenderer& textRenderer,
|
||||
const Eigen::Matrix4f& cameraViewMatrix,
|
||||
const Eigen::Matrix4f& projectionMatrix,
|
||||
const std::string& displayName)
|
||||
{
|
||||
auto snapshot = stateSnapshot();
|
||||
if (!snapshot) return;
|
||||
static const std::array<float, 4> color = {0.f, 1.f, 0.f, 1.f};
|
||||
drawCharacterNameLabel(
|
||||
textRenderer, cameraViewMatrix, projectionMatrix,
|
||||
*snapshot, displayName, color);
|
||||
}
|
||||
|
||||
void Character::drawHealthBar(Renderer& renderer,
|
||||
const Eigen::Matrix4f& cameraViewMatrix,
|
||||
const Eigen::Matrix4f& projectionMatrix)
|
||||
{
|
||||
if (characterState.isPlayer || !characterState.canAttack) return;
|
||||
if (!characterState.enabled) return;
|
||||
if (characterState.hp <= 0.f) return;
|
||||
if (characterState.initialHp <= 0.f) return;
|
||||
auto stateSnapshot = this->stateSnapshot();
|
||||
if (!stateSnapshot) return;
|
||||
const CharacterState& state = *stateSnapshot;
|
||||
if (state.isPlayer || !state.canAttack) return;
|
||||
if (!state.enabled) return;
|
||||
if (state.hp <= 0.f) return;
|
||||
if (state.initialHp <= 0.f) return;
|
||||
|
||||
Eigen::Vector4f worldPos(characterState.position.x(), characterState.position.y() + 1.75f, characterState.position.z(), 1.f);
|
||||
Eigen::Vector4f worldPos(state.position.x(), state.position.y() + 1.75f, state.position.z(), 1.f);
|
||||
Eigen::Vector4f clip = projectionMatrix * cameraViewMatrix * worldPos;
|
||||
if (clip.w() <= 0.f) return;
|
||||
float ndcX = clip.x() / clip.w();
|
||||
@@ -980,7 +1077,7 @@ void Character::drawHealthBar(Renderer& renderer,
|
||||
const float bottom = sy - barH * 0.5f;
|
||||
const float top = sy + barH * 0.5f;
|
||||
|
||||
float frac = characterState.hp / characterState.initialHp;
|
||||
float frac = state.hp / state.initialHp;
|
||||
if (frac < 0.f) frac = 0.f;
|
||||
if (frac > 1.f) frac = 1.f;
|
||||
const float split = left + barW * frac;
|
||||
|
||||
Reference in new issue
Block a user