From d58c55ce8d0b3efd8d03d3c3f105d45efef37ab8 Mon Sep 17 00:00:00 2001 From: Kelsi Date: Fri, 13 Mar 2026 01:49:22 -0700 Subject: [PATCH] fix: allow ribbon-only M2 models to load and silence transport doodad load errors Two follow-up fixes for the ribbon emitter implementation and the transport-doodad stall fix: 1. loadModel() rejected any M2 with no vertices AND no particles, but ribbon-only spell-effect models (e.g. weapon trail or aura ribbons) have neither. These models were silently invisible even though the ribbon rendering pipeline added in 1108aa9 is fully capable of rendering them. Extended the guard to also accept models that have ribbon emitters, matching the particle-emitter precedent. 2. processPendingTransportDoodads() ignored the bool return of loadModel(), calling createInstance() even when the model was rejected, generating spurious "Cannot create instance: model X not loaded" warnings for every failed doodad path. Check the return value and continue to the next doodad on failure. --- src/core/application.cpp | 2 +- src/rendering/m2_renderer.cpp | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/core/application.cpp b/src/core/application.cpp index a782363c..44a82570 100644 --- a/src/core/application.cpp +++ b/src/core/application.cpp @@ -8247,7 +8247,7 @@ void Application::processPendingTransportDoodads() { } if (!m2Model.isValid()) continue; - m2Renderer->loadModel(m2Model, doodadModelId); + if (!m2Renderer->loadModel(m2Model, doodadModelId)) continue; uint32_t m2InstanceId = m2Renderer->createInstance(doodadModelId, glm::vec3(0.0f), glm::vec3(0.0f), 1.0f); if (m2InstanceId == 0) continue; m2Renderer->setSkipCollision(m2InstanceId, true); diff --git a/src/rendering/m2_renderer.cpp b/src/rendering/m2_renderer.cpp index c5af6c76..d7ae0b2a 100644 --- a/src/rendering/m2_renderer.cpp +++ b/src/rendering/m2_renderer.cpp @@ -944,8 +944,9 @@ bool M2Renderer::loadModel(const pipeline::M2Model& model, uint32_t modelId) { bool hasGeometry = !model.vertices.empty() && !model.indices.empty(); bool hasParticles = !model.particleEmitters.empty(); - if (!hasGeometry && !hasParticles) { - LOG_WARNING("M2 model has no geometry and no particles: ", model.name); + bool hasRibbons = !model.ribbonEmitters.empty(); + if (!hasGeometry && !hasParticles && !hasRibbons) { + LOG_WARNING("M2 model has no renderable content: ", model.name); return false; }