Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Warhead refactor part 3: Add WarheadArgs #17119

Merged
merged 1 commit into from
Jan 21, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 5 additions & 7 deletions OpenRA.Game/Effects/DelayedImpact.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#endregion

using System.Collections.Generic;
using OpenRA.GameRules;
using OpenRA.Graphics;
using OpenRA.Traits;

Expand All @@ -18,26 +19,23 @@ namespace OpenRA.Effects
public class DelayedImpact : IEffect
{
readonly Target target;
readonly Actor firedBy;
readonly IEnumerable<int> damageModifiers;
readonly IWarhead wh;
readonly WarheadArgs args;

int delay;

public DelayedImpact(int delay, IWarhead wh, Target target, Actor firedBy, IEnumerable<int> damageModifiers)
public DelayedImpact(int delay, IWarhead wh, Target target, WarheadArgs args)
{
this.wh = wh;
this.delay = delay;

this.target = target;
this.firedBy = firedBy;
this.damageModifiers = damageModifiers;
this.args = args;
}

public void Tick(World world)
{
if (--delay <= 0)
world.AddFrameEndTask(w => { w.Remove(this); wh.DoImpact(target, firedBy, damageModifiers); });
world.AddFrameEndTask(w => { w.Remove(this); wh.DoImpact(target, args); });
}

public IEnumerable<IRenderable> Render(WorldRenderer wr) { yield break; }
Expand Down
43 changes: 40 additions & 3 deletions OpenRA.Game/GameRules/WeaponInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,27 @@ public class ProjectileArgs
public Target GuidedTarget;
}

public class WarheadArgs
reaperrr marked this conversation as resolved.
Show resolved Hide resolved
{
public WeaponInfo Weapon;
public int[] DamageModifiers = { };
public WPos Source;
public Actor SourceActor;
public Target WeaponTarget;

public WarheadArgs(ProjectileArgs args)
{
Weapon = args.Weapon;
DamageModifiers = args.DamageModifiers;
Source = args.Source;
SourceActor = args.SourceActor;
WeaponTarget = args.GuidedTarget;
}

// Default empty constructor for callers that want to initialize fields themselves
public WarheadArgs() { }
}

public interface IProjectile : IEffect { }
public interface IProjectileInfo { IProjectile Create(ProjectileArgs args); }

Expand Down Expand Up @@ -177,17 +198,33 @@ public bool IsValidAgainst(FrozenActor victim, Actor firedBy)
}

/// <summary>Applies all the weapon's warheads to the target.</summary>
public void Impact(Target target, Actor firedBy, IEnumerable<int> damageModifiers)
public void Impact(Target target, WarheadArgs args)
{
var world = args.SourceActor.World;
foreach (var warhead in Warheads)
{
var wh = warhead; // force the closure to bind to the current warhead

if (wh.Delay > 0)
firedBy.World.AddFrameEndTask(w => w.Add(new DelayedImpact(wh.Delay, wh, target, firedBy, damageModifiers)));
world.AddFrameEndTask(w => w.Add(new DelayedImpact(wh.Delay, wh, target, args)));
else
wh.DoImpact(target, firedBy, damageModifiers);
wh.DoImpact(target, args);
}
}

/// <summary>Applies all the weapon's warheads to the target. Only use for projectile-less, special-case impacts.</summary>
public void Impact(Target target, Actor firedBy)
{
// The impact will happen immediately at target.CenterPosition.
var args = new WarheadArgs
{
Weapon = this,
Source = firedBy.CenterPosition,
SourceActor = firedBy,
WeaponTarget = target
};

Impact(target, args);
}
}
}
3 changes: 2 additions & 1 deletion OpenRA.Game/Traits/TraitsInterfaces.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
using System.Diagnostics.CodeAnalysis;
using OpenRA.Activities;
using OpenRA.FileSystem;
using OpenRA.GameRules;
using OpenRA.Graphics;
using OpenRA.Network;
using OpenRA.Primitives;
Expand Down Expand Up @@ -490,7 +491,7 @@ public interface IWarhead
int Delay { get; }
bool IsValidAgainst(Actor victim, Actor firedBy);
bool IsValidAgainst(FrozenActor victim, Actor firedBy);
void DoImpact(Target target, Actor firedBy, IEnumerable<int> damageModifiers);
void DoImpact(Target target, WarheadArgs args);
}

public interface IRulesetLoaded<TInfo> { void RulesetLoaded(Ruleset rules, TInfo info); }
Expand Down
11 changes: 10 additions & 1 deletion OpenRA.Mods.Cnc/Projectiles/IonCannon.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,18 @@ public IonCannon(Player firedBy, WeaponInfo weapon, World world, WPos launchPos,
public void Tick(World world)
{
anim.Tick();

if (!impacted && weaponDelay-- <= 0)
{
weapon.Impact(target, firedBy.PlayerActor, Enumerable.Empty<int>());
var warheadArgs = new WarheadArgs
{
Weapon = weapon,
Source = target.CenterPosition,
SourceActor = firedBy.PlayerActor,
pchote marked this conversation as resolved.
Show resolved Hide resolved
WeaponTarget = target
};

weapon.Impact(target, warheadArgs);
impacted = true;
}
}
Expand Down
2 changes: 1 addition & 1 deletion OpenRA.Mods.Cnc/Projectiles/TeslaZap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public void Tick(World world)
target = args.Weapon.TargetActorCenter ? args.GuidedTarget.CenterPosition : args.GuidedTarget.Positions.PositionClosestTo(args.Source);

if (damageDuration-- > 0)
args.Weapon.Impact(Target.FromPos(target), args.SourceActor, args.DamageModifiers);
args.Weapon.Impact(Target.FromPos(target), new WarheadArgs(args));
}

public IEnumerable<IRenderable> Render(WorldRenderer wr)
Expand Down
2 changes: 1 addition & 1 deletion OpenRA.Mods.Cnc/Traits/EnergyWall.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ void ITick.Tick(Actor self)
{
var blockers = self.World.ActorMap.GetActorsAt(loc).Where(a => !a.IsDead && a != self);
foreach (var blocker in blockers)
info.WeaponInfo.Impact(Target.FromActor(blocker), self, Enumerable.Empty<int>());
info.WeaponInfo.Impact(Target.FromActor(blocker), self);
}
}

Expand Down
4 changes: 2 additions & 2 deletions OpenRA.Mods.Cnc/Traits/MadTank.cs
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ public override bool Tick(Actor self)
if (mad.info.ThumpDamageWeapon != null)
{
// Use .FromPos since this weapon needs to affect more than just the MadTank actor
mad.info.ThumpDamageWeaponInfo.Impact(Target.FromPos(self.CenterPosition), self, Enumerable.Empty<int>());
mad.info.ThumpDamageWeaponInfo.Impact(Target.FromPos(self.CenterPosition), self);
}

screenShaker.AddEffect(mad.info.ThumpShakeTime, self.CenterPosition, mad.info.ThumpShakeIntensity, mad.info.ThumpShakeMultiplier);
Expand All @@ -241,7 +241,7 @@ protected override void OnLastRun(Actor self)
if (mad.info.DetonationWeapon != null)
{
// Use .FromPos since this actor is killed. Cannot use Target.FromActor
mad.info.DetonationWeaponInfo.Impact(Target.FromPos(self.CenterPosition), self, Enumerable.Empty<int>());
mad.info.DetonationWeaponInfo.Impact(Target.FromPos(self.CenterPosition), self);
}

self.Kill(self, mad.info.DamageTypes);
Expand Down
2 changes: 1 addition & 1 deletion OpenRA.Mods.Common/Activities/Air/FallToEarth.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public override bool Tick(Actor self)
if (info.ExplosionWeapon != null)
{
// Use .FromPos since this actor is killed. Cannot use Target.FromActor
info.ExplosionWeapon.Impact(Target.FromPos(self.CenterPosition), self, Enumerable.Empty<int>());
info.ExplosionWeapon.Impact(Target.FromPos(self.CenterPosition), self);
}

self.Kill(self);
Expand Down
9 changes: 8 additions & 1 deletion OpenRA.Mods.Common/Projectiles/AreaBeam.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

using System;
using System.Collections.Generic;
using System.Linq;
using OpenRA.GameRules;
using OpenRA.Graphics;
using OpenRA.Mods.Common.Graphics;
Expand Down Expand Up @@ -231,7 +232,13 @@ public void Tick(World world)
foreach (var a in actors)
{
var adjustedModifiers = args.DamageModifiers.Append(GetFalloff((args.Source - a.CenterPosition).Length));
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unrelated to this PR, but... am I reading this wrong, or does damage fall off the farther the hit actor is from the source actor, instead of the farther it is from the beam's center (which would be the correct behavior)?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like the desired behaviour according to #9357 was to have a certain section of the beam between headPos and x that deals maximum damage, then a linear falloff in damage between x and y, and then the remaining section from y to tailPos deal minimum damage.

args.Weapon.Impact(Target.FromActor(a), args.SourceActor, adjustedModifiers);

var warheadArgs = new WarheadArgs(args)
{
DamageModifiers = adjustedModifiers.ToArray(),
};

args.Weapon.Impact(Target.FromActor(a), warheadArgs);
}
}

Expand Down
2 changes: 1 addition & 1 deletion OpenRA.Mods.Common/Projectiles/Bullet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ void Explode(World world)

world.AddFrameEndTask(w => w.Remove(this));

args.Weapon.Impact(Target.FromPos(pos), args.SourceActor, args.DamageModifiers);
args.Weapon.Impact(Target.FromPos(pos), new WarheadArgs(args));
}

bool AnyValidTargetsInRadius(World world, WPos pos, WDist radius, Actor firedBy, bool checkTargetType)
Expand Down
3 changes: 2 additions & 1 deletion OpenRA.Mods.Common/Projectiles/GravityBomb.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,8 @@ public void Tick(World world)
{
pos += new WVec(0, 0, args.PassiveTarget.Z - pos.Z);
world.AddFrameEndTask(w => w.Remove(this));
args.Weapon.Impact(Target.FromPos(pos), args.SourceActor, args.DamageModifiers);

args.Weapon.Impact(Target.FromPos(pos), new WarheadArgs(args));
}

if (anim != null)
Expand Down
2 changes: 1 addition & 1 deletion OpenRA.Mods.Common/Projectiles/InstantHit.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public void Tick(World world)
target = Target.FromPos(blockedPos);
}

args.Weapon.Impact(target, args.SourceActor, args.DamageModifiers);
args.Weapon.Impact(target, new WarheadArgs(args));
world.AddFrameEndTask(w => w.Remove(this));
}

Expand Down
2 changes: 1 addition & 1 deletion OpenRA.Mods.Common/Projectiles/LaserZap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ public void Tick(World world)

if (ticks < info.DamageDuration && --interval <= 0)
{
args.Weapon.Impact(Target.FromPos(target), args.SourceActor, args.DamageModifiers);
args.Weapon.Impact(Target.FromPos(target), new WarheadArgs(args));
interval = info.DamageInterval;
}

Expand Down
2 changes: 1 addition & 1 deletion OpenRA.Mods.Common/Projectiles/Missile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -891,7 +891,7 @@ void Explode(World world)
if (ticks <= info.Arm)
return;

args.Weapon.Impact(Target.FromPos(pos), args.SourceActor, args.DamageModifiers);
args.Weapon.Impact(Target.FromPos(pos), new WarheadArgs(args));
}

public IEnumerable<IRenderable> Render(WorldRenderer wr)
Expand Down
12 changes: 11 additions & 1 deletion OpenRA.Mods.Common/Projectiles/NukeLaunch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,17 @@ void Explode(World world, bool removeProjectile)
if (detonated)
return;

weapon.Impact(Target.FromPos(pos), firedBy.PlayerActor, Enumerable.Empty<int>());
var target = Target.FromPos(pos);
var warheadArgs = new WarheadArgs
{
Weapon = weapon,
Source = target.CenterPosition,
SourceActor = firedBy.PlayerActor,
WeaponTarget = target
};

weapon.Impact(target, warheadArgs);

world.WorldActor.Trait<ScreenShaker>().AddEffect(20, pos, 5);

foreach (var flash in world.WorldActor.TraitsImplementing<FlashPaletteEffect>())
Expand Down
4 changes: 2 additions & 2 deletions OpenRA.Mods.Common/Projectiles/Railgun.cs
Original file line number Diff line number Diff line change
Expand Up @@ -188,12 +188,12 @@ public void Tick(World world)
animationComplete = true;

if (!info.DamageActorsInLine)
args.Weapon.Impact(Target.FromPos(target), args.SourceActor, args.DamageModifiers);
args.Weapon.Impact(Target.FromPos(target), new WarheadArgs(args));
else
{
var actors = world.FindActorsOnLine(args.Source, target, info.BeamWidth);
foreach (var a in actors)
args.Weapon.Impact(Target.FromActor(a), args.SourceActor, args.DamageModifiers);
args.Weapon.Impact(Target.FromActor(a), new WarheadArgs(args));
}
}

