mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-03-23 07:40:14 +00:00
Fix NPC apparel fallback and reduce world-entry stutter
Hide NPC cloak/object-skin mesh when no cape texture resolves by using a transparent texture fallback, preventing skin-texture bleed on cloaks. Tighten NPC equipment region compositing by slot and add safe humanoid geoset selection to avoid robe-over-pants conflicts and odd pants texturing. Reduce login/runtime hitching by deferring non-critical world-system initialization across frames, lowering per-frame transport doodad spawn budget, and demoting high-volume transport/MO_TRANSPORT diagnostics to debug. Gate M2 glow diagnostics behind WOWEE_M2_GLOW_DIAG and make zone music prewarm opt-in via WOWEE_PREWARM_ZONE_MUSIC.
This commit is contained in:
parent
48d9de810d
commit
3368dbb9ec
10 changed files with 369 additions and 91 deletions
|
|
@ -57,6 +57,7 @@
|
|||
#include <cctype>
|
||||
#include <cmath>
|
||||
#include <chrono>
|
||||
#include <cstdlib>
|
||||
#include <optional>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
|
@ -80,6 +81,16 @@ static std::unordered_map<std::string, EmoteInfo> EMOTE_TABLE;
|
|||
static std::unordered_map<uint32_t, const EmoteInfo*> EMOTE_BY_DBCID; // reverse lookup: dbcId → EmoteInfo*
|
||||
static bool emoteTableLoaded = false;
|
||||
|
||||
static bool envFlagEnabled(const char* key, bool defaultValue) {
|
||||
const char* raw = std::getenv(key);
|
||||
if (!raw || !*raw) return defaultValue;
|
||||
std::string v(raw);
|
||||
std::transform(v.begin(), v.end(), v.begin(), [](unsigned char c) {
|
||||
return static_cast<char>(std::tolower(c));
|
||||
});
|
||||
return !(v == "0" || v == "false" || v == "off" || v == "no");
|
||||
}
|
||||
|
||||
static std::vector<std::string> parseEmoteCommands(const std::string& raw) {
|
||||
std::vector<std::string> out;
|
||||
std::string cur;
|
||||
|
|
@ -250,6 +261,7 @@ Renderer::~Renderer() = default;
|
|||
|
||||
bool Renderer::initialize(core::Window* win) {
|
||||
window = win;
|
||||
deferredWorldInitEnabled_ = envFlagEnabled("WOWEE_DEFER_WORLD_SYSTEMS", true);
|
||||
LOG_INFO("Initializing renderer");
|
||||
|
||||
// Create camera (in front of Stormwind gate, looking north)
|
||||
|
|
@ -1909,6 +1921,7 @@ void Renderer::update(float deltaTime) {
|
|||
if (musicSwitchCooldown_ > 0.0f) {
|
||||
musicSwitchCooldown_ = std::max(0.0f, musicSwitchCooldown_ - deltaTime);
|
||||
}
|
||||
runDeferredWorldInitStep(deltaTime);
|
||||
|
||||
auto updateStart = std::chrono::steady_clock::now();
|
||||
lastDeltaTime_ = deltaTime; // Cache for use in updateCharacterAnimation()
|
||||
|
|
@ -2455,6 +2468,46 @@ void Renderer::update(float deltaTime) {
|
|||
}
|
||||
}
|
||||
|
||||
void Renderer::runDeferredWorldInitStep(float deltaTime) {
|
||||
if (!deferredWorldInitEnabled_ || !deferredWorldInitPending_ || !cachedAssetManager) return;
|
||||
if (deferredWorldInitCooldown_ > 0.0f) {
|
||||
deferredWorldInitCooldown_ = std::max(0.0f, deferredWorldInitCooldown_ - deltaTime);
|
||||
if (deferredWorldInitCooldown_ > 0.0f) return;
|
||||
}
|
||||
|
||||
switch (deferredWorldInitStage_) {
|
||||
case 0:
|
||||
if (ambientSoundManager) {
|
||||
ambientSoundManager->initialize(cachedAssetManager);
|
||||
}
|
||||
if (terrainManager && ambientSoundManager) {
|
||||
terrainManager->setAmbientSoundManager(ambientSoundManager.get());
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (uiSoundManager) uiSoundManager->initialize(cachedAssetManager);
|
||||
break;
|
||||
case 2:
|
||||
if (combatSoundManager) combatSoundManager->initialize(cachedAssetManager);
|
||||
break;
|
||||
case 3:
|
||||
if (spellSoundManager) spellSoundManager->initialize(cachedAssetManager);
|
||||
break;
|
||||
case 4:
|
||||
if (movementSoundManager) movementSoundManager->initialize(cachedAssetManager);
|
||||
break;
|
||||
case 5:
|
||||
if (questMarkerRenderer) questMarkerRenderer->initialize(cachedAssetManager);
|
||||
break;
|
||||
default:
|
||||
deferredWorldInitPending_ = false;
|
||||
return;
|
||||
}
|
||||
|
||||
deferredWorldInitStage_++;
|
||||
deferredWorldInitCooldown_ = 0.12f;
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// Selection Circle
|
||||
// ============================================================
|
||||
|
|
@ -3197,39 +3250,46 @@ bool Renderer::loadTestTerrain(pipeline::AssetManager* assetManager, const std::
|
|||
if (npcVoiceManager) {
|
||||
npcVoiceManager->initialize(assetManager);
|
||||
}
|
||||
if (ambientSoundManager) {
|
||||
ambientSoundManager->initialize(assetManager);
|
||||
}
|
||||
if (uiSoundManager) {
|
||||
uiSoundManager->initialize(assetManager);
|
||||
}
|
||||
if (combatSoundManager) {
|
||||
combatSoundManager->initialize(assetManager);
|
||||
}
|
||||
if (spellSoundManager) {
|
||||
spellSoundManager->initialize(assetManager);
|
||||
}
|
||||
if (movementSoundManager) {
|
||||
movementSoundManager->initialize(assetManager);
|
||||
}
|
||||
if (questMarkerRenderer) {
|
||||
questMarkerRenderer->initialize(assetManager);
|
||||
}
|
||||
|
||||
// Prewarm frequently used zone/tavern music so zone transitions don't stall on MPQ I/O.
|
||||
if (zoneManager) {
|
||||
for (const auto& musicPath : zoneManager->getAllMusicPaths()) {
|
||||
musicManager->preloadMusic(musicPath);
|
||||
if (!deferredWorldInitEnabled_) {
|
||||
if (ambientSoundManager) {
|
||||
ambientSoundManager->initialize(assetManager);
|
||||
}
|
||||
}
|
||||
static const std::vector<std::string> tavernTracks = {
|
||||
"Sound\\Music\\ZoneMusic\\TavernAlliance\\TavernAlliance01.mp3",
|
||||
"Sound\\Music\\ZoneMusic\\TavernAlliance\\TavernAlliance02.mp3",
|
||||
"Sound\\Music\\ZoneMusic\\TavernHuman\\RA_HumanTavern1A.mp3",
|
||||
"Sound\\Music\\ZoneMusic\\TavernHuman\\RA_HumanTavern2A.mp3",
|
||||
};
|
||||
for (const auto& musicPath : tavernTracks) {
|
||||
musicManager->preloadMusic(musicPath);
|
||||
if (uiSoundManager) {
|
||||
uiSoundManager->initialize(assetManager);
|
||||
}
|
||||
if (combatSoundManager) {
|
||||
combatSoundManager->initialize(assetManager);
|
||||
}
|
||||
if (spellSoundManager) {
|
||||
spellSoundManager->initialize(assetManager);
|
||||
}
|
||||
if (movementSoundManager) {
|
||||
movementSoundManager->initialize(assetManager);
|
||||
}
|
||||
if (questMarkerRenderer) {
|
||||
questMarkerRenderer->initialize(assetManager);
|
||||
}
|
||||
|
||||
if (envFlagEnabled("WOWEE_PREWARM_ZONE_MUSIC", false)) {
|
||||
if (zoneManager) {
|
||||
for (const auto& musicPath : zoneManager->getAllMusicPaths()) {
|
||||
musicManager->preloadMusic(musicPath);
|
||||
}
|
||||
}
|
||||
static const std::vector<std::string> tavernTracks = {
|
||||
"Sound\\Music\\ZoneMusic\\TavernAlliance\\TavernAlliance01.mp3",
|
||||
"Sound\\Music\\ZoneMusic\\TavernAlliance\\TavernAlliance02.mp3",
|
||||
"Sound\\Music\\ZoneMusic\\TavernHuman\\RA_HumanTavern1A.mp3",
|
||||
"Sound\\Music\\ZoneMusic\\TavernHuman\\RA_HumanTavern2A.mp3",
|
||||
};
|
||||
for (const auto& musicPath : tavernTracks) {
|
||||
musicManager->preloadMusic(musicPath);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
deferredWorldInitPending_ = true;
|
||||
deferredWorldInitStage_ = 0;
|
||||
deferredWorldInitCooldown_ = 0.25f;
|
||||
}
|
||||
|
||||
cachedAssetManager = assetManager;
|
||||
|
|
@ -3316,23 +3376,29 @@ bool Renderer::loadTerrainArea(const std::string& mapName, int centerX, int cent
|
|||
if (npcVoiceManager && cachedAssetManager) {
|
||||
npcVoiceManager->initialize(cachedAssetManager);
|
||||
}
|
||||
if (ambientSoundManager && cachedAssetManager) {
|
||||
ambientSoundManager->initialize(cachedAssetManager);
|
||||
}
|
||||
if (uiSoundManager && cachedAssetManager) {
|
||||
uiSoundManager->initialize(cachedAssetManager);
|
||||
}
|
||||
if (combatSoundManager && cachedAssetManager) {
|
||||
combatSoundManager->initialize(cachedAssetManager);
|
||||
}
|
||||
if (spellSoundManager && cachedAssetManager) {
|
||||
spellSoundManager->initialize(cachedAssetManager);
|
||||
}
|
||||
if (movementSoundManager && cachedAssetManager) {
|
||||
movementSoundManager->initialize(cachedAssetManager);
|
||||
}
|
||||
if (questMarkerRenderer && cachedAssetManager) {
|
||||
questMarkerRenderer->initialize(cachedAssetManager);
|
||||
if (!deferredWorldInitEnabled_) {
|
||||
if (ambientSoundManager && cachedAssetManager) {
|
||||
ambientSoundManager->initialize(cachedAssetManager);
|
||||
}
|
||||
if (uiSoundManager && cachedAssetManager) {
|
||||
uiSoundManager->initialize(cachedAssetManager);
|
||||
}
|
||||
if (combatSoundManager && cachedAssetManager) {
|
||||
combatSoundManager->initialize(cachedAssetManager);
|
||||
}
|
||||
if (spellSoundManager && cachedAssetManager) {
|
||||
spellSoundManager->initialize(cachedAssetManager);
|
||||
}
|
||||
if (movementSoundManager && cachedAssetManager) {
|
||||
movementSoundManager->initialize(cachedAssetManager);
|
||||
}
|
||||
if (questMarkerRenderer && cachedAssetManager) {
|
||||
questMarkerRenderer->initialize(cachedAssetManager);
|
||||
}
|
||||
} else {
|
||||
deferredWorldInitPending_ = true;
|
||||
deferredWorldInitStage_ = 0;
|
||||
deferredWorldInitCooldown_ = 0.1f;
|
||||
}
|
||||
|
||||
// Wire ambient sound manager to terrain manager for emitter registration
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue