diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj index a352efeb2b..ef7508cd05 100644 --- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj +++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj @@ -574,6 +574,7 @@ + diff --git a/OpenRA.Mods.Common/Projectiles/InstantHit.cs b/OpenRA.Mods.Common/Projectiles/InstantHit.cs index ee4eb1ae15..309201abd7 100644 --- a/OpenRA.Mods.Common/Projectiles/InstantHit.cs +++ b/OpenRA.Mods.Common/Projectiles/InstantHit.cs @@ -10,6 +10,7 @@ #endregion using System.Collections.Generic; +using System.Linq; using OpenRA.GameRules; using OpenRA.Graphics; using OpenRA.Mods.Common.Traits; @@ -40,46 +41,42 @@ namespace OpenRA.Mods.Common.Projectiles readonly ProjectileArgs args; readonly InstantHitInfo info; - bool doneDamage; - WPos target; + Target target; WPos source; public InstantHit(InstantHitInfo info, ProjectileArgs args) { this.args = args; this.info = info; - target = args.PassiveTarget; source = args.Source; + + if (info.Inaccuracy.Length > 0) + { + var inaccuracy = Util.ApplyPercentageModifiers(info.Inaccuracy.Length, args.InaccuracyModifiers); + var maxOffset = inaccuracy * (args.PassiveTarget - source).Length / args.Weapon.Range.Length; + target = Target.FromPos(args.PassiveTarget + WVec.FromPDF(args.SourceActor.World.SharedRandom, 2) * maxOffset / 1024); + } + else + target = args.GuidedTarget; } public void Tick(World world) { // Check for blocking actors WPos blockedPos; - if (info.Blockable && BlocksProjectiles.AnyBlockingActorsBetween(world, source, target, + if (info.Blockable && BlocksProjectiles.AnyBlockingActorsBetween(world, source, target.CenterPosition, info.Width, info.TargetExtraSearchRadius, out blockedPos)) { - target = blockedPos; + target = Target.FromPos(blockedPos); } - if (info.Inaccuracy.Length > 0) - { - var inaccuracy = OpenRA.Mods.Common.Util.ApplyPercentageModifiers(info.Inaccuracy.Length, args.InaccuracyModifiers); - var maxOffset = inaccuracy * (target - source).Length / args.Weapon.Range.Length; - target += WVec.FromPDF(args.SourceActor.World.SharedRandom, 2) * maxOffset / 1024; - } - - if (!doneDamage) - { - args.Weapon.Impact(Target.FromPos(target), args.SourceActor, args.DamageModifiers); - doneDamage = true; - world.AddFrameEndTask(w => w.Remove(this)); - } + args.Weapon.Impact(target, args.SourceActor, args.DamageModifiers); + world.AddFrameEndTask(w => w.Remove(this)); } public IEnumerable Render(WorldRenderer wr) { - yield break; + return Enumerable.Empty(); } } } diff --git a/OpenRA.Mods.Common/Warheads/TargetDamageWarhead.cs b/OpenRA.Mods.Common/Warheads/TargetDamageWarhead.cs new file mode 100644 index 0000000000..751a261b31 --- /dev/null +++ b/OpenRA.Mods.Common/Warheads/TargetDamageWarhead.cs @@ -0,0 +1,62 @@ +#region Copyright & License Information +/* + * Copyright 2007-2017 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, either version 3 of + * the License, or (at your option) any later version. For more + * information, see COPYING. + */ +#endregion + +using System.Collections.Generic; +using OpenRA.GameRules; +using OpenRA.Mods.Common.Traits; +using OpenRA.Traits; + +namespace OpenRA.Mods.Common.Warheads +{ + public class TargetDamageWarhead : DamageWarhead + { + public override void DoImpact(Target target, Actor firedBy, IEnumerable damageModifiers) + { + // Damages a single actor, rather than a position. Only support by InstantHit for now. + // TODO: Add support for 'area of damage' + if (target.Type == TargetType.Actor) + DoImpact(target.Actor, firedBy, damageModifiers); + } + + public override void DoImpact(WPos pos, Actor firedBy, IEnumerable damageModifiers) + { + // For now this only displays debug overlay + // TODO: Add support for 'area of effect' / multiple targets + var world = firedBy.World; + var debugOverlayRange = new[] { WDist.Zero, new WDist(128) }; + + if (world.LocalPlayer != null) + { + var devMode = world.LocalPlayer.PlayerActor.TraitOrDefault(); + if (devMode != null && devMode.ShowCombatGeometry) + world.WorldActor.Trait().AddImpact(pos, debugOverlayRange, DebugOverlayColor); + } + } + + public override void DoImpact(Actor victim, Actor firedBy, IEnumerable damageModifiers) + { + if (!IsValidAgainst(victim, firedBy)) + return; + + var damage = Util.ApplyPercentageModifiers(Damage, damageModifiers.Append(DamageVersus(victim))); + victim.InflictDamage(firedBy, new Damage(damage, DamageTypes)); + + var world = firedBy.World; + if (world.LocalPlayer != null) + { + var debugOverlayRange = new[] { WDist.Zero, new WDist(128) }; + var devMode = world.LocalPlayer.PlayerActor.TraitOrDefault(); + if (devMode != null && devMode.ShowCombatGeometry) + world.WorldActor.Trait().AddImpact(victim.CenterPosition, debugOverlayRange, DebugOverlayColor); + } + } + } +} diff --git a/mods/d2k/weapons/other.yaml b/mods/d2k/weapons/other.yaml index 184bacea9a..59c324dcf4 100644 --- a/mods/d2k/weapons/other.yaml +++ b/mods/d2k/weapons/other.yaml @@ -60,10 +60,8 @@ WormJaw: ReloadDelay: 10 InvalidTargets: Structure, Infantry Range: 1c512 - Warhead@1Dam: SpreadDamage # HACK: The warhead is needed for targeting + Warhead@1Dam: TargetDamage # HACK: The warhead is needed for targeting InvalidTargets: Structure, Infantry - Spread: 0 - Falloff: 0,0 OrniBomb: ReloadDelay: 25 diff --git a/mods/ts/weapons/healweapons.yaml b/mods/ts/weapons/healweapons.yaml index 6e82fbdff3..a6c2057c54 100644 --- a/mods/ts/weapons/healweapons.yaml +++ b/mods/ts/weapons/healweapons.yaml @@ -1,25 +1,21 @@ -Heal: +^HealWeapon: ReloadDelay: 80 Range: 2c849 Report: healer1.aud ValidTargets: Infantry - Projectile: Bullet - Speed: 1c682 - Warhead@1Dam: SpreadDamage + Projectile: InstantHit + Warhead@1Dam: TargetDamage DebugOverlayColor: 00FF00 - Spread: 213 Damage: -50 ValidTargets: Infantry +Heal: + Inherits: ^HealWeapon + Repair: - ReloadDelay: 80 + Inherits: ^HealWeapon Range: 1c819 Report: repair11.aud ValidTargets: Repair - Projectile: Bullet - Speed: 1c682 - Warhead@1Dam: SpreadDamage - DebugOverlayColor: 00FF00 - Spread: 213 - Damage: -50 + Warhead@1Dam: TargetDamage ValidTargets: Repair diff --git a/mods/ts/weapons/otherweapons.yaml b/mods/ts/weapons/otherweapons.yaml index ce92133034..205957c3e8 100644 --- a/mods/ts/weapons/otherweapons.yaml +++ b/mods/ts/weapons/otherweapons.yaml @@ -9,7 +9,8 @@ FireballLauncher: Burst: 5 BurstDelay: 5 Warhead@1Dam: SpreadDamage - Spread: 341 + Spread: 288 + Falloff: 100, 50, 25, 12, 6, 3, 0 Damage: 25 Versus: None: 600 @@ -33,7 +34,8 @@ Bomb: Shadow: true Palette: ra Warhead@1Dam: SpreadDamage - Spread: 298 + Spread: 512 + Falloff: 100, 50, 25, 12, 6, 3, 0 Damage: 160 Versus: None: 200 @@ -55,6 +57,8 @@ Bomb: Warhead@4Smu: LeaveSmudge SmudgeType: MediumCrater InvalidTargets: Vehicle, Building, Wall + Warhead@5Res: DestroyResource + Size: 1 FiendShard: ReloadDelay: 30 @@ -86,7 +90,7 @@ SlimeAttack: Range: 1c384 Report: vicer1.aud Projectile: InstantHit - Warhead@1Dam: SpreadDamage + Warhead@1Dam: TargetDamage Damage: 100 Versus: Light: 60 @@ -96,8 +100,7 @@ SlimeAttack: Veins: ReloadDelay: 16 - Warhead@Damage: SpreadDamage - Spread: 42 + Warhead@Damage: TargetDamage Damage: 5 DamageTypes: BulletDeath Warhead@Effect: CreateEffect