Expand Down
2 changes: 1 addition & 1 deletion OpenRA.Mods.Common/Traits/Buildings/Bridge.cs
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,7 @@ public void Demolish(Actor saboteur, int direction)
self.World.AddFrameEndTask(w =>
{
// Use .FromPos since this actor is killed. Cannot use Target.FromActor
info.DemolishWeaponInfo.Impact(Target.FromPos(self.CenterPosition), saboteur, Enumerable.Empty<int>());
info.DemolishWeaponInfo.Impact(Target.FromPos(self.CenterPosition), saboteur);

self.Kill(saboteur);
});
Expand Down
2 changes: 1 addition & 1 deletion OpenRA.Mods.Common/Traits/Buildings/GroundLevelBridge.cs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ void IBridgeSegment.Demolish(Actor saboteur)
return;

// Use .FromPos since this actor is dead. Cannot use Target.FromActor
Info.DemolishWeaponInfo.Impact(Target.FromPos(self.CenterPosition), saboteur, Enumerable.Empty<int>());
Info.DemolishWeaponInfo.Impact(Target.FromPos(self.CenterPosition), saboteur);

self.Kill(saboteur);
});
Expand Down
2 changes: 1 addition & 1 deletion OpenRA.Mods.Common/Traits/Crates/ExplodeCrateAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public ExplodeCrateAction(Actor self, ExplodeCrateActionInfo info)
public override void Activate(Actor collector)
{
var weapon = collector.World.Map.Rules.Weapons[info.Weapon.ToLowerInvariant()];
weapon.Impact(Target.FromPos(collector.CenterPosition), collector, Enumerable.Empty<int>());
weapon.Impact(Target.FromPos(collector.CenterPosition), collector);

base.Activate(collector);
}
Expand Down
4 changes: 2 additions & 2 deletions OpenRA.Mods.Common/Traits/Explodes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -120,13 +120,13 @@ void INotifyKilled.Killed(Actor self, AttackInfo e)
{
var cells = buildingInfo.UnpathableTiles(self.Location);
foreach (var c in cells)
weapon.Impact(Target.FromPos(self.World.Map.CenterOfCell(c)), source, Enumerable.Empty<int>());
weapon.Impact(Target.FromPos(self.World.Map.CenterOfCell(c)), source);

return;
}

// Use .FromPos since this actor is killed. Cannot use Target.FromActor
weapon.Impact(Target.FromPos(self.CenterPosition), source, Enumerable.Empty<int>());
weapon.Impact(Target.FromPos(self.CenterPosition), source);
}

WeaponInfo ChooseWeaponForExplosion(Actor self)
Expand Down
2 changes: 1 addition & 1 deletion OpenRA.Mods.Common/Traits/ExplosionOnDamageTransition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ void INotifyDamageStateChanged.DamageStateChanged(Actor self, AttackInfo e)
triggered = true;

// Use .FromPos since the actor might have been killed, don't use Target.FromActor
info.WeaponInfo.Impact(Target.FromPos(self.CenterPosition), e.Attacker, Enumerable.Empty<int>());
info.WeaponInfo.Impact(Target.FromPos(self.CenterPosition), e.Attacker);
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion OpenRA.Mods.Common/Warheads/ChangeOwnerWarhead.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#endregion

using System.Collections.Generic;
using OpenRA.GameRules;
using OpenRA.Mods.Common.Traits;
using OpenRA.Traits;

Expand All @@ -23,8 +24,9 @@ public class ChangeOwnerWarhead : Warhead

public readonly WDist Range = WDist.FromCells(1);

public override void DoImpact(Target target, Actor firedBy, IEnumerable<int> damageModifiers)
public override void DoImpact(Target target, WarheadArgs args)
{
var firedBy = args.SourceActor;
var actors = target.Type == TargetType.Actor ? new[] { target.Actor } :
firedBy.World.FindActorsInCircle(target.CenterPosition, Range);

Expand Down
4 changes: 3 additions & 1 deletion OpenRA.Mods.Common/Warheads/CreateEffectWarhead.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

using System.Collections.Generic;
using System.Linq;
using OpenRA.GameRules;
using OpenRA.Mods.Common.Effects;
using OpenRA.Mods.Common.Traits;
using OpenRA.Primitives;
Expand Down Expand Up @@ -103,8 +104,9 @@ public ImpactTargetType GetDirectHitTargetType(World world, CPos cell, WPos pos,
return invalidHit ? ImpactTargetType.InvalidActor : ImpactTargetType.NoActor;
}

public override void DoImpact(Target target, Actor firedBy, IEnumerable<int> damageModifiers)
public override void DoImpact(Target target, WarheadArgs args)
{
var firedBy = args.SourceActor;
if (!target.IsValidFor(firedBy))
return;

Expand Down
Loading