Fix lantern glow rendering and add NPC combat animations

Disable depth testing for additive/mod blend mode batches so glow quads
render as proper light halos instead of visible transparent discs. Add
NPC swing callback to play attack animation (anim 16) when NPCs melee
in single-player combat.
This commit is contained in:
Kelsi 2026-02-06 03:39:36 -08:00
parent f74c37ba74
commit 273245720a
4 changed files with 25 additions and 1 deletions

View file

@ -256,6 +256,10 @@ public:
using MeleeSwingCallback = std::function<void()>;
void setMeleeSwingCallback(MeleeSwingCallback cb) { meleeSwingCallback_ = std::move(cb); }
// NPC swing callback (single-player combat: plays attack animation on NPC)
using NpcSwingCallback = std::function<void(uint64_t guid)>;
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;

View file

@ -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;

View file

@ -3747,6 +3747,10 @@ void GameHandler::performNpcSwing(uint64_t guid) {
if (!entity || entity->getType() != ObjectType::UNIT) return;
auto unit = std::static_pointer_cast<Unit>(entity);
if (npcSwingCallback_) {
npcSwingCallback_(guid);
}
static std::mt19937 rng(std::random_device{}());
std::uniform_real_distribution<float> roll(0.0f, 1.0f);

View file

@ -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);
}