Cache WeaponInfo look-ups

This commit is contained in:
atlimit8
2015-10-03 22:29:40 -05:00
parent f2f2fd8871
commit 49d7604bd9
12 changed files with 82 additions and 53 deletions

View File

@@ -23,12 +23,12 @@ namespace OpenRA.Mods.Cnc.Effects
readonly Animation anim;
readonly Player firedBy;
readonly string palette;
readonly string weapon;
readonly WeaponInfo weapon;
int weaponDelay;
bool impacted = false;
public IonCannon(Player firedBy, string weapon, World world, CPos location, string effect, string palette, int delay)
public IonCannon(Player firedBy, WeaponInfo weapon, World world, CPos location, string effect, string palette, int delay)
{
this.firedBy = firedBy;
this.weapon = weapon;
@@ -44,7 +44,6 @@ namespace OpenRA.Mods.Cnc.Effects
anim.Tick();
if (!impacted && weaponDelay-- <= 0)
{
var weapon = world.Map.Rules.Weapons[this.weapon.ToLowerInvariant()];
weapon.Impact(target, firedBy.PlayerActor, Enumerable.Empty<int>());
impacted = true;
}

View File

@@ -16,12 +16,15 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Cnc.Traits
{
class PoisonedByTiberiumInfo : UpgradableTraitInfo
class PoisonedByTiberiumInfo : UpgradableTraitInfo, IRulesetLoaded
{
[WeaponReference] public readonly string Weapon = "Tiberium";
public readonly HashSet<string> Resources = new HashSet<string> { "Tiberium", "BlueTiberium" };
public WeaponInfo WeaponInfo { get; private set; }
public override object Create(ActorInitializer init) { return new PoisonedByTiberium(this); }
public void RulesetLoaded(Ruleset rules, ActorInfo ai) { WeaponInfo = rules.Weapons[Weapon.ToLowerInvariant()]; }
}
class PoisonedByTiberium : UpgradableTrait<PoisonedByTiberiumInfo>, ITick, ISync
@@ -45,10 +48,8 @@ namespace OpenRA.Mods.Cnc.Traits
if (r == null || !Info.Resources.Contains(r.Info.Name))
return;
var weapon = self.World.Map.Rules.Weapons[Info.Weapon.ToLowerInvariant()];
weapon.Impact(Target.FromActor(self), self.World.WorldActor, Enumerable.Empty<int>());
poisonTicks = weapon.ReloadDelay;
Info.WeaponInfo.Impact(Target.FromActor(self), self.World.WorldActor, Enumerable.Empty<int>());
poisonTicks = Info.WeaponInfo.ReloadDelay;
}
}
}

View File

@@ -8,6 +8,7 @@
*/
#endregion
using OpenRA.GameRules;
using OpenRA.Mods.Cnc.Effects;
using OpenRA.Mods.Common.Activities;
using OpenRA.Mods.Common.Traits;
@@ -16,7 +17,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Cnc.Traits
{
class IonCannonPowerInfo : SupportPowerInfo
class IonCannonPowerInfo : SupportPowerInfo, IRulesetLoaded
{
[ActorReference]
[Desc("Actor to spawn when the attack starts")]
@@ -32,10 +33,13 @@ namespace OpenRA.Mods.Cnc.Traits
[Desc("Which weapon to fire"), WeaponReference]
public readonly string Weapon = "IonCannon";
public WeaponInfo WeaponInfo { get; private set; }
[Desc("Apply the weapon impact this many ticks into the effect")]
public readonly int WeaponDelay = 7;
public override object Create(ActorInitializer init) { return new IonCannonPower(init.Self, this); }
public void RulesetLoaded(Ruleset rules, ActorInfo ai) { WeaponInfo = rules.Weapons[Weapon.ToLowerInvariant()]; }
}
class IonCannonPower : SupportPower
@@ -55,7 +59,7 @@ namespace OpenRA.Mods.Cnc.Traits
self.World.AddFrameEndTask(w =>
{
Game.Sound.Play(Info.LaunchSound, self.World.Map.CenterOfCell(order.TargetLocation));
w.Add(new IonCannon(self.Owner, info.Weapon, w, order.TargetLocation, info.Effect, info.EffectPalette, info.WeaponDelay));
w.Add(new IonCannon(self.Owner, info.WeaponInfo, w, order.TargetLocation, info.Effect, info.EffectPalette, info.WeaponDelay));
if (info.CameraActor == null)
return;

View File

@@ -35,12 +35,10 @@ namespace OpenRA.Mods.Common.Activities
{
if (self.CenterPosition.Z <= 0)
{
if (info.Explosion != null)
if (info.ExplosionWeapon != null)
{
var weapon = self.World.Map.Rules.Weapons[info.Explosion.ToLowerInvariant()];
// Use .FromPos since this actor is killed. Cannot use Target.FromActor
weapon.Impact(Target.FromPos(self.CenterPosition), self, Enumerable.Empty<int>());
info.ExplosionWeapon.Impact(Target.FromPos(self.CenterPosition), self, Enumerable.Empty<int>());
}
self.Dispose();

View File

@@ -22,7 +22,7 @@ namespace OpenRA.Mods.Common.Effects
{
readonly Player firedBy;
readonly Animation anim;
readonly string weapon;
readonly WeaponInfo weapon;
readonly string flashType;
readonly WPos ascendSource;
@@ -35,7 +35,7 @@ namespace OpenRA.Mods.Common.Effects
WPos pos;
int ticks;
public NukeLaunch(Player firedBy, string weapon, WPos launchPos, WPos targetPos, WDist velocity, int delay, bool skipAscent, string flashType)
public NukeLaunch(Player firedBy, string name, WeaponInfo weapon, WPos launchPos, WPos targetPos, WDist velocity, int delay, bool skipAscent, string flashType)
{
this.firedBy = firedBy;
this.weapon = weapon;
@@ -49,13 +49,12 @@ namespace OpenRA.Mods.Common.Effects
descendSource = targetPos + offset;
descendTarget = targetPos;
anim = new Animation(firedBy.World, weapon);
anim = new Animation(firedBy.World, name);
anim.PlayRepeating("up");
pos = launchPos;
var weaponRules = firedBy.World.Map.Rules.Weapons[weapon.ToLowerInvariant()];
if (weaponRules.Report != null && weaponRules.Report.Any())
Game.Sound.Play(weaponRules.Report.Random(firedBy.World.SharedRandom), pos);
if (weapon.Report != null && weapon.Report.Any())
Game.Sound.Play(weapon.Report.Random(firedBy.World.SharedRandom), pos);
if (skipAscent)
ticks = turn;
@@ -82,7 +81,6 @@ namespace OpenRA.Mods.Common.Effects
void Explode(World world)
{
world.AddFrameEndTask(w => w.Remove(this));
var weapon = world.Map.Rules.Weapons[this.weapon.ToLowerInvariant()];
weapon.Impact(Target.FromPos(pos), firedBy.PlayerActor, Enumerable.Empty<int>());
world.WorldActor.Trait<ScreenShaker>().AddEffect(20, pos, 5);

View File

@@ -16,7 +16,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[Desc("Causes aircraft husks that are spawned in the air to crash to the ground.")]
public class FallsToEarthInfo : ITraitInfo
public class FallsToEarthInfo : ITraitInfo, IRulesetLoaded
{
[WeaponReference]
public readonly string Explosion = "UnitExplode";
@@ -25,7 +25,13 @@ namespace OpenRA.Mods.Common.Traits
public readonly bool Moves = false;
public readonly WDist Velocity = new WDist(43);
public WeaponInfo ExplosionWeapon { get; private set; }
public object Create(ActorInitializer init) { return new FallsToEarth(init.Self, this); }
public void RulesetLoaded(Ruleset rules, ActorInfo ai)
{
ExplosionWeapon = string.IsNullOrEmpty(Explosion) ? null : rules.Weapons[Explosion.ToLowerInvariant()];
}
}
public class FallsToEarth

View File

@@ -12,13 +12,14 @@ using System;
using System.Collections.Generic;
using System.Linq;
using OpenRA.Effects;
using OpenRA.GameRules;
using OpenRA.Graphics;
using OpenRA.Primitives;
using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
class BridgeInfo : ITraitInfo, Requires<HealthInfo>, Requires<BuildingInfo>
class BridgeInfo : ITraitInfo, IRulesetLoaded, Requires<HealthInfo>, Requires<BuildingInfo>
{
public readonly bool Long = false;
@@ -41,8 +42,12 @@ namespace OpenRA.Mods.Common.Traits
[Desc("The name of the weapon to use when demolishing the bridge")]
[WeaponReference] public readonly string DemolishWeapon = "Demolish";
public WeaponInfo DemolishWeaponInfo { get; private set; }
public object Create(ActorInitializer init) { return new Bridge(init.Self, this); }
public void RulesetLoaded(Ruleset rules, ActorInfo ai) { DemolishWeaponInfo = rules.Weapons[DemolishWeapon.ToLowerInvariant()]; }
public IEnumerable<Pair<ushort, int>> Templates
{
get
@@ -333,10 +338,8 @@ namespace OpenRA.Mods.Common.Traits
var initialDamage = health.DamageState;
self.World.AddFrameEndTask(w =>
{
var weapon = saboteur.World.Map.Rules.Weapons[info.DemolishWeapon.ToLowerInvariant()];
// Use .FromPos since this actor is killed. Cannot use Target.FromActor
weapon.Impact(Target.FromPos(self.CenterPosition), saboteur, Enumerable.Empty<int>());
info.DemolishWeaponInfo.Impact(Target.FromPos(self.CenterPosition), saboteur, Enumerable.Empty<int>());
self.World.WorldActor.Trait<ScreenShaker>().AddEffect(15, self.CenterPosition, 6);
self.Kill(saboteur);

View File

@@ -11,13 +11,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using OpenRA.GameRules;
using OpenRA.Mods.Common.Warheads;
using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[Desc("This actor explodes when killed.")]
public class ExplodesInfo : ITraitInfo
public class ExplodesInfo : ITraitInfo, IRulesetLoaded
{
[WeaponReference, FieldLoader.Require, Desc("Weapon to use for explosion if ammo/payload is loaded.")]
public readonly string Weapon = "UnitExplode";
@@ -34,7 +35,15 @@ namespace OpenRA.Mods.Common.Traits
[Desc("DeathType(s) to apply upon explosion.")]
public readonly HashSet<string> DeathType = new HashSet<string>();
public WeaponInfo WeaponInfo { get; private set; }
public WeaponInfo EmptyWeaponInfo { get; private set; }
public object Create(ActorInitializer init) { return new Explodes(this); }
public void RulesetLoaded(Ruleset rules, ActorInfo ai)
{
WeaponInfo = string.IsNullOrEmpty(Weapon) ? null : rules.Weapons[Weapon.ToLowerInvariant()];
EmptyWeaponInfo = string.IsNullOrEmpty(EmptyWeapon) ? null : rules.Weapons[EmptyWeapon.ToLowerInvariant()];
}
}
public class Explodes : INotifyKilled
@@ -55,15 +64,10 @@ namespace OpenRA.Mods.Common.Traits
if (info.DeathType.Count > 0 && warhead != null && !warhead.DamageTypes.Overlaps(info.DeathType))
return;
var weaponName = ChooseWeaponForExplosion(self);
if (string.IsNullOrEmpty(weaponName))
var weapon = ChooseWeaponForExplosion(self);
if (weapon == null)
return;
if (!e.Attacker.World.Map.Rules.Weapons.ContainsKey(weaponName.ToLowerInvariant()))
throw new InvalidOperationException("Actor " + self.Info.Name
+ ": Could not find weapon '" + weaponName.ToLowerInvariant() + "', check for typos.");
var weapon = e.Attacker.World.Map.Rules.Weapons[weaponName.ToLowerInvariant()];
if (weapon.Report != null && weapon.Report.Any())
Game.Sound.Play(weapon.Report.Random(e.Attacker.World.SharedRandom), self.CenterPosition);
@@ -71,11 +75,11 @@ namespace OpenRA.Mods.Common.Traits
weapon.Impact(Target.FromPos(self.CenterPosition), e.Attacker, Enumerable.Empty<int>());
}
string ChooseWeaponForExplosion(Actor self)
WeaponInfo ChooseWeaponForExplosion(Actor self)
{
var shouldExplode = self.TraitsImplementing<IExplodeModifier>().All(a => a.ShouldExplode(self));
var useFullExplosion = self.World.SharedRandom.Next(100) <= info.LoadedChance;
return (shouldExplode && useFullExplosion) ? info.Weapon : info.EmptyWeapon;
return (shouldExplode && useFullExplosion) ? info.WeaponInfo : info.EmptyWeaponInfo;
}
}
}

View File

@@ -10,6 +10,7 @@
using System;
using OpenRA.Effects;
using OpenRA.GameRules;
using OpenRA.Mods.Common.Activities;
using OpenRA.Mods.Common.Effects;
using OpenRA.Primitives;
@@ -17,7 +18,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
class NukePowerInfo : SupportPowerInfo, Requires<BodyOrientationInfo>
class NukePowerInfo : SupportPowerInfo, IRulesetLoaded, Requires<BodyOrientationInfo>
{
[WeaponReference]
public readonly string MissileWeapon = "";
@@ -51,7 +52,10 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Sequence the launching actor should play when activating this power.")]
public readonly string ActivationSequence = "active";
public WeaponInfo WeaponInfo { get; private set; }
public override object Create(ActorInitializer init) { return new NukePower(init.Self, this); }
public void RulesetLoaded(Ruleset rules, ActorInfo ai) { WeaponInfo = rules.Weapons[MissileWeapon.ToLowerInvariant()]; }
}
class NukePower : SupportPower
@@ -82,7 +86,7 @@ namespace OpenRA.Mods.Common.Traits
}
var targetPosition = self.World.Map.CenterOfCell(order.TargetLocation);
var missile = new NukeLaunch(self.Owner, info.MissileWeapon,
var missile = new NukeLaunch(self.Owner, info.MissileWeapon, info.WeaponInfo,
self.CenterPosition + body.LocalToWorld(info.SpawnOffset),
targetPosition,
info.FlightVelocity, info.FlightDelay, info.SkipAscent,

View File

@@ -15,13 +15,20 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[Desc("Throws particles when the actor is destroyed that do damage on impact.")]
public class ThrowsShrapnelInfo : ITraitInfo
public class ThrowsShrapnelInfo : ITraitInfo, IRulesetLoaded
{
[WeaponReference, FieldLoader.Require]
public string[] Weapons = { };
public int[] Pieces = { 3, 10 };
public WDist[] Range = { WDist.FromCells(2), WDist.FromCells(5) };
public WeaponInfo[] WeaponInfos { get; private set; }
public object Create(ActorInitializer actor) { return new ThrowsShrapnel(this); }
public void RulesetLoaded(Ruleset rules, ActorInfo ai)
{
WeaponInfos = Weapons.Select(w => rules.Weapons[w.ToLowerInvariant()]).ToArray();
}
}
class ThrowsShrapnel : INotifyKilled
@@ -35,9 +42,8 @@ namespace OpenRA.Mods.Common.Traits
public void Killed(Actor self, AttackInfo attack)
{
foreach (var name in info.Weapons)
foreach (var wep in info.WeaponInfos)
{
var wep = self.World.Map.Rules.Weapons[name.ToLowerInvariant()];
var pieces = self.World.SharedRandom.Next(info.Pieces[0], info.Pieces[1]);
var range = self.World.SharedRandom.Next(info.Range[0].Length, info.Range[1].Length);

View File

@@ -16,21 +16,23 @@ using OpenRA.Traits;
namespace OpenRA.Mods.D2k.Traits
{
[Desc("Reduces health points over time when the actor is placed on unsafe terrain.")]
class DamagedWithoutFoundationInfo : ITraitInfo, Requires<HealthInfo>
class DamagedWithoutFoundationInfo : ITraitInfo, IRulesetLoaded, Requires<HealthInfo>
{
[WeaponReference]
public readonly string Weapon = "weathering";
public readonly HashSet<string> SafeTerrain = new HashSet<string> { "Concrete" };
public readonly int DamageThreshold = 50;
public WeaponInfo WeaponInfo { get; private set; }
public object Create(ActorInitializer init) { return new DamagedWithoutFoundation(init.Self, this); }
public void RulesetLoaded(Ruleset rules, ActorInfo ai) { WeaponInfo = rules.Weapons[Weapon.ToLowerInvariant()]; }
}
class DamagedWithoutFoundation : ITick, ISync, INotifyAddedToWorld
{
readonly DamagedWithoutFoundationInfo info;
readonly Health health;
readonly WeaponInfo weapon;
[Sync] int damageThreshold = 100;
[Sync] int damageTicks;
@@ -39,7 +41,6 @@ namespace OpenRA.Mods.D2k.Traits
{
this.info = info;
health = self.Trait<Health>();
weapon = self.World.Map.Rules.Weapons[info.Weapon.ToLowerInvariant()];
}
public void AddedToWorld(Actor self)
@@ -69,8 +70,8 @@ namespace OpenRA.Mods.D2k.Traits
if (health.HP <= damageThreshold || --damageTicks > 0)
return;
weapon.Impact(Target.FromActor(self), self.World.WorldActor, Enumerable.Empty<int>());
damageTicks = weapon.ReloadDelay;
info.WeaponInfo.Impact(Target.FromActor(self), self.World.WorldActor, Enumerable.Empty<int>());
damageTicks = info.WeaponInfo.ReloadDelay;
}
}
}

View File

@@ -12,6 +12,7 @@ using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using OpenRA.Activities;
using OpenRA.GameRules;
using OpenRA.Mods.Common;
using OpenRA.Mods.Common.Activities;
using OpenRA.Mods.Common.Orders;
@@ -22,7 +23,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.RA.Traits
{
class MadTankInfo : ITraitInfo, Requires<ExplodesInfo>, Requires<WithFacingSpriteBodyInfo>
class MadTankInfo : ITraitInfo, IRulesetLoaded, Requires<ExplodesInfo>, Requires<WithFacingSpriteBodyInfo>
{
[SequenceReference] public readonly string ThumpSequence = "piston";
public readonly int ThumpInterval = 8;
@@ -47,7 +48,15 @@ namespace OpenRA.Mods.RA.Traits
[VoiceReference] public readonly string Voice = "Action";
public WeaponInfo ThumpDamageWeaponInfo { get; private set; }
public WeaponInfo DetonationWeaponInfo { get; private set; }
public object Create(ActorInitializer init) { return new MadTank(init.Self, this); }
public void RulesetLoaded(Ruleset rules, ActorInfo ai)
{
ThumpDamageWeaponInfo = rules.Weapons[ThumpDamageWeapon.ToLowerInvariant()];
DetonationWeaponInfo = rules.Weapons[DetonationWeapon.ToLowerInvariant()];
}
}
class MadTank : IIssueOrder, IResolveOrder, IOrderVoice, ITick, IPreventsTeleport
@@ -76,10 +85,8 @@ namespace OpenRA.Mods.RA.Traits
{
if (info.ThumpDamageWeapon != null)
{
var weapon = self.World.Map.Rules.Weapons[info.ThumpDamageWeapon.ToLowerInvariant()];
// Use .FromPos since this weapon needs to affect more than just the MadTank actor
weapon.Impact(Target.FromPos(self.CenterPosition), self, Enumerable.Empty<int>());
info.ThumpDamageWeaponInfo.Impact(Target.FromPos(self.CenterPosition), self, Enumerable.Empty<int>());
}
screenShaker.AddEffect(info.ThumpShakeTime, self.CenterPosition, info.ThumpShakeIntensity, info.ThumpShakeMultiplier);
@@ -118,10 +125,8 @@ namespace OpenRA.Mods.RA.Traits
{
if (info.DetonationWeapon != null)
{
var weapon = self.World.Map.Rules.Weapons[info.DetonationWeapon.ToLowerInvariant()];
// Use .FromPos since this actor is killed. Cannot use Target.FromActor
weapon.Impact(Target.FromPos(self.CenterPosition), self, Enumerable.Empty<int>());
info.DetonationWeaponInfo.Impact(Target.FromPos(self.CenterPosition), self, Enumerable.Empty<int>());
}
self.Kill(self);