Merge pull request #2665 from Mailaender/pvecfloat-combat

Fix floating point inconsistencies to reduce desyncs
This commit is contained in:
Chris Forbes
2013-03-02 00:01:53 -08:00
18 changed files with 34 additions and 39 deletions

View File

@@ -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()
{

View File

@@ -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);
}

View File

@@ -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>();
}

View File

@@ -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;
}

View File

@@ -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 );

View File

@@ -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;

View File

@@ -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 */

View File

@@ -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));

View File

@@ -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);

View File

@@ -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;

View File

@@ -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++ )
{

View File

@@ -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();
}

View File

@@ -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); }

View File

@@ -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 */

View File

@@ -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());
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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(

View File

@@ -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,