Convert weapons to world coords.

This commit is contained in:
Paul Chote
2013-12-24 23:10:05 +13:00
parent aca897fa76
commit ecdae4cbbe
13 changed files with 44 additions and 64 deletions

View File

@@ -18,8 +18,8 @@ namespace OpenRA.GameRules
{ {
public class WarheadInfo public class WarheadInfo
{ {
[Desc("Distance (in pixels) from the explosion center at which damage is 1/2.")] [Desc("Distance from the explosion center at which damage is 1/2.")]
public readonly int Spread = 1; public readonly WRange Spread = new WRange(43);
[FieldLoader.LoadUsing("LoadVersus")] [FieldLoader.LoadUsing("LoadVersus")]
[Desc("Damage vs each armortype. 0% = can't target.")] [Desc("Damage vs each armortype. 0% = can't target.")]
public readonly Dictionary<string, float> Versus; public readonly Dictionary<string, float> Versus;
@@ -99,7 +99,7 @@ namespace OpenRA.GameRules
public class WeaponInfo public class WeaponInfo
{ {
public readonly float Range = 0; public readonly WRange Range = WRange.Zero;
public readonly string[] Report = null; public readonly string[] Report = null;
[Desc("Rate of Fire")] [Desc("Rate of Fire")]
public readonly int ROF = 1; public readonly int ROF = 1;
@@ -109,7 +109,7 @@ namespace OpenRA.GameRules
public readonly string[] ValidTargets = { "Ground", "Water" }; public readonly string[] ValidTargets = { "Ground", "Water" };
public readonly string[] InvalidTargets = { }; public readonly string[] InvalidTargets = { };
public readonly int BurstDelay = 5; public readonly int BurstDelay = 5;
public readonly float MinRange = 0; public readonly WRange MinRange = WRange.Zero;
[FieldLoader.LoadUsing("LoadProjectile")] public IProjectileInfo Projectile; [FieldLoader.LoadUsing("LoadProjectile")] public IProjectileInfo Projectile;
[FieldLoader.LoadUsing("LoadWarheads")] public List<WarheadInfo> Warheads; [FieldLoader.LoadUsing("LoadWarheads")] public List<WarheadInfo> Warheads;

View File

@@ -107,13 +107,10 @@ namespace OpenRA.Mods.RA
if (limitedAmmo != null && !limitedAmmo.HasAmmo()) if (limitedAmmo != null && !limitedAmmo.HasAmmo())
return; return;
// TODO: Define weapon ranges as WRange if (!target.IsInRange(self.CenterPosition, Weapon.Range))
var range = new WRange((int)(1024*Weapon.Range));
var minRange = new WRange((int)(1024*Weapon.MinRange));
if (!target.IsInRange(self.CenterPosition, range))
return; return;
if (minRange != WRange.Zero && target.IsInRange(self.CenterPosition, minRange)) if (Weapon.MinRange != WRange.Zero && target.IsInRange(self.CenterPosition, Weapon.MinRange))
return; return;
if (!Weapon.IsValidAgainst(target, self.World)) if (!Weapon.IsValidAgainst(target, self.World))

View File

@@ -144,7 +144,7 @@ namespace OpenRA.Mods.RA
public abstract Activity GetAttackActivity(Actor self, Target newTarget, bool allowMove); public abstract Activity GetAttackActivity(Actor self, Target newTarget, bool allowMove);
public bool HasAnyValidWeapons(Target t) { return Armaments.Any(a => a.Weapon.IsValidAgainst(t, self.World)); } public bool HasAnyValidWeapons(Target t) { return Armaments.Any(a => a.Weapon.IsValidAgainst(t, self.World)); }
public WRange GetMaximumRange() { return new WRange((int)(1024 * Armaments.Max(a => a.Weapon.Range))); } public WRange GetMaximumRange() { return Armaments.Max(a => a.Weapon.Range); }
public Armament ChooseArmamentForTarget(Target t) { return Armaments.FirstOrDefault(a => a.Weapon.IsValidAgainst(t, self.World)); } public Armament ChooseArmamentForTarget(Target t) { return Armaments.FirstOrDefault(a => a.Weapon.IsValidAgainst(t, self.World)); }

View File

@@ -52,9 +52,7 @@ namespace OpenRA.Mods.RA
if (a == null) if (a == null)
return null; return null;
// TODO: Define weapon ranges as WRange return new Activities.Attack(newTarget, a.Weapon.Range, allowMove);
var range = new WRange(Math.Max(0,(int)(1024*a.Weapon.Range)));
return new Activities.Attack(newTarget, range, allowMove);
} }
} }
} }

View File

