mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-03-22 23:30:14 +00:00
Infer and animate elevator transport paths
This commit is contained in:
parent
c5ecf7d475
commit
76edd3260f
4 changed files with 40 additions and 8 deletions
|
|
@ -102,6 +102,12 @@ public:
|
|||
// Returns 0 when no suitable path match is found.
|
||||
uint32_t inferMovingPathForSpawn(const glm::vec3& spawnWorldPos, float maxDistance = 1200.0f) const;
|
||||
|
||||
// Infer a DBC path by spawn position, optionally including z-only elevator paths.
|
||||
// Returns 0 when no suitable path match is found.
|
||||
uint32_t inferDbcPathForSpawn(const glm::vec3& spawnWorldPos,
|
||||
float maxDistance,
|
||||
bool allowZOnly) const;
|
||||
|
||||
// Choose a deterministic fallback moving DBC path for known server transport entries/displayIds.
|
||||
// Returns 0 when no suitable moving path is available.
|
||||
uint32_t pickFallbackMovingPath(uint32_t entry, uint32_t displayId) const;
|
||||
|
|
|
|||
|
|
@ -1250,7 +1250,11 @@ void Application::setupUICallbacks() {
|
|||
LOG_INFO("Server-first transport registration: using entry DBC path for entry ", entry);
|
||||
}
|
||||
} else if (!hasUsablePath) {
|
||||
uint32_t inferredPath = transportManager->inferMovingPathForSpawn(canonicalSpawnPos);
|
||||
// Remap/infer path by spawn position when entry doesn't map 1:1 to DBC ids.
|
||||
// For elevators (TB lift platforms), we must allow z-only paths here.
|
||||
bool allowZOnly = (displayId == 455 || displayId == 462);
|
||||
uint32_t inferredPath = transportManager->inferDbcPathForSpawn(
|
||||
canonicalSpawnPos, 1200.0f, allowZOnly);
|
||||
if (inferredPath != 0) {
|
||||
pathId = inferredPath;
|
||||
LOG_INFO("Using inferred transport path ", pathId, " for entry ", entry);
|
||||
|
|
@ -1359,7 +1363,9 @@ void Application::setupUICallbacks() {
|
|||
" displayId=", displayId, " wmoInstance=", wmoInstanceId);
|
||||
}
|
||||
} else if (!hasUsablePath) {
|
||||
uint32_t inferredPath = transportManager->inferMovingPathForSpawn(canonicalSpawnPos);
|
||||
bool allowZOnly = (displayId == 455 || displayId == 462);
|
||||
uint32_t inferredPath = transportManager->inferDbcPathForSpawn(
|
||||
canonicalSpawnPos, 1200.0f, allowZOnly);
|
||||
if (inferredPath != 0) {
|
||||
pathId = inferredPath;
|
||||
LOG_INFO("Auto-spawned transport with inferred path: entry=", entry,
|
||||
|
|
|
|||
|
|
@ -2701,6 +2701,7 @@ void GameHandler::handleUpdateObject(network::Packet& packet) {
|
|||
if (block.updateFlags & 0x0002) {
|
||||
transportGuids_.insert(block.guid);
|
||||
LOG_INFO("Detected transport GameObject: 0x", std::hex, block.guid, std::dec,
|
||||
" entry=", go->getEntry(),
|
||||
" displayId=", go->getDisplayId(),
|
||||
" pos=(", go->getX(), ", ", go->getY(), ", ", go->getZ(), ")");
|
||||
// Note: TransportSpawnCallback will be invoked from Application after WMO instance is created
|
||||
|
|
|
|||
|
|
@ -891,15 +891,23 @@ bool TransportManager::loadTransportAnimationDBC(pipeline::AssetManager* assetMg
|
|||
float maxX = timedPoints[0].pos.x;
|
||||
float minY = timedPoints[0].pos.y;
|
||||
float maxY = timedPoints[0].pos.y;
|
||||
float minZ = timedPoints[0].pos.z;
|
||||
float maxZ = timedPoints[0].pos.z;
|
||||
for (const auto& pt : timedPoints) {
|
||||
minX = std::min(minX, pt.pos.x);
|
||||
maxX = std::max(maxX, pt.pos.x);
|
||||
minY = std::min(minY, pt.pos.y);
|
||||
maxY = std::max(maxY, pt.pos.y);
|
||||
minZ = std::min(minZ, pt.pos.z);
|
||||
maxZ = std::max(maxZ, pt.pos.z);
|
||||
}
|
||||
float rangeX = maxX - minX;
|
||||
float rangeY = maxY - minY;
|
||||
bool isZOnly = (rangeX < 0.01f && rangeY < 0.01f);
|
||||
float rangeZ = maxZ - minZ;
|
||||
float rangeXY = std::max(rangeX, rangeY);
|
||||
// Some elevator paths have tiny XY jitter. Treat them as z-only when horizontal travel
|
||||
// is negligible compared to vertical motion.
|
||||
bool isZOnly = (rangeXY < 0.01f) || (rangeXY < 1.0f && rangeZ > 2.0f);
|
||||
|
||||
// Store path
|
||||
TransportPath path;
|
||||
|
|
@ -921,7 +929,8 @@ bool TransportManager::loadTransportAnimationDBC(pipeline::AssetManager* assetMg
|
|||
glm::vec3 lastOffset = timedPoints[timedPoints.size() - 2].pos; // -2 to skip wrap duplicate
|
||||
LOG_INFO(" Transport ", transportEntry, ": ", timedPoints.size() - 1, " waypoints + wrap, ",
|
||||
durationMs, "ms duration (wrap=", wrapMs, "ms, t0_normalized=", timedPoints[0].tMs, "ms)",
|
||||
" rangeXY=(", rangeX, ",", rangeY, ") ", (isZOnly ? "[Z-ONLY]" : "[XY-PATH]"),
|
||||
" rangeXY=(", rangeX, ",", rangeY, ") rangeZ=", rangeZ, " ",
|
||||
(isZOnly ? "[Z-ONLY]" : "[XY-PATH]"),
|
||||
" firstOffset=(", firstOffset.x, ", ", firstOffset.y, ", ", firstOffset.z, ")",
|
||||
" midOffset=(", midOffset.x, ", ", midOffset.y, ", ", midOffset.z, ")",
|
||||
" lastOffset=(", lastOffset.x, ", ", lastOffset.y, ", ", lastOffset.z, ")");
|
||||
|
|
@ -960,12 +969,17 @@ bool TransportManager::hasUsableMovingPathForEntry(uint32_t entry, float minXYRa
|
|||
return rangeXY >= minXYRange;
|
||||
}
|
||||
|
||||
uint32_t TransportManager::inferMovingPathForSpawn(const glm::vec3& spawnWorldPos, float maxDistance) const {
|
||||
uint32_t TransportManager::inferDbcPathForSpawn(const glm::vec3& spawnWorldPos,
|
||||
float maxDistance,
|
||||
bool allowZOnly) const {
|
||||
float bestD2 = maxDistance * maxDistance;
|
||||
uint32_t bestPathId = 0;
|
||||
|
||||
for (const auto& [pathId, path] : paths_) {
|
||||
if (!path.fromDBC || path.durationMs == 0 || path.zOnly || path.points.empty()) {
|
||||
if (!path.fromDBC || path.durationMs == 0 || path.points.empty()) {
|
||||
continue;
|
||||
}
|
||||
if (!allowZOnly && path.zOnly) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -981,14 +995,19 @@ uint32_t TransportManager::inferMovingPathForSpawn(const glm::vec3& spawnWorldPo
|
|||
}
|
||||
|
||||
if (bestPathId != 0) {
|
||||
LOG_INFO("TransportManager: Inferred moving DBC path ", bestPathId,
|
||||
" for spawn at (", spawnWorldPos.x, ", ", spawnWorldPos.y, ", ", spawnWorldPos.z,
|
||||
LOG_INFO("TransportManager: Inferred DBC path ", bestPathId,
|
||||
" (allowZOnly=", allowZOnly ? "yes" : "no",
|
||||
") for spawn at (", spawnWorldPos.x, ", ", spawnWorldPos.y, ", ", spawnWorldPos.z,
|
||||
"), dist=", std::sqrt(bestD2));
|
||||
}
|
||||
|
||||
return bestPathId;
|
||||
}
|
||||
|
||||
uint32_t TransportManager::inferMovingPathForSpawn(const glm::vec3& spawnWorldPos, float maxDistance) const {
|
||||
return inferDbcPathForSpawn(spawnWorldPos, maxDistance, /*allowZOnly=*/false);
|
||||
}
|
||||
|
||||
uint32_t TransportManager::pickFallbackMovingPath(uint32_t entry, uint32_t displayId) const {
|
||||
auto isUsableMovingPath = [this](uint32_t pathId) -> bool {
|
||||
auto it = paths_.find(pathId);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue