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) 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)) 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; 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 #endregion
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using OpenRA.Effects; using OpenRA.Effects;
@@ -15,83 +16,6 @@ using OpenRA.Traits;
namespace OpenRA.GameRules 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 class ProjectileArgs
{ {
public WeaponInfo Weapon; public WeaponInfo Weapon;
@@ -107,20 +31,38 @@ namespace OpenRA.GameRules
public class WeaponInfo public class WeaponInfo
{ {
[Desc("The maximum range the weapon can fire.")]
public readonly WRange Range = WRange.Zero; public readonly WRange Range = WRange.Zero;
[Desc("The sound played when the weapon is fired.")]
public readonly string[] Report = null; 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; public readonly int ROF = 1;
[Desc("Number of shots in a single ammo magazine.")]
public readonly int Burst = 1; public readonly int Burst = 1;
public readonly bool Charges = false; public readonly bool Charges = false;
public readonly string Palette = "effect"; public readonly string Palette = "effect";
[Desc("What types of targets are affected.")]
public readonly string[] ValidTargets = { "Ground", "Water" }; public readonly string[] ValidTargets = { "Ground", "Water" };
[Desc("What types of targets are unaffected.", "Overrules ValidTargets.")]
public readonly string[] InvalidTargets = { }; public readonly string[] InvalidTargets = { };
[Desc("Delay in ticks between firing shots from the same ammo magazine.")]
public readonly int BurstDelay = 5; public readonly int BurstDelay = 5;
[Desc("The minimum range the weapon can fire.")]
public readonly WRange MinRange = WRange.Zero; public readonly WRange MinRange = WRange.Zero;
[FieldLoader.LoadUsing("LoadProjectile")] public IProjectileInfo Projectile; [FieldLoader.LoadUsing("LoadProjectile")]
[FieldLoader.LoadUsing("LoadWarheads")] public List<WarheadInfo> Warheads; public readonly IProjectileInfo Projectile;
[FieldLoader.LoadUsing("LoadWarheads")]
public readonly List<Warhead> Warheads = new List<Warhead>();
public WeaponInfo(string name, MiniYaml content) public WeaponInfo(string name, MiniYaml content)
{ {
@@ -139,47 +81,24 @@ namespace OpenRA.GameRules
static object LoadWarheads(MiniYaml yaml) static object LoadWarheads(MiniYaml yaml)
{ {
var ret = new List<WarheadInfo>(); var retList = new List<Warhead>();
foreach (var w in yaml.Nodes) foreach (var node in yaml.Nodes.Where(n => n.Key.StartsWith("Warhead")))
if (w.Key.Split('@')[0] == "Warhead") {
ret.Add(new WarheadInfo(w.Value)); 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) public bool IsValidAgainst(Target target, World world, Actor firedBy)
{
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)
{ {
if (target.Type == TargetType.Actor) if (target.Type == TargetType.Actor)
return IsValidAgainst(target.Actor); return IsValidAgainst(target.Actor, firedBy);
if (target.Type == TargetType.FrozenActor) if (target.Type == TargetType.FrozenActor)
return IsValidAgainst(target.FrozenActor); return IsValidAgainst(target.FrozenActor, firedBy);
if (target.Type == TargetType.Terrain) if (target.Type == TargetType.Terrain)
{ {
@@ -197,5 +116,47 @@ namespace OpenRA.GameRules
return false; 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>
<ItemGroup> <ItemGroup>
<Compile Include="Actor.cs" /> <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="Graphics\QuadRenderer.cs" />
<Compile Include="Download.cs" /> <Compile Include="Download.cs" />
<Compile Include="Effects\DelayedAction.cs" /> <Compile Include="Effects\DelayedAction.cs" />

View File

@@ -98,7 +98,7 @@ namespace OpenRA.Traits
nd.AppliedDamage(repairer, self, ai); 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! */ 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; 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; if (self.Destroyed) return;
var health = self.TraitOrDefault<Health>(); var health = self.TraitOrDefault<Health>();

View File

@@ -27,7 +27,7 @@ namespace OpenRA.Traits
public class AttackInfo public class AttackInfo
{ {
public Actor Attacker; public Actor Attacker;
public WarheadInfo Warhead; public DamageWarhead Warhead;
public int Damage; public int Damage;
public DamageState DamageState; public DamageState DamageState;
public DamageState PreviousDamageState; 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 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 ISpeedModifier { decimal GetSpeedModifier(); }
public interface IFirepowerModifier { float GetFirepowerModifier(); } public interface IFirepowerModifier { float GetFirepowerModifier(); }
public interface ILoadsPalettes { void LoadPalettes(WorldRenderer wr); } public interface ILoadsPalettes { void LoadPalettes(WorldRenderer wr); }

View File

@@ -10,6 +10,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using OpenRA.Effects; using OpenRA.Effects;
using OpenRA.GameRules;
using OpenRA.Graphics; using OpenRA.Graphics;
using OpenRA.Mods.RA; using OpenRA.Mods.RA;
using OpenRA.Traits; using OpenRA.Traits;
@@ -44,7 +45,8 @@ namespace OpenRA.Mods.Cnc.Effects
void Finish(World world) void Finish(World world)
{ {
world.AddFrameEndTask(w => w.Remove(this)); world.AddFrameEndTask(w => w.Remove(this));
Combat.DoExplosion(firedBy.PlayerActor, weapon, target.CenterPosition); var weapon = world.Map.Rules.Weapons[this.weapon.ToLowerInvariant()];
weapon.Impact(target.CenterPosition, firedBy.PlayerActor, 1f);
} }
} }
} }

View File

@@ -11,6 +11,7 @@
using System.Linq; using System.Linq;
using OpenRA.Traits; using OpenRA.Traits;
using OpenRA.Mods.RA; using OpenRA.Mods.RA;
using OpenRA.GameRules;
namespace OpenRA.Mods.Cnc namespace OpenRA.Mods.Cnc
{ {
@@ -42,8 +43,7 @@ namespace OpenRA.Mods.Cnc
if (!info.Resources.Contains(r.Info.Name)) return; if (!info.Resources.Contains(r.Info.Name)) return;
var weapon = self.World.Map.Rules.Weapons[info.Weapon.ToLowerInvariant()]; var weapon = self.World.Map.Rules.Weapons[info.Weapon.ToLowerInvariant()];
weapon.Impact(self.CenterPosition, self.World.WorldActor, 1f);
self.InflictDamage(self.World.WorldActor, weapon.Warheads[0].Damage, weapon.Warheads[0]);
poisonTicks = weapon.ROF; poisonTicks = weapon.ROF;
} }
} }

View File

@@ -65,9 +65,7 @@ namespace OpenRA.Mods.D2k
if (health.HP <= damageThreshold || --damageTicks > 0) if (health.HP <= damageThreshold || --damageTicks > 0)
return; return;
foreach (var w in weapon.Warheads) weapon.Impact(self.CenterPosition, self.World.WorldActor, 1f);
health.InflictDamage(self, self.World.WorldActor, w.Damage, w, false);
damageTicks = weapon.ROF; damageTicks = weapon.ROF;
} }
} }

View File

@@ -13,6 +13,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using AI.Fuzzy.Library; using AI.Fuzzy.Library;
using OpenRA.Mods.RA.Move; using OpenRA.Mods.RA.Move;
using OpenRA.GameRules;
using OpenRA.Traits; using OpenRA.Traits;
namespace OpenRA.Mods.RA.AI namespace OpenRA.Mods.RA.AI
@@ -195,8 +196,11 @@ namespace OpenRA.Mods.RA.AI
var sumOfDamage = 0; var sumOfDamage = 0;
var arms = a.TraitsImplementing<Armament>(); var arms = a.TraitsImplementing<Armament>();
foreach (var arm in arms) foreach (var arm in arms)
if (arm.Weapon.Warheads[0] != null) {
sumOfDamage += arm.Weapon.Warheads[0].Damage; var warhead = arm.Weapon.Warheads.Select(w => w as DamageWarhead).FirstOrDefault(w => w != null);
if (warhead != null)
sumOfDamage += warhead.Damage;
}
return sumOfDamage; return sumOfDamage;
}); });
} }

View File

@@ -63,7 +63,7 @@ namespace OpenRA.Mods.RA.Activities
mobile.IsMoving = false; mobile.IsMoving = false;
self.World.ActorMap.GetUnitsAt(mobile.toCell, mobile.toSubCell) self.World.ActorMap.GetUnitsAt(mobile.toCell, mobile.toSubCell)
.Except(new []{self}).Where(t => weapon.IsValidAgainst(t)) .Except(new []{self}).Where(t => weapon.IsValidAgainst(t, self))
.Do(t => t.Kill(self)); .Do(t => t.Kill(self));
return NextActivity; return NextActivity;

View File

@@ -8,6 +8,7 @@
*/ */
#endregion #endregion
using OpenRA.GameRules;
using OpenRA.Traits; using OpenRA.Traits;
namespace OpenRA.Mods.RA.Air namespace OpenRA.Mods.RA.Air
@@ -51,7 +52,10 @@ namespace OpenRA.Mods.RA.Air
if (self.CenterPosition.Z <= 0) if (self.CenterPosition.Z <= 0)
{ {
if (info.Explosion != null) if (info.Explosion != null)
Combat.DoExplosion(self, info.Explosion, self.CenterPosition); {
var weapon = self.World.Map.Rules.Weapons[info.Explosion.ToLowerInvariant()];
weapon.Impact(self.CenterPosition, self, 1f);
}
self.Destroy(); self.Destroy();
return null; return null;

View File

@@ -142,7 +142,7 @@ namespace OpenRA.Mods.RA
if (Weapon.MinRange != WRange.Zero && target.IsInRange(self.CenterPosition, Weapon.MinRange)) if (Weapon.MinRange != WRange.Zero && target.IsInRange(self.CenterPosition, Weapon.MinRange))
return null; return null;
if (!Weapon.IsValidAgainst(target, self.World)) if (!Weapon.IsValidAgainst(target, self.World, self))
return null; return null;
var barrel = Barrels[Burst % Barrels.Length]; var barrel = Barrels[Burst % Barrels.Length];

View File

@@ -12,6 +12,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.Linq; using System.Linq;
using OpenRA.GameRules;
using OpenRA.Mods.RA.Buildings; using OpenRA.Mods.RA.Buildings;
using OpenRA.Traits; using OpenRA.Traits;
@@ -87,11 +88,11 @@ namespace OpenRA.Mods.RA
{ {
get get
{ {
var armament = Armaments.FirstOrDefault(); var armament = Armaments.FirstOrDefault(a => a.Weapon.Warheads.Any(w => (w is DamageWarhead)));
if (armament == null) if (armament == null)
yield break; yield break;
var negativeDamage = armament.Weapon.Warheads[0].Damage < 0; var negativeDamage = (armament.Weapon.Warheads.FirstOrDefault(w => (w is DamageWarhead)) as DamageWarhead).Damage < 0;
yield return new AttackOrderTargeter(this, "Attack", 6, negativeDamage); yield return new AttackOrderTargeter(this, "Attack", 6, negativeDamage);
} }
} }
@@ -134,13 +135,13 @@ 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, self)); }
public WRange GetMaximumRange() public WRange GetMaximumRange()
{ {
return Armaments.Select(a => a.Weapon.Range).Append(WRange.Zero).Max(); return Armaments.Select(a => a.Weapon.Range).Append(WRange.Zero).Max();
} }
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, self)); }
public void AttackTarget(Target target, bool queued, bool allowMove) public void AttackTarget(Target target, bool queued, bool allowMove)
{ {

View File

@@ -22,6 +22,8 @@ namespace OpenRA.Mods.RA
[Desc("How many game ticks should pass before closing the actor's turret.")] [Desc("How many game ticks should pass before closing the actor's turret.")]
public int CloseDelay = 125; public int CloseDelay = 125;
public int DefaultFacing = 0; public int DefaultFacing = 0;
[Desc("The factor damage received is multiplied by while this actor is closed.")]
public float ClosedDamageMultiplier = 0.5f; public float ClosedDamageMultiplier = 0.5f;
public override object Create(ActorInitializer init) { return new AttackPopupTurreted(init, this); } public override object Create(ActorInitializer init) { return new AttackPopupTurreted(init, this); }
@@ -103,7 +105,7 @@ namespace OpenRA.Mods.RA
} }
} }
public float GetDamageModifier(Actor attacker, WarheadInfo warhead) public float GetDamageModifier(Actor attacker, DamageWarhead warhead)
{ {
return state == PopupState.Closed ? info.ClosedDamageMultiplier : 1f; return state == PopupState.Closed ? info.ClosedDamageMultiplier : 1f;
} }

View File

@@ -11,6 +11,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using OpenRA.Effects; using OpenRA.Effects;
using OpenRA.GameRules;
using OpenRA.Graphics; using OpenRA.Graphics;
using OpenRA.Primitives; using OpenRA.Primitives;
using OpenRA.Traits; using OpenRA.Traits;
@@ -294,7 +295,8 @@ namespace OpenRA.Mods.RA
var initialDamage = Health.DamageState; var initialDamage = Health.DamageState;
self.World.AddFrameEndTask(w => self.World.AddFrameEndTask(w =>
{ {
Combat.DoExplosion(saboteur, "Demolish", self.CenterPosition); var weapon = saboteur.World.Map.Rules.Weapons["demolish"];
weapon.Impact(self.CenterPosition, saboteur, 1f);
self.World.WorldActor.Trait<ScreenShaker>().AddEffect(15, self.CenterPosition, 6); self.World.WorldActor.Trait<ScreenShaker>().AddEffect(15, self.CenterPosition, 6);
self.Kill(saboteur); self.Kill(saboteur);
}); });

View File

@@ -1,232 +0,0 @@
#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.GameRules;
using OpenRA.Mods.RA.Effects;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
// some utility bits that are shared between various things
public static class Combat
{
static string GetImpactSound(WarheadInfo warhead, bool isWater)
{
if (isWater && warhead.WaterImpactSound != null)
return warhead.WaterImpactSound;
if (warhead.ImpactSound != null)
return warhead.ImpactSound;
return null;
}
public static void DoImpact(WPos pos, WarheadInfo warhead, WeaponInfo weapon, Actor firedBy, float firepowerModifier)
{
var world = firedBy.World;
var targetTile = world.Map.CellContaining(pos);
if (!world.Map.Contains(targetTile))
return;
var isWater = pos.Z <= 0 && world.Map.GetTerrainInfo(targetTile).IsWater;
var explosionType = isWater ? warhead.WaterExplosion : warhead.Explosion;
var explosionTypePalette = isWater ? warhead.WaterExplosionPalette : warhead.ExplosionPalette;
if (explosionType != null)
world.AddFrameEndTask(w => w.Add(new Explosion(w, pos, explosionType, explosionTypePalette)));
Sound.Play(GetImpactSound(warhead, isWater), pos);
var smudgeLayers = world.WorldActor.TraitsImplementing<SmudgeLayer>().ToDictionary(x => x.Info.Type);
var resLayer = warhead.DestroyResources || !string.IsNullOrEmpty(warhead.AddsResourceType) ? world.WorldActor.Trait<ResourceLayer>() : null;
if (warhead.Size[0] > 0)
{
var allCells = world.Map.FindTilesInCircle(targetTile, warhead.Size[0]).ToList();
// `smudgeCells` might want to just be an outer shell of the cells:
IEnumerable<CPos> smudgeCells = allCells;
if (warhead.Size.Length == 2)
smudgeCells = smudgeCells.Except(world.Map.FindTilesInCircle(targetTile, warhead.Size[1]));
// Draw the smudges:
foreach (var sc in smudgeCells)
{
var smudgeType = world.Map.GetTerrainInfo(sc).AcceptsSmudgeType.FirstOrDefault(t => warhead.SmudgeType.Contains(t));
if (smudgeType == null) continue;
SmudgeLayer smudgeLayer;
if (!smudgeLayers.TryGetValue(smudgeType, out smudgeLayer))
throw new NotImplementedException("Unknown smudge type `{0}`".F(smudgeType));
smudgeLayer.AddSmudge(sc);
if (warhead.DestroyResources)
resLayer.Destroy(sc);
}
// Destroy all resources in range, not just the outer shell:
if (warhead.DestroyResources)
foreach (var cell in allCells)
resLayer.Destroy(cell);
// Splatter resources:
if (!string.IsNullOrEmpty(warhead.AddsResourceType))
{
var resourceType = world.WorldActor.TraitsImplementing<ResourceType>()
.FirstOrDefault(t => t.Info.Name == warhead.AddsResourceType);
if (resourceType == null)
Log.Write("debug", "Warhead defines an invalid resource type '{0}'".F(warhead.AddsResourceType));
else
{
foreach (var cell in allCells)
{
if (!resLayer.CanSpawnResourceAt(resourceType, cell))
continue;
var splash = world.SharedRandom.Next(1, resourceType.Info.MaxDensity - resLayer.GetResourceDensity(cell));
resLayer.AddResource(resourceType, cell, splash);
}
}
}
}
else
{
var smudgeType = world.Map.GetTerrainInfo(targetTile).AcceptsSmudgeType.FirstOrDefault(t => warhead.SmudgeType.Contains(t));
if (smudgeType != null)
{
SmudgeLayer smudgeLayer;
if (!smudgeLayers.TryGetValue(smudgeType, out smudgeLayer))
throw new NotImplementedException("Unknown smudge type `{0}`".F(smudgeType));
smudgeLayer.AddSmudge(targetTile);
}
}
if (warhead.DestroyResources)
world.WorldActor.Trait<ResourceLayer>().Destroy(targetTile);
switch (warhead.DamageModel)
{
case DamageModel.Normal:
{
var spreadMax = warhead.MaxSpread.Range;
var maxSpreadCalculation = spreadMax >= warhead.Spread.Range ? spreadMax : (warhead.Spread.Range * (float)Math.Log(Math.Abs(warhead.Damage), 2));
var maxSpread = new WRange((int)(maxSpreadCalculation));
var hitActors = world.FindActorsInCircle(pos, maxSpread);
foreach (var victim in hitActors)
{
var damage = (int)GetDamageToInflict(pos, victim, warhead, weapon, firepowerModifier, true);
victim.InflictDamage(firedBy, damage, warhead);
}
}
break;
case DamageModel.PerCell:
{
foreach (var t in world.Map.FindTilesInCircle(targetTile, warhead.Size[0]))
{
foreach (var unit in world.ActorMap.GetUnitsAt(t))
{
var damage = (int)GetDamageToInflict(pos, unit, warhead, weapon, firepowerModifier, false);
unit.InflictDamage(firedBy, damage, warhead);
}
}
}
break;
case DamageModel.HealthPercentage:
{
var range = new WRange(warhead.Size[0] * 1024);
var hitActors = world.FindActorsInCircle(pos, range);
foreach (var victim in hitActors)
{
var damage = GetDamageToInflict(pos, victim, warhead, weapon, firepowerModifier, false);
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, warhead);
}
}
break;
}
}
public static void DoImpacts(WPos pos, Actor firedBy, WeaponInfo weapon, float damageModifier)
{
foreach (var wh in weapon.Warheads)
{
var warhead = wh;
Action a = () => DoImpact(pos, warhead, weapon, firedBy, damageModifier);
if (warhead.Delay > 0)
firedBy.World.AddFrameEndTask(
w => w.Add(new DelayedAction(warhead.Delay, a)));
else
a();
}
}
public static void DoExplosion(Actor attacker, string weapontype, WPos pos)
{
var weapon = attacker.World.Map.Rules.Weapons[weapontype.ToLowerInvariant()];
if (weapon.Report != null && weapon.Report.Any())
Sound.Play(weapon.Report.Random(attacker.World.SharedRandom), pos);
DoImpacts(pos, attacker, weapon, 1f);
}
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);
}
static float GetDamageToInflict(WPos pos, Actor target, WarheadInfo warhead, WeaponInfo weapon, float modifier, bool withFalloff)
{
// don't hit air units with splash from ground explosions, etc
if (!weapon.IsValidAgainst(target))
return 0;
var healthInfo = target.Info.Traits.GetOrDefault<HealthInfo>();
if (healthInfo == null)
return 0;
var rawDamage = (float)warhead.Damage;
if (withFalloff)
{
var distance = Math.Max(0, (target.CenterPosition - pos).Length - healthInfo.Radius.Range);
var falloff = (float)GetDamageFalloff(distance * 1f / warhead.Spread.Range);
rawDamage = (float)(falloff * rawDamage);
}
return (float)(rawDamage * modifier * (float)warhead.EffectivenessAgainst(target.Info));
}
}
}

View File

@@ -8,6 +8,7 @@
*/ */
#endregion #endregion
using OpenRA.GameRules;
using OpenRA.Traits; using OpenRA.Traits;
namespace OpenRA.Mods.RA namespace OpenRA.Mods.RA
@@ -28,7 +29,8 @@ namespace OpenRA.Mods.RA
public override void Activate(Actor collector) public override void Activate(Actor collector)
{ {
Combat.DoExplosion(self, ((ExplodeCrateActionInfo)info).Weapon, collector.CenterPosition); var weapon = self.World.Map.Rules.Weapons[((ExplodeCrateActionInfo)info).Weapon.ToLowerInvariant()];
weapon.Impact(collector.CenterPosition, self, 1f);
base.Activate(collector); base.Activate(collector);
} }
} }

View File

@@ -172,7 +172,7 @@ namespace OpenRA.Mods.RA.Effects
world.AddFrameEndTask(w => w.Remove(this)); world.AddFrameEndTask(w => w.Remove(this));
Combat.DoImpacts(pos, args.SourceActor, args.Weapon, args.FirepowerModifier); args.Weapon.Impact(pos, args.SourceActor, args.FirepowerModifier);
} }
} }
} }

View File

@@ -56,7 +56,7 @@ namespace OpenRA.Mods.RA.Effects
{ {
pos += new WVec(0, 0, args.PassiveTarget.Z - pos.Z); pos += new WVec(0, 0, args.PassiveTarget.Z - pos.Z);
world.AddFrameEndTask(w => w.Remove(this)); world.AddFrameEndTask(w => w.Remove(this));
Combat.DoImpacts(pos, args.SourceActor, args.Weapon, args.FirepowerModifier); args.Weapon.Impact(pos, args.SourceActor, args.FirepowerModifier);
} }
anim.Tick(); anim.Tick();

View File

@@ -69,7 +69,7 @@ namespace OpenRA.Mods.RA.Effects
if (hitanim != null) if (hitanim != null)
hitanim.PlayThen("idle", () => animationComplete = true); hitanim.PlayThen("idle", () => animationComplete = true);
Combat.DoImpacts(target, args.SourceActor, args.Weapon, args.FirepowerModifier); args.Weapon.Impact(target, args.SourceActor, args.FirepowerModifier);
doneDamage = true; doneDamage = true;
} }

View File

@@ -180,7 +180,7 @@ namespace OpenRA.Mods.RA.Effects
if (ticks <= info.Arm) if (ticks <= info.Arm)
return; return;
Combat.DoImpacts(pos, args.SourceActor, args.Weapon, args.FirepowerModifier); args.Weapon.Impact(pos, args.SourceActor, args.FirepowerModifier);
} }
public IEnumerable<IRenderable> Render(WorldRenderer wr) public IEnumerable<IRenderable> Render(WorldRenderer wr)

View File

@@ -11,6 +11,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using OpenRA.Effects; using OpenRA.Effects;
using OpenRA.GameRules;
using OpenRA.Graphics; using OpenRA.Graphics;
using OpenRA.Traits; using OpenRA.Traits;
@@ -79,7 +80,8 @@ namespace OpenRA.Mods.RA.Effects
void Explode(World world) void Explode(World world)
{ {
world.AddFrameEndTask(w => w.Remove(this)); world.AddFrameEndTask(w => w.Remove(this));
Combat.DoExplosion(firedBy.PlayerActor, weapon, pos); var weapon = world.Map.Rules.Weapons[this.weapon.ToLowerInvariant()];
weapon.Impact(pos, firedBy.PlayerActor, 1f);
world.WorldActor.Trait<ScreenShaker>().AddEffect(20, pos, 5); world.WorldActor.Trait<ScreenShaker>().AddEffect(20, pos, 5);
foreach (var a in world.ActorsWithTrait<NukePaletteEffect>()) foreach (var a in world.ActorsWithTrait<NukePaletteEffect>())

View File

@@ -47,7 +47,7 @@ namespace OpenRA.Mods.RA.Effects
if (!doneDamage) if (!doneDamage)
{ {
var pos = Args.GuidedTarget.IsValidFor(Args.SourceActor) ? Args.GuidedTarget.CenterPosition : Args.PassiveTarget; var pos = Args.GuidedTarget.IsValidFor(Args.SourceActor) ? Args.GuidedTarget.CenterPosition : Args.PassiveTarget;
Combat.DoImpacts(pos, Args.SourceActor, Args.Weapon, Args.FirepowerModifier); Args.Weapon.Impact(pos, Args.SourceActor, Args.FirepowerModifier);
doneDamage = true; doneDamage = true;
} }
} }

View File

@@ -9,6 +9,7 @@
#endregion #endregion
using System.Linq; using System.Linq;
using OpenRA.GameRules;
using OpenRA.Traits; using OpenRA.Traits;
namespace OpenRA.Mods.RA namespace OpenRA.Mods.RA
@@ -43,9 +44,15 @@ namespace OpenRA.Mods.RA
if (explodesInfo.InfDeath != null && e.Warhead != null && !explodesInfo.InfDeath.Contains(e.Warhead.InfDeath)) if (explodesInfo.InfDeath != null && e.Warhead != null && !explodesInfo.InfDeath.Contains(e.Warhead.InfDeath))
return; return;
var weapon = ChooseWeaponForExplosion(self); var weaponName = ChooseWeaponForExplosion(self);
if (weapon != null) if (weaponName != null)
Combat.DoExplosion(e.Attacker, weapon, self.CenterPosition); {
var weapon = e.Attacker.World.Map.Rules.Weapons[weaponName.ToLowerInvariant()];
if (weapon.Report != null && weapon.Report.Any())
Sound.Play(weapon.Report.Random(e.Attacker.World.SharedRandom), self.CenterPosition);
weapon.Impact(self.CenterPosition, e.Attacker, 1f);
}
} }
string ChooseWeaponForExplosion(Actor self) string ChooseWeaponForExplosion(Actor self)

View File

@@ -82,7 +82,7 @@ namespace OpenRA.Mods.RA
} }
} }
public float GetDamageModifier(Actor attacker, WarheadInfo warhead) public float GetDamageModifier(Actor attacker, DamageWarhead warhead)
{ {
return Level > 0 ? 1 / info.ArmorModifier[Level - 1] : 1; return Level > 0 ? 1 / info.ArmorModifier[Level - 1] : 1;
} }

View File

@@ -67,7 +67,7 @@ namespace OpenRA.Mods.RA
return FirepowerLevel > 0 ? (1 + FirepowerLevel * info.FirepowerModifier) : 1; return FirepowerLevel > 0 ? (1 + FirepowerLevel * info.FirepowerModifier) : 1;
} }
public float GetDamageModifier(Actor attacker, WarheadInfo warhead) public float GetDamageModifier(Actor attacker, DamageWarhead warhead)
{ {
return ArmorLevel > 0 ? (1 / (1 + ArmorLevel * info.ArmorModifier)) : 1; return ArmorLevel > 0 ? (1 / (1 + ArmorLevel * info.ArmorModifier)) : 1;
} }

View File

@@ -18,6 +18,6 @@ namespace OpenRA.Mods.RA
class Invulnerable : IDamageModifier class Invulnerable : IDamageModifier
{ {
public float GetDamageModifier(Actor attacker, WarheadInfo warhead) { return 0.0f; } public float GetDamageModifier(Actor attacker, DamageWarhead warhead) { return 0.0f; }
} }
} }

View File

@@ -28,7 +28,7 @@ namespace OpenRA.Mods.RA
RemainingTicks--; RemainingTicks--;
} }
public float GetDamageModifier(Actor attacker, WarheadInfo warhead) public float GetDamageModifier(Actor attacker, DamageWarhead warhead)
{ {
return (RemainingTicks > 0) ? 0.0f : 1.0f; return (RemainingTicks > 0) ? 0.0f : 1.0f;
} }

View File

@@ -10,6 +10,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using OpenRA.GameRules;
using OpenRA.Mods.RA.Activities; using OpenRA.Mods.RA.Activities;
using OpenRA.Mods.RA.Move; using OpenRA.Mods.RA.Move;
using OpenRA.Mods.RA.Orders; using OpenRA.Mods.RA.Orders;
@@ -68,7 +69,10 @@ namespace OpenRA.Mods.RA
if (++tick >= info.ThumpInterval) if (++tick >= info.ThumpInterval)
{ {
if (info.ThumpDamageWeapon != null) if (info.ThumpDamageWeapon != null)
Combat.DoExplosion(self, info.ThumpDamageWeapon, self.CenterPosition); {
var weapon = self.World.Map.Rules.Weapons[info.ThumpDamageWeapon.ToLowerInvariant()];
weapon.Impact(self.CenterPosition, self, 1f);
}
screenShaker.AddEffect(info.ThumpShakeTime, self.CenterPosition, info.ThumpShakeIntensity, info.ThumpShakeMultiplier); screenShaker.AddEffect(info.ThumpShakeTime, self.CenterPosition, info.ThumpShakeIntensity, info.ThumpShakeMultiplier);
tick = 0; tick = 0;
} }
@@ -104,7 +108,10 @@ namespace OpenRA.Mods.RA
self.World.AddFrameEndTask(w => self.World.AddFrameEndTask(w =>
{ {
if (info.DetonationWeapon != null) if (info.DetonationWeapon != null)
Combat.DoExplosion(self, info.DetonationWeapon, self.CenterPosition); {
var weapon = self.World.Map.Rules.Weapons[info.DetonationWeapon.ToLowerInvariant()];
weapon.Impact(self.CenterPosition, self, 1f);
}
self.Kill(self); self.Kill(self);
}); });
} }

View File

@@ -189,7 +189,6 @@
<Compile Include="ChronoshiftPaletteEffect.cs" /> <Compile Include="ChronoshiftPaletteEffect.cs" />
<Compile Include="Chronoshiftable.cs" /> <Compile Include="Chronoshiftable.cs" />
<Compile Include="Cloak.cs" /> <Compile Include="Cloak.cs" />
<Compile Include="Combat.cs" />
<Compile Include="ConquestVictoryConditions.cs" /> <Compile Include="ConquestVictoryConditions.cs" />
<Compile Include="ContainsCrate.cs" /> <Compile Include="ContainsCrate.cs" />
<Compile Include="Crate.cs" /> <Compile Include="Crate.cs" />
@@ -289,6 +288,10 @@
<Compile Include="Player\ProductionQueue.cs" /> <Compile Include="Player\ProductionQueue.cs" />
<Compile Include="Player\ProvidesTechPrerequisite.cs" /> <Compile Include="Player\ProvidesTechPrerequisite.cs" />
<Compile Include="PortableChrono.cs" /> <Compile Include="PortableChrono.cs" />
<Compile Include="Warheads\DestroyResourceWarhead.cs" />
<Compile Include="Warheads\CreateEffectWarhead.cs" />
<Compile Include="Warheads\CreateResourceWarhead.cs" />
<Compile Include="Warheads\LeaveSmudgeWarhead.cs" />
<Compile Include="World\RadarPings.cs" /> <Compile Include="World\RadarPings.cs" />
<Compile Include="Player\TechTree.cs" /> <Compile Include="Player\TechTree.cs" />
<Compile Include="PrimaryBuilding.cs" /> <Compile Include="PrimaryBuilding.cs" />

View File

@@ -20,7 +20,7 @@ namespace OpenRA.Mods.RA
{ {
public bool Invulnerable = false; public bool Invulnerable = false;
public float GetDamageModifier(Actor attacker, WarheadInfo warhead) public float GetDamageModifier(Actor attacker, DamageWarhead warhead)
{ {
return Invulnerable ? 0.0f : 1.0f; return Invulnerable ? 0.0f : 1.0f;
} }

View File

@@ -61,7 +61,7 @@ namespace OpenRA.Mods.RA
LocalOffset = WVec.Zero; LocalOffset = WVec.Zero;
} }
public float GetDamageModifier(Actor attacker, WarheadInfo warhead) public float GetDamageModifier(Actor attacker, DamageWarhead warhead)
{ {
return IsProne && warhead != null ? warhead.ProneModifier / 100f : 1f; return IsProne && warhead != null ? warhead.ProneModifier / 100f : 1f;
} }

View File

@@ -0,0 +1,86 @@
#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.GameRules;
using OpenRA.Traits;
using OpenRA.Mods.RA.Effects;
namespace OpenRA.Mods.RA
{
public class CreateEffectWarhead : Warhead
{
[Desc("Size of the area. An explosion animation will be created in each tile.", "Provide 2 values for a ring effect (outer/inner).")]
public readonly int[] Size = { 0, 0 };
[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("Sound to play on impact.")]
public readonly string ImpactSound = null;
[Desc("Sound to play on impact with water")]
public readonly string WaterImpactSound = null;
public override void DoImpact(Target target, Actor firedBy, float firepowerModifier)
{
DoImpact(target.CenterPosition, firedBy, firepowerModifier);
}
public void DoImpact(WPos pos, Actor firedBy, float firepowerModifier)
{
var world = firedBy.World;
var targetTile = world.Map.CellContaining(pos);
if (!world.Map.Contains(targetTile))
return;
var minRange = (Size.Length > 1 && Size[1] > 0) ? Size[1] : 0;
var allCells = world.Map.FindTilesInAnnulus(targetTile, minRange, Size[0]);
// Draw the effects
foreach (var currentCell in allCells)
{
var currentPos = world.Map.CenterOfCell(currentCell);
// TODO: #5937 should go in here after rebase.
var isWater = currentPos.Z <= 0 && world.Map.GetTerrainInfo(currentCell).IsWater;
var explosionType = isWater ? WaterExplosion : Explosion;
var explosionTypePalette = isWater ? WaterExplosionPalette : ExplosionPalette;
if (explosionType != null)
world.AddFrameEndTask(w => w.Add(new Explosion(w, currentPos, explosionType, explosionTypePalette)));
}
string sound = null;
var isTargetWater = pos.Z <= 0 && world.Map.GetTerrainInfo(targetTile).IsWater;
if (isTargetWater && WaterImpactSound != null)
sound = WaterImpactSound;
if (ImpactSound != null)
sound = ImpactSound;
Sound.Play(sound, pos);
}
public override float EffectivenessAgainst(ActorInfo ai) { return 1f; }
}
}

View File

@@ -0,0 +1,66 @@
#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.GameRules;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
public class CreateResourceWarhead : Warhead
{
[Desc("Size of the area. The resources are seeded within this area.", "Provide 2 values for a ring effect (outer/inner).")]
public readonly int[] Size = { 0, 0 };
[Desc("Will this splatter resources and which?")]
public readonly string AddsResourceType = null;
// TODO: Allow maximum resource splatter to be defined. (Per tile, and in total).
public override void DoImpact(Target target, Actor firedBy, float firepowerModifier)
{
DoImpact(target.CenterPosition, firedBy, firepowerModifier);
}
public void DoImpact(WPos pos, Actor firedBy, float firepowerModifier)
{
if (string.IsNullOrEmpty(AddsResourceType))
return;
var world = firedBy.World;
var targetTile = world.Map.CellContaining(pos);
var resLayer = world.WorldActor.Trait<ResourceLayer>();
var minRange = (Size.Length > 1 && Size[1] > 0) ? Size[1] : 0;
var allCells = world.Map.FindTilesInAnnulus(targetTile, minRange, Size[0]);
var resourceType = world.WorldActor.TraitsImplementing<ResourceType>()
.FirstOrDefault(t => t.Info.Name == AddsResourceType);
if (resourceType == null)
Log.Write("debug", "Warhead defines an invalid resource type '{0}'".F(AddsResourceType));
else
{
foreach (var cell in allCells)
{
if (!resLayer.CanSpawnResourceAt(resourceType, cell))
continue;
var splash = world.SharedRandom.Next(1, resourceType.Info.MaxDensity - resLayer.GetResourceDensity(cell));
resLayer.AddResource(resourceType, cell, splash);
}
}
}
public override float EffectivenessAgainst(ActorInfo ai) { return 1f; }
}
}

View File

@@ -0,0 +1,47 @@
#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.GameRules;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
public class DestroyResourceWarhead : Warhead
{
[Desc("Size of the area. The resources are seeded within this area.", "Provide 2 values for a ring effect (outer/inner).")]
public readonly int[] Size = { 0, 0 };
// TODO: Allow maximum resource removal to be defined. (Per tile, and in total).
public override void DoImpact(Target target, Actor firedBy, float firepowerModifier)
{
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 resLayer = world.WorldActor.Trait<ResourceLayer>();
var minRange = (Size.Length > 1 && Size[1] > 0) ? Size[1] : 0;
var allCells = world.Map.FindTilesInAnnulus(targetTile, minRange, Size[0]);
// Destroy all resources in the selected tiles
foreach (var cell in allCells)
resLayer.Destroy(cell);
}
public override float EffectivenessAgainst(ActorInfo ai) { return 1f; }
}
}

View File

@@ -0,0 +1,58 @@
#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.GameRules;
using OpenRA.Traits;
namespace OpenRA.Mods.RA
{
public class LeaveSmudgeWarhead : Warhead
{
[Desc("Size of the area. A smudge will be created in each tile.", "Provide 2 values for a ring effect (outer/inner).")]
public readonly int[] Size = { 0, 0 };
[Desc("Type of smudge to apply to terrain.")]
public readonly string[] SmudgeType = { };
public override void DoImpact(Target target, Actor firedBy, float firepowerModifier)
{
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 smudgeLayers = world.WorldActor.TraitsImplementing<SmudgeLayer>().ToDictionary(x => x.Info.Type);
var minRange = (Size.Length > 1 && Size[1] > 0) ? Size[1] : 0;
var allCells = world.Map.FindTilesInAnnulus(targetTile, minRange, Size[0]);
// Draw the smudges:
foreach (var sc in allCells)
{
var smudgeType = world.Map.GetTerrainInfo(sc).AcceptsSmudgeType.FirstOrDefault(t => SmudgeType.Contains(t));
if (smudgeType == null) continue;
SmudgeLayer smudgeLayer;
if (!smudgeLayers.TryGetValue(smudgeType, out smudgeLayer))
throw new NotImplementedException("Unknown smudge type `{0}`".F(smudgeType));
smudgeLayer.AddSmudge(sc);
}
}
public override float EffectivenessAgainst(ActorInfo ai) { return 1f; }
}
}

View File

@@ -422,6 +422,180 @@ namespace OpenRA.Utility
node.Key = "DestroyResources"; node.Key = "DestroyResources";
} }
if (engineVersion < 20140720)
{
// Split out the warheads to individual warhead types.
if (depth == 0)
{
var warheadCounter = 0;
foreach(var curNode in node.Value.Nodes.ToArray())
{
if (curNode.Key.Contains("Warhead") && curNode.Value.Value == null)
{
var newNodes = new List<MiniYamlNode>();
var oldNodeAtName = "";
if (curNode.Key.Contains('@'))
oldNodeAtName = "_" + curNode.Key.Split('@')[1];
// Per Cell Damage Model
if (curNode.Value.Nodes.Where(n => n.Key.Contains("DamageModel") &&
n.Value.Value.Contains("PerCell")).Any())
{
warheadCounter++;
var newYaml = new List<MiniYamlNode>();
var keywords = new List<String>{ "Size","Damage","InfDeath","PreventProne","ProneModifier","Delay","ValidTargets","InvalidTargets" };
foreach(var keyword in keywords)
{
var temp = curNode.Value.Nodes.FirstOrDefault(n => n.Key == keyword);
if (temp != null)
newYaml.Add(new MiniYamlNode(keyword, temp.Value.Value));
}
var tempVersus = curNode.Value.Nodes.FirstOrDefault(n => n.Key == "Versus");
if (tempVersus != null)
newYaml.Add(new MiniYamlNode("Versus", tempVersus.Value));
newNodes.Add(new MiniYamlNode("Warhead@" + warheadCounter.ToString() + "Dam" + oldNodeAtName, "PerCellDamage", newYaml));
}
// HealthPercentage damage model
if (curNode.Value.Nodes.Where(n => n.Key.Contains("DamageModel") &&
n.Value.Value.Contains("HealthPercentage")).Any())
{
warheadCounter++;
var newYaml = new List<MiniYamlNode>();
var temp = curNode.Value.Nodes.FirstOrDefault(n => n.Key == "Size"); // New HealthPercentage warhead allows spreads, as opposed to size
if (temp != null)
{
var newValue = temp.Value.Value.Split(',').First() + "c0";
if (temp.Value.Value.Contains(','))
newValue = newValue + "," + temp.Value.Value.Split(',')[1] + "c0"; ;
newYaml.Add(new MiniYamlNode("Spread", newValue));
}
var keywords = new List<String>{ "Damage","InfDeath","PreventProne","ProneModifier","Delay","ValidTargets","InvalidTargets" };
foreach(var keyword in keywords)
{
var temp2 = curNode.Value.Nodes.FirstOrDefault(n => n.Key == keyword);
if (temp2 != null)
newYaml.Add(new MiniYamlNode(keyword, temp2.Value.Value));
}
var tempVersus = curNode.Value.Nodes.FirstOrDefault(n => n.Key == "Versus");
if (tempVersus != null)
newYaml.Add(new MiniYamlNode("Versus", tempVersus.Value));
newNodes.Add(new MiniYamlNode("Warhead@" + warheadCounter.ToString() + "Dam" + oldNodeAtName, "HealthPercentageDamage", newYaml));
}
// SpreadDamage
{ // Always occurs, since by definition all warheads were SpreadDamage warheads before
warheadCounter++;
var newYaml = new List<MiniYamlNode>();
var keywords = new List<String>{ "Spread","Damage","InfDeath","PreventProne","ProneModifier","Delay","ValidTargets","InvalidTargets" };
foreach(var keyword in keywords)
{
var temp = curNode.Value.Nodes.FirstOrDefault(n => n.Key == keyword);
if (temp != null)
newYaml.Add(new MiniYamlNode(keyword, temp.Value.Value));
}
var tempVersus = curNode.Value.Nodes.FirstOrDefault(n => n.Key == "Versus");
if (tempVersus != null)
newYaml.Add(new MiniYamlNode("Versus", tempVersus.Value));
newNodes.Add(new MiniYamlNode("Warhead@" + warheadCounter.ToString() + "Dam" + oldNodeAtName, "SpreadDamage", newYaml));
}
// DestroyResource
if (curNode.Value.Nodes.Where(n => n.Key.Contains("DestroyResources") ||
n.Key.Contains("Ore")).Any())
{
warheadCounter++;
var newYaml = new List<MiniYamlNode>();
var keywords = new List<String>{ "Size","Delay","ValidTargets","InvalidTargets" };
foreach(var keyword in keywords)
{
var temp = curNode.Value.Nodes.FirstOrDefault(n => n.Key == keyword);
if (temp != null)
newYaml.Add(new MiniYamlNode(keyword, temp.Value.Value));
}
newNodes.Add(new MiniYamlNode("Warhead@" + warheadCounter.ToString() + "Res" + oldNodeAtName, "DestroyResource", newYaml));
}
// CreateResource
if (curNode.Value.Nodes.Where(n => n.Key.Contains("AddsResourceType")).Any())
{
warheadCounter++;
var newYaml = new List<MiniYamlNode>();
var keywords = new List<String>{ "AddsResourceType","Size","Delay","ValidTargets","InvalidTargets" };
foreach(var keyword in keywords)
{
var temp = curNode.Value.Nodes.FirstOrDefault(n => n.Key == keyword);
if (temp != null)
newYaml.Add(new MiniYamlNode(keyword, temp.Value.Value));
}
newNodes.Add(new MiniYamlNode("Warhead@" + warheadCounter.ToString() + "Res" + oldNodeAtName, "CreateResource", newYaml));
}
// LeaveSmudge
if (curNode.Value.Nodes.Where(n => n.Key.Contains("SmudgeType")).Any())
{
warheadCounter++;
var newYaml = new List<MiniYamlNode>();
var keywords = new List<String>{ "SmudgeType","Size","Delay","ValidTargets","InvalidTargets" };
foreach(var keyword in keywords)
{
var temp = curNode.Value.Nodes.FirstOrDefault(n => n.Key == keyword);
if (temp != null)
newYaml.Add(new MiniYamlNode(keyword, temp.Value.Value));
}
newNodes.Add(new MiniYamlNode("Warhead@" + warheadCounter.ToString() + "Smu" + oldNodeAtName, "LeaveSmudge", newYaml));
}
// CreateEffect
if (curNode.Value.Nodes.Where(n => n.Key.Contains("Explosion") ||
n.Key.Contains("WaterExplosion") ||
n.Key.Contains("ImpactSound") ||
n.Key.Contains("WaterImpactSound")).Any())
{
warheadCounter++;
var newYaml = new List<MiniYamlNode>();
var keywords = new List<String>{ "Explosion","WaterExplosion","ImpactSound","WaterImpactSound","Delay","ValidTargets","InvalidTargets" };
foreach(var keyword in keywords)
{
var temp = curNode.Value.Nodes.FirstOrDefault(n => n.Key == keyword);
if (temp != null)
newYaml.Add(new MiniYamlNode(keyword, temp.Value.Value));
}
newNodes.Add(new MiniYamlNode("Warhead@" + warheadCounter.ToString() + "Eff" + oldNodeAtName, "CreateEffect", newYaml));
}
node.Value.Nodes.InsertRange(node.Value.Nodes.IndexOf(curNode),newNodes);
node.Value.Nodes.Remove(curNode);
}
}
}
}
UpgradeWeaponRules(engineVersion, ref node.Value.Nodes, node, depth + 1); UpgradeWeaponRules(engineVersion, ref node.Value.Nodes, node, depth + 1);
} }
} }

View File

@@ -535,10 +535,10 @@ VoxelSequences:
Weapons: Weapons:
BoatMissile: BoatMissile:
Warhead: Warhead: SpreadDamage
Versus: Versus:
Heavy: 50% Heavy: 50%
Damage: 50 Damage: 50
Voices: Voices:

View File

@@ -572,7 +572,7 @@ VoxelSequences:
Weapons: Weapons:
Tiberium: Tiberium:
Warhead: Warhead: SpreadDamage
Damage: 6 Damage: 6
Voices: Voices:

View File

@@ -653,7 +653,7 @@ VoxelSequences:
Weapons: Weapons:
Tiberium: Tiberium:
Warhead: Warhead: SpreadDamage
Damage: 4 Damage: 4
Voices: Voices:

View File

@@ -913,7 +913,7 @@ VoxelSequences:
Weapons: Weapons:
Rockets: Rockets:
Warhead: Warhead: SpreadDamage
Versus: Versus:
None: 20% None: 20%

File diff suppressed because it is too large Load Diff

View File

@@ -8,16 +8,17 @@ LMG:
TrailInterval: 1 TrailInterval: 1
ContrailDelay: 0 ContrailDelay: 0
ContrailUsePlayerColor: true ContrailUsePlayerColor: true
Warhead: Warhead@1Dam: SpreadDamage
Spread: 96 Spread: 96
Damage: 15
InfDeath: 2
Versus: Versus:
Wood: 25% Wood: 25%
Light: 40% Light: 40%
Heavy: 10% Heavy: 10%
Concrete: 20% Concrete: 20%
Warhead@2Eff: CreateEffect
Explosion: piffs Explosion: piffs
InfDeath: 2
Damage: 15
Bazooka: Bazooka:
ROF: 50 ROF: 50
@@ -32,18 +33,20 @@ Bazooka:
Image: RPG Image: RPG
ROT: 5 ROT: 5
RangeLimit: 35 RangeLimit: 35
Warhead: Warhead@1Dam: SpreadDamage
Spread: 96 Spread: 96
Damage: 50
InfDeath: 4
Versus: Versus:
None: 10% None: 10%
Wood: 75% Wood: 75%
Light: 60% Light: 60%
Heavy: 90% Heavy: 90%
Concrete: 40% Concrete: 40%
Explosion: small_explosion Warhead@2Smu: LeaveSmudge
InfDeath: 4
SmudgeType: SandCrater, RockCrater SmudgeType: SandCrater, RockCrater
Damage: 50 Warhead@3Eff: CreateEffect
Explosion: small_explosion
ImpactSound: EXPLSML1.WAV ImpactSound: EXPLSML1.WAV
Sniper: Sniper:
@@ -56,16 +59,16 @@ Sniper:
TrailInterval: 1 TrailInterval: 1
ContrailDelay: 0 ContrailDelay: 0
ContrailUsePlayerColor: true ContrailUsePlayerColor: true
Warhead: Warhead@1Dam: SpreadDamage
Damage: 60
Spread: 32 Spread: 32
Damage: 60
InfDeath: 2
Versus: Versus:
None: 100% None: 100%
Wood: 0% Wood: 0%
Light: 1% Light: 1%
Heavy: 0% Heavy: 0%
Concrete: 0% Concrete: 0%
InfDeath: 2
Vulcan: Vulcan:
ROF: 30 ROF: 30
@@ -78,16 +81,17 @@ Vulcan:
TrailInterval: 1 TrailInterval: 1
ContrailDelay: 0 ContrailDelay: 0
ContrailUsePlayerColor: true ContrailUsePlayerColor: true
Warhead: Warhead@1Dam: SpreadDamage
Spread: 96 Spread: 96
Damage: 30
InfDeath: 2
Versus: Versus:
Wood: 0% Wood: 0%
Light: 60% Light: 60%
Heavy: 10% Heavy: 10%
Concrete: 0% Concrete: 0%
Warhead@2Eff: CreateEffect
Explosion: piffs Explosion: piffs
InfDeath: 2
Damage: 30
Slung: Slung:
ROF: 60 ROF: 60
@@ -102,17 +106,18 @@ Slung:
Angle: 88 Angle: 88
Inaccuracy: 384 Inaccuracy: 384
Image: MISSILE Image: MISSILE
Warhead: Warhead@1Dam: SpreadDamage
Spread: 192 Spread: 192
Damage: 30
InfDeath: 4
Versus: Versus:
None: 0% None: 0%
Wood: 75% Wood: 75%
Light: 40% Light: 40%
Heavy: 90% Heavy: 90%
Concrete: 50% Concrete: 50%
Warhead@2Eff: CreateEffect
Explosion: small_explosion Explosion: small_explosion
InfDeath: 4
Damage: 30
ImpactSound: EXPLLG5.WAV ImpactSound: EXPLLG5.WAV
HMG: HMG:
@@ -127,16 +132,17 @@ HMG:
TrailInterval: 1 TrailInterval: 1
ContrailDelay: 0 ContrailDelay: 0
ContrailUsePlayerColor: true ContrailUsePlayerColor: true
Warhead: Warhead@1Dam: SpreadDamage
Spread: 96 Spread: 96
Damage: 30
InfDeath: 2
Versus: Versus:
Wood: 15% Wood: 15%
Light: 45% Light: 45%
Heavy: 20% Heavy: 20%
Concrete: 20% Concrete: 20%
Warhead@2Eff: CreateEffect
Explosion: piffs Explosion: piffs
InfDeath: 2
Damage: 30
HMGo: HMGo:
ROF: 30 ROF: 30
@@ -150,16 +156,17 @@ HMGo:
TrailInterval: 1 TrailInterval: 1
ContrailDelay: 0 ContrailDelay: 0
ContrailUsePlayerColor: true ContrailUsePlayerColor: true
Warhead: Warhead@1Dam: SpreadDamage
Spread: 96 Spread: 96
Damage: 40
InfDeath: 2
Versus: Versus:
Wood: 15% Wood: 15%
Light: 45% Light: 45%
Heavy: 25% Heavy: 25%
Concrete: 20% Concrete: 20%
Warhead@2Eff: CreateEffect
Explosion: piffs Explosion: piffs
InfDeath: 2
Damage: 40
QuadRockets: QuadRockets:
ROF: 40 ROF: 40
@@ -175,19 +182,21 @@ QuadRockets:
ROT: 10 ROT: 10
Speed: 256 Speed: 256
RangeLimit: 40 RangeLimit: 40
Warhead: Warhead@1Dam: SpreadDamage
Spread: 96 Spread: 96
Damage: 25
InfDeath: 4
Versus: Versus:
None: 35% None: 35%
Wood: 45% Wood: 45%
Light: 100% Light: 100%
Heavy: 100% Heavy: 100%
Concrete: 35% Concrete: 35%
InfDeath: 4 Warhead@2Smu: LeaveSmudge
SmudgeType: SandCrater, RockCrater
Warhead@3Eff: CreateEffect
Explosion: med_explosion Explosion: med_explosion
ImpactSound: EXPLSML1.WAV ImpactSound: EXPLSML1.WAV
SmudgeType: SandCrater, RockCrater
Damage: 25
TurretGun: TurretGun:
ROF: 35 ROF: 35
@@ -199,18 +208,20 @@ TurretGun:
Shadow: no Shadow: no
Inaccuracy: 288 Inaccuracy: 288
Image: 120mm Image: 120mm
Warhead: Warhead@1Dam: SpreadDamage
Spread: 256 Spread: 256
Damage: 55
InfDeath: 4
Versus: Versus:
None: 50% None: 50%
Wood: 75% Wood: 75%
Light: 100% Light: 100%
Concrete: 65% Concrete: 65%
Warhead@2Smu: LeaveSmudge
SmudgeType: SandCrater, RockCrater
Warhead@3Eff: CreateEffect
Explosion: small_napalm Explosion: small_napalm
ImpactSound: EXPLSML4.WAV ImpactSound: EXPLSML4.WAV
InfDeath: 4
SmudgeType: SandCrater, RockCrater
Damage: 55
TowerMissile: TowerMissile:
ROF: 35 ROF: 35
@@ -230,19 +241,21 @@ TowerMissile:
Speed: 256 Speed: 256
RangeLimit: 50 RangeLimit: 50
Angle: 110 Angle: 110
Warhead: Warhead@1Dam: SpreadDamage
Spread: 384 Spread: 384
Damage: 50
InfDeath: 3
Versus: Versus:
None: 50% None: 50%
Wood: 45% Wood: 45%
Light: 100% Light: 100%
Heavy: 50% Heavy: 50%
Concrete: 35% Concrete: 35%
InfDeath: 3 Warhead@2Smu: LeaveSmudge
SmudgeType: SandCrater, RockCrater
Warhead@3Eff: CreateEffect
Explosion: small_explosion Explosion: small_explosion
ImpactSound: EXPLMD1.WAV ImpactSound: EXPLMD1.WAV
SmudgeType: SandCrater, RockCrater
Damage: 50
90mm: 90mm:
ROF: 50 ROF: 50
@@ -252,18 +265,20 @@ TowerMissile:
Speed: 640 Speed: 640
Inaccuracy: 384 Inaccuracy: 384
Image: 120mm Image: 120mm
Warhead: Warhead@1Dam: SpreadDamage
Spread: 256 Spread: 256
Damage: 40
InfDeath: 4
Versus: Versus:
None: 50% None: 50%
Wood: 50% Wood: 50%
Light: 100% Light: 100%
Concrete: 50% Concrete: 50%
Warhead@2Smu: LeaveSmudge
SmudgeType: SandCrater, RockCrater
Warhead@3Eff: CreateEffect
Explosion: small_napalm Explosion: small_napalm
ImpactSound: EXPLSML4.WAV ImpactSound: EXPLSML4.WAV
InfDeath: 4
SmudgeType: SandCrater, RockCrater
Damage: 40
90mma: 90mma:
ROF: 50 ROF: 50
@@ -273,18 +288,20 @@ TowerMissile:
Speed: 704 Speed: 704
Inaccuracy: 352 Inaccuracy: 352
Image: 120mm Image: 120mm
Warhead: Warhead@1Dam: SpreadDamage
Spread: 256 Spread: 256
Damage: 40
InfDeath: 4
Versus: Versus:
None: 50% None: 50%
Wood: 50% Wood: 50%
Light: 100% Light: 100%
Concrete: 50% Concrete: 50%
Warhead@2Smu: LeaveSmudge
SmudgeType: SandCrater, RockCrater
Warhead@3Eff: CreateEffect
Explosion: small_napalm Explosion: small_napalm
ImpactSound: EXPLSML4.WAV ImpactSound: EXPLSML4.WAV
InfDeath: 4
SmudgeType: SandCrater, RockCrater
Damage: 40
DevBullet: DevBullet:
ROF: 50 ROF: 50
@@ -293,18 +310,20 @@ DevBullet:
Projectile: Bullet Projectile: Bullet
Speed: 640 Speed: 640
Image: doubleblastbullet Image: doubleblastbullet
Warhead: Warhead@1Dam: SpreadDamage
Spread: 256 Spread: 256
Damage: 100
InfDeath: 4
Versus: Versus:
None: 100% None: 100%
Wood: 50% Wood: 50%
Light: 100% Light: 100%
Heavy: 100% Heavy: 100%
Concrete: 80% Concrete: 80%
Explosion: shockwave Warhead@2Smu: LeaveSmudge
InfDeath: 4
SmudgeType: SandCrater, RockCrater SmudgeType: SandCrater, RockCrater
Damage: 100 Warhead@3Eff: CreateEffect
Explosion: shockwave
227mm: 227mm:
ROF: 100 ROF: 100
@@ -324,19 +343,21 @@ DevBullet:
Image: MISSILE2 Image: MISSILE2
ROT: 5 ROT: 5
ContrailLength: 5 ContrailLength: 5
Warhead: Warhead@1Dam: SpreadDamage
Spread: 384 Spread: 384
Damage: 60
InfDeath: 4
Versus: Versus:
None: 20% None: 20%
Wood: 50% Wood: 50%
Light: 100% Light: 100%
Heavy: 50% Heavy: 50%
Concrete: 80% Concrete: 80%
InfDeath: 4 Warhead@2Smu: LeaveSmudge
SmudgeType: SandCrater, RockCrater
Warhead@3Eff: CreateEffect
Explosion: mini_explosion Explosion: mini_explosion
ImpactSound: EXPLMD3.WAV ImpactSound: EXPLMD3.WAV
SmudgeType: SandCrater, RockCrater
Damage: 60
FakeMissile: FakeMissile:
ROF: 120 ROF: 120
@@ -352,15 +373,17 @@ FakeMissile:
Image: MISSILE Image: MISSILE
ContrailLength: 15 ContrailLength: 15
ContrailUsePlayerColor: True ContrailUsePlayerColor: True
Warhead: Warhead@1Dam: SpreadDamage
Spread: 96 Spread: 96
Damage: 10
Versus: Versus:
None: 0% None: 0%
Wood: 0% Wood: 0%
Concrete: 0% Concrete: 0%
Explosion: deviator Warhead@2Smu: LeaveSmudge
SmudgeType: SandCrater, RockCrater SmudgeType: SandCrater, RockCrater
Damage: 10 Warhead@3Eff: CreateEffect
Explosion: deviator
ImpactSound: EXPLSML2.WAV ImpactSound: EXPLSML2.WAV
155mm: 155mm:
@@ -376,19 +399,21 @@ FakeMissile:
Inaccuracy: 1c256 Inaccuracy: 1c256
ContrailLength: 20 ContrailLength: 20
Image: 155mm Image: 155mm
Warhead: Warhead@1Dam: SpreadDamage
Spread: 384 Spread: 384
Damage: 100
InfDeath: 3
Versus: Versus:
None: 100% None: 100%
Wood: 80% Wood: 80%
Light: 75% Light: 75%
Heavy: 50% Heavy: 50%
Concrete: 100% Concrete: 100%
Warhead@2Smu: LeaveSmudge
SmudgeType: SandCrater, RockCrater
Warhead@3Eff: CreateEffect
Explosion: large_explosion Explosion: large_explosion
ImpactSound: EXPLLG3.WAV ImpactSound: EXPLLG3.WAV
InfDeath: 3
SmudgeType: SandCrater, RockCrater
Damage: 100
Sound: Sound:
ROF: 100 ROF: 100
@@ -399,15 +424,15 @@ Sound:
HitAnim: laserfire HitAnim: laserfire
BeamDuration: 8 BeamDuration: 8
UsePlayerColor: true UsePlayerColor: true
Warhead: Warhead@1Dam: SpreadDamage
Spread: 32 Spread: 32
Damage: 150
InfDeath: 6
Versus: Versus:
None: 60% None: 60%
Wood: 85% Wood: 85%
Light: 80% Light: 80%
Concrete: 75% Concrete: 75%
InfDeath: 6
Damage: 150
ChainGun: ChainGun:
ROF: 10 ROF: 10
@@ -417,16 +442,17 @@ ChainGun:
Projectile: Bullet Projectile: Bullet
Speed: 1c256 Speed: 1c256
High: true High: true
Warhead: Warhead@1Dam: SpreadDamage
Spread: 96 Spread: 96
Damage: 20
InfDeath: 2
Versus: Versus:
Wood: 50% Wood: 50%
Light: 60% Light: 60%
Heavy: 25% Heavy: 25%
Concrete: 25% Concrete: 25%
Warhead@2Eff: CreateEffect
Explosion: piffs Explosion: piffs
InfDeath: 2
Damage: 20
Heal: Heal:
ROF: 160 ROF: 160
@@ -434,26 +460,26 @@ Heal:
Report: Report:
Projectile: Bullet Projectile: Bullet
Speed: 1c256 Speed: 1c256
Warhead: Warhead@1Dam: SpreadDamage
Spread: 160 Spread: 160
Damage: -50
InfDeath: 1
Versus: Versus:
Wood: 0% Wood: 0%
Light: 0% Light: 0%
Heavy: 0% Heavy: 0%
Concrete: 0% Concrete: 0%
InfDeath: 1
Damage: -50
WormJaw: WormJaw:
ROF: 10 ROF: 10
Range: 3c0 Range: 3c0
Report: WORM.WAV Report: WORM.WAV
Warhead: Warhead@1Dam: SpreadDamage
Spread: 160 Spread: 160
Damage: 100
Versus: Versus:
Wood: 0% Wood: 0%
Concrete: 0% Concrete: 0%
Damage: 100
ParaBomb: ParaBomb:
ROF: 10 ROF: 10
@@ -461,17 +487,19 @@ ParaBomb:
Report: Report:
Projectile: GravityBomb Projectile: GravityBomb
Image: BOMBS Image: BOMBS
Warhead: Warhead@1Dam: SpreadDamage
Spread: 192 Spread: 192
Damage: 500
InfDeath: 4
Versus: Versus:
None: 30% None: 30%
Wood: 75% Wood: 75%
Light: 75% Light: 75%
Concrete: 50% Concrete: 50%
Explosion: self_destruct Warhead@2Smu: LeaveSmudge
InfDeath: 4
SmudgeType: Crater SmudgeType: Crater
Damage: 500 Warhead@3Eff: CreateEffect
Explosion: self_destruct
ImpactSound: EXPLLG3.WAV ImpactSound: EXPLLG3.WAV
Napalm: Napalm:
@@ -479,121 +507,132 @@ Napalm:
Range: 3c0 Range: 3c0
Projectile: GravityBomb Projectile: GravityBomb
Image: BOMBS Image: BOMBS
Warhead: Warhead@1Dam: SpreadDamage
Spread: 640 Spread: 640
Damage: 300
InfDeath: 4
Versus: Versus:
None: 20% None: 20%
Wood: 100% Wood: 100%
Light: 30% Light: 30%
Heavy: 20% Heavy: 20%
Concrete: 70% Concrete: 70%
InfDeath: 4 Warhead@2Smu: LeaveSmudge
SmudgeType: Crater
Warhead@3Eff: CreateEffect
Explosion: artillery Explosion: artillery
ImpactSound: NAPALM1.WAV ImpactSound: NAPALM1.WAV
SmudgeType: Crater
Damage: 300
Crush: Crush:
Warhead: Warhead@1Dam: SpreadDamage
ImpactSound: CRUSH1.WAV
Damage: 100 Damage: 100
Warhead@2Eff: CreateEffect
ImpactSound: CRUSH1.WAV
Demolish: Demolish:
Warhead: Warhead@1Dam: SpreadDamage
ImpactSound: EXPLLG2.WAV Warhead@2Eff: CreateEffect
Explosion: building Explosion: building
ImpactSound: EXPLLG2.WAV
Atomic: Atomic:
Warhead: Warhead@1Dam: SpreadDamage
Damage: 1800
Spread: 2c0 Spread: 2c0
Damage: 1800
InfDeath: 5
Versus: Versus:
None: 100% None: 100%
Wood: 100% Wood: 100%
Light: 100% Light: 100%
Heavy: 50% Heavy: 50%
Concrete: 50% Concrete: 50%
Warhead@2Eff: CreateEffect
Explosion: nuke Explosion: nuke
InfDeath: 5
ImpactSound: EXPLLG2.WAV ImpactSound: EXPLLG2.WAV
CrateNuke: CrateNuke:
Warhead: Warhead@1Dam: SpreadDamage
Damage: 800
Spread: 1c576 Spread: 1c576
Damage: 800
InfDeath: 5
Versus: Versus:
None: 20% None: 20%
Wood: 75% Wood: 75%
Light: 25% Light: 25%
Heavy: 25% Heavy: 25%
Concrete: 50% Concrete: 50%
Warhead@2Eff: CreateEffect
Explosion: nuke Explosion: nuke
InfDeath: 5
ImpactSound: EXPLLG2.WAV ImpactSound: EXPLLG2.WAV
CrateExplosion: CrateExplosion:
Warhead: Warhead@1Dam: SpreadDamage
Damage: 400
Spread: 320 Spread: 320
Damage: 400
InfDeath: 4
Versus: Versus:
None: 90% None: 90%
Wood: 75% Wood: 75%
Light: 60% Light: 60%
Heavy: 25% Heavy: 25%
Warhead@2Eff: CreateEffect
Explosion: building Explosion: building
InfDeath: 4
ImpactSound: EXPLSML4.WAV ImpactSound: EXPLSML4.WAV
UnitExplode: UnitExplode:
Warhead: Warhead@1Dam: SpreadDamage
Damage: 500
Spread: 320 Spread: 320
Damage: 500
InfDeath: 4
Versus: Versus:
None: 90% None: 90%
Wood: 75% Wood: 75%
Light: 60% Light: 60%
Heavy: 25% Heavy: 25%
Warhead@2Eff: CreateEffect
Explosion: building Explosion: building
InfDeath: 4
ImpactSound: EXPLMD1.WAV ImpactSound: EXPLMD1.WAV
UnitExplodeSmall: UnitExplodeSmall:
Warhead: Warhead@1Dam: SpreadDamage
Damage: 60
Spread: 320 Spread: 320
Damage: 60
InfDeath: 4
Versus: Versus:
None: 90% None: 90%
Wood: 75% Wood: 75%
Light: 60% Light: 60%
Heavy: 25% Heavy: 25%
Warhead@2Eff: CreateEffect
Explosion: self_destruct Explosion: self_destruct
InfDeath: 4
ImpactSound: EXPLHG1.WAV, EXPLLG1.WAV, EXPLMD1.WAV, EXPLSML4.WAV ImpactSound: EXPLHG1.WAV, EXPLLG1.WAV, EXPLMD1.WAV, EXPLSML4.WAV
UnitExplodeTiny: UnitExplodeTiny:
Warhead: Warhead@1Dam: SpreadDamage
Damage: 30
Spread: 224 Spread: 224
Damage: 30
InfDeath: 4
Versus: Versus:
None: 90% None: 90%
Wood: 75% Wood: 75%
Light: 60% Light: 60%
Heavy: 25% Heavy: 25%
Warhead@2Eff: CreateEffect
Explosion: med_explosion Explosion: med_explosion
InfDeath: 4
ImpactSound: EXPLMD2.WAV, EXPLSML1.WAV, EXPLSML2.WAV, EXPLSML3.WAV ImpactSound: EXPLMD2.WAV, EXPLSML1.WAV, EXPLSML2.WAV, EXPLSML3.WAV
UnitExplodeScale: UnitExplodeScale:
Warhead: Warhead@1Dam: SpreadDamage
Damage: 90
Spread: 416 Spread: 416
Damage: 90
InfDeath: 4
Versus: Versus:
None: 90% None: 90%
Wood: 75% Wood: 75%
Light: 60% Light: 60%
Heavy: 25% Heavy: 25%
Warhead@2Eff: CreateEffect
Explosion: building Explosion: building
InfDeath: 4
ImpactSound: EXPLLG2.WAV, EXPLLG3.WAV, EXPLLG5.WAV ImpactSound: EXPLLG2.WAV, EXPLLG3.WAV, EXPLLG5.WAV
Grenade: Grenade:
@@ -606,22 +645,24 @@ Grenade:
Angle: 62 Angle: 62
Inaccuracy: 416 Inaccuracy: 416
Image: BOMBS Image: BOMBS
Warhead: Warhead@1Dam: SpreadDamage
Spread: 192 Spread: 192
Damage: 60
InfDeath: 3
Versus: Versus:
None: 50% None: 50%
Wood: 100% Wood: 100%
Light: 25% Light: 25%
Heavy: 5% Heavy: 5%
Explosion: med_explosion Warhead@2Smu: LeaveSmudge
InfDeath: 3
SmudgeType: SandCrater SmudgeType: SandCrater
Damage: 60 Warhead@3Eff: CreateEffect
Explosion: med_explosion
ImpactSound: EXPLLG5.WAV ImpactSound: EXPLLG5.WAV
Weathering: Weathering:
ROF: 100 ROF: 100
Warhead: Warhead@1Dam: SpreadDamage
Damage: 5 Damage: 5
Shrapnel: Shrapnel:
@@ -634,31 +675,35 @@ Shrapnel:
Angle: 91, 264 Angle: 91, 264
Inaccuracy: 416 Inaccuracy: 416
Image: bombs Image: bombs
Warhead: Warhead@1Dam: SpreadDamage
Spread: 192 Spread: 192
Damage: 60
InfDeath: 3
Versus: Versus:
None: 50% None: 50%
Wood: 100% Wood: 100%
Light: 25% Light: 25%
Heavy: 5% Heavy: 5%
Explosion: med_explosion Warhead@2Smu: LeaveSmudge
InfDeath: 3
SmudgeType: SandCrater SmudgeType: SandCrater
Damage: 60 Warhead@3Eff: CreateEffect
Explosion: med_explosion
ImpactSound: EXPLLG5.WAV ImpactSound: EXPLLG5.WAV
SpiceExplosion: SpiceExplosion:
Warhead: Warhead@1Dam: SpreadDamage
Damage: 10
Spread: 9 Spread: 9
Size: 2,2 Damage: 10
InfDeath: 3
Versus: Versus:
None: 90% None: 90%
Wood: 75% Wood: 75%
Light: 60% Light: 60%
Heavy: 25% Heavy: 25%
Explosion: med_explosion Warhead@2Res: CreateResource
InfDeath: 3
ImpactSound: EXPLLG5.WAV
AddsResourceType: Spice AddsResourceType: Spice
Size: 2,2
Warhead@3Eff: CreateEffect
Explosion: med_explosion
ImpactSound: EXPLLG5.WAV

