mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-03-22 23:30:14 +00:00
Fix WMO spawn presets to avoid terrain snapping
This commit is contained in:
parent
ae37e5592e
commit
28a8e806e1
3 changed files with 28 additions and 18 deletions
|
|
@ -92,6 +92,7 @@ private:
|
||||||
bool singlePlayerMode = false;
|
bool singlePlayerMode = false;
|
||||||
bool playerCharacterSpawned = false;
|
bool playerCharacterSpawned = false;
|
||||||
bool npcsSpawned = false;
|
bool npcsSpawned = false;
|
||||||
|
bool spawnSnapToGround = true;
|
||||||
float lastFrameTime = 0.0f;
|
float lastFrameTime = 0.0f;
|
||||||
float movementHeartbeatTimer = 0.0f;
|
float movementHeartbeatTimer = 0.0f;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,17 +11,20 @@ struct SpawnPreset {
|
||||||
glm::vec3 spawnCanonical; // Canonical WoW coords: +X=North, +Y=West, +Z=Up
|
glm::vec3 spawnCanonical; // Canonical WoW coords: +X=North, +Y=West, +Z=Up
|
||||||
float yawDeg;
|
float yawDeg;
|
||||||
float pitchDeg;
|
float pitchDeg;
|
||||||
|
bool snapToGround; // true=terrain/WMO floor search, false=preserve explicit Z
|
||||||
};
|
};
|
||||||
|
|
||||||
// Spawn positions in canonical WoW world coordinates (X=north, Y=west, Z=up).
|
// Spawn positions in canonical WoW world coordinates (X=north, Y=west, Z=up).
|
||||||
// Tile is computed from position via: tileN = floor(32 - wowN / 533.33333)
|
// Tile is computed from position via: tileN = floor(32 - wowN / 533.33333)
|
||||||
inline const SpawnPreset SPAWN_PRESETS[] = {
|
inline const SpawnPreset SPAWN_PRESETS[] = {
|
||||||
{"goldshire", "Goldshire", "Azeroth", glm::vec3( 62.0f, -9464.0f, 200.0f), 0.0f, -5.0f},
|
{"goldshire", "Goldshire", "Azeroth", glm::vec3( 62.0f, -9464.0f, 200.0f), 0.0f, -5.0f, true},
|
||||||
{"stormwind", "Stormwind Gate", "Azeroth", glm::vec3( 425.0f, -9176.0f, 120.0f), 35.0f, -8.0f},
|
{"stormwind", "Stormwind Gate", "Azeroth", glm::vec3( 425.0f, -9176.0f, 120.0f), 35.0f, -8.0f, true},
|
||||||
{"ironforge", "Ironforge", "Azeroth", glm::vec3( -882.0f, -4981.0f, 510.0f), -20.0f, -8.0f},
|
// Stormwind city center plaza on WMO floor (not terrain intersection).
|
||||||
{"westfall", "Westfall", "Azeroth", glm::vec3( 1215.0f,-10440.0f, 80.0f), 10.0f, -8.0f},
|
{"sw_plaza", "Stormwind Plaza","Azeroth", glm::vec3( 620.0f, -8830.0f, 95.0f), 180.0f, -8.0f, false},
|
||||||
|
{"ironforge", "Ironforge", "Azeroth", glm::vec3( -882.0f, -4981.0f, 510.0f), -20.0f, -8.0f, true},
|
||||||
|
{"westfall", "Westfall", "Azeroth", glm::vec3( 1215.0f,-10440.0f, 80.0f), 10.0f, -8.0f, true},
|
||||||
};
|
};
|
||||||
|
|
||||||
inline constexpr int SPAWN_PRESET_COUNT = 4;
|
inline constexpr int SPAWN_PRESET_COUNT = static_cast<int>(sizeof(SPAWN_PRESETS) / sizeof(SPAWN_PRESETS[0]));
|
||||||
|
|
||||||
} // namespace wowee::core
|
} // namespace wowee::core
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ const SpawnPreset* selectSpawnPreset(const char* envValue) {
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_WARNING("Unknown WOW_SPAWN='", key, "', falling back to goldshire");
|
LOG_WARNING("Unknown WOW_SPAWN='", key, "', falling back to goldshire");
|
||||||
LOG_INFO("Available WOW_SPAWN presets: goldshire, stormwind, ironforge, westfall");
|
LOG_INFO("Available WOW_SPAWN presets: goldshire, stormwind, sw_plaza, ironforge, westfall");
|
||||||
return &SPAWN_PRESETS[0];
|
return &SPAWN_PRESETS[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -676,12 +676,12 @@ void Application::spawnPlayerCharacter() {
|
||||||
LOG_INFO("Loaded fallback cube model (no MPQ data)");
|
LOG_INFO("Loaded fallback cube model (no MPQ data)");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Spawn character at the camera controller's default position (matches hearthstone),
|
// Spawn character at the camera controller's default position (matches hearthstone).
|
||||||
// but snap Z to actual terrain height so the character doesn't float.
|
// Most presets snap to floor; explicit WMO-floor presets keep their authored Z.
|
||||||
auto* camCtrl = renderer->getCameraController();
|
auto* camCtrl = renderer->getCameraController();
|
||||||
glm::vec3 spawnPos = camCtrl ? camCtrl->getDefaultPosition()
|
glm::vec3 spawnPos = camCtrl ? camCtrl->getDefaultPosition()
|
||||||
: (camera->getPosition() - glm::vec3(0.0f, 0.0f, 5.0f));
|
: (camera->getPosition() - glm::vec3(0.0f, 0.0f, 5.0f));
|
||||||
if (renderer->getTerrainManager()) {
|
if (spawnSnapToGround && renderer->getTerrainManager()) {
|
||||||
auto terrainH = renderer->getTerrainManager()->getHeightAt(spawnPos.x, spawnPos.y);
|
auto terrainH = renderer->getTerrainManager()->getHeightAt(spawnPos.x, spawnPos.y);
|
||||||
if (terrainH) {
|
if (terrainH) {
|
||||||
spawnPos.z = *terrainH + 0.1f;
|
spawnPos.z = *terrainH + 0.1f;
|
||||||
|
|
@ -913,6 +913,7 @@ void Application::startSinglePlayer() {
|
||||||
std::string mapName = spawnPreset ? spawnPreset->mapName : "Azeroth";
|
std::string mapName = spawnPreset ? spawnPreset->mapName : "Azeroth";
|
||||||
float spawnYaw = spawnPreset ? spawnPreset->yawDeg : 0.0f;
|
float spawnYaw = spawnPreset ? spawnPreset->yawDeg : 0.0f;
|
||||||
float spawnPitch = spawnPreset ? spawnPreset->pitchDeg : -5.0f;
|
float spawnPitch = spawnPreset ? spawnPreset->pitchDeg : -5.0f;
|
||||||
|
spawnSnapToGround = spawnPreset ? spawnPreset->snapToGround : true;
|
||||||
|
|
||||||
if (auto envSpawnPos = parseVec3Csv(std::getenv("WOW_SPAWN_POS"))) {
|
if (auto envSpawnPos = parseVec3Csv(std::getenv("WOW_SPAWN_POS"))) {
|
||||||
spawnCanonical = *envSpawnPos;
|
spawnCanonical = *envSpawnPos;
|
||||||
|
|
@ -1014,8 +1015,8 @@ void Application::startSinglePlayer() {
|
||||||
LOG_INFO("Terrain streaming complete: ", terrainMgr->getLoadedTileCount(), " tiles loaded");
|
LOG_INFO("Terrain streaming complete: ", terrainMgr->getLoadedTileCount(), " tiles loaded");
|
||||||
|
|
||||||
// Re-snap camera to ground now that all surrounding tiles are loaded
|
// Re-snap camera to ground now that all surrounding tiles are loaded
|
||||||
// (the initial reset inside loadTestTerrain only had 1 tile)
|
// (the initial reset inside loadTestTerrain only had 1 tile).
|
||||||
if (renderer->getCameraController()) {
|
if (spawnSnapToGround && renderer->getCameraController()) {
|
||||||
renderer->getCameraController()->reset();
|
renderer->getCameraController()->reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1027,7 +1028,7 @@ void Application::startSinglePlayer() {
|
||||||
|
|
||||||
// Final camera reset: now that follow target exists and terrain is loaded,
|
// Final camera reset: now that follow target exists and terrain is loaded,
|
||||||
// snap the third-person camera into the correct orbit position.
|
// snap the third-person camera into the correct orbit position.
|
||||||
if (renderer && renderer->getCameraController()) {
|
if (spawnSnapToGround && renderer && renderer->getCameraController()) {
|
||||||
renderer->getCameraController()->reset();
|
renderer->getCameraController()->reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1055,6 +1056,7 @@ void Application::teleportTo(int presetIndex) {
|
||||||
|
|
||||||
const auto& preset = SPAWN_PRESETS[presetIndex];
|
const auto& preset = SPAWN_PRESETS[presetIndex];
|
||||||
LOG_INFO("Teleporting to: ", preset.label);
|
LOG_INFO("Teleporting to: ", preset.label);
|
||||||
|
spawnSnapToGround = preset.snapToGround;
|
||||||
|
|
||||||
// Convert canonical WoW → engine rendering coordinates (swap X/Y)
|
// Convert canonical WoW → engine rendering coordinates (swap X/Y)
|
||||||
glm::vec3 spawnRender = core::coords::canonicalToRender(preset.spawnCanonical);
|
glm::vec3 spawnRender = core::coords::canonicalToRender(preset.spawnCanonical);
|
||||||
|
|
@ -1120,16 +1122,20 @@ void Application::teleportTo(int presetIndex) {
|
||||||
LOG_INFO("Teleport terrain streaming complete: ", terrainMgr->getLoadedTileCount(), " tiles loaded");
|
LOG_INFO("Teleport terrain streaming complete: ", terrainMgr->getLoadedTileCount(), " tiles loaded");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset camera — this snaps character position to terrain via followTarget
|
// Floor-snapping presets use camera reset. WMO-floor presets keep explicit Z.
|
||||||
if (renderer && renderer->getCameraController()) {
|
if (spawnSnapToGround && renderer && renderer->getCameraController()) {
|
||||||
renderer->getCameraController()->reset();
|
renderer->getCameraController()->reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sync the terrain-snapped character position to game handler
|
if (!spawnSnapToGround && renderer) {
|
||||||
|
renderer->getCharacterPosition() = spawnRender;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sync final character position to game handler
|
||||||
if (renderer && gameHandler) {
|
if (renderer && gameHandler) {
|
||||||
glm::vec3 snappedRender = renderer->getCharacterPosition();
|
glm::vec3 finalRender = renderer->getCharacterPosition();
|
||||||
glm::vec3 snappedCanonical = core::coords::renderToCanonical(snappedRender);
|
glm::vec3 finalCanonical = core::coords::renderToCanonical(finalRender);
|
||||||
gameHandler->setPosition(snappedCanonical.x, snappedCanonical.y, snappedCanonical.z);
|
gameHandler->setPosition(finalCanonical.x, finalCanonical.y, finalCanonical.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_INFO("Teleport to ", preset.label, " complete");
|
LOG_INFO("Teleport to ", preset.label, " complete");
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue