diff --git a/OpenRA.Game/Traits/TraitsInterfaces.cs b/OpenRA.Game/Traits/TraitsInterfaces.cs index ec83ce99b6..b0741a0203 100644 --- a/OpenRA.Game/Traits/TraitsInterfaces.cs +++ b/OpenRA.Game/Traits/TraitsInterfaces.cs @@ -130,7 +130,6 @@ namespace OpenRA.Traits public interface INotifyAddedToWorld { void AddedToWorld(Actor self); } public interface INotifyRemovedFromWorld { void RemovedFromWorld(Actor self); } public interface INotifyDamage { void Damaged(Actor self, AttackInfo e); } - public interface INotifyDamageStateChanged { void DamageStateChanged(Actor self, AttackInfo e); } public interface INotifyKilled { void Killed(Actor self, AttackInfo e); } public interface INotifyActorDisposing { void Disposing(Actor self); } public interface INotifyAppliedDamage { void AppliedDamage(Actor self, Actor damaged, AttackInfo e); } diff --git a/OpenRA.Mods.Cnc/Traits/AttackPopupTurreted.cs b/OpenRA.Mods.Cnc/Traits/AttackPopupTurreted.cs index c2d8808af4..1feba5c954 100644 --- a/OpenRA.Mods.Cnc/Traits/AttackPopupTurreted.cs +++ b/OpenRA.Mods.Cnc/Traits/AttackPopupTurreted.cs @@ -83,7 +83,7 @@ namespace OpenRA.Mods.Cnc.Traits return true; } - public void TickIdle(Actor self) + void INotifyIdle.TickIdle(Actor self) { if (state == PopupState.Open && idleTicks++ > info.CloseDelay) { @@ -102,7 +102,7 @@ namespace OpenRA.Mods.Cnc.Traits } } - public void BuildingComplete(Actor self) + void INotifyBuildComplete.BuildingComplete(Actor self) { if (skippedMakeAnimation) { diff --git a/OpenRA.Mods.Cnc/Traits/Render/WithReloadingSpriteTurret.cs b/OpenRA.Mods.Cnc/Traits/Render/WithReloadingSpriteTurret.cs index 1eae2c31c3..103547a083 100644 --- a/OpenRA.Mods.Cnc/Traits/Render/WithReloadingSpriteTurret.cs +++ b/OpenRA.Mods.Cnc/Traits/Render/WithReloadingSpriteTurret.cs @@ -57,7 +57,7 @@ namespace OpenRA.Mods.Cnc.Traits.Render ammoSuffix = (initialAmmoStage * reloadStages / ammo).ToString(); } - public override void Tick(Actor self) + protected override void Tick(Actor self) { if (Info.AimSequence != null) sequence = Attack.IsAttacking ? Info.AimSequence : Info.Sequence; diff --git a/OpenRA.Mods.Common/Scripting/ScriptTriggers.cs b/OpenRA.Mods.Common/Scripting/ScriptTriggers.cs index e9ed7be5f4..d370c8f3f2 100644 --- a/OpenRA.Mods.Common/Scripting/ScriptTriggers.cs +++ b/OpenRA.Mods.Common/Scripting/ScriptTriggers.cs @@ -302,7 +302,7 @@ namespace OpenRA.Mods.Common.Scripting OnCapturedInternal(self); } - public void Infiltrated(Actor self, Actor infiltrator) + void INotifyInfiltrated.Infiltrated(Actor self, Actor infiltrator) { if (world.Disposing) return; diff --git a/OpenRA.Mods.Common/Traits/Armament.cs b/OpenRA.Mods.Common/Traits/Armament.cs index 7be8a2cad8..fc09205ed1 100644 --- a/OpenRA.Mods.Common/Traits/Armament.cs +++ b/OpenRA.Mods.Common/Traits/Armament.cs @@ -139,7 +139,7 @@ namespace OpenRA.Mods.Common.Traits return new WDist(Util.ApplyPercentageModifiers(Weapon.Range.Length, rangeModifiers)); } - public virtual void Created(Actor self) + protected virtual void Created(Actor self) { turret = self.TraitsImplementing().FirstOrDefault(t => t.Name == Info.Turret); ammoPool = self.TraitsImplementing().FirstOrDefault(la => la.Info.Name == Info.AmmoPoolName); @@ -147,7 +147,7 @@ namespace OpenRA.Mods.Common.Traits rangeModifiers = self.TraitsImplementing().ToArray().Select(m => m.GetRangeModifier()); } - public virtual void Tick(Actor self) + protected virtual void Tick(Actor self) { if (IsTraitDisabled) return; @@ -168,6 +168,18 @@ namespace OpenRA.Mods.Common.Traits delayedActions.RemoveAll(a => a.First <= 0); } + void INotifyCreated.Created(Actor self) + { + // Split into a protected method to allow subclassing + Created(self); + } + + void ITick.Tick(Actor self) + { + // Split into a protected method to allow subclassing + Tick(self); + } + protected void ScheduleDelayedAction(int t, Action a) { if (t > 0) diff --git a/OpenRA.Mods.Common/Traits/Buildings/Bridge.cs b/OpenRA.Mods.Common/Traits/Buildings/Bridge.cs index 241e7656b9..979ecdf9c1 100644 --- a/OpenRA.Mods.Common/Traits/Buildings/Bridge.cs +++ b/OpenRA.Mods.Common/Traits/Buildings/Bridge.cs @@ -308,7 +308,7 @@ namespace OpenRA.Mods.Common.Traits } } - public void DamageStateChanged(Actor self, AttackInfo e) + void INotifyDamageStateChanged.DamageStateChanged(Actor self, AttackInfo e) { Do((b, d) => b.UpdateState()); diff --git a/OpenRA.Mods.Common/Traits/ExplosionOnDamageTransition.cs b/OpenRA.Mods.Common/Traits/ExplosionOnDamageTransition.cs index 3e4c2fe113..cdb3f7ec3a 100644 --- a/OpenRA.Mods.Common/Traits/ExplosionOnDamageTransition.cs +++ b/OpenRA.Mods.Common/Traits/ExplosionOnDamageTransition.cs @@ -49,7 +49,7 @@ namespace OpenRA.Mods.Common.Traits this.info = info; } - public void DamageStateChanged(Actor self, AttackInfo e) + void INotifyDamageStateChanged.DamageStateChanged(Actor self, AttackInfo e) { if (!self.IsInWorld) return; diff --git a/OpenRA.Mods.Common/Traits/Harvester.cs b/OpenRA.Mods.Common/Traits/Harvester.cs index 5d4ba7be23..9b0b0ff9ef 100644 --- a/OpenRA.Mods.Common/Traits/Harvester.cs +++ b/OpenRA.Mods.Common/Traits/Harvester.cs @@ -105,13 +105,13 @@ namespace OpenRA.Mods.Common.Traits self.QueueActivity(new CallFunc(() => ChooseNewProc(self, null))); } - public void Created(Actor self) + void INotifyCreated.Created(Actor self) { if (Info.SearchOnCreation) self.QueueActivity(new FindResources(self)); } - public void BuildingComplete(Actor self) + void INotifyBuildComplete.BuildingComplete(Actor self) { if (Info.SearchOnCreation) self.QueueActivity(new FindResources(self)); @@ -254,7 +254,7 @@ namespace OpenRA.Mods.Common.Traits } } - public void TickIdle(Actor self) + void INotifyIdle.TickIdle(Actor self) { // Should we be intelligent while idle? if (!idleSmart) return; diff --git a/OpenRA.Mods.Common/Traits/Render/WithGateSpriteBody.cs b/OpenRA.Mods.Common/Traits/Render/WithGateSpriteBody.cs index 921bcd1c46..3d38bcab91 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithGateSpriteBody.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithGateSpriteBody.cs @@ -45,7 +45,7 @@ namespace OpenRA.Mods.Common.Traits.Render } } - class WithGateSpriteBody : WithSpriteBody, INotifyRemovedFromWorld, INotifyBuildComplete, IWallConnector, ITick + class WithGateSpriteBody : WithSpriteBody, INotifyRemovedFromWorld, IWallConnector, ITick { readonly WithGateSpriteBodyInfo gateInfo; readonly Gate gate; @@ -83,12 +83,12 @@ namespace OpenRA.Mods.Common.Traits.Render return int2.Lerp(0, DefaultAnimation.CurrentSequence.Length - 1, gate.Position, gate.OpenPosition); } - public override void DamageStateChanged(Actor self, AttackInfo e) + protected override void DamageStateChanged(Actor self) { UpdateState(self); } - public override void BuildingComplete(Actor self) + protected override void OnBuildComplete(Actor self) { UpdateState(self); UpdateNeighbours(self); @@ -107,7 +107,7 @@ namespace OpenRA.Mods.Common.Traits.Render rb.SetDirty(); } - public void RemovedFromWorld(Actor self) + void INotifyRemovedFromWorld.RemovedFromWorld(Actor self) { UpdateNeighbours(self); } diff --git a/OpenRA.Mods.Common/Traits/Render/WithSiloAnimation.cs b/OpenRA.Mods.Common/Traits/Render/WithSiloAnimation.cs index 19987f0c97..6d738f138c 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithSiloAnimation.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithSiloAnimation.cs @@ -38,7 +38,7 @@ namespace OpenRA.Mods.Common.Traits.Render playerResources = init.Self.Owner.PlayerActor.Trait(); } - public void BuildingComplete(Actor self) + void INotifyBuildComplete.BuildingComplete(Actor self) { wsb.DefaultAnimation.PlayFetchIndex(wsb.NormalizeSequence(self, info.Sequence), () => playerResources.ResourceCapacity != 0 @@ -46,7 +46,7 @@ namespace OpenRA.Mods.Common.Traits.Render : 0); } - public void OnOwnerChanged(Actor self, Player oldOwner, Player newOwner) + void INotifyOwnerChanged.OnOwnerChanged(Actor self, Player oldOwner, Player newOwner) { playerResources = newOwner.PlayerActor.Trait(); diff --git a/OpenRA.Mods.Common/Traits/Render/WithSpriteBody.cs b/OpenRA.Mods.Common/Traits/Render/WithSpriteBody.cs index 4fc235c0bc..2be28793f0 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithSpriteBody.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithSpriteBody.cs @@ -75,12 +75,17 @@ namespace OpenRA.Mods.Common.Traits.Render return RenderSprites.NormalizeSequence(DefaultAnimation, self.GetDamageState(), sequence); } - // TODO: Get rid of INotifyBuildComplete in favor of using the upgrade system - public virtual void BuildingComplete(Actor self) + protected virtual void OnBuildComplete(Actor self) { DefaultAnimation.PlayRepeating(NormalizeSequence(self, Info.Sequence)); } + // TODO: Get rid of INotifyBuildComplete in favor of using the upgrade system + void INotifyBuildComplete.BuildingComplete(Actor self) + { + OnBuildComplete(self); + } + public void PlayCustomAnimation(Actor self, string name, Action after = null) { DefaultAnimation.PlayThen(NormalizeSequence(self, name), () => @@ -112,10 +117,15 @@ namespace OpenRA.Mods.Common.Traits.Render DefaultAnimation.PlayRepeating(NormalizeSequence(self, Info.Sequence)); } - public virtual void DamageStateChanged(Actor self, AttackInfo e) + protected virtual void DamageStateChanged(Actor self) { if (DefaultAnimation.CurrentSequence != null) DefaultAnimation.ReplaceAnim(NormalizeSequence(self, DefaultAnimation.CurrentSequence.Name)); } + + void INotifyDamageStateChanged.DamageStateChanged(Actor self, AttackInfo e) + { + DamageStateChanged(self); + } } } diff --git a/OpenRA.Mods.Common/Traits/Render/WithSpriteTurret.cs b/OpenRA.Mods.Common/Traits/Render/WithSpriteTurret.cs index abfcaa4be1..17b5603b2b 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithSpriteTurret.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithSpriteTurret.cs @@ -113,13 +113,13 @@ namespace OpenRA.Mods.Common.Traits.Render return RenderSprites.NormalizeSequence(DefaultAnimation, self.GetDamageState(), sequence); } - public virtual void DamageStateChanged(Actor self, AttackInfo e) + protected virtual void DamageStateChanged(Actor self) { if (DefaultAnimation.CurrentSequence != null) DefaultAnimation.ReplaceAnim(NormalizeSequence(self, DefaultAnimation.CurrentSequence.Name)); } - public virtual void Tick(Actor self) + protected virtual void Tick(Actor self) { if (Info.AimSequence == null) return; @@ -128,6 +128,17 @@ namespace OpenRA.Mods.Common.Traits.Render DefaultAnimation.ReplaceAnim(sequence); } + void INotifyDamageStateChanged.DamageStateChanged(Actor self, AttackInfo e) + { + DamageStateChanged(self); + } + + void ITick.Tick(Actor self) + { + // Split into a protected method to allow subclassing + Tick(self); + } + void INotifyBuildComplete.BuildingComplete(Actor self) { buildComplete = true; } void INotifySold.Selling(Actor self) { buildComplete = false; } void INotifySold.Sold(Actor self) { } diff --git a/OpenRA.Mods.Common/Traits/Render/WithTurretedSpriteBody.cs b/OpenRA.Mods.Common/Traits/Render/WithTurretedSpriteBody.cs index 2c90b53b6d..796de98c99 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithTurretedSpriteBody.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithTurretedSpriteBody.cs @@ -54,9 +54,9 @@ namespace OpenRA.Mods.Common.Traits.Render turreted.QuantizedFacings = DefaultAnimation.CurrentSequence.Facings; } - public override void DamageStateChanged(Actor self, AttackInfo e) + protected override void DamageStateChanged(Actor self) { - base.DamageStateChanged(self, e); + base.DamageStateChanged(self); turreted.QuantizedFacings = DefaultAnimation.CurrentSequence.Facings; } } diff --git a/OpenRA.Mods.Common/Traits/Render/WithWallSpriteBody.cs b/OpenRA.Mods.Common/Traits/Render/WithWallSpriteBody.cs index 891e0dcecd..dbaaaf2e83 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithWallSpriteBody.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithWallSpriteBody.cs @@ -101,12 +101,12 @@ namespace OpenRA.Mods.Common.Traits.Render wallInfo = info; } - public override void DamageStateChanged(Actor self, AttackInfo e) + protected override void DamageStateChanged(Actor self) { DefaultAnimation.PlayFetchIndex(NormalizeSequence(self, Info.Sequence), () => adjacent); } - public void Tick(Actor self) + void ITick.Tick(Actor self) { if (!dirty) return; @@ -136,7 +136,7 @@ namespace OpenRA.Mods.Common.Traits.Render dirty = false; } - public override void BuildingComplete(Actor self) + protected override void OnBuildComplete(Actor self) { DefaultAnimation.PlayFetchIndex(NormalizeSequence(self, Info.Sequence), () => adjacent); UpdateNeighbours(self); diff --git a/OpenRA.Mods.Common/Traits/Sound/AnnounceOnBuild.cs b/OpenRA.Mods.Common/Traits/Sound/AnnounceOnBuild.cs index c2c1bc6293..9cf416d0cd 100644 --- a/OpenRA.Mods.Common/Traits/Sound/AnnounceOnBuild.cs +++ b/OpenRA.Mods.Common/Traits/Sound/AnnounceOnBuild.cs @@ -31,7 +31,7 @@ namespace OpenRA.Mods.Common.Traits.Sound this.info = info; } - public void BuildingComplete(Actor self) + void INotifyBuildComplete.BuildingComplete(Actor self) { self.PlayVoice(info.Voice); } diff --git a/OpenRA.Mods.Common/Traits/Sound/SoundOnDamageTransition.cs b/OpenRA.Mods.Common/Traits/Sound/SoundOnDamageTransition.cs index 27f9a37b59..6c2e1050a2 100644 --- a/OpenRA.Mods.Common/Traits/Sound/SoundOnDamageTransition.cs +++ b/OpenRA.Mods.Common/Traits/Sound/SoundOnDamageTransition.cs @@ -33,7 +33,7 @@ namespace OpenRA.Mods.Common.Traits.Sound this.info = info; } - public void DamageStateChanged(Actor self, AttackInfo e) + void INotifyDamageStateChanged.DamageStateChanged(Actor self, AttackInfo e) { var rand = Game.CosmeticRandom; diff --git a/OpenRA.Mods.Common/TraitsInterfaces.cs b/OpenRA.Mods.Common/TraitsInterfaces.cs index 906830150c..2cc0a67c33 100644 --- a/OpenRA.Mods.Common/TraitsInterfaces.cs +++ b/OpenRA.Mods.Common/TraitsInterfaces.cs @@ -70,7 +70,12 @@ namespace OpenRA.Mods.Common.Traits void PreparingAttack(Actor self, Target target, Armament a, Barrel barrel); } + [RequireExplicitImplementation] public interface INotifyBuildComplete { void BuildingComplete(Actor self); } + + [RequireExplicitImplementation] + public interface INotifyDamageStateChanged { void DamageStateChanged(Actor self, AttackInfo e); } + public interface INotifyBuildingPlaced { void BuildingPlaced(Actor self); } public interface INotifyRepair { void Repairing(Actor self, Actor target); } public interface INotifyBurstComplete { void FiredBurst(Actor self, Target target, Armament a); } @@ -82,11 +87,13 @@ namespace OpenRA.Mods.Common.Traits public interface INotifyDocking { void Docked(Actor self, Actor harvester); void Undocked(Actor self, Actor harvester); } public interface INotifyParachuteLanded { void OnLanded(Actor ignore); } public interface INotifyCapture { void OnCapture(Actor self, Actor captor, Player oldOwner, Player newOwner); } - public interface INotifyInfiltrated { void Infiltrated(Actor self, Actor infiltrator); } public interface INotifyDiscovered { void OnDiscovered(Actor self, Player discoverer, bool playNotification); } public interface IRenderActorPreviewInfo : ITraitInfo { IEnumerable RenderPreview(ActorPreviewInitializer init); } public interface ICruiseAltitudeInfo : ITraitInfo { WDist GetCruiseAltitude(); } + [RequireExplicitImplementation] + public interface INotifyInfiltrated { void Infiltrated(Actor self, Actor infiltrator); } + [RequireExplicitImplementation] public interface INotifyBlockingMove { void OnNotifyBlockingMove(Actor self, Actor blocking); } diff --git a/OpenRA.Mods.D2k/Traits/Render/WithCrumbleOverlay.cs b/OpenRA.Mods.D2k/Traits/Render/WithCrumbleOverlay.cs index da2d41b3ae..1961a07866 100644 --- a/OpenRA.Mods.D2k/Traits/Render/WithCrumbleOverlay.cs +++ b/OpenRA.Mods.D2k/Traits/Render/WithCrumbleOverlay.cs @@ -51,7 +51,7 @@ namespace OpenRA.Mods.D2k.Traits.Render rs.Add(anim, info.Palette, info.IsPlayerPalette); } - public void BuildingComplete(Actor self) + void INotifyBuildComplete.BuildingComplete(Actor self) { buildComplete = true; } diff --git a/OpenRA.Mods.RA/Traits/Infiltration/InfiltrateForCash.cs b/OpenRA.Mods.RA/Traits/Infiltration/InfiltrateForCash.cs index d2f9e6f36b..0f88a42abb 100644 --- a/OpenRA.Mods.RA/Traits/Infiltration/InfiltrateForCash.cs +++ b/OpenRA.Mods.RA/Traits/Infiltration/InfiltrateForCash.cs @@ -41,7 +41,7 @@ namespace OpenRA.Mods.RA.Traits public InfiltrateForCash(InfiltrateForCashInfo info) { this.info = info; } - public void Infiltrated(Actor self, Actor infiltrator) + void INotifyInfiltrated.Infiltrated(Actor self, Actor infiltrator) { var targetResources = self.Owner.PlayerActor.Trait(); var spyResources = infiltrator.Owner.PlayerActor.Trait(); diff --git a/OpenRA.Mods.RA/Traits/Infiltration/InfiltrateForDecoration.cs b/OpenRA.Mods.RA/Traits/Infiltration/InfiltrateForDecoration.cs index 4a3bab997e..704bea6604 100644 --- a/OpenRA.Mods.RA/Traits/Infiltration/InfiltrateForDecoration.cs +++ b/OpenRA.Mods.RA/Traits/Infiltration/InfiltrateForDecoration.cs @@ -30,7 +30,7 @@ namespace OpenRA.Mods.RA.Traits public InfiltrateForDecoration(Actor self, InfiltrateForDecorationInfo info) : base(self, info) { } - public void Infiltrated(Actor self, Actor infiltrator) + void INotifyInfiltrated.Infiltrated(Actor self, Actor infiltrator) { infiltrators.Add(infiltrator.Owner); } diff --git a/OpenRA.Mods.RA/Traits/Infiltration/InfiltrateForExploration.cs b/OpenRA.Mods.RA/Traits/Infiltration/InfiltrateForExploration.cs index 85dfd86ef3..f8e58d8d48 100644 --- a/OpenRA.Mods.RA/Traits/Infiltration/InfiltrateForExploration.cs +++ b/OpenRA.Mods.RA/Traits/Infiltration/InfiltrateForExploration.cs @@ -19,7 +19,7 @@ namespace OpenRA.Mods.RA.Traits class InfiltrateForExploration : INotifyInfiltrated { - public void Infiltrated(Actor self, Actor infiltrator) + void INotifyInfiltrated.Infiltrated(Actor self, Actor infiltrator) { infiltrator.Owner.Shroud.Explore(self.Owner.Shroud); if (!self.Owner.HasFogVisibility) diff --git a/OpenRA.Mods.RA/Traits/Infiltration/InfiltrateForPowerOutage.cs b/OpenRA.Mods.RA/Traits/Infiltration/InfiltrateForPowerOutage.cs index b8f064136e..78f93f0105 100644 --- a/OpenRA.Mods.RA/Traits/Infiltration/InfiltrateForPowerOutage.cs +++ b/OpenRA.Mods.RA/Traits/Infiltration/InfiltrateForPowerOutage.cs @@ -32,12 +32,12 @@ namespace OpenRA.Mods.RA.Traits playerPower = self.Owner.PlayerActor.Trait(); } - public void Infiltrated(Actor self, Actor infiltrator) + void INotifyInfiltrated.Infiltrated(Actor self, Actor infiltrator) { playerPower.TriggerPowerOutage(info.Duration); } - public void OnOwnerChanged(Actor self, Player oldOwner, Player newOwner) + void INotifyOwnerChanged.OnOwnerChanged(Actor self, Player oldOwner, Player newOwner) { playerPower = self.Owner.PlayerActor.Trait(); } diff --git a/OpenRA.Mods.RA/Traits/Infiltration/InfiltrateForSupportPower.cs b/OpenRA.Mods.RA/Traits/Infiltration/InfiltrateForSupportPower.cs index 2513a86d16..d6cb524522 100644 --- a/OpenRA.Mods.RA/Traits/Infiltration/InfiltrateForSupportPower.cs +++ b/OpenRA.Mods.RA/Traits/Infiltration/InfiltrateForSupportPower.cs @@ -31,7 +31,7 @@ namespace OpenRA.Mods.RA.Traits this.info = info; } - public void Infiltrated(Actor self, Actor infiltrator) + void INotifyInfiltrated.Infiltrated(Actor self, Actor infiltrator) { infiltrator.World.AddFrameEndTask(w => w.CreateActor(info.Proxy, new TypeDictionary {