View File

@@ -615,7 +615,7 @@ Weapons:
Range: 5c0 Range: 5c0
ROF: 20 ROF: 20
Burst: 1 Burst: 1
Warhead: Warhead: SpreadDamage
Damage: 20 Damage: 20
Voices: Voices:

View File

@@ -951,7 +951,7 @@ Weapons:
Range: 5c0 Range: 5c0
ROF: 20 ROF: 20
Burst: 1 Burst: 1
Warhead: Warhead: SpreadDamage
Damage: 20 Damage: 20
Voices: Voices:

View File

@@ -364,7 +364,7 @@ Weapons:
PortaTesla: PortaTesla:
ROF: 20 ROF: 20
Range: 10c0 Range: 10c0
Warhead: Warhead: SpreadDamage
Spread: 42 Spread: 42
InfDeath: 5 InfDeath: 5
Damage: 80 Damage: 80

View File

@@ -313,20 +313,22 @@ Weapons:
Inaccuracy: 3c341 Inaccuracy: 3c341
Image: 120MM Image: 120MM
ContrailLength: 30 ContrailLength: 30
Warhead: Warhead: SpreadDamage
Spread: 128 Spread: 128
Versus: Versus:
None: 60% None: 60%
Wood: 75% Wood: 75%
Light: 60% Light: 60%
Heavy: 25% Heavy: 25%
InfDeath: 2
Damage: 250
Warhead@1Eff: CreateEffect
Explosion: large_explosion Explosion: large_explosion
WaterExplosion: large_splash WaterExplosion: large_splash
InfDeath: 2
SmudgeType: Crater
Damage: 250
ImpactSound: kaboom12.aud ImpactSound: kaboom12.aud
WaterImpactSound: splash9.aud WaterImpactSound: splash9.aud
Warhead@2Smu: LeaveSmudge
SmudgeType: Crater
SubMissile: SubMissile:
ROF: 250 ROF: 250
Range: 32c0 Range: 32c0
@@ -340,19 +342,21 @@ Weapons:
Image: MISSILE Image: MISSILE
Trail: smokey Trail: smokey
ContrailLength: 30 ContrailLength: 30
Warhead: Warhead: SpreadDamage
Spread: 426 Spread: 426
Versus: Versus:
None: 40% None: 40%
Light: 30% Light: 30%
Heavy: 30% Heavy: 30%
InfDeath: blownaway
Damage: 400
Warhead@1Eff: CreateEffect
Explosion: large_explosion Explosion: large_explosion
WaterExplosion: large_splash WaterExplosion: large_splash
InfDeath: blownaway
SmudgeType: Crater
Damage: 400
ImpactSound: kaboom12.aud ImpactSound: kaboom12.aud
WaterImpactSound: splash9.aud WaterImpactSound: splash9.aud
Warhead@2Smu: LeaveSmudge
SmudgeType: Crater
Voices: Voices:

View File

@@ -259,7 +259,7 @@ Weapons:
PortaTesla: PortaTesla:
ROF: 20 ROF: 20
Range: 10c0 Range: 10c0
Warhead: Warhead: SpreadDamage
Spread: 42 Spread: 42
InfDeath: 5 InfDeath: 5
Damage: 80 Damage: 80

View File

@@ -771,24 +771,26 @@ Weapons:
Inaccuracy: 1c682 Inaccuracy: 1c682
Image: 120MM Image: 120MM
ContrailLength: 50 ContrailLength: 50
Warhead: Warhead: SpreadDamage
Spread: 256 Spread: 256
Versus: Versus:
None: 75% None: 75%
Wood: 75% Wood: 75%
Light: 75% Light: 75%
Concrete: 100% Concrete: 100%
InfDeath: 4
Damage: 150
Warhead@2Smu: LeaveSmudge
SmudgeType: Crater
Warhead@3Eff: CreateEffect
Explosion: self_destruct Explosion: self_destruct
WaterExplosion: self_destruct WaterExplosion: self_destruct
InfDeath: 4
SmudgeType: Crater
Damage: 150
MammothTusk: MammothTusk:
ROF: 300 ROF: 300
Range: 10c0 Range: 10c0
Report: MISSILE6.AUD Report: MISSILE6.AUD
Burst: 2 Burst: 2
ValidTargets: Ground, Air ValidTargets: Ground, Air, Enemy, Neutral, Ally
Projectile: Missile Projectile: Missile
Speed: 128 Speed: 128
Arm: 2 Arm: 2
@@ -801,7 +803,7 @@ Weapons:
Image: DRAGON Image: DRAGON
ROT: 10 ROT: 10
RangeLimit: 80 RangeLimit: 80
Warhead: Warhead: SpreadDamage
Spread: 640 Spread: 640
Versus: Versus:
None: 125% None: 125%
@@ -809,16 +811,18 @@ Weapons:
Light: 110% Light: 110%
Heavy: 100% Heavy: 100%
Concrete: 200% Concrete: 200%
InfDeath: 3
Damage: 250
Warhead@2Smu: LeaveSmudge
SmudgeType: Crater
Warhead@3Eff: CreateEffect
Explosion: nuke Explosion: nuke
WaterExplosion: nuke WaterExplosion: nuke
InfDeath: 3
SmudgeType: Crater
Damage: 250
TankNapalm: TankNapalm:
ROF: 40 ROF: 40
Range: 8c0 Range: 8c0
Report: AACANON3.AUD Report: AACANON3.AUD
ValidTargets: Ground ValidTargets: Ground, Enemy, Neutral, Ally
Burst: 6 Burst: 6
BurstDelay: 1 BurstDelay: 1
Projectile: Bullet Projectile: Bullet
@@ -827,7 +831,7 @@ Weapons:
Inaccuracy: 2c512 Inaccuracy: 2c512
Trail: smokey Trail: smokey
ContrailLength: 2 ContrailLength: 2
Warhead: Warhead: SpreadDamage
Spread: 341 Spread: 341
Versus: Versus:
None: 90% None: 90%
@@ -835,31 +839,35 @@ Weapons:
Light: 100% Light: 100%
Heavy: 100% Heavy: 100%
Concrete: 100% Concrete: 100%
InfDeath: 4
Damage: 15
Warhead@2Smu: LeaveSmudge
SmudgeType: Scorch
Warhead@3Eff: CreateEffect
Explosion: small_explosion Explosion: small_explosion
WaterExplosion: small_explosion WaterExplosion: small_explosion
InfDeath: 4
SmudgeType: Scorch
ImpactSound: firebl3.aud ImpactSound: firebl3.aud
Damage: 15
ParaBomb: ParaBomb:
ROF: 5 ROF: 5
Range: 5c0 Range: 5c0
Report: CHUTE1.AUD Report: CHUTE1.AUD
Projectile: GravityBomb Projectile: GravityBomb
Image: BOMBLET Image: BOMBLET
Warhead: Warhead: SpreadDamage
Spread: 426 Spread: 426
Versus: Versus:
None: 125% None: 125%
Wood: 100% Wood: 100%
Light: 60% Light: 60%
Concrete: 25% Concrete: 25%
InfDeath: 5
Damage: 200
Warhead@2Smu: LeaveSmudge
SmudgeType: Crater
Warhead@3Eff: CreateEffect
Explosion: napalm Explosion: napalm
ImpactSound: firebl3.aud ImpactSound: firebl3.aud
WaterExplosion: napalm WaterExplosion: napalm
InfDeath: 5
SmudgeType: Crater
Damage: 200
155mm: 155mm:
ROF: 10 ROF: 10
Range: 7c5 Range: 7c5
@@ -874,7 +882,7 @@ Weapons:
Angle: 30 Angle: 30
Inaccuracy: 1c682 Inaccuracy: 1c682
ContrailLength: 2 ContrailLength: 2
Warhead: Warhead: SpreadDamage
Spread: 426 Spread: 426
Versus: Versus:
None: 80% None: 80%
@@ -882,21 +890,23 @@ Weapons:
Light: 60% Light: 60%
Heavy: 75% Heavy: 75%
Concrete: 35% Concrete: 35%
InfDeath: 5
Damage: 10
Warhead@2Smu: LeaveSmudge
SmudgeType: Scorch
Warhead@3Eff: CreateEffect
Explosion: small_napalm Explosion: small_napalm
WaterExplosion: small_napalm WaterExplosion: small_napalm
InfDeath: 5
SmudgeType: Scorch
ImpactSound: firebl3.aud ImpactSound: firebl3.aud
Damage: 10
FLAK-23: FLAK-23:
ROF: 10 ROF: 10
Range: 8c0 Range: 8c0
Report: AACANON3.AUD Report: AACANON3.AUD
ValidTargets: Air,Ground ValidTargets: Air, Ground, Enemy, Neutral, Ally
Projectile: Bullet Projectile: Bullet
Speed: 1c682 Speed: 1c682
High: true High: true
Warhead: Warhead: SpreadDamage
Spread: 213 Spread: 213
Versus: Versus:
None: 35% None: 35%
@@ -904,8 +914,11 @@ Weapons:
Light: 30% Light: 30%
Heavy: 40% Heavy: 40%
Concrete: 30% Concrete: 30%
Explosion: med_explosion
Damage: 25 Damage: 25
Warhead@2Smu: LeaveSmudge
SmudgeType: Scorch
Warhead@3Eff: CreateEffect
Explosion: med_explosion
SCUD: SCUD:
ROF: 280 ROF: 280
Range: 7c0 Range: 7c0
@@ -921,18 +934,20 @@ Weapons:
Inaccuracy: 426 Inaccuracy: 426
Image: V2 Image: V2
Angle: 216 Angle: 216
Warhead: Warhead: SpreadDamage
Spread: 853 Spread: 853
Versus: Versus:
None: 100% None: 100%
Wood: 90% Wood: 90%
Light: 80% Light: 80%
Heavy: 70% Heavy: 70%
InfDeath: 3
Damage: 500
Warhead@2Smu: LeaveSmudge
SmudgeType: Crater
Warhead@3Eff: CreateEffect
Explosion: nuke Explosion: nuke
WaterExplosion: large_splash WaterExplosion: large_splash
InfDeath: 3
SmudgeType: Crater
Damage: 500
ImpactSound: kaboom1.aud ImpactSound: kaboom1.aud
WaterImpactSound: kaboom1.aud WaterImpactSound: kaboom1.aud
SilencedPPK: SilencedPPK:
@@ -941,16 +956,17 @@ Weapons:
Report: silppk.aud Report: silppk.aud
Projectile: Bullet Projectile: Bullet
Speed: 1c682 Speed: 1c682
Warhead: Warhead: SpreadDamage
Spread: 128 Spread: 128
Versus: Versus:
Wood: 0% Wood: 0%
Light: 0% Light: 0%
Heavy: 50% Heavy: 50%
Concrete: 0% Concrete: 0%
Explosion: piffs
InfDeath: 2 InfDeath: 2
Damage: 150 Damage: 150
Warhead@2Eff: CreateEffect
Explosion: piffs
Voices: Voices:

View File

@@ -2333,7 +2333,7 @@ Weapons:
Nike: Nike:
Range: 9c0 Range: 9c0
Maverick: Maverick:
Warhead: Warhead: SpreadDamage
Damage: 175 Damage: 175
Voices: Voices:

View File

@@ -1076,12 +1076,10 @@ VoxelSequences:
Weapons: Weapons:
CrateNuke: CrateNuke:
Warhead@areanuke2: Warhead@areanuke2: SpreadDamage
DamageModel: PerCell DamageModel: PerCell
Damage: 250 Damage: 250
SmudgeType: Scorch Size: 4
Size: 4,3
Ore: true
Versus: Versus:
None: 90% None: 90%
Light: 60% Light: 60%
@@ -1089,13 +1087,21 @@ Weapons:
Concrete: 50% Concrete: 50%
Delay: 12 Delay: 12
InfDeath: 4 InfDeath: 4
Warhead@areanuke2Smu: LeaveSmudge
SmudgeType: Scorch
Size: 4,3
Delay: 12
Warhead@areanuke2Res: DestroyResource
DestroyResources: true
Size: 4,3
Delay: 12
Warhead@areanuke2Eff: CreateEffect
ImpactSound: kaboom22 ImpactSound: kaboom22
Warhead@areanuke3: Delay: 12
Warhead@areanuke3: SpreadDamage
DamageModel: PerCell DamageModel: PerCell
Damage: 250 Damage: 250
SmudgeType: Scorch Size: 3
Size: 3,2
Ore: true
Versus: Versus:
None: 90% None: 90%
Light: 60% Light: 60%
@@ -1103,13 +1109,20 @@ Weapons:
Concrete: 50% Concrete: 50%
Delay: 24 Delay: 24
InfDeath: 4 InfDeath: 4
Warhead@areanuke3Smu: LeaveSmudge
SmudgeType: Scorch
Size: 3,2
Delay: 24
Warhead@areanuke3Res: DestroyResource
DestroyResources: true
Size: 3,2
Delay: 24
Warhead@areanuke3Eff: CreateEffect
ImpactSound: kaboom22 ImpactSound: kaboom22
Warhead@areanuke4: Delay: 24
Warhead@areanuke4: SpreadDamage
DamageModel: PerCell DamageModel: PerCell
Damage: 250 Damage: 250
SmudgeType: Scorch
Size: 2,1
Ore: true
Versus: Versus:
None: 90% None: 90%
Light: 60% Light: 60%
@@ -1117,7 +1130,17 @@ Weapons:
Concrete: 50% Concrete: 50%
Delay: 36 Delay: 36
InfDeath: 4 InfDeath: 4
Warhead@areanuke4Smu: LeaveSmudge
SmudgeType: Scorch
Size: 2,1
Delay: 36
Warhead@areanuke4Res: DestroyResource
DestroyResources: true
Size: 2,1
Delay: 36
Warhead@areanuke4Eff: CreateEffect
ImpactSound: kaboom22 ImpactSound: kaboom22
Delay: 36
Voices: Voices:

File diff suppressed because it is too large Load Diff

View File

