Merge pull request #6030 from UberWaffe/CustomWarheads

Custom Warheads refactor
This commit is contained in:
Taryn Hill
2014-08-03 10:35:36 -05:00
59 changed files with 2275 additions and 1233 deletions

View File

@@ -509,10 +509,16 @@ namespace OpenRA
internal Func<MiniYaml, object> GetLoader(Type type)
{
const BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static;
const BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.FlattenHierarchy;
if (!string.IsNullOrEmpty(Loader))
return (Func<MiniYaml, object>)Delegate.CreateDelegate(typeof(Func<MiniYaml, object>), type.GetMethod(Loader, flags));
{
var method = type.GetMethod(Loader, flags);
if (method == null)
throw new InvalidOperationException("{0} does not specify a loader function '{1}'".F(type.Name, Loader));
return (Func<MiniYaml, object>)Delegate.CreateDelegate(typeof(Func<MiniYaml, object>), method);
}
return null;
}

View File

@@ -0,0 +1,102 @@
#region Copyright & License Information
/*
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System.Collections.Generic;
using System.Linq;
using OpenRA.Effects;
using OpenRA.Traits;
namespace OpenRA.GameRules
{
[Desc("Base warhead class. This can be used to derive other warheads from.")]
public abstract class Warhead
{
[Desc("What types of targets are affected.")]
public readonly string[] ValidTargets = { "Air", "Ground", "Water" };
[Desc("What types of targets are unaffected.", "Overrules ValidTargets.")]
public readonly string[] InvalidTargets = { };
[Desc("Delay in ticks before applying the warhead effect.","0 = instant (old model).")]
public readonly int Delay = 0;
public abstract void DoImpact(Target target, Actor firedBy, float firepowerModifier);
public abstract float EffectivenessAgainst(ActorInfo ai);
public bool IsValidAgainst(Target target, World world, Actor firedBy)
{
if (target.Type == TargetType.Actor)
return IsValidAgainst(target.Actor, firedBy);
if (target.Type == TargetType.FrozenActor)
return IsValidAgainst(target.FrozenActor, firedBy);
if (target.Type == TargetType.Terrain)
{
var cell = world.Map.CellContaining(target.CenterPosition);
if (!world.Map.Contains(cell))
return false;
var cellInfo = world.Map.GetTerrainInfo(cell);
if (!ValidTargets.Intersect(cellInfo.TargetTypes).Any()
|| InvalidTargets.Intersect(cellInfo.TargetTypes).Any())
return false;
return true;
}
return false;
}
public bool IsValidAgainst(Actor victim, Actor firedBy)
{
// A target type is valid if it is in the valid targets list, and not in the invalid targets list.
return InTargetList(victim, firedBy, ValidTargets) &&
!InTargetList(victim, firedBy, InvalidTargets);
}
public static bool InTargetList(Actor victim, Actor firedBy, string[] targetList)
{
if (!targetList.Any())
return false;
var targetable = victim.TraitOrDefault<ITargetable>();
if (targetable == null)
return false;
if (!targetList.Intersect(targetable.TargetTypes).Any())
return false;
return true;
}
public bool IsValidAgainst(FrozenActor victim, Actor firedBy)
{
// A target type is valid if it is in the valid targets list, and not in the invalid targets list.
return InTargetList(victim, firedBy, ValidTargets) &&
!InTargetList(victim, firedBy, InvalidTargets);
}
public static bool InTargetList(FrozenActor victim, Actor firedBy, string[] targetList)
{
// Frozen Actors need to be handled slightly differently. Since FrozenActor.Actor can be null if the Actor is dead.
if (!targetList.Any())
return false;
var targetable = victim.Info.Traits.GetOrDefault<ITargetableInfo>();
if (targetable == null)
return false;
if (!targetList.Intersect(targetable.GetTargetTypes()).Any())
return false;
return true;
}
}
}

View File

@@ -0,0 +1,84 @@
#region Copyright & License Information
/*
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using OpenRA.Effects;
using OpenRA.Traits;
namespace OpenRA.GameRules
{
public class AbsoluteSpreadDamageWarhead : DamageWarhead
{
[Desc("Maximum spread of the associated SpreadFactor.")]
public readonly WRange[] Spread = { new WRange(43) };
[Desc("What factor to multiply the Damage by for this spread range.", "Each factor specified must have an associated Spread defined.")]
public readonly float[] SpreadFactor = { 1f };
public override void DoImpact(Target target, Actor firedBy, float firepowerModifier)
{
// Used by traits that damage a single actor, rather than a position
if (target.Type == TargetType.Actor)
DoImpact(target.Actor, firedBy, firepowerModifier);
else
DoImpact(target.CenterPosition, firedBy, firepowerModifier);
}
public void DoImpact(WPos pos, Actor firedBy, float firepowerModifier)
{
var world = firedBy.World;
for (var i = 0; i < Spread.Length; i++)
{
var currentSpread = Spread[i];
var currentFactor = SpreadFactor[i];
var previousSpread = WRange.Zero;
if (i > 0)
previousSpread = Spread[i - 1];
if (currentFactor <= 0f)
continue;
var hitActors = world.FindActorsInCircle(pos, currentSpread);
if (previousSpread.Range > 0)
hitActors.Except(world.FindActorsInCircle(pos, previousSpread));
foreach (var victim in hitActors)
if (IsValidAgainst(victim, firedBy))
{
var damage = GetDamageToInflict(victim, firedBy, firepowerModifier * currentFactor);
victim.InflictDamage(firedBy, damage, this);
}
}
}
public void DoImpact(Actor victim, Actor firedBy, float firepowerModifier)
{
if (IsValidAgainst(victim, firedBy))
{
var currentFactor = SpreadFactor[0];
var damage = (int)GetDamageToInflict(victim, firedBy, firepowerModifier * currentFactor);
victim.InflictDamage(firedBy, damage, this);
}
}
public int GetDamageToInflict(Actor target, Actor firedBy, float modifier)
{
var healthInfo = target.Info.Traits.GetOrDefault<HealthInfo>();
if (healthInfo == null)
return 0;
var rawDamage = (float)Damage;
return (int)(rawDamage * modifier * EffectivenessAgainst(target.Info));
}
}
}

View File

@@ -0,0 +1,59 @@
#region Copyright & License Information
/*
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using OpenRA.Effects;
using OpenRA.Traits;
namespace OpenRA.GameRules
{
public abstract class DamageWarhead : Warhead
{
[Desc("How much (raw) damage to deal")]
public readonly int Damage = 0;
[Desc("Infantry death animation to use")]
public readonly string InfDeath = "1";
[Desc("Whether we should prevent prone response for infantry.")]
public readonly bool PreventProne = false;
[Desc("By what percentage should damage be modified against prone infantry.")]
public readonly int ProneModifier = 50;
[FieldLoader.LoadUsing("LoadVersus")]
[Desc("Damage vs each armortype. 0% = can't target.")]
public readonly Dictionary<string, float> Versus;
public static object LoadVersus(MiniYaml yaml)
{
var nd = yaml.ToDictionary();
return nd.ContainsKey("Versus")
? nd["Versus"].ToDictionary(my => FieldLoader.GetValue<float>("(value)", my.Value))
: new Dictionary<string, float>();
}
public override float EffectivenessAgainst(ActorInfo ai)
{
var health = ai.Traits.GetOrDefault<HealthInfo>();
if (health == null)
return 0f;
var armor = ai.Traits.GetOrDefault<ArmorInfo>();
if (armor == null || armor.Type == null)
return 1f;
float versus;
return Versus.TryGetValue(armor.Type, out versus) ? versus : 1f;
}
}
}

View File

@@ -0,0 +1,71 @@
#region Copyright & License Information
/*
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using OpenRA.Effects;
using OpenRA.Traits;
namespace OpenRA.GameRules
{
public class HealthPercentageDamageWarhead : DamageWarhead
{
[Desc("Size of the area. Damage will be applied to this area.", "If two spreads are defined, the area of effect is a ring, where the second value is the inner radius.")]
public readonly WRange[] Spread = { new WRange(43), WRange.Zero };
public override void DoImpact(Target target, Actor firedBy, float firepowerModifier)
{
// Used by traits that damage a single actor, rather than a position
if (target.Type == TargetType.Actor)
DoImpact(target.Actor, firedBy, firepowerModifier);
else
DoImpact(target.CenterPosition, firedBy, firepowerModifier);
}
public void DoImpact(WPos pos, Actor firedBy, float firepowerModifier)
{
var world = firedBy.World;
var range = Spread[0];
var hitActors = world.FindActorsInCircle(pos, range);
if (Spread.Length > 1 && Spread[1].Range > 0)
hitActors.Except(world.FindActorsInCircle(pos, Spread[1]));
foreach (var victim in hitActors)
DoImpact(victim, firedBy, firepowerModifier);
}
public void DoImpact(Actor victim, Actor firedBy, float firepowerModifier)
{
if (IsValidAgainst(victim, firedBy))
{
var damage = GetDamageToInflict(victim, firedBy, firepowerModifier);
if (damage != 0) // will be 0 if the target doesn't have HealthInfo
{
var healthInfo = victim.Info.Traits.Get<HealthInfo>();
damage = (float)(damage / 100 * healthInfo.HP);
}
victim.InflictDamage(firedBy, (int)damage, this);
}
}
public float GetDamageToInflict(Actor target, Actor firedBy, float modifier)
{
var healthInfo = target.Info.Traits.GetOrDefault<HealthInfo>();
if (healthInfo == null)
return 0;
var rawDamage = (float)Damage;
return rawDamage * modifier * EffectivenessAgainst(target.Info);
}
}
}

View File

@@ -0,0 +1,65 @@
#region Copyright & License Information
/*
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using OpenRA.Effects;
using OpenRA.Traits;
namespace OpenRA.GameRules
{
public class PerCellDamageWarhead : DamageWarhead
{
[Desc("Size of the area. Damage will be applied to this area.")]
public readonly int[] Size = { 0, 0 };
public override void DoImpact(Target target, Actor firedBy, float firepowerModifier)
{
// Used by traits that damage a single actor, rather than a position
if (target.Type == TargetType.Actor)
DoImpact(target.Actor, firedBy, firepowerModifier);
else
DoImpact(target.CenterPosition, firedBy, firepowerModifier);
}
public void DoImpact(WPos pos, Actor firedBy, float firepowerModifier)
{
var world = firedBy.World;
var targetTile = world.Map.CellContaining(pos);
var minRange = (Size.Length > 1 && Size[1] > 0) ? Size[1] : 0;
var affectedTiles = world.Map.FindTilesInAnnulus(targetTile, minRange, Size[0]);
foreach (var t in affectedTiles)
foreach (var victim in world.ActorMap.GetUnitsAt(t))
DoImpact(victim, firedBy, firepowerModifier);
}
public void DoImpact(Actor victim, Actor firedBy, float firepowerModifier)
{
if (IsValidAgainst(victim, firedBy))
{
var damage = GetDamageToInflict(victim, firedBy, firepowerModifier);
victim.InflictDamage(firedBy, damage, this);
}
}
public int GetDamageToInflict(Actor target, Actor firedBy, float modifier)
{
var healthInfo = target.Info.Traits.GetOrDefault<HealthInfo>();
if (healthInfo == null)
return 0;
var rawDamage = (float)Damage;
return (int)(rawDamage * modifier * EffectivenessAgainst(target.Info));
}
}
}

View File

@@ -0,0 +1,83 @@
#region Copyright & License Information
/*
* Copyright 2007-2014 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation. For more information,
* see COPYING.
*/
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using OpenRA.Effects;
using OpenRA.Traits;
namespace OpenRA.GameRules
{
public class SpreadDamageWarhead : DamageWarhead
{
[Desc("For Normal DamageModel: Distance from the explosion center at which damage is 1/2.")]
public readonly WRange Spread = new WRange(43);
public override void DoImpact(Target target, Actor firedBy, float firepowerModifier)
{
// Used by traits that damage a single actor, rather than a position
if (target.Type == TargetType.Actor)
DoImpact(target.Actor, firedBy, firepowerModifier);
else
DoImpact(target.CenterPosition, firedBy, firepowerModifier);
}
public void DoImpact(WPos pos, Actor firedBy, float firepowerModifier)
{
var world = firedBy.World;
var maxSpread = new WRange((int)(Spread.Range * (float)Math.Log(Math.Abs(Damage), 2)));
var hitActors = world.FindActorsInCircle(pos, maxSpread);
foreach (var victim in hitActors)
if (IsValidAgainst(victim, firedBy))
{
var damage = (int)GetDamageToInflict(pos, victim, firedBy, firepowerModifier);
victim.InflictDamage(firedBy, damage, this);
}
}
public void DoImpact(Actor victim, Actor firedBy, float firepowerModifier)
{
if (IsValidAgainst(victim, firedBy))
{
var damage = GetDamageToInflict(victim.CenterPosition, victim, firedBy, firepowerModifier);
victim.InflictDamage(firedBy, damage, this);
}
}
public int GetDamageToInflict(WPos pos, Actor target, Actor firedBy, float modifier)
{
var healthInfo = target.Info.Traits.GetOrDefault<HealthInfo>();
if (healthInfo == null)
return 0;
var distance = Math.Max(0, (target.CenterPosition - pos).Length - healthInfo.Radius.Range);
var falloff = (float)GetDamageFalloff(distance * 1f / Spread.Range);
var rawDamage = (float)(falloff * Damage);
return (int)(rawDamage * modifier * EffectivenessAgainst(target.Info));
}
static readonly float[] falloff =
{
1f, 0.3678795f, 0.1353353f, 0.04978707f,
0.01831564f, 0.006737947f, 0.002478752f, 0.000911882f
};
static float GetDamageFalloff(float x)
{
var u = (int)x;
if (u >= falloff.Length - 1) return 0;
var t = x - u;
return (falloff[u] * (1 - t)) + (falloff[u + 1] * t);
}
}
}