@@ -42,9 +42,7 @@ namespace OpenRA.Mods.RA
if (a == null) if (a == null)
return; return;
// TODO: Define weapon ranges as WRange if (!target.IsInRange(self.CenterPosition, a.Weapon.Range))
var range = new WRange((int)(1024*a.Weapon.Range));
if (!target.IsInRange(self.CenterPosition, range))
return; return;
self.CancelActivity(); self.CancelActivity();

View File

@@ -31,9 +31,7 @@ namespace OpenRA.Mods.RA
if (arm == null) if (arm == null)
return; return;
// TODO: Define weapon ranges as WRange if (!target.IsInRange(self.CenterPosition, arm.Weapon.Range))
var range = new WRange((int)(1024*arm.Weapon.Range));
if (!target.IsInRange(self.CenterPosition, range))
return; return;
var facing = self.TraitOrDefault<IFacing>(); var facing = self.TraitOrDefault<IFacing>();

View File

@@ -33,9 +33,7 @@ namespace OpenRA.Mods.RA
if (a == null) if (a == null)
return null; return null;
// TODO: Define weapon ranges as WRange return new Activities.Heal(newTarget, a.Weapon.Range, allowMove);
var range = new WRange(Math.Max(0, (int)(1024 * a.Weapon.Range)));
return new Activities.Heal(newTarget, range, allowMove);
} }
} }
} }

View File

@@ -96,7 +96,7 @@ namespace OpenRA.Mods.RA
if (weapon != null) if (weapon != null)
{ {
var range = WRange.FromCells(Math.Max(0, (int)weapon.Weapon.Range - RangeTolerance)); var range = WRange.FromCells(Math.Max(0, weapon.Weapon.Range.Range / 1024 - RangeTolerance));
attack.Target = target; attack.Target = target;
if (allowMove && self.HasTrait<Mobile>() && !self.Info.Traits.Get<MobileInfo>().OnRails) if (allowMove && self.HasTrait<Mobile>() && !self.Info.Traits.Get<MobileInfo>().OnRails)

View File

@@ -49,8 +49,7 @@ namespace OpenRA.Mods.RA
// Bombs drop anywhere in range // Bombs drop anywhere in range
foreach (var a in Armaments.Where(a => a.Info.Name == info.Bombs)) foreach (var a in Armaments.Where(a => a.Info.Name == info.Bombs))
{ {
var range = new WRange((int)(1024 * a.Weapon.Range)); if (!target.IsInRange(self.CenterPosition, a.Weapon.Range))
if (!target.IsInRange(self.CenterPosition, range))
continue; continue;
a.CheckFire(self, this, facing, bombTarget); a.CheckFire(self, this, facing, bombTarget);
@@ -63,11 +62,10 @@ namespace OpenRA.Mods.RA
foreach (var a in Armaments.Where(a => a.Info.Name == info.Guns)) foreach (var a in Armaments.Where(a => a.Info.Name == info.Guns))
{ {
var range = new WRange((int)(1024 * a.Weapon.Range)); if (!target.IsInRange(self.CenterPosition, a.Weapon.Range))
if (!target.IsInRange(self.CenterPosition, range))
continue; continue;
var t = Target.FromPos(cp - new WVec(0, range.Range / 2, cp.Z).Rotate(WRot.FromFacing(facing.Facing))); var t = Target.FromPos(cp - new WVec(0, a.Weapon.Range.Range / 2, cp.Z).Rotate(WRot.FromFacing(facing.Facing)));
a.CheckFire(self, this, facing, t); a.CheckFire(self, this, facing, t);
} }
} }

View File

@@ -101,9 +101,8 @@ namespace OpenRA.Mods.RA
{ {
case DamageModel.Normal: case DamageModel.Normal:
{ {
var maxSpread = warhead.Spread * (float)Math.Log(Math.Abs(warhead.Damage), 2); var maxSpread = new WRange((int)(warhead.Spread.Range * (float)Math.Log(Math.Abs(warhead.Damage), 2)));
var range = new WRange((int)maxSpread * 1024 / Game.CellSize); var hitActors = world.FindActorsInCircle(pos, maxSpread);
var hitActors = world.FindActorsInCircle(pos, range);
foreach (var victim in hitActors) foreach (var victim in hitActors)
{ {
@@ -192,8 +191,8 @@ namespace OpenRA.Mods.RA
var rawDamage = (float)warhead.Damage; var rawDamage = (float)warhead.Damage;
if (withFalloff) if (withFalloff)
{ {
var distance = Math.Max(0, (target.CenterPosition - pos).Length - healthInfo.Radius.Range) * Game.CellSize / 1024; var distance = Math.Max(0, (target.CenterPosition - pos).Length - healthInfo.Radius.Range);
var falloff = (float)GetDamageFalloff(distance / warhead.Spread); var falloff = (float)GetDamageFalloff(distance * 1f / warhead.Spread.Range);
rawDamage = (float)(falloff * rawDamage); rawDamage = (float)(falloff * rawDamage);
} }
return (float)(rawDamage * modifier * (float)warhead.EffectivenessAgainst(target.Info)); return (float)(rawDamage * modifier * (float)warhead.EffectivenessAgainst(target.Info));

View File

@@ -22,15 +22,16 @@ namespace OpenRA.Mods.RA.Effects
{ {
public class BulletInfo : IProjectileInfo public class BulletInfo : IProjectileInfo
{ {
public readonly int Speed = 1; [Desc("Projectile speed in WRange / tick")]
public readonly WRange Speed = new WRange(17);
public readonly string Trail = null; public readonly string Trail = null;
[Desc("Pixels at maximum range")] [Desc("Maximum offset at the maximum range")]
public readonly float Inaccuracy = 0; public readonly WRange Inaccuracy = WRange.Zero;
public readonly string Image = null; public readonly string Image = null;
[Desc("Check for whether an actor with Wall: trait blocks fire")] [Desc("Check for whether an actor with Wall: trait blocks fire")]
public readonly bool High = false; public readonly bool High = false;
public readonly bool Shadow = false; public readonly bool Shadow = false;
public readonly float Angle = 0; public readonly WAngle Angle = WAngle.Zero;
public readonly int TrailInterval = 2; public readonly int TrailInterval = 2;
public readonly int TrailDelay = 1; public readonly int TrailDelay = 1;
public readonly int ContrailLength = 0; public readonly int ContrailLength = 0;
@@ -49,7 +50,6 @@ namespace OpenRA.Mods.RA.Effects
ContrailRenderable trail; ContrailRenderable trail;
Animation anim; Animation anim;
[Sync] WAngle angle;
[Sync] WPos pos, target; [Sync] WPos pos, target;
[Sync] int length; [Sync] int length;
[Sync] int facing; [Sync] int facing;
@@ -63,22 +63,15 @@ namespace OpenRA.Mods.RA.Effects
this.args = args; this.args = args;
this.pos = args.Source; this.pos = args.Source;
// Convert ProjectileArg definitions to world coordinates
// TODO: Change the yaml definitions so we don't need this
var range = new WRange((int)(1024 * args.Weapon.Range)); // Range in world units
var inaccuracy = new WRange((int)(info.Inaccuracy * 1024 / Game.CellSize)); // Offset in world units at max range
var speed = (int)(info.Speed * 4 * 1024 / (10 * Game.CellSize)); // Speed in world units per tick
angle = WAngle.ArcTan((int)(info.Angle * 4 * 1024), 1024); // Angle in world angle
target = args.PassiveTarget; target = args.PassiveTarget;
if (info.Inaccuracy > 0) if (info.Inaccuracy.Range > 0)
{ {
var maxOffset = inaccuracy.Range * (target - pos).Length / range.Range; var maxOffset = info.Inaccuracy.Range * (target - pos).Length / args.Weapon.Range.Range;
target += WVec.FromPDF(args.SourceActor.World.SharedRandom, 2) * maxOffset / 1024; target += WVec.FromPDF(args.SourceActor.World.SharedRandom, 2) * maxOffset / 1024;
} }
facing = Traits.Util.GetFacing(target - pos, 0); facing = Traits.Util.GetFacing(target - pos, 0);
length = Math.Max((target - pos).Length / speed, 1); length = Math.Max((target - pos).Length / info.Speed.Range, 1);
if (info.Image != null) if (info.Image != null)
{ {
@@ -98,7 +91,7 @@ namespace OpenRA.Mods.RA.Effects
int GetEffectiveFacing() int GetEffectiveFacing()
{ {
var at = (float)ticks / (length - 1); var at = (float)ticks / (length - 1);
var attitude = angle.Tan() * (1 - 2 * at) / (4 * 1024); var attitude = info.Angle.Tan() * (1 - 2 * at) / (4 * 1024);
var u = (facing % 128) / 128f; var u = (facing % 128) / 128f;
var scale = 512 * u * (1 - u); var scale = 512 * u * (1 - u);
@@ -113,11 +106,11 @@ namespace OpenRA.Mods.RA.Effects
if (anim != null) if (anim != null)
anim.Tick(); anim.Tick();
pos = WPos.LerpQuadratic(args.Source, target, angle, ticks, length); pos = WPos.LerpQuadratic(args.Source, target, info.Angle, ticks, length);
if (info.Trail != null && --smokeTicks < 0) if (info.Trail != null && --smokeTicks < 0)
{ {
var delayedPos = WPos.LerpQuadratic(args.Source, target, angle, ticks - info.TrailDelay, length); var delayedPos = WPos.LerpQuadratic(args.Source, target, info.Angle, ticks - info.TrailDelay, length);
world.AddFrameEndTask(w => w.Add(new Smoke(w, delayedPos, info.Trail))); world.AddFrameEndTask(w => w.Add(new Smoke(w, delayedPos, info.Trail)));
smokeTicks = info.TrailInterval; smokeTicks = info.TrailInterval;
} }

View File

@@ -21,13 +21,15 @@ namespace OpenRA.Mods.RA.Effects
{ {
class MissileInfo : IProjectileInfo class MissileInfo : IProjectileInfo
{ {
public readonly int Speed = 1; [Desc("Projectile speed in WRange / tick")]
public readonly WRange Speed = new WRange(8);
public readonly WAngle MaximumPitch = WAngle.FromDegrees(30); public readonly WAngle MaximumPitch = WAngle.FromDegrees(30);
public readonly int Arm = 0; public readonly int Arm = 0;
[Desc("Check for whether an actor with Wall: trait blocks fire")] [Desc("Check for whether an actor with Wall: trait blocks fire")]
public readonly bool High = false; public readonly bool High = false;
public readonly string Trail = null; public readonly string Trail = null;
public readonly float Inaccuracy = 0; [Desc("Maximum offset at the maximum range")]
public readonly WRange Inaccuracy = WRange.Zero;
public readonly string Image = null; public readonly string Image = null;
[Desc("Rate of Turning")] [Desc("Rate of Turning")]
public readonly int ROT = 5; public readonly int ROT = 5;
@@ -46,12 +48,15 @@ namespace OpenRA.Mods.RA.Effects
class Missile : IEffect, ISync class Missile : IEffect, ISync
{ {
// HACK: the missile movement code isn't smart enough to explode
// when the projectile passes the actor. This defines an arbitrary
// proximity radius that they will explode within, which makes
// missiles difficult to consistently balance.
static readonly WRange MissileCloseEnough = new WRange(298); static readonly WRange MissileCloseEnough = new WRange(298);
readonly MissileInfo info; readonly MissileInfo info;
readonly ProjectileArgs args; readonly ProjectileArgs args;
readonly Animation anim; readonly Animation anim;
readonly int speed;
int ticksToNextSmoke; int ticksToNextSmoke;
ContrailRenderable trail; ContrailRenderable trail;
@@ -76,13 +81,8 @@ namespace OpenRA.Mods.RA.Effects
targetPosition = args.PassiveTarget; targetPosition = args.PassiveTarget;
// Convert ProjectileArg definitions to world coordinates if (info.Inaccuracy.Range > 0)
// TODO: Change the yaml definitions so we don't need this offset = WVec.FromPDF(args.SourceActor.World.SharedRandom, 2) * info.Inaccuracy.Range / 1024;
var inaccuracy = (int)(info.Inaccuracy * 1024 / Game.CellSize);
speed = info.Speed * 1024 / (5 * Game.CellSize);
if (info.Inaccuracy > 0)
offset = WVec.FromPDF(args.SourceActor.World.SharedRandom, 2) * inaccuracy / 1024;
if (info.Image != null) if (info.Image != null)
{ {
@@ -131,7 +131,7 @@ namespace OpenRA.Mods.RA.Effects
desiredFacing = facing; desiredFacing = facing;
facing = Traits.Util.TickFacing(facing, desiredFacing, info.ROT); facing = Traits.Util.TickFacing(facing, desiredFacing, info.ROT);
var move = new WVec(0, -1024, 0).Rotate(WRot.FromFacing(facing)) * speed / 1024; var move = new WVec(0, -1024, 0).Rotate(WRot.FromFacing(facing)) * info.Speed.Range / 1024;
if (targetPosition.Z > 0 && info.TurboBoost) if (targetPosition.Z > 0 && info.TurboBoost)
move = (move * 3) / 2; move = (move * 3) / 2;

View File

@@ -27,11 +27,12 @@ namespace OpenRA.Mods.RA
public void Render(WorldRenderer wr, World w, ActorInfo ai, WPos centerPosition) public void Render(WorldRenderer wr, World w, ActorInfo ai, WPos centerPosition)
{ {
var range = ai.Traits.WithInterface<ArmamentInfo>() var range = ai.Traits.WithInterface<ArmamentInfo>()
.Select(a => Rules.Weapons[a.Weapon.ToLowerInvariant()].Range).Max(); .Select(a => Rules.Weapons[a.Weapon.ToLowerInvariant()].Range)
.Max();
wr.DrawRangeCircleWithContrast( wr.DrawRangeCircleWithContrast(
centerPosition, centerPosition,
new WRange((int)(1024 * range)), range,
Color.FromArgb(128, Color.Yellow), Color.FromArgb(128, Color.Yellow),
Color.FromArgb(96, Color.Black) Color.FromArgb(96, Color.Black)
); );