@@ -1,27 +1,29 @@
UnitExplode: UnitExplode:
Warhead: Warhead@1Dam: SpreadDamage
Damage: 500
Spread: 426 Spread: 426
Damage: 500
InfDeath: 2
Versus: Versus:
None: 90% None: 90%
Wood: 75% Wood: 75%
Light: 60% Light: 60%
Heavy: 25% Heavy: 25%
Warhead@2Eff: CreateEffect
Explosion: large_twlt Explosion: large_twlt
InfDeath: 2
ImpactSound: expnew09.aud ImpactSound: expnew09.aud
UnitExplodeSmall: UnitExplodeSmall:
Warhead: Warhead@1Dam: SpreadDamage
Damage: 40
Spread: 426 Spread: 426
Damage: 40
InfDeath: 2
Versus: Versus:
None: 90% None: 90%
Wood: 75% Wood: 75%
Light: 60% Light: 60%
Heavy: 25% Heavy: 25%
Warhead@2Eff: CreateEffect
Explosion: medium_brnl Explosion: medium_brnl
InfDeath: 2
ImpactSound: expnew13.aud ImpactSound: expnew13.aud
Minigun: Minigun:
@@ -30,17 +32,18 @@ Minigun:
Report: INFGUN3.AUD Report: INFGUN3.AUD
Projectile: Bullet Projectile: Bullet
Speed: 1c682 Speed: 1c682
Warhead: Warhead@1Dam: SpreadDamage
Spread: 128 Spread: 128
Damage: 12
InfDeath: 1
ProneModifier: 70
Versus: Versus:
Wood: 60% Wood: 60%
Light: 40% Light: 40%
Heavy: 25% Heavy: 25%
Concrete: 10% Concrete: 10%
Warhead@2Eff: CreateEffect
Explosion: piffpiff Explosion: piffpiff
InfDeath: 1
Damage: 12
ProneModifier: 70
Grenade: Grenade:
ROF: 60 ROF: 60
@@ -52,17 +55,18 @@ Grenade:
Angle: 62 Angle: 62
Inaccuracy: 554 Inaccuracy: 554
Image: DISCUS Image: DISCUS
Warhead: Warhead@1Dam: SpreadDamage
Spread: 171 Spread: 171
Damage: 40
InfDeath: 3
ProneModifier: 70
Versus: Versus:
None: 100% None: 100%
Wood: 85% Wood: 85%
Light: 70% Light: 70%
Heavy: 35% Heavy: 35%
Concrete: 28% Concrete: 28%
InfDeath: 3 Warhead@2Eff: CreateEffect
Damage: 40
ProneModifier: 70
Explosion: large_grey_explosion Explosion: large_grey_explosion
ImpactSound: expnew13.aud ImpactSound: expnew13.aud
@@ -81,16 +85,17 @@ Bazooka:
Image: DRAGON Image: DRAGON
ROT: 8 ROT: 8
RangeLimit: 35 RangeLimit: 35
Warhead: Warhead@1Dam: SpreadDamage
Spread: 128 Spread: 128
Damage: 25
InfDeath: 2
Versus: Versus:
None: 25% None: 25%
Wood: 65% Wood: 65%
Light: 75% Light: 75%
Heavy: 100% Heavy: 100%
Concrete: 60% Concrete: 60%
InfDeath: 2 Warhead@2Eff: CreateEffect
Damage: 25
Explosion: small_clsn Explosion: small_clsn
ImpactSound: expnew12.aud ImpactSound: expnew12.aud
@@ -109,16 +114,17 @@ MultiCluster:
Image: DRAGON Image: DRAGON
ROT: 8 ROT: 8
RangeLimit: 35 RangeLimit: 35
Warhead: Warhead@1Dam: SpreadDamage
Spread: 128 Spread: 128
Damage: 65
InfDeath: 3
Versus: Versus:
None: 25% None: 25%
Wood: 65% Wood: 65%
Light: 75% Light: 75%
Heavy: 100% Heavy: 100%
Concrete: 60% Concrete: 60%
InfDeath: 3 Warhead@2Eff: CreateEffect
Damage: 65
Explosion: large_explosion Explosion: large_explosion
ImpactSound: expnew09.aud ImpactSound: expnew09.aud
@@ -128,16 +134,16 @@ Heal:
Report: HEALER1.AUD Report: HEALER1.AUD
Projectile: Bullet Projectile: Bullet
Speed: 1c682 Speed: 1c682
Warhead: Warhead@1Dam: SpreadDamage
Spread: 213 Spread: 213
Damage: -50
InfDeath: 1
ProneModifier: 100
Versus: Versus:
Wood: 0% Wood: 0%
Light: 0% Light: 0%
Heavy: 0% Heavy: 0%
Concrete: 0% Concrete: 0%
InfDeath: 1
Damage: -50
ProneModifier: 100
Sniper: Sniper:
ROF: 60 ROF: 60
@@ -145,17 +151,17 @@ Sniper:
Report: SILENCER.AUD Report: SILENCER.AUD
Projectile: Bullet Projectile: Bullet
Speed: 1c682 Speed: 1c682
Warhead: Warhead@1Dam: SpreadDamage
Damage: 150
ProneModifier: 100
Spread: 42 Spread: 42
Damage: 150
InfDeath: 1
ProneModifier: 100
Versus: Versus:
None: 100% None: 100%
Wood: 0% Wood: 0%
Light: 0% Light: 0%
Heavy: 0% Heavy: 0%
Concrete: 0% Concrete: 0%
InfDeath: 1
M1Carbine: M1Carbine:
ROF: 20 ROF: 20
@@ -163,17 +169,18 @@ M1Carbine:
Report: INFGUN3.AUD Report: INFGUN3.AUD
Projectile: Bullet Projectile: Bullet
Speed: 1c682 Speed: 1c682
Warhead: Warhead@1Dam: SpreadDamage
Spread: 128 Spread: 128
Damage: 15
InfDeath: 1
ProneModifier: 70
Versus: Versus:
Wood: 60% Wood: 60%
Light: 40% Light: 40%
Heavy: 25% Heavy: 25%
Concrete: 10% Concrete: 10%
Warhead@2Eff: CreateEffect
Explosion: piffpiff Explosion: piffpiff
InfDeath: 1
Damage: 15
ProneModifier: 70
LtRail: LtRail:
ROF: 60 ROF: 60
@@ -184,17 +191,17 @@ LtRail:
BeamWidth: 1 BeamWidth: 1
BeamDuration: 10 BeamDuration: 10
Color: 200,0,128,255 Color: 200,0,128,255
Warhead: Warhead@1Dam: SpreadDamage
Damage: 150
ProneModifier: 100
Spread: 42 Spread: 42
Damage: 150
InfDeath: 2
ProneModifier: 100
Versus: Versus:
None: 100% None: 100%
Wood: 130% Wood: 130%
Light: 150% Light: 150%
Heavy: 110% Heavy: 110%
Concrete: 5% Concrete: 5%
InfDeath: 2
CyCannon: CyCannon:
ROF: 50 ROF: 50
@@ -206,17 +213,18 @@ CyCannon:
High: yes High: yes
Shadow: true Shadow: true
Image: TORPEDO Image: TORPEDO
Warhead: Warhead@1Dam: SpreadDamage
Spread: 256 Spread: 256
Damage: 120
InfDeath: 6
ProneModifier: 100
Versus: Versus:
None: 100% None: 100%
Wood: 65% Wood: 65%
Light: 75% Light: 75%
Heavy: 50% Heavy: 50%
Concrete: 40% Concrete: 40%
InfDeath: 6 Warhead@2Eff: CreateEffect
Damage: 120
ProneModifier: 100
Explosion: large_bang Explosion: large_bang
ImpactSound: expnew12.aud ImpactSound: expnew12.aud
@@ -227,17 +235,18 @@ Vulcan3:
Report: CYGUN1.AUD Report: CYGUN1.AUD
Projectile: Bullet Projectile: Bullet
Speed: 1c682 Speed: 1c682
Warhead: Warhead@1Dam: SpreadDamage
Spread: 128 Spread: 128
Damage: 10
InfDeath: 1
ProneModifier: 70
Versus: Versus:
Wood: 60% Wood: 60%
Light: 40% Light: 40%
Heavy: 25% Heavy: 25%
Concrete: 10% Concrete: 10%
Warhead@2Eff: CreateEffect
Explosion: piffpiff Explosion: piffpiff
InfDeath: 1
Damage: 10
ProneModifier: 70
Vulcan2: Vulcan2:
ROF: 50 ROF: 50
@@ -246,18 +255,19 @@ Vulcan2:
Report: TSGUN4.AUD Report: TSGUN4.AUD
Projectile: Bullet Projectile: Bullet
Speed: 1c682 Speed: 1c682
Warhead: Warhead@1Dam: SpreadDamage
Spread: 128 Spread: 128
Damage: 50
InfDeath: 1
ProneModifier: 70
Versus: Versus:
None: 100% None: 100%
Wood: 60% Wood: 60%
Light: 40% Light: 40%
Heavy: 25% Heavy: 25%
Concrete: 10% Concrete: 10%
Warhead@2Eff: CreateEffect
Explosion: piffpiff Explosion: piffpiff
InfDeath: 1
Damage: 50
ProneModifier: 70
Vulcan: Vulcan:
ROF: 60 ROF: 60
@@ -265,17 +275,18 @@ Vulcan:
Report: CHAINGN1.AUD Report: CHAINGN1.AUD
Projectile: Bullet Projectile: Bullet
Speed: 1c682 Speed: 1c682
Warhead: Warhead@1Dam: SpreadDamage
Spread: 128 Spread: 128
Damage: 20
InfDeath: 1
ProneModifier: 70
Versus: Versus:
Wood: 60% Wood: 60%
Light: 40% Light: 40%
Heavy: 25% Heavy: 25%
Concrete: 10% Concrete: 10%
Warhead@2Eff: CreateEffect
Explosion: piffpiff Explosion: piffpiff
InfDeath: 1
Damage: 20
ProneModifier: 70
FiendShard: FiendShard:
ROF: 30 ROF: 30
@@ -289,15 +300,15 @@ FiendShard:
Inaccuracy: 512 Inaccuracy: 512
Shadow: true Shadow: true
Angle: 88 Angle: 88
Warhead: Warhead@1Dam: SpreadDamage
Damage: 35
InfDeath: 1
ProneModifier: 100
Versus: Versus:
Wood: 60% Wood: 60%
Light: 40% Light: 40%
Heavy: 25% Heavy: 25%
Concrete: 10% Concrete: 10%
InfDeath: 1
Damage: 35
ProneModifier: 100
JumpCannon: JumpCannon:
ROF: 40 ROF: 40
@@ -306,17 +317,18 @@ JumpCannon:
Report: JUMPJET1.AUD Report: JUMPJET1.AUD
Projectile: Bullet Projectile: Bullet
Speed: 1c682 Speed: 1c682
Warhead: Warhead@1Dam: SpreadDamage
Spread: 128 Spread: 128
Damage: 15
InfDeath: 1
ProneModifier: 70
Versus: Versus:
Wood: 60% Wood: 60%
Light: 40% Light: 40%
Heavy: 25% Heavy: 25%
Concrete: 10% Concrete: 10%
Warhead@2Eff: CreateEffect
Explosion: piffpiff Explosion: piffpiff
InfDeath: 1
Damage: 15
ProneModifier: 70
HoverMissile: HoverMissile:
ROF: 68 ROF: 68
@@ -334,16 +346,17 @@ HoverMissile:
Image: DRAGON Image: DRAGON
ROT: 8 ROT: 8
RangeLimit: 35 RangeLimit: 35
Warhead: Warhead@1Dam: SpreadDamage
Spread: 128 Spread: 128
Damage: 30
InfDeath: 2
Versus: Versus:
None: 25% None: 25%
Wood: 65% Wood: 65%
Light: 75% Light: 75%
Heavy: 100% Heavy: 100%
Concrete: 60% Concrete: 60%
InfDeath: 2 Warhead@2Eff: CreateEffect
Damage: 30
Explosion: small_clsn Explosion: small_clsn
ImpactSound: expnew12.aud ImpactSound: expnew12.aud
@@ -359,16 +372,17 @@ HoverMissile:
Image: 120mm Image: 120mm
Shadow: true Shadow: true
Angle: 62 Angle: 62
Warhead: Warhead@1Dam: SpreadDamage
Spread: 128 Spread: 128
Damage: 50
InfDeath: 2
Versus: Versus:
None: 25% None: 25%
Wood: 65% Wood: 65%
Light: 75% Light: 75%
Heavy: 100% Heavy: 100%
Concrete: 60% Concrete: 60%
InfDeath: 2 Warhead@2Eff: CreateEffect
Damage: 50
Explosion: medium_clsn Explosion: medium_clsn
ImpactSound: expnew14.aud ImpactSound: expnew14.aud
@@ -388,17 +402,18 @@ MammothTusk:
ROT: 10 ROT: 10
Speed: 170 Speed: 170
RangeLimit: 35 RangeLimit: 35
Warhead: Warhead@1Dam: SpreadDamage
Spread: 171 Spread: 171
Damage: 40
InfDeath: 3
ProneModifier: 70
Versus: Versus:
None: 100% None: 100%
Wood: 85% Wood: 85%
Light: 70% Light: 70%
Heavy: 35% Heavy: 35%
Concrete: 28% Concrete: 28%
InfDeath: 3 Warhead@2Eff: CreateEffect
Damage: 40
ProneModifier: 70
Explosion: medium_bang Explosion: medium_bang
ImpactSound: expnew12.aud ImpactSound: expnew12.aud
@@ -408,17 +423,17 @@ Repair:
Report: REPAIR11.AUD Report: REPAIR11.AUD
Projectile: Bullet Projectile: Bullet
Speed: 1c682 Speed: 1c682
Warhead: Warhead@1Dam: SpreadDamage
Spread: 213 Spread: 213
Damage: -50
InfDeath: 1
ProneModifier: 100
Versus: Versus:
None: 0% None: 0%
Wood: 0% Wood: 0%
Light: 100% Light: 100%
Heavy: 100% Heavy: 100%
Concrete: 0% Concrete: 0%
InfDeath: 1
Damage: -50
ProneModifier: 100
SlimeAttack: SlimeAttack:
ROF: 80 ROF: 80
@@ -427,30 +442,30 @@ SlimeAttack:
Report: VICER1.AUD Report: VICER1.AUD
Projectile: Bullet Projectile: Bullet
Speed: 426 Speed: 426
Warhead: Warhead@1Dam: SpreadDamage
Damage: 100
InfDeath: 2
ProneModifier: 100
Versus: Versus:
Wood: 25% Wood: 25%
Light: 30% Light: 30%
Heavy: 10% Heavy: 10%
Concrete: 10% Concrete: 10%
InfDeath: 2
Damage: 100
ProneModifier: 100
SuicideBomb: SuicideBomb:
ROF: 1 ROF: 1
Range: 0c512 Range: 0c512
Report: HUNTER2.AUD Report: HUNTER2.AUD
Warhead: Warhead@1Dam: SpreadDamage
Damage: 11000
Spread: 256 Spread: 256
DestroyResources: true Damage: 11000
InfDeath: 5
Versus: Versus:
None: 90% None: 90%
Light: 60% Light: 60%
Heavy: 25% Heavy: 25%
Concrete: 50% Concrete: 50%
InfDeath: 5 Warhead@2Res: DestroyResource
120mm: 120mm:
ROF: 80 ROF: 80
@@ -458,16 +473,17 @@ SuicideBomb:
Report: 120MMF.AUD Report: 120MMF.AUD
Projectile: Bullet Projectile: Bullet
Speed: 1c512 Speed: 1c512
Warhead: Warhead@1Dam: SpreadDamage
Spread: 128 Spread: 128
Damage: 70
InfDeath: 2
Versus: Versus:
None: 25% None: 25%
Wood: 65% Wood: 65%
Light: 75% Light: 75%
Heavy: 100% Heavy: 100%
Concrete: 60% Concrete: 60%
InfDeath: 2 Warhead@2Eff: CreateEffect
Damage: 70
Explosion: large_clsn Explosion: large_clsn
ImpactSound: expnew14.aud ImpactSound: expnew14.aud
@@ -480,17 +496,17 @@ MechRailgun:
Projectile: LaserZap Projectile: LaserZap
Color: 200,0,255,255 Color: 200,0,255,255
BeamWidth: 3 BeamWidth: 3
Warhead: Warhead@1Dam: SpreadDamage
Spread: 42 Spread: 42
Damage: 200
InfDeath: 5
ProneModifier: 100
Versus: Versus:
None: 200% None: 200%
Wood: 175% Wood: 175%
Light: 160% Light: 160%
Heavy: 100% Heavy: 100%
Concrete: 25% Concrete: 25%
InfDeath: 5
Damage: 200
ProneModifier: 100
AssaultCannon: AssaultCannon:
ROF: 50 ROF: 50
@@ -498,17 +514,18 @@ AssaultCannon:
Report: TSGUN4.AUD Report: TSGUN4.AUD
Projectile: Bullet Projectile: Bullet
Speed: 1c682 Speed: 1c682
Warhead: Warhead@1Dam: SpreadDamage
Spread: 128 Spread: 128
Damage: 40
InfDeath: 1
ProneModifier: 70
Versus: Versus:
Wood: 60% Wood: 60%
Light: 40% Light: 40%
Heavy: 25% Heavy: 25%
Concrete: 10% Concrete: 10%
Warhead@2Eff: CreateEffect
Explosion: piffpiff Explosion: piffpiff
InfDeath: 1
Damage: 40
ProneModifier: 70
BikeMissile: BikeMissile:
ROF: 60 ROF: 60
@@ -527,38 +544,40 @@ BikeMissile:
ROT: 8 ROT: 8
Speed: 213 Speed: 213
RangeLimit: 35 RangeLimit: 35
Warhead: Warhead@1Dam: SpreadDamage
Spread: 256 Spread: 256
Damage: 40
InfDeath: 2
Versus: Versus:
None: 25% None: 25%
Wood: 65% Wood: 65%
Light: 75% Light: 75%
Heavy: 100% Heavy: 100%
Concrete: 60% Concrete: 60%
InfDeath: 2 Warhead@2Eff: CreateEffect
Damage: 40
Explosion: small_clsn Explosion: small_clsn
ImpactSound: expnew12.aud ImpactSound: expnew12.aud
RaiderCannon: RaiderCannon:
ROF: 55 ROF: 55
Range: 4c0 Range: 4c0
Burst: 2 #purely cosmetical, for alternate muzzle position Burst: 2
BurstDelay: 55 BurstDelay: 55
Report: CHAINGN1.AUD Report: CHAINGN1.AUD
Projectile: Bullet Projectile: Bullet
Speed: 1c682 Speed: 1c682
Warhead: Warhead@1Dam: SpreadDamage
Spread: 128 Spread: 128
Damage: 40
InfDeath: 1
ProneModifier: 70
Versus: Versus:
Wood: 60% Wood: 60%
Light: 40% Light: 40%
Heavy: 25% Heavy: 25%
Concrete: 10% Concrete: 10%
Warhead@2Eff: CreateEffect
Explosion: piffpiff Explosion: piffpiff
InfDeath: 1
Damage: 40
ProneModifier: 70
FireballLauncher: FireballLauncher:
ROF: 50 ROF: 50
@@ -570,17 +589,17 @@ FireballLauncher:
Inacuracy: 384 Inacuracy: 384
Burst: 5 Burst: 5
BurstDelay: 5 BurstDelay: 5
Warhead: Warhead@1Dam: SpreadDamage
Spread: 341 Spread: 341
Damage: 25
InfDeath: 5
ProneModifier: 100
Versus: Versus:
None: 600% None: 600%
Wood: 148% Wood: 148%
Light: 59% Light: 59%
Heavy: 6% Heavy: 6%
Concrete: 2% Concrete: 2%
InfDeath: 5
Damage: 25
ProneModifier: 100
SonicZap: SonicZap:
ROF: 120 ROF: 120
@@ -591,13 +610,13 @@ SonicZap:
Color: 200,0,255,255 Color: 200,0,255,255
BeamWidth: 12 BeamWidth: 12
BeamDuration: 50 BeamDuration: 50
Warhead: Warhead@1Dam: SpreadDamage
Spread: 42 Spread: 42
Damage: 100
InfDeath: 5
Versus: Versus:
Heavy: 80% Heavy: 80%
Concrete: 60% Concrete: 60%
InfDeath: 5
Damage: 100
Dragon: Dragon:
ROF: 50 ROF: 50
@@ -615,16 +634,17 @@ Dragon:
Image: DRAGON Image: DRAGON
ROT: 8 ROT: 8
RangeLimit: 35 RangeLimit: 35
Warhead: Warhead@1Dam: SpreadDamage
Spread: 128 Spread: 128
Damage: 30
InfDeath: 2
Versus: Versus:
None: 25% None: 25%
Wood: 65% Wood: 65%
Light: 75% Light: 75%
Heavy: 100% Heavy: 100%
Concrete: 60% Concrete: 60%
InfDeath: 2 Warhead@2Eff: CreateEffect
Damage: 30
Explosion: small_clsn Explosion: small_clsn
ImpactSound: expnew12.aud ImpactSound: expnew12.aud
@@ -638,16 +658,17 @@ Dragon:
Image: 120mm Image: 120mm
Shadow: true Shadow: true
Angle: 62 Angle: 62
Warhead: Warhead@1Dam: SpreadDamage
Spread: 128 Spread: 128
Damage: 36
InfDeath: 2
Versus: Versus:
None: 25% None: 25%
Wood: 65% Wood: 65%
Light: 75% Light: 75%
Heavy: 100% Heavy: 100%
Concrete: 60% Concrete: 60%
InfDeath: 2 Warhead@2Eff: CreateEffect
Damage: 36
Explosion: medium_clsn Explosion: medium_clsn
ImpactSound: expnew14.aud ImpactSound: expnew14.aud
@@ -663,17 +684,18 @@ Dragon:
Shadow: true Shadow: true
High: yes High: yes
MinRange: 5c0 MinRange: 5c0
Warhead: Warhead@1Dam: SpreadDamage
Spread: 298 Spread: 298
Damage: 150
InfDeath: 3
ProneModifier: 100
Versus: Versus:
None: 100% None: 100%
Wood: 85% Wood: 85%
Light: 68% Light: 68%
Heavy: 35% Heavy: 35%
Concrete: 35% Concrete: 35%
InfDeath: 3 Warhead@2Eff: CreateEffect
Damage: 150
ProneModifier: 100
Explosion: large_explosion Explosion: large_explosion
ImpactSound: expnew09.aud ImpactSound: expnew09.aud
@@ -693,16 +715,17 @@ Hellfire:
Image: DRAGON Image: DRAGON
ROT: 8 ROT: 8
RangeLimit: 35 RangeLimit: 35
Warhead: Warhead@1Dam: SpreadDamage
Spread: 85 Spread: 85
Damage: 30
InfDeath: 2
Versus: Versus:
None: 30% None: 30%
Wood: 65% Wood: 65%
Light: 150% Light: 150%
Heavy: 100% Heavy: 100%
Concrete: 30% Concrete: 30%
InfDeath: 2 Warhead@2Eff: CreateEffect
Damage: 30
Explosion: small_bang Explosion: small_bang
ImpactSound: expnew12.aud ImpactSound: expnew12.aud
@@ -714,17 +737,18 @@ Bomb:
Speed: 170 Speed: 170
Image: canister Image: canister
Shadow: true Shadow: true
Warhead: Warhead@1Dam: SpreadDamage
Spread: 298 Spread: 298
Damage: 160
InfDeath: 3
ProneModifier: 100
Versus: Versus:
None: 200% None: 200%
Wood: 90% Wood: 90%
Light: 75% Light: 75%
Heavy: 32% Heavy: 32%
Concrete: 100% Concrete: 100%
InfDeath: 3 Warhead@2Eff: CreateEffect
Damage: 160
ProneModifier: 100
Explosion: large_explosion Explosion: large_explosion
ImpactSound: expnew09.aud ImpactSound: expnew09.aud
@@ -743,16 +767,17 @@ Proton:
Image: TORPEDO Image: TORPEDO
ROT: 1 ROT: 1
RangeLimit: 35 RangeLimit: 35
Warhead: Warhead@1Dam: SpreadDamage
Spread: 128 Spread: 128
Damage: 20
InfDeath: 3
Versus: Versus:
None: 25% None: 25%
Wood: 65% Wood: 65%
Light: 75% Light: 75%
Heavy: 100% Heavy: 100%
Concrete: 60% Concrete: 60%
InfDeath: 3 Warhead@2Eff: CreateEffect
Damage: 20
Explosion: small_bang Explosion: small_bang
ImpactSound: expnew12.aud ImpactSound: expnew12.aud
@@ -763,17 +788,18 @@ HarpyClaw:
Projectile: Bullet Projectile: Bullet
Speed: 1c682 Speed: 1c682
ValidTargets: Ground, Air ValidTargets: Ground, Air
Warhead: Warhead@1Dam: SpreadDamage
Spread: 128 Spread: 128
Damage: 60
InfDeath: 1
ProneModifier: 70
Versus: Versus:
Wood: 60% Wood: 60%
Light: 40% Light: 40%
Heavy: 25% Heavy: 25%
Concrete: 10% Concrete: 10%
Warhead@2Eff: CreateEffect
Explosion: piffpiff Explosion: piffpiff
InfDeath: 1
Damage: 60
ProneModifier: 70
Pistola: Pistola:
ROF: 20 ROF: 20
@@ -781,49 +807,57 @@ Pistola:
Report: GUN18.AUD Report: GUN18.AUD
Projectile: Bullet Projectile: Bullet
Speed: 1c682 Speed: 1c682
Warhead: Warhead@1Dam: SpreadDamage
Spread: 128 Spread: 128
Damage: 2
InfDeath: 1
ProneModifier: 70
Versus: Versus:
Wood: 60% Wood: 60%
Light: 40% Light: 40%
Heavy: 25% Heavy: 25%
Concrete: 10% Concrete: 10%
Warhead@2Eff: CreateEffect
Explosion: piff Explosion: piff
InfDeath: 1
Damage: 2
ProneModifier: 70
Tiberium: Tiberium:
ROF: 16 ROF: 16
Warhead: Warhead@1Dam: SpreadDamage
Spread: 42 Spread: 42
InfDeath: 6
Damage: 2 Damage: 2
InfDeath: 6
PreventProne: yes PreventProne: yes
TiberiumHeal: TiberiumHeal:
ROF: 16 ROF: 16
Warhead: Warhead@1Dam: SpreadDamage
Spread: 42 Spread: 42
InfDeath: 6
Damage: -2 Damage: -2
InfDeath: 6
PreventProne: yes PreventProne: yes
IonCannon: IonCannon:
ValidTargets: Ground, Air ValidTargets: Ground, Air
Warhead@impact: Warhead@1Dam_impact: SpreadDamage
Damage: 1000
Spread: 1c0 Spread: 1c0
Damage: 1000
InfDeath: 5 InfDeath: 5
Explosion: ring1
ProneModifier: 100 ProneModifier: 100
Warhead@area: Warhead@2Eff_impact: CreateEffect
DamageModel: PerCell Explosion: ring1
Warhead@3Dam_area: PerCellDamage
Size: 2,1
Damage: 250 Damage: 250
InfDeath: 5
Delay: 3
Warhead@4Dam_area: SpreadDamage
Damage: 250
InfDeath: 5
Delay: 3
Warhead@5Smu_area: LeaveSmudge
SmudgeType: Scorch SmudgeType: Scorch
Size: 2,1 Size: 2,1
Delay: 3 Delay: 3
InfDeath: 5
VulcanTower: VulcanTower:
ROF: 26 ROF: 26
@@ -831,16 +865,17 @@ VulcanTower:
Report: CHAINGN1.AUD Report: CHAINGN1.AUD
Projectile: Bullet Projectile: Bullet
Speed: 1c682 Speed: 1c682
Warhead: Warhead@1Dam: SpreadDamage
Spread: 128 Spread: 128
Damage: 18
InfDeath: 1
Versus: Versus:
Wood: 60% Wood: 60%
Light: 40% Light: 40%
Heavy: 25% Heavy: 25%
Concrete: 10% Concrete: 10%
Warhead@2Eff: CreateEffect
Explosion: piffpiff Explosion: piffpiff
InfDeath: 1
Damage: 18
RPGTower: RPGTower:
ROF: 80 ROF: 80
@@ -853,17 +888,18 @@ RPGTower:
Shadow: true Shadow: true
Angle: 62 Angle: 62
Image: canister Image: canister
Warhead: Warhead@1Dam: SpreadDamage
Spread: 128 Spread: 128
Damage: 110
InfDeath: 2
ProneModifier: 70
Versus: Versus:
None: 30% None: 30%
Wood: 75% Wood: 75%
Light: 90% Light: 90%
Heavy: 100% Heavy: 100%
Concrete: 70% Concrete: 70%
InfDeath: 2 Warhead@2Eff: CreateEffect
Damage: 110
ProneModifier: 70
Explosion: large_clsn Explosion: large_clsn
ImpactSound: expnew14.aud ImpactSound: expnew14.aud
@@ -882,10 +918,11 @@ SAMTower:
Image: DRAGON Image: DRAGON
ROT: 5 ROT: 5
RangeLimit: 60 RangeLimit: 60
Warhead: Warhead@1Dam: SpreadDamage
Spread: 128 Spread: 128
InfDeath: 2
Damage: 33 Damage: 33
InfDeath: 2
Warhead@2Eff: CreateEffect
Explosion: small_clsn Explosion: small_clsn
ImpactSound: expnew12.aud ImpactSound: expnew12.aud
@@ -896,12 +933,13 @@ ObeliskLaser:
Report: OBELRAY1.AUD Report: OBELRAY1.AUD
Projectile: LaserZap Projectile: LaserZap
BeamWidth: 4 BeamWidth: 4
Warhead: Warhead@1Dam: SpreadDamage
Spread: 42 Spread: 42
InfDeath: 5
SmudgeType: Scorch
Damage: 250 Damage: 250
InfDeath: 5
ProneModifier: 60 ProneModifier: 60
Warhead@2Smu: LeaveSmudge
SmudgeType: Scorch
TurretLaser: TurretLaser:
ROF: 40 ROF: 40
@@ -910,24 +948,28 @@ TurretLaser:
Projectile: LaserZap Projectile: LaserZap
BeamWidth: 2 BeamWidth: 2
BeamDuration: 5 BeamDuration: 5
Warhead: Warhead@1Dam: SpreadDamage
Spread: 42 Spread: 42
InfDeath: 5
SmudgeType: Scorch
Damage: 30 Damage: 30
InfDeath: 5
ProneModifier: 60 ProneModifier: 60
Warhead@2Smu: LeaveSmudge
SmudgeType: Scorch
TiberiumExplosion: TiberiumExplosion:
Warhead: Warhead@1Dam: SpreadDamage
Damage: 10
Spread: 9 Spread: 9
Size: 1,1 Damage: 10
InfDeath: 3
Versus: Versus:
None: 90% None: 90%
Wood: 75% Wood: 75%
Light: 60% Light: 60%
Heavy: 25% Heavy: 25%
InfDeath: 3 Warhead@2Res: CreateResource
AddsResourceType: Tiberium
Size: 1,1
Warhead@3Eff: CreateEffect
Explosion: large_explosion Explosion: large_explosion
ImpactSound: expnew09.aud ImpactSound: expnew09.aud
AddsResourceType: Tiberium