View File

@@ -8,6 +8,7 @@
*/
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using OpenRA.Effects;
@@ -15,83 +16,6 @@ using OpenRA.Traits;
namespace OpenRA.GameRules
{
public class WarheadInfo
{
[Desc("Distance from the explosion center at which damage is 1/2.")]
public readonly WRange Spread = new WRange(43);
[Desc("Maximum Spread. If a value >= Spread is set, this sets a fixed maximum area of damage.")]
public readonly WRange MaxSpread = new WRange(0);
[FieldLoader.LoadUsing("LoadVersus")]
[Desc("Damage vs each armortype. 0% = can't target.")]
public readonly Dictionary<string, float> Versus;
[Desc("Can this damage resource patches?")]
public readonly bool DestroyResources = false;
[Desc("Will this splatter resources and which?")]
public readonly string AddsResourceType = null;
[Desc("Explosion effect to use.")]
public readonly string Explosion = null;
[Desc("Palette to use for explosion effect.")]
public readonly string ExplosionPalette = "effect";
[Desc("Explosion effect on hitting water (usually a splash).")]
public readonly string WaterExplosion = null;
[Desc("Palette to use for effect on hitting water (usually a splash).")]
public readonly string WaterExplosionPalette = "effect";
[Desc("Type of smudge to apply to terrain.")]
public readonly string[] SmudgeType = { };
[Desc("Size of the explosion. provide 2 values for a ring effect (outer/inner).")]
public readonly int[] Size = { 0, 0 };
[Desc("Infantry death animation to use")]
public readonly string InfDeath = "1";
[Desc("Sound to play on impact.")]
public readonly string ImpactSound = null;
[Desc("Sound to play on impact with water")]
public readonly string WaterImpactSound = null;
[Desc("How much (raw) damage to deal")]
public readonly int Damage = 0;
[Desc("Delay in ticks before dealing the damage, 0 = instant (old model).")]
public readonly int Delay = 0;
[Desc("Which damage model to use.")]
public readonly DamageModel DamageModel = DamageModel.Normal;
[Desc("Whether we should prevent prone response for infantry.")]
public readonly bool PreventProne = false;
[Desc("By what percentage should damage be modified against prone infantry.")]
public readonly int ProneModifier = 50;
public float EffectivenessAgainst(ActorInfo ai)
{
var health = ai.Traits.GetOrDefault<HealthInfo>();
if (health == null)
return 0f;
var armor = ai.Traits.GetOrDefault<ArmorInfo>();
if (armor == null || armor.Type == null)
return 1;
float versus;
return Versus.TryGetValue(armor.Type, out versus) ? versus : 1;
}
public WarheadInfo(MiniYaml yaml)
{
FieldLoader.Load(this, yaml);
}
static object LoadVersus(MiniYaml y)
{
var nd = y.ToDictionary();
return nd.ContainsKey("Versus")
? nd["Versus"].ToDictionary(my => FieldLoader.GetValue<float>("(value)", my.Value))
: new Dictionary<string, float>();
}
}
public enum DamageModel
{
Normal, // classic RA damage model: point actors, distance-based falloff
PerCell, // like RA's "nuke damage"
HealthPercentage // for MAD Tank
}
public class ProjectileArgs
{
public WeaponInfo Weapon;
@@ -107,20 +31,38 @@ namespace OpenRA.GameRules
public class WeaponInfo
{
[Desc("The maximum range the weapon can fire.")]
public readonly WRange Range = WRange.Zero;
[Desc("The sound played when the weapon is fired.")]
public readonly string[] Report = null;
[Desc("Rate of Fire")]
[Desc("Rate of Fire = Delay in ticks between reloading ammo magazines.")]
public readonly int ROF = 1;
[Desc("Number of shots in a single ammo magazine.")]
public readonly int Burst = 1;
public readonly bool Charges = false;
public readonly string Palette = "effect";
[Desc("What types of targets are affected.")]
public readonly string[] ValidTargets = { "Ground", "Water" };
[Desc("What types of targets are unaffected.", "Overrules ValidTargets.")]
public readonly string[] InvalidTargets = { };
[Desc("Delay in ticks between firing shots from the same ammo magazine.")]
public readonly int BurstDelay = 5;
[Desc("The minimum range the weapon can fire.")]
public readonly WRange MinRange = WRange.Zero;
[FieldLoader.LoadUsing("LoadProjectile")] public IProjectileInfo Projectile;
[FieldLoader.LoadUsing("LoadWarheads")] public List<WarheadInfo> Warheads;
[FieldLoader.LoadUsing("LoadProjectile")]
public readonly IProjectileInfo Projectile;
[FieldLoader.LoadUsing("LoadWarheads")]
public readonly List<Warhead> Warheads = new List<Warhead>();
public WeaponInfo(string name, MiniYaml content)
{
@@ -139,47 +81,24 @@ namespace OpenRA.GameRules
static object LoadWarheads(MiniYaml yaml)
{
var ret = new List<WarheadInfo>();
foreach (var w in yaml.Nodes)
if (w.Key.Split('@')[0] == "Warhead")
ret.Add(new WarheadInfo(w.Value));
var retList = new List<Warhead>();
foreach (var node in yaml.Nodes.Where(n => n.Key.StartsWith("Warhead")))
{
var ret = Game.CreateObject<Warhead>(node.Value.Value + "Warhead");
FieldLoader.Load(ret, node.Value);
retList.Add(ret);
}
return ret;
return retList;
}
public bool IsValidAgainst(Actor a)
{
var targetable = a.TraitOrDefault<ITargetable>();
if (targetable == null || !ValidTargets.Intersect(targetable.TargetTypes).Any()
|| InvalidTargets.Intersect(targetable.TargetTypes).Any())
return false;
if (Warheads.All(w => w.EffectivenessAgainst(a.Info) <= 0))
return false;
return true;
}
public bool IsValidAgainst(FrozenActor a)
{
var targetable = a.Info.Traits.GetOrDefault<ITargetableInfo>();
if (targetable == null || !ValidTargets.Intersect(targetable.GetTargetTypes()).Any()
|| InvalidTargets.Intersect(targetable.GetTargetTypes()).Any())
return false;
if (Warheads.All(w => w.EffectivenessAgainst(a.Info) <= 0))
return false;
return true;
}
public bool IsValidAgainst(Target target, World world)
public bool IsValidAgainst(Target target, World world, Actor firedBy)
{
if (target.Type == TargetType.Actor)
return IsValidAgainst(target.Actor);
return IsValidAgainst(target.Actor, firedBy);
if (target.Type == TargetType.FrozenActor)
return IsValidAgainst(target.FrozenActor);
return IsValidAgainst(target.FrozenActor, firedBy);
if (target.Type == TargetType.Terrain)
{
@@ -197,5 +116,47 @@ namespace OpenRA.GameRules
return false;
}
public bool IsValidAgainst(Actor victim, Actor firedBy)
{
if (!Warheads.Any(w => w.IsValidAgainst(victim, firedBy)))
return false;
var targetable = victim.TraitOrDefault<ITargetable>();
if (targetable == null || !ValidTargets.Intersect(targetable.TargetTypes).Any()
|| InvalidTargets.Intersect(targetable.TargetTypes).Any())
return false;
return true;
}
public bool IsValidAgainst(FrozenActor victim, Actor firedBy)
{
// Frozen Actors are treated slightly differently.
if (!Warheads.Any(w => w.IsValidAgainst(victim, firedBy)))
return false;
var targetable = victim.Info.Traits.GetOrDefault<ITargetableInfo>();
if (targetable == null || !ValidTargets.Intersect(targetable.GetTargetTypes()).Any()
|| InvalidTargets.Intersect(targetable.GetTargetTypes()).Any())
return false;
return true;
}
public void Impact(WPos pos, Actor firedBy, float damageModifier)
{
foreach (var wh in Warheads)
{
Action a;
a = () => wh.DoImpact(Target.FromPos(pos), firedBy, damageModifier);
if (wh.Delay > 0)
firedBy.World.AddFrameEndTask(
w => w.Add(new DelayedAction(wh.Delay, a)));
else
a();
}
}
}
}

View File

@@ -75,6 +75,12 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Actor.cs" />
<Compile Include="GameRules\Warhead.cs" />
<Compile Include="GameRules\Warheads\AbsoluteSpreadDamageWarhead.cs" />
<Compile Include="GameRules\Warheads\DamageWarhead.cs" />
<Compile Include="GameRules\Warheads\HealthPercentageDamageWarhead.cs" />
<Compile Include="GameRules\Warheads\PerCellDamageWarhead.cs" />
<Compile Include="GameRules\Warheads\SpreadDamageWarhead.cs" />
<Compile Include="Graphics\QuadRenderer.cs" />
<Compile Include="Download.cs" />
<Compile Include="Effects\DelayedAction.cs" />

View File

@@ -98,7 +98,7 @@ namespace OpenRA.Traits
nd.AppliedDamage(repairer, self, ai);
}
public void InflictDamage(Actor self, Actor attacker, int damage, WarheadInfo warhead, bool ignoreModifiers)
public void InflictDamage(Actor self, Actor attacker, int damage, DamageWarhead warhead, bool ignoreModifiers)
{
if (IsDead) return; /* overkill! don't count extra hits as more kills! */
@@ -177,7 +177,7 @@ namespace OpenRA.Traits
return (health == null) ? DamageState.Undamaged : health.DamageState;
}
public static void InflictDamage(this Actor self, Actor attacker, int damage, WarheadInfo warhead)
public static void InflictDamage(this Actor self, Actor attacker, int damage, DamageWarhead warhead)
{
if (self.Destroyed) return;
var health = self.TraitOrDefault<Health>();

View File

@@ -27,7 +27,7 @@ namespace OpenRA.Traits
public class AttackInfo
{
public Actor Attacker;
public WarheadInfo Warhead;
public DamageWarhead Warhead;
public int Damage;
public DamageState DamageState;
public DamageState PreviousDamageState;
@@ -149,7 +149,7 @@ namespace OpenRA.Traits
}
public interface IRenderModifier { IEnumerable<IRenderable> ModifyRender(Actor self, WorldRenderer wr, IEnumerable<IRenderable> r); }
public interface IDamageModifier { float GetDamageModifier(Actor attacker, WarheadInfo warhead); }
public interface IDamageModifier { float GetDamageModifier(Actor attacker, DamageWarhead warhead); }
public interface ISpeedModifier { decimal GetSpeedModifier(); }
public interface IFirepowerModifier { float GetFirepowerModifier(); }
public interface ILoadsPalettes { void LoadPalettes(WorldRenderer wr); }