Merge INotifyRearm/Repair into INotifyResupply

And streamline its notify methods.
Also cache INotifyResupply traits at beginning
of Resupply activity.
This commit is contained in:
reaperrr
2019-03-24 16:59:09 +01:00
committed by Paul Chote
parent ba4b5738d7
commit 83934074a4
4 changed files with 73 additions and 106 deletions

View File

@@ -26,12 +26,11 @@ namespace OpenRA.Mods.Common.Activities
readonly Repairable repairable;
readonly RepairableNear repairableNear;
readonly Rearmable rearmable;
readonly INotifyResupply[] notifyResupplies;
int remainingTicks;
bool played;
bool paused;
bool repairComplete;
bool rearmComplete;
ResupplyType activeResupplyTypes = ResupplyType.None;
public Resupply(Actor self, Actor host, WDist closeEnough)
{
@@ -42,13 +41,19 @@ namespace OpenRA.Mods.Common.Activities
repairable = self.TraitOrDefault<Repairable>();
repairableNear = self.TraitOrDefault<RepairableNear>();
rearmable = self.TraitOrDefault<Rearmable>();
notifyResupplies = host.TraitsImplementing<INotifyResupply>().ToArray();
repairComplete = health == null || health.DamageState == DamageState.Undamaged
var cannotRepairAtHost = health == null || health.DamageState == DamageState.Undamaged
|| !allRepairsUnits.Any()
|| ((repairable == null || !repairable.Info.RepairActors.Contains(host.Info.Name))
&& (repairableNear == null || !repairableNear.Info.RepairActors.Contains(host.Info.Name)));
rearmComplete = rearmable == null || !rearmable.Info.RearmActors.Contains(host.Info.Name) || rearmable.RearmableAmmoPools.All(p => p.FullAmmo());
if (!cannotRepairAtHost)
activeResupplyTypes |= ResupplyType.Repair;
var cannotRearmAtHost = rearmable == null || !rearmable.Info.RearmActors.Contains(host.Info.Name) || rearmable.RearmableAmmoPools.All(p => p.FullAmmo());
if (!cannotRearmAtHost)
activeResupplyTypes |= ResupplyType.Rearm;
}
protected override void OnFirstRun(Actor self)
@@ -56,21 +61,16 @@ namespace OpenRA.Mods.Common.Activities
if (host.Type == TargetType.Invalid)
return;
if (!repairComplete)
foreach (var notifyRepair in host.Actor.TraitsImplementing<INotifyRepair>())
notifyRepair.BeforeRepair(host.Actor, self);
if (activeResupplyTypes > 0)
foreach (var notifyResupply in notifyResupplies)
notifyResupply.BeforeResupply(host.Actor, self, activeResupplyTypes);
if (!rearmComplete)
{
foreach (var notifyRearm in host.Actor.TraitsImplementing<INotifyRearm>())
notifyRearm.RearmingStarted(host.Actor, self);
// Reset the ReloadDelay to avoid any issues with early cancellation
// from previous reload attempts (explicit order, host building died, etc).
// HACK: this really shouldn't be managed from here
// Reset the ReloadDelay to avoid any issues with early cancellation
// from previous reload attempts (explicit order, host building died, etc).
// HACK: this really shouldn't be managed from here
if (activeResupplyTypes.HasFlag(ResupplyType.Rearm))
foreach (var pool in rearmable.RearmableAmmoPools)
pool.RemainingTicks = pool.Info.ReloadDelay;
}
}
public override Activity Tick(Actor self)
@@ -78,19 +78,22 @@ namespace OpenRA.Mods.Common.Activities
if (IsCanceling)
return NextActivity;
if (host.Type == TargetType.Invalid || health == null)
if (host.Type == TargetType.Invalid)
return NextActivity;
if (closeEnough.LengthSquared > 0 && !host.IsInRange(self.CenterPosition, closeEnough))
return NextActivity;
if (!repairComplete)
if (activeResupplyTypes.HasFlag(ResupplyType.Repair))
RepairTick(self);
if (!rearmComplete)
if (activeResupplyTypes.HasFlag(ResupplyType.Rearm))
RearmTick(self);
if (repairComplete && rearmComplete)
foreach (var notifyResupply in notifyResupplies)
notifyResupply.ResupplyTick(host.Actor, self, activeResupplyTypes);
if (activeResupplyTypes == 0)
return NextActivity;
return this;
@@ -99,26 +102,11 @@ namespace OpenRA.Mods.Common.Activities
void RepairTick(Actor self)
{
// First active.
RepairsUnits repairsUnits = null;
paused = false;
foreach (var r in allRepairsUnits)
{
if (!r.IsTraitDisabled)
{
if (r.IsTraitPaused)
paused = true;
else
{
repairsUnits = r;
break;
}
}
}
var repairsUnits = allRepairsUnits.FirstOrDefault(r => !r.IsTraitDisabled && !r.IsTraitPaused);
if (repairsUnits == null)
{
if (!paused)
repairComplete = true;
if (!allRepairsUnits.Any(r => r.IsTraitPaused))
activeResupplyTypes &= ~ResupplyType.Repair;
return;
}
@@ -134,10 +122,7 @@ namespace OpenRA.Mods.Common.Activities
Game.Sound.PlayNotification(self.World.Map.Rules, self.Owner, "Speech", repairsUnits.Info.FinishRepairingNotification, self.Owner.Faction.InternalName);
foreach (var notifyRepair in host.Actor.TraitsImplementing<INotifyRepair>())
notifyRepair.AfterRepair(host.Actor, self);
repairComplete = true;
activeResupplyTypes &= ~ResupplyType.Repair;
return;
}
@@ -163,10 +148,6 @@ namespace OpenRA.Mods.Common.Activities
}
self.InflictDamage(host.Actor, new Damage(-hpToRepair));
foreach (var depot in host.Actor.TraitsImplementing<INotifyRepair>())
depot.RepairTick(host.Actor, self);
remainingTicks = repairsUnits.Info.Interval;
}
else
@@ -175,34 +156,26 @@ namespace OpenRA.Mods.Common.Activities
void RearmTick(Actor self)
{
rearmComplete = true;
foreach (var pool in rearmable.RearmableAmmoPools)
var rearmComplete = true;
foreach (var ammoPool in rearmable.RearmableAmmoPools)
{
if (!pool.FullAmmo())
if (!ammoPool.FullAmmo())
{
Reload(self, host.Actor, pool);
if (--ammoPool.RemainingTicks <= 0)
{
ammoPool.RemainingTicks = ammoPool.Info.ReloadDelay;
if (!string.IsNullOrEmpty(ammoPool.Info.RearmSound))
Game.Sound.PlayToPlayer(SoundType.World, self.Owner, ammoPool.Info.RearmSound, self.CenterPosition);
ammoPool.GiveAmmo(self, ammoPool.Info.ReloadCount);
}
rearmComplete = false;
}
}
if (rearmComplete)
foreach (var notifyRearm in host.Actor.TraitsImplementing<INotifyRearm>())
notifyRearm.RearmingFinished(host.Actor, self);
}
void Reload(Actor self, Actor host, AmmoPool ammoPool)
{
if (--ammoPool.RemainingTicks <= 0)
{
foreach (var notify in host.TraitsImplementing<INotifyRearm>())
notify.Rearming(host, self);
ammoPool.RemainingTicks = ammoPool.Info.ReloadDelay;
if (!string.IsNullOrEmpty(ammoPool.Info.RearmSound))
Game.Sound.PlayToPlayer(SoundType.World, self.Owner, ammoPool.Info.RearmSound, self.CenterPosition);
ammoPool.GiveAmmo(self, ammoPool.Info.ReloadCount);
}
activeResupplyTypes &= ~ResupplyType.Rearm;
}
}
}

