Merge pull request #2665 from Mailaender/pvecfloat-combat
Fix floating point inconsistencies to reduce desyncs
This commit is contained in:
4
OpenRA.FileFormats/Thirdparty/Random.cs
vendored
4
OpenRA.FileFormats/Thirdparty/Random.cs
vendored
@@ -20,6 +20,7 @@ namespace OpenRA.Thirdparty
|
||||
int index = 0;
|
||||
|
||||
public int Last;
|
||||
public int TotalCount = 0;
|
||||
|
||||
public Random() : this(Environment.TickCount) { }
|
||||
|
||||
@@ -41,13 +42,14 @@ namespace OpenRA.Thirdparty
|
||||
y ^= y >> 18;
|
||||
|
||||
index = (index + 1) % 624;
|
||||
TotalCount++;
|
||||
Last = (int)(y % int.MaxValue);
|
||||
return Last;
|
||||
}
|
||||
|
||||
public int Next(int low, int high) { return low + Next() % (high - low); }
|
||||
public int Next(int high) { return Next() % high; }
|
||||
public double NextDouble() { return Math.Abs(Next() / (double)0x7fffffff); }
|
||||
public float NextFloat() { return Math.Abs(Next() / (float)0x7fffffff); }
|
||||
|
||||
void Generate()
|
||||
{
|
||||
|
||||
@@ -143,22 +143,14 @@ namespace OpenRA
|
||||
var si = Info.Traits.GetOrDefault<SelectableInfo>();
|
||||
if (si != null && si.Bounds != null && si.Bounds.Length > 2)
|
||||
{
|
||||
#if true
|
||||
loc += new PVecInt(si.Bounds[2], si.Bounds[3]);
|
||||
#else
|
||||
loc.X += si.Bounds[2];
|
||||
loc.Y += si.Bounds[3];
|
||||
#endif
|
||||
}
|
||||
|
||||
var move = Move.Value;
|
||||
if (move != null)
|
||||
{
|
||||
#if true
|
||||
loc -= new PVecInt(0, move.Altitude);
|
||||
#else
|
||||
loc.Y -= move.Altitude;
|
||||
#endif
|
||||
|
||||
if (useAltitude)
|
||||
size = new PVecInt(size.X, size.Y + move.Altitude);
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ namespace OpenRA.Network
|
||||
{
|
||||
report.Frame = orderManager.NetFrameNumber;
|
||||
report.SyncedRandom = orderManager.world.SharedRandom.Last;
|
||||
report.TotalCount = orderManager.world.SharedRandom.TotalCount;
|
||||
report.Traits.Clear();
|
||||
foreach (var a in orderManager.world.ActorsWithTrait<ISync>())
|
||||
{
|
||||
@@ -58,7 +59,7 @@ namespace OpenRA.Network
|
||||
if (r.Frame == frame)
|
||||
{
|
||||
Log.Write("sync", "Sync for net frame {0} -------------", r.Frame);
|
||||
Log.Write("sync", "SharedRandom: "+r.SyncedRandom);
|
||||
Log.Write("sync", "SharedRandom: {0} (#{1})", r.SyncedRandom, r.TotalCount);
|
||||
Log.Write("sync", "Synced Traits:");
|
||||
foreach (var a in r.Traits)
|
||||
Log.Write("sync", "\t {0} {1} {2} {3} ({4})".F(
|
||||
@@ -77,6 +78,7 @@ namespace OpenRA.Network
|
||||
{
|
||||
public int Frame;
|
||||
public int SyncedRandom;
|
||||
public int TotalCount;
|
||||
public List<TraitReport> Traits = new List<TraitReport>();
|
||||
}
|
||||
|
||||
|
||||
@@ -127,7 +127,7 @@ namespace OpenRA
|
||||
|
||||
public static float Gauss1D(this Thirdparty.Random r, int samples)
|
||||
{
|
||||
return Exts.MakeArray(samples, _ => (float)r.NextDouble() * 2 - 1f)
|
||||
return Exts.MakeArray(samples, _ => r.NextFloat() * 2 - 1f)
|
||||
.Sum() / samples;
|
||||
}
|
||||
|
||||
|
||||
@@ -38,13 +38,12 @@ namespace OpenRA.Mods.RA.Air
|
||||
}
|
||||
|
||||
var attack = self.Trait<AttackHeli>();
|
||||
var range = attack.GetMaximumRange() * 0.625f;
|
||||
var dist = target.CenterLocation - self.CenterLocation;
|
||||
|
||||
var desiredFacing = Util.GetFacing(dist, aircraft.Facing);
|
||||
aircraft.Facing = Util.TickFacing(aircraft.Facing, desiredFacing, aircraft.ROT);
|
||||
|
||||
if( !float2.WithinEpsilon( float2.Zero, dist.ToFloat2(), range * Game.CellSize ) )
|
||||
if (!Combat.IsInRange(self.CenterLocation, attack.GetMaximumRange(), target))
|
||||
aircraft.TickMove(PSubPos.PerPx * aircraft.MovementSpeed, desiredFacing);
|
||||
|
||||
attack.DoAttack( self, target );
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace OpenRA.Mods.RA.Air
|
||||
}
|
||||
|
||||
var dist = Dest - aircraft.PxPosition;
|
||||
if (float2.WithinEpsilon(float2.Zero, dist.ToFloat2(), 2))
|
||||
if (Math.Abs(dist.X) < 2 && Math.Abs(dist.Y) < 2)
|
||||
{
|
||||
aircraft.SubPxPosition = Dest.ToPSubPos();
|
||||
return NextActivity;
|
||||
|
||||
@@ -56,17 +56,17 @@ namespace OpenRA.Mods.RA.Air
|
||||
var altitude = aircraft.Altitude;
|
||||
if (altitude == 0) altitude = self.Info.Traits.Get<PlaneInfo>().CruiseAltitude;
|
||||
|
||||
var approachStart = landPos.ToFloat2() - new float2(altitude * speed, 0);
|
||||
var approachStart = landPos.ToInt2() - new float2(altitude * speed, 0);
|
||||
var turnRadius = (128f / self.Info.Traits.Get<AircraftInfo>().ROT) * speed / (float)Math.PI;
|
||||
|
||||
/* work out the center points */
|
||||
var fwd = -float2.FromAngle(aircraft.Facing / 128f * (float)Math.PI);
|
||||
var side = new float2(-fwd.Y, fwd.X); /* rotate */
|
||||
var sideTowardBase = new[] { side, -side }
|
||||
.OrderBy(a => float2.Dot(a, self.CenterLocation.ToFloat2() - approachStart))
|
||||
.OrderBy(a => float2.Dot(a, self.CenterLocation.ToInt2() - approachStart))
|
||||
.First();
|
||||
|
||||
var c1 = self.CenterLocation.ToFloat2() + turnRadius * sideTowardBase;
|
||||
var c1 = self.CenterLocation.ToInt2() + turnRadius * sideTowardBase;
|
||||
var c2 = approachStart + new float2(0, turnRadius * Math.Sign(self.CenterLocation.Y - approachStart.Y)); // above or below start point
|
||||
|
||||
/* work out tangent points */
|
||||
|
||||
@@ -107,7 +107,7 @@ namespace OpenRA.Mods.RA
|
||||
{
|
||||
var info = self.Info.Traits.Get<AttackBaseInfo>();
|
||||
nextScanTime = (int)(25 * (info.ScanTimeAverage +
|
||||
(self.World.SharedRandom.NextDouble() * 2 - 1) * info.ScanTimeSpread));
|
||||
(self.World.SharedRandom.NextFloat() * 2 - 1) * info.ScanTimeSpread));
|
||||
|
||||
var inRange = self.World.FindUnitsInCircle(self.CenterLocation, (int)(Game.CellSize * range));
|
||||
|
||||
|
||||
@@ -208,18 +208,18 @@ namespace OpenRA.Mods.RA
|
||||
return false;
|
||||
}
|
||||
|
||||
static float2 GetRecoil(Actor self, float recoil)
|
||||
static PVecFloat GetRecoil(Actor self, float recoil)
|
||||
{
|
||||
if (!self.HasTrait<RenderUnitTurreted>())
|
||||
return float2.Zero;
|
||||
return PVecFloat.Zero;
|
||||
|
||||
var facing = self.Trait<Turreted>().turretFacing;
|
||||
var localRecoil = new float2(0, recoil); // vector in turret-space.
|
||||
|
||||
return Util.RotateVectorByFacing(localRecoil, facing, .7f);
|
||||
return (PVecFloat)Util.RotateVectorByFacing(localRecoil, facing, .7f);
|
||||
}
|
||||
|
||||
public static PVecInt GetTurretPosition(Actor self, IFacing facing, Turret turret)
|
||||
public static PVecFloat GetTurretPosition(Actor self, IFacing facing, Turret turret)
|
||||
{
|
||||
if (facing == null) return turret.ScreenSpacePosition; /* things that don't have a rotating base don't need the turrets repositioned */
|
||||
|
||||
@@ -228,23 +228,23 @@ namespace OpenRA.Mods.RA
|
||||
var bodyFacing = facing.Facing;
|
||||
var quantizedFacing = Util.QuantizeFacing(bodyFacing, numDirs) * (256 / numDirs);
|
||||
|
||||
return (PVecInt) ((PVecFloat)(Util.RotateVectorByFacing(turret.UnitSpacePosition.ToFloat2(), quantizedFacing, .7f)
|
||||
+ GetRecoil(self, turret.Recoil))
|
||||
+ turret.ScreenSpacePosition);
|
||||
return (PVecFloat)Util.RotateVectorByFacing(turret.UnitSpacePosition.ToFloat2(), quantizedFacing, .7f)
|
||||
+ GetRecoil(self, turret.Recoil)
|
||||
+ (PVecFloat)turret.ScreenSpacePosition.ToFloat2();
|
||||
}
|
||||
|
||||
static PVecInt GetUnitspaceBarrelOffset(Actor self, IFacing facing, Turret turret, Barrel barrel)
|
||||
static PVecFloat GetUnitspaceBarrelOffset(Actor self, IFacing facing, Turret turret, Barrel barrel)
|
||||
{
|
||||
var turreted = self.TraitOrDefault<Turreted>();
|
||||
if (turreted == null && facing == null)
|
||||
return PVecInt.Zero;
|
||||
return PVecFloat.Zero;
|
||||
|
||||
var turretFacing = turreted != null ? turreted.turretFacing : facing.Facing;
|
||||
return (PVecInt)(PVecFloat)Util.RotateVectorByFacing(barrel.TurretSpaceOffset.ToFloat2(), turretFacing, .7f);
|
||||
return (PVecFloat)Util.RotateVectorByFacing(barrel.TurretSpaceOffset.ToFloat2(), turretFacing, .7f);
|
||||
}
|
||||
|
||||
// gets the screen-space position of a barrel.
|
||||
public static PVecInt GetBarrelPosition(Actor self, IFacing facing, Turret turret, Barrel barrel)
|
||||
public static PVecFloat GetBarrelPosition(Actor self, IFacing facing, Turret turret, Barrel barrel)
|
||||
{
|
||||
return GetTurretPosition(self, facing, turret) + barrel.ScreenSpaceOffset
|
||||
+ GetUnitspaceBarrelOffset(self, facing, turret, barrel);
|
||||
|
||||
@@ -78,7 +78,7 @@ namespace OpenRA.Mods.RA
|
||||
|
||||
void SpawnCrate(Actor self)
|
||||
{
|
||||
var inWater = self.World.SharedRandom.NextDouble() < Info.WaterChance;
|
||||
var inWater = self.World.SharedRandom.NextFloat() < Info.WaterChance;
|
||||
var pp = ChooseDropCell(self, inWater, 100);
|
||||
if (pp == null) return;
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ namespace OpenRA.Mods.RA
|
||||
void SpawnCrate(Actor self, CrateSpawnerInfo info)
|
||||
{
|
||||
var threshold = 100;
|
||||
var inWater = self.World.SharedRandom.NextDouble() < info.WaterChance;
|
||||
var inWater = self.World.SharedRandom.NextFloat() < info.WaterChance;
|
||||
|
||||
for (var n = 0; n < threshold; n++ )
|
||||
{
|
||||
|
||||
@@ -57,7 +57,7 @@ namespace OpenRA.Mods.RA.Effects
|
||||
|
||||
if (info.Inaccuracy > 0)
|
||||
{
|
||||
var factor = ((Args.dest - Args.src).Length / (float)Game.CellSize) / args.weapon.Range;
|
||||
var factor = ((Args.dest - Args.src).Length / Game.CellSize) / (float)args.weapon.Range;
|
||||
Args.dest += (PVecInt) (info.Inaccuracy * factor * args.firedBy.World.SharedRandom.Gauss2D(2)).ToInt2();
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace OpenRA.Mods.RA
|
||||
|
||||
public void Tick(Actor self)
|
||||
{
|
||||
history.Tick(self.CenterLocation - new PVecInt(0, move.Altitude) - Combat.GetTurretPosition(self, facing, contrailTurret));
|
||||
history.Tick(self.CenterLocation - new PVecInt(0, move.Altitude) - (PVecInt)Combat.GetTurretPosition(self, facing, contrailTurret).ToInt2());
|
||||
}
|
||||
|
||||
public void RenderAfterWorld(WorldRenderer wr, Actor self) { history.Render(self); }
|
||||
|
||||
@@ -81,7 +81,7 @@ namespace OpenRA.Mods.RA
|
||||
var p = end - start;
|
||||
var q = new float2(p.Y, -p.X);
|
||||
q = (start != end) ? (1 / q.Length) * q : new float2(1, 0);
|
||||
var c = -float2.Dot(q, start.ToFloat2());
|
||||
var c = -float2.Dot(q, start.ToInt2());
|
||||
|
||||
/* return all points such that |ax + by + c| < depth */
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ namespace OpenRA.Mods.RA
|
||||
|
||||
wr.DrawRangeCircle(
|
||||
Color.FromArgb(128, Color.Yellow),
|
||||
self.CenterLocation.ToFloat2(), (int)self.Trait<AttackBase>().GetMaximumRange());
|
||||
self.CenterLocation.ToFloat2(), self.Trait<AttackBase>().GetMaximumRange());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace OpenRA.Mods.RA
|
||||
|
||||
wr.DrawRangeCircle(
|
||||
Color.FromArgb(128, Color.Cyan),
|
||||
self.CenterLocation.ToFloat2(), (int)self.Info.Traits.Get<CreatesShroudInfo>().Range);
|
||||
self.CenterLocation.ToFloat2(), self.Info.Traits.Get<CreatesShroudInfo>().Range);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace OpenRA.Mods.RA
|
||||
{
|
||||
var facing = self.Trait<IFacing>();
|
||||
var altitude = new PVecInt(0, move.Altitude);
|
||||
position = (self.CenterLocation - Combat.GetTurretPosition(self, facing, smokeTurret));
|
||||
position = (self.CenterLocation - (PVecInt)Combat.GetTurretPosition(self, facing, smokeTurret).ToInt2());
|
||||
|
||||
if (self.World.RenderedShroud.IsVisible(position.ToCPos()))
|
||||
self.World.AddFrameEndTask(
|
||||
|
||||
@@ -126,7 +126,7 @@ namespace OpenRA.Mods.RA
|
||||
firedBy = self,
|
||||
target = target,
|
||||
|
||||
src = (self.CenterLocation + Combat.GetBarrelPosition(self, facing, Turret, barrel)),
|
||||
src = (self.CenterLocation + (PVecInt)Combat.GetBarrelPosition(self, facing, Turret, barrel).ToInt2()),
|
||||
srcAltitude = move != null ? move.Altitude : 0,
|
||||
dest = target.CenterLocation,
|
||||
destAltitude = destMove != null ? destMove.Altitude : 0,
|
||||
|
||||
Reference in New Issue
Block a user