feat(vfx): port retail hidden and teleport presentation

Preserve canonical live-object ownership across Hidden transitions and remote teleport placement so effects, collision, streaming, and targeting remain synchronized.
This commit is contained in:
Erik 2026-07-14 14:59:48 +02:00
parent a51ebc66e9
commit 1e98d81448
46 changed files with 4883 additions and 127 deletions

View file

@ -96,6 +96,46 @@ public sealed class RadarSnapshotProviderTests
Assert.True(snapshot.UiLocked);
}
[Fact]
public void BuildSnapshot_UsesCanonicalPlayerWhileHiddenTargetsStayExcluded()
{
const uint player = 20u;
const uint hiddenTarget = 21u;
var objects = new ClientObjectTable();
objects.Ingest(Weenie(player, "Player", ItemType.Creature));
objects.Ingest(Weenie(hiddenTarget, "Hidden target", ItemType.Creature) with
{
RadarBehavior = (byte)RadarBehavior.ShowAlways,
});
var canonical = new Dictionary<uint, WorldEntity>
{
[player] = Entity(player, Vector3.Zero, Quaternion.Identity),
[hiddenTarget] = Entity(hiddenTarget, new Vector3(5f, 0f, 0f), Quaternion.Identity),
};
var interactionVisible = new Dictionary<uint, WorldEntity>();
var spawns = new Dictionary<uint, WorldSession.EntitySpawn>
{
[player] = Spawn(player),
[hiddenTarget] = Spawn(hiddenTarget),
};
var provider = new RadarSnapshotProvider(
objects,
interactionVisible,
spawns,
playerGuid: () => player,
playerYawRadians: () => 0f,
playerCellId: () => 0xA9B40001u,
selectedGuid: () => hiddenTarget,
coordinatesOnRadar: () => true,
uiLocked: () => false,
playerEntities: canonical);
var snapshot = provider.BuildSnapshot();
Assert.NotNull(snapshot.CoordinatesText);
Assert.Empty(snapshot.Blips);
}
private static WorldEntity Entity(uint guid, Vector3 position, Quaternion rotation) => new()
{
Id = guid,