View File

@@ -14,6 +14,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits.Render
{
// TODO: Refactor this trait into WithResupplyOverlay
[Desc("Displays an overlay when the building is being repaired by the player.")]
public class WithRepairOverlayInfo : PausableConditionalTraitInfo, Requires<RenderSpritesInfo>, Requires<BodyOrientationInfo>
{
@@ -38,10 +39,11 @@ namespace OpenRA.Mods.Common.Traits.Render
public override object Create(ActorInitializer init) { return new WithRepairOverlay(init.Self, this); }
}
public class WithRepairOverlay : PausableConditionalTrait<WithRepairOverlayInfo>, INotifyDamageStateChanged, INotifyRepair
public class WithRepairOverlay : PausableConditionalTrait<WithRepairOverlayInfo>, INotifyDamageStateChanged, INotifyResupply
{
readonly Animation overlay;
bool visible;
bool repairing;
public WithRepairOverlay(Actor self, WithRepairOverlayInfo info)
: base(info)
@@ -65,8 +67,12 @@ namespace OpenRA.Mods.Common.Traits.Render
overlay.ReplaceAnim(RenderSprites.NormalizeSequence(overlay, e.DamageState, overlay.CurrentSequence.Name));
}
void INotifyRepair.BeforeRepair(Actor self, Actor host)
void INotifyResupply.BeforeResupply(Actor self, Actor target, ResupplyType types)
{
repairing = types.HasFlag(ResupplyType.Repair);
if (!repairing)
return;
if (Info.StartSequence != null)
{
visible = true;
@@ -75,18 +81,18 @@ namespace OpenRA.Mods.Common.Traits.Render
}
}
void INotifyRepair.RepairTick(Actor self, Actor host)
void INotifyResupply.ResupplyTick(Actor self, Actor target, ResupplyType types)
{
if (Info.StartSequence == null)
var wasRepairing = repairing;
repairing = types.HasFlag(ResupplyType.Repair);
if (repairing && Info.StartSequence == null && !visible)
{
visible = true;
overlay.PlayThen(overlay.CurrentSequence.Name, () => visible = false);
}
}
void INotifyRepair.AfterRepair(Actor self, Actor target)
{
if (Info.EndSequence != null)
if (!repairing && wasRepairing && Info.EndSequence != null)
{
visible = true;
overlay.PlayThen(Info.EndSequence, () => visible = false);

View File

@@ -15,13 +15,6 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits.Render
{
[Flags]
public enum ResupplyType
{
Rearm = 1,
Repair = 2
}
[Desc("Replaces the default animation when actor resupplies a unit.")]
public class WithResupplyAnimationInfo : ConditionalTraitInfo, Requires<WithSpriteBodyInfo>
{
@@ -37,7 +30,7 @@ namespace OpenRA.Mods.Common.Traits.Render
public override object Create(ActorInitializer init) { return new WithResupplyAnimation(init.Self, this); }
}
public class WithResupplyAnimation : ConditionalTrait<WithResupplyAnimationInfo>, INotifyRepair, INotifyRearm, ITick
public class WithResupplyAnimation : ConditionalTrait<WithResupplyAnimationInfo>, INotifyResupply, ITick
{
readonly WithSpriteBody wsb;
bool animPlaying;
@@ -71,28 +64,16 @@ namespace OpenRA.Mods.Common.Traits.Render
}
}
void INotifyRepair.BeforeRepair(Actor self, Actor target)
void INotifyResupply.BeforeResupply(Actor self, Actor target, ResupplyType types)
{
repairing = true;
repairing = types.HasFlag(ResupplyType.Repair);
rearming = types.HasFlag(ResupplyType.Rearm);
}
void INotifyRepair.RepairTick(Actor self, Actor target) { }
void INotifyRepair.AfterRepair(Actor self, Actor target)
void INotifyResupply.ResupplyTick(Actor self, Actor target, ResupplyType types)
{
repairing = false;
}
void INotifyRearm.RearmingStarted(Actor self, Actor target)
{
rearming = true;
}
void INotifyRearm.Rearming(Actor self, Actor target) { }
void INotifyRearm.RearmingFinished(Actor self, Actor target)
{
rearming = false;
repairing = types.HasFlag(ResupplyType.Repair);
rearming = types.HasFlag(ResupplyType.Rearm);
}
protected override void TraitDisabled(Actor self)

View File

@@ -24,6 +24,14 @@ namespace OpenRA.Mods.Common.Traits
public enum AttackDelayType { Preparation, Attack }
[Flags]
public enum ResupplyType
{
None = 0,
Rearm = 1,
Repair = 2
}
public interface IQuantizeBodyOrientationInfo : ITraitInfo
{
int QuantizedBodyFacings(ActorInfo ai, SequenceProvider sequenceProvider, string race);
@@ -116,11 +124,10 @@ namespace OpenRA.Mods.Common.Traits
public interface INotifyAppliedDamage { void AppliedDamage(Actor self, Actor damaged, AttackInfo e); }
[RequireExplicitImplementation]
public interface INotifyRepair
public interface INotifyResupply
{
void BeforeRepair(Actor self, Actor target);
void RepairTick(Actor self, Actor target);
void AfterRepair(Actor self, Actor target);
void BeforeResupply(Actor host, Actor target, ResupplyType types);
void ResupplyTick(Actor host, Actor target, ResupplyType types);
}
[RequireExplicitImplementation]