namespace XFEEDToolBox.Plugin;
internal static unsafe partial class Navigation
{
private static nuint dockingZeroAxisRoot;
private static ulong dockingZeroAxisVersion,dockingZeroAxisCommits,dockingZeroAxisRestoresSkipped;
private static void RememberDockingZero(nuint root)
{dockingZeroAxisRoot=root;dockingZeroAxisVersion++;dockingZeroAxisCommits++;}
private static void RestoreOverlayAxis(nuint root,int axis,float previous,float written,ulong version)
{
// FSD can run inside an input-evaluation overlay. A durable original
// zero must also survive restoration of that outer invocation.
if(axis==0&&root==dockingZeroAxisRoot&&version!=dockingZeroAxisVersion)
{dockingZeroAxisRestoresSkipped++;return;}
var address=root+0x70+(nuint)axis*0x10;
if(Read<float>(address)==written)Write(address,previous);
}
// SetSpeedZero updates the original controller, but an SCA exit can leave
// its last .75 value in the newly materialised ship's input buffer. Commit
// the requested zero only after overlays have been released. The caller
// has already checked the current main ship, owner, target and ATC grant.
private static bool CommitOriginalDockingZeroAxis(nuint inputRoot,nuint controller,float sampledThrottle,
bool originalInputConfirmed,bool inputLeaseReleased,out bool committed)
{
committed=false;
if(!originalInputConfirmed||!inputLeaseReleased||inputRoot<0x10000||controller<0x10000
||!float.IsFinite(sampledThrottle)||Math.Abs(sampledThrottle)>1.001f
||Pointer(inputRoot+0x2F8)!=controller||Read<float>(controller+0x680)!=0)return false;
var current=Read<float>(inputRoot+0x70);
if(current==0){RememberDockingZero(inputRoot);return true;}
// A changed sample may be a player input. Never overwrite it.
if(current!=sampledThrottle)return false;
Write(inputRoot+0x70,0f);
committed=Read<float>(inputRoot+0x70)==0;
if(committed)RememberDockingZero(inputRoot);
return committed;
}
}
namespace XFEEDToolBox.Plugin;
internal static unsafe partial class Navigation
{
private static nuint dockingZeroAxisRoot;
private static ulong dockingZeroAxisVersion,dockingZeroAxisCommits,dockingZeroAxisRestoresSkipped;
private static void RememberDockingZero(nuint root)
{dockingZeroAxisRoot=root;dockingZeroAxisVersion++;dockingZeroAxisCommits++;}
private static void RestoreOverlayAxis(nuint root,int axis,float previous,float written,ulong version)
{
// FSD can run inside an input-evaluation overlay. A durable original
// zero must also survive restoration of that outer invocation.
if(axis==0&&root==dockingZeroAxisRoot&&version!=dockingZeroAxisVersion)
{dockingZeroAxisRestoresSkipped++;return;}
var address=root+0x70+(nuint)axis*0x10;
if(Read<float>(address)==written)Write(address,previous);
}
// SetSpeedZero updates the original controller, but an SCA exit can leave
// its last .75 value in the newly materialised ship's input buffer. Commit
// the requested zero only after overlays have been released. The caller
// has already checked the current main ship, owner, target and ATC grant.
private static bool CommitOriginalDockingZeroAxis(nuint inputRoot,nuint controller,float sampledThrottle,
bool originalInputConfirmed,bool inputLeaseReleased,out bool committed)
{
committed=false;
if(!originalInputConfirmed||!inputLeaseReleased||inputRoot<0x10000||controller<0x10000
||!float.IsFinite(sampledThrottle)||Math.Abs(sampledThrottle)>1.001f
||Pointer(inputRoot+0x2F8)!=controller||Read<float>(controller+0x680)!=0)return false;
var current=Read<float>(inputRoot+0x70);
if(current==0){RememberDockingZero(inputRoot);return true;}
// A changed sample may be a player input. Never overwrite it.
if(current!=sampledThrottle)return false;
Write(inputRoot+0x70,0f);
committed=Read<float>(inputRoot+0x70)==0;
if(committed)RememberDockingZero(inputRoot);
return committed;
}
}