diff --git a/include/game/game_handler.hpp b/include/game/game_handler.hpp index 618786df..931adb8e 100644 --- a/include/game/game_handler.hpp +++ b/include/game/game_handler.hpp @@ -256,6 +256,10 @@ public: using MeleeSwingCallback = std::function; void setMeleeSwingCallback(MeleeSwingCallback cb) { meleeSwingCallback_ = std::move(cb); } + // NPC swing callback (single-player combat: plays attack animation on NPC) + using NpcSwingCallback = std::function; + void setNpcSwingCallback(NpcSwingCallback cb) { npcSwingCallback_ = std::move(cb); } + // Local player stats (single-player) uint32_t getLocalPlayerHealth() const { return localPlayerHealth_; } uint32_t getLocalPlayerMaxHealth() const { return localPlayerMaxHealth_; } @@ -625,6 +629,7 @@ private: static constexpr float SWING_SPEED = 2.0f; NpcDeathCallback npcDeathCallback_; MeleeSwingCallback meleeSwingCallback_; + NpcSwingCallback npcSwingCallback_; uint32_t localPlayerHealth_ = 0; uint32_t localPlayerMaxHealth_ = 0; uint32_t localPlayerLevel_ = 1; diff --git a/src/core/application.cpp b/src/core/application.cpp index cd0bdad5..75383494 100644 --- a/src/core/application.cpp +++ b/src/core/application.cpp @@ -1135,6 +1135,12 @@ void Application::spawnNpcs() { cr->playAnimation(instanceId, 1, false); // animation ID 1 = Death } }); + gameHandler->setNpcSwingCallback([npcMgr, cr](uint64_t guid) { + uint32_t instanceId = npcMgr->findRenderInstanceId(guid); + if (instanceId != 0 && cr) { + cr->playAnimation(instanceId, 16, false); // animation ID 16 = Attack1 + } + }); } npcsSpawned = true; diff --git a/src/game/game_handler.cpp b/src/game/game_handler.cpp index b9fda259..f5eaf1b9 100644 --- a/src/game/game_handler.cpp +++ b/src/game/game_handler.cpp @@ -3747,6 +3747,10 @@ void GameHandler::performNpcSwing(uint64_t guid) { if (!entity || entity->getType() != ObjectType::UNIT) return; auto unit = std::static_pointer_cast(entity); + if (npcSwingCallback_) { + npcSwingCallback_(guid); + } + static std::mt19937 rng(std::random_device{}()); std::uniform_real_distribution roll(0.0f, 1.0f); diff --git a/src/rendering/m2_renderer.cpp b/src/rendering/m2_renderer.cpp index 241d14eb..eef91596 100644 --- a/src/rendering/m2_renderer.cpp +++ b/src/rendering/m2_renderer.cpp @@ -1306,6 +1306,12 @@ void M2Renderer::render(const Camera& camera, const glm::mat4& view, const glm:: glDepthMask(GL_FALSE); } + // Disable depth testing entirely for additive/mod blends (glow, light halos) + bool disableDepth = (batch.blendMode >= 3); + if (disableDepth) { + glDisable(GL_DEPTH_TEST); + } + // Unlit: material flag 0x01 or additive/mod blend modes bool unlit = (batch.materialFlags & 0x01) != 0 || batch.blendMode >= 3; shader->setUniform("uUnlit", unlit); @@ -1323,7 +1329,10 @@ void M2Renderer::render(const Camera& camera, const glm::mat4& view, const glm:: glDrawElements(GL_TRIANGLES, batch.indexCount, GL_UNSIGNED_SHORT, (void*)(batch.indexStart * sizeof(uint16_t))); - // Restore depth writes and blend func after transparent batch + // Restore depth test, depth writes, and blend func after transparent batch + if (disableDepth) { + glEnable(GL_DEPTH_TEST); + } if (batchTransparent && fadeAlpha >= 1.0f) { glDepthMask(GL_TRUE); }