fix(combat): escape occupied login positions
Port retail's radius-aware placement ring so a relogging player is seated beside creatures occupying the saved location, and register the local body in the shared resolved-shadow pipeline. Route new forward movement and jump through AbortAutomaticAttack so repeat combat cancels immediately on movement. Co-Authored-By: Codex <codex@openai.com>
This commit is contained in:
parent
e671b8a5c4
commit
00fe993f6f
11 changed files with 643 additions and 16 deletions
|
|
@ -607,13 +607,14 @@ internal sealed class RemotePhysicsUpdater
|
|||
/// </summary>
|
||||
public void SyncRemoteShadowToBody(uint entityId, RemoteMotion rm, int liveCenterX, int liveCenterY)
|
||||
{
|
||||
int shLbX = (int)((rm.CellId >> 24) & 0xFFu);
|
||||
int shLbY = (int)((rm.CellId >> 16) & 0xFFu);
|
||||
float shOffX = (shLbX - liveCenterX) * 192f;
|
||||
float shOffY = (shLbY - liveCenterY) * 192f;
|
||||
_physicsEngine.ShadowObjects.UpdatePosition(
|
||||
entityId, rm.Body.Position, rm.Body.Orientation,
|
||||
shOffX, shOffY, rm.CellId, seedCellId: rm.CellId);
|
||||
ShadowPositionSynchronizer.Sync(
|
||||
_physicsEngine.ShadowObjects,
|
||||
entityId,
|
||||
rm.Body.Position,
|
||||
rm.Body.Orientation,
|
||||
rm.CellId,
|
||||
liveCenterX,
|
||||
liveCenterY);
|
||||
rm.LastShadowSyncPos = rm.Body.Position;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
39
src/AcDream.App/Physics/ShadowPositionSynchronizer.cs
Normal file
39
src/AcDream.App/Physics/ShadowPositionSynchronizer.cs
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
using System.Numerics;
|
||||
using AcDream.Core.Physics;
|
||||
|
||||
namespace AcDream.App.Physics;
|
||||
|
||||
/// <summary>
|
||||
/// Shared host adapter for retail's moved-object shadow re-registration
|
||||
/// (<c>CPhysicsObj::SetPositionInternal</c> 0x00515330). Both the local body
|
||||
/// and remote dead-reckoning bodies publish their resolved position through
|
||||
/// this one cell-offset calculation.
|
||||
/// </summary>
|
||||
internal static class ShadowPositionSynchronizer
|
||||
{
|
||||
public static void Sync(
|
||||
ShadowObjectRegistry registry,
|
||||
uint entityId,
|
||||
Vector3 position,
|
||||
Quaternion orientation,
|
||||
uint cellId,
|
||||
int liveCenterX,
|
||||
int liveCenterY)
|
||||
{
|
||||
if (cellId == 0)
|
||||
return;
|
||||
|
||||
int landblockX = (int)((cellId >> 24) & 0xFFu);
|
||||
int landblockY = (int)((cellId >> 16) & 0xFFu);
|
||||
float worldOffsetX = (landblockX - liveCenterX) * 192f;
|
||||
float worldOffsetY = (landblockY - liveCenterY) * 192f;
|
||||
registry.UpdatePosition(
|
||||
entityId,
|
||||
position,
|
||||
orientation,
|
||||
worldOffsetX,
|
||||
worldOffsetY,
|
||||
cellId,
|
||||
seedCellId: cellId);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue