Update opcode data and movement integration docs/code

This commit is contained in:
Kelsi 2026-02-18 03:15:25 -08:00
parent 69b23f4edd
commit 73e7c86621
11 changed files with 41 additions and 15 deletions

View file

@ -3419,6 +3419,20 @@ void Application::spawnOnlineCreature(uint64_t guid, uint32_t displayId, float x
}
}
// Use the entity's latest server-authoritative position rather than the stale spawn
// position. Movement packets (SMSG_MONSTER_MOVE) can arrive while a creature is still
// queued in pendingCreatureSpawns_ and get silently dropped. getLatestX/Y/Z returns
// the movement destination if the entity is mid-move, which is always up-to-date
// regardless of distance culling (unlike getX/Y/Z which requires updateMovement).
if (gameHandler) {
if (auto entity = gameHandler->getEntityManager().getEntity(guid)) {
x = entity->getLatestX();
y = entity->getLatestY();
z = entity->getLatestZ();
orientation = entity->getOrientation();
}
}
// Convert canonical → render coordinates
glm::vec3 renderPos = core::coords::canonicalToRender(glm::vec3(x, y, z));

View file

@ -126,6 +126,7 @@ static const OpcodeNameEntry kOpcodeNames[] = {
{"CMSG_BINDER_ACTIVATE", LogicalOpcode::CMSG_BINDER_ACTIVATE},
{"SMSG_LOG_XPGAIN", LogicalOpcode::SMSG_LOG_XPGAIN},
{"SMSG_MONSTER_MOVE", LogicalOpcode::SMSG_MONSTER_MOVE},
{"SMSG_COMPRESSED_MOVES", LogicalOpcode::SMSG_COMPRESSED_MOVES},
{"CMSG_ATTACKSWING", LogicalOpcode::CMSG_ATTACKSWING},
{"CMSG_ATTACKSTOP", LogicalOpcode::CMSG_ATTACKSTOP},
{"SMSG_ATTACKSTART", LogicalOpcode::SMSG_ATTACKSTART},

View file

@ -1175,22 +1175,15 @@ bool M2Renderer::loadModel(const pipeline::M2Model& model, uint32_t modelId) {
}
bgpu.texture = tex;
bgpu.hasAlpha = (tex != 0 && tex != whiteTexture);
bgpu.textureUnit = static_cast<uint8_t>(batch.textureUnit & 0x1);
// textureCoordIndex is an index into a texture coord combo table, not directly
// a UV set selector. Most batches have index=0 (UV set 0). We always use UV set 0
// since we don't have the full combo table — dual-UV effects are rare edge cases.
bgpu.textureUnit = 0;
// Resolve opacity: texture weight track × color animation alpha
// Batches whose texture failed to load are hidden (avoid white shell artifacts)
// Batch is hidden only when its named texture failed to load (avoids white shell artifacts).
// Do NOT bake transparency/color animation tracks here — they animate over time and
// baking the first keyframe value causes legitimate meshes to become invisible.
bgpu.batchOpacity = texFailed ? 0.0f : 1.0f;
// Texture weight track (via transparency lookup)
if (batch.transparencyIndex < model.textureTransformLookup.size()) {
uint16_t trackIdx = model.textureTransformLookup[batch.transparencyIndex];
if (trackIdx < model.textureWeights.size()) {
bgpu.batchOpacity *= model.textureWeights[trackIdx];
}
}
// Color animation alpha (M2Color.alpha, indexed directly by colorIndex)
if (batch.colorIndex < model.colorAlphas.size()) {
bgpu.batchOpacity *= model.colorAlphas[batch.colorIndex];
}
// Compute batch center and radius for glow sprite positioning
if (bgpu.blendMode >= 3 && batch.indexCount > 0) {