From afb97ac4b450eeba087ac24250956dbb100905e9 Mon Sep 17 00:00:00 2001 From: penev92 Date: Tue, 5 May 2015 03:51:50 +0300 Subject: [PATCH 1/2] Make WithInfantryBody upgradable --- .../Traits/Render/WithInfantryBody.cs | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/OpenRA.Mods.Common/Traits/Render/WithInfantryBody.cs b/OpenRA.Mods.Common/Traits/Render/WithInfantryBody.cs index 4d738874d8..56dfdaec86 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithInfantryBody.cs +++ b/OpenRA.Mods.Common/Traits/Render/WithInfantryBody.cs @@ -16,7 +16,8 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { - public class WithInfantryBodyInfo : ITraitInfo, IQuantizeBodyOrientationInfo, IRenderActorPreviewSpritesInfo, Requires, Requires + public class WithInfantryBodyInfo : UpgradableTraitInfo, ITraitInfo, IQuantizeBodyOrientationInfo, IRenderActorPreviewSpritesInfo, + Requires, Requires { public readonly int MinIdleWaitTicks = 30; public readonly int MaxIdleWaitTicks = 110; @@ -46,29 +47,28 @@ namespace OpenRA.Mods.Common.Traits } } - public class WithInfantryBody : ITick, INotifyAttack, INotifyIdle + public class WithInfantryBody : UpgradableTrait, ITick, INotifyAttack, INotifyIdle { - readonly WithInfantryBodyInfo info; readonly IMove move; + readonly IRenderInfantrySequenceModifier rsm; protected readonly Animation DefaultAnimation; - bool dirty = false; + bool dirty; string idleSequence; int idleDelay; AnimationState state; - IRenderInfantrySequenceModifier rsm; bool IsModifyingSequence { get { return rsm != null && rsm.IsModifyingSequence; } } bool wasModifying; public WithInfantryBody(ActorInitializer init, WithInfantryBodyInfo info) + : base(info) { - this.info = info; var self = init.Self; var rs = self.Trait(); DefaultAnimation = new Animation(init.World, rs.GetImage(self), RenderSprites.MakeFacingFunc(self)); - rs.Add(DefaultAnimation); + rs.Add(new AnimationWithOffset(DefaultAnimation, null, () => IsTraitDisabled)); DefaultAnimation.PlayFetchIndex(NormalizeInfantrySequence(init.Self, info.StandSequences.Random(Game.CosmeticRandom)), () => 0); state = AnimationState.Waiting; @@ -94,8 +94,8 @@ namespace OpenRA.Mods.Common.Traits public void Attacking(Actor self, Target target) { state = AnimationState.Attacking; - if (DefaultAnimation.HasSequence(NormalizeInfantrySequence(self, info.AttackSequence))) - DefaultAnimation.PlayThen(NormalizeInfantrySequence(self, info.AttackSequence), () => state = AnimationState.Idle); + if (DefaultAnimation.HasSequence(NormalizeInfantrySequence(self, Info.AttackSequence))) + DefaultAnimation.PlayThen(NormalizeInfantrySequence(self, Info.AttackSequence), () => state = AnimationState.Idle); } public void Attacking(Actor self, Target target, Armament a, Barrel barrel) @@ -116,12 +116,12 @@ namespace OpenRA.Mods.Common.Traits if ((state == AnimationState.Moving || dirty) && !move.IsMoving) { state = AnimationState.Waiting; - DefaultAnimation.PlayFetchIndex(NormalizeInfantrySequence(self, info.StandSequences.Random(Game.CosmeticRandom)), () => 0); + DefaultAnimation.PlayFetchIndex(NormalizeInfantrySequence(self, Info.StandSequences.Random(Game.CosmeticRandom)), () => 0); } else if ((state != AnimationState.Moving || dirty) && move.IsMoving) { state = AnimationState.Moving; - DefaultAnimation.PlayRepeating(NormalizeInfantrySequence(self, info.MoveSequence)); + DefaultAnimation.PlayRepeating(NormalizeInfantrySequence(self, Info.MoveSequence)); } dirty = false; @@ -131,13 +131,13 @@ namespace OpenRA.Mods.Common.Traits { if (state != AnimationState.Idle && state != AnimationState.IdleAnimating && state != AnimationState.Attacking) { - DefaultAnimation.PlayFetchIndex(NormalizeInfantrySequence(self, info.StandSequences.Random(Game.CosmeticRandom)), () => 0); + DefaultAnimation.PlayFetchIndex(NormalizeInfantrySequence(self, Info.StandSequences.Random(Game.CosmeticRandom)), () => 0); state = AnimationState.Idle; - if (info.IdleSequences.Length > 0) + if (Info.IdleSequences.Length > 0) { - idleSequence = info.IdleSequences.Random(self.World.SharedRandom); - idleDelay = self.World.SharedRandom.Next(info.MinIdleWaitTicks, info.MaxIdleWaitTicks); + idleSequence = Info.IdleSequences.Random(self.World.SharedRandom); + idleDelay = self.World.SharedRandom.Next(Info.MinIdleWaitTicks, Info.MaxIdleWaitTicks); } } else if (AllowIdleAnimation(self)) @@ -149,14 +149,14 @@ namespace OpenRA.Mods.Common.Traits state = AnimationState.IdleAnimating; DefaultAnimation.PlayThen(idleSequence, () => { - DefaultAnimation.PlayRepeating(NormalizeInfantrySequence(self, info.StandSequences.Random(Game.CosmeticRandom))); + DefaultAnimation.PlayRepeating(NormalizeInfantrySequence(self, Info.StandSequences.Random(Game.CosmeticRandom))); state = AnimationState.Waiting; }); } } else { - DefaultAnimation.PlayRepeating(NormalizeInfantrySequence(self, info.StandSequences.Random(Game.CosmeticRandom))); + DefaultAnimation.PlayRepeating(NormalizeInfantrySequence(self, Info.StandSequences.Random(Game.CosmeticRandom))); state = AnimationState.Waiting; } } From 5b00fddfc96ffec22ae0fca372dcf19dec0cdc31 Mon Sep 17 00:00:00 2001 From: penev92 Date: Tue, 5 May 2015 04:14:15 +0300 Subject: [PATCH 2/2] Make AttractsWorms upgradable --- OpenRA.Mods.D2k/Traits/AttractsWorms.cs | 34 ++++++++++++---- OpenRA.Mods.D2k/Traits/Sandworm.cs | 54 +++++++++---------------- 2 files changed, 47 insertions(+), 41 deletions(-) diff --git a/OpenRA.Mods.D2k/Traits/AttractsWorms.cs b/OpenRA.Mods.D2k/Traits/AttractsWorms.cs index 34a41abda9..84bac6eda9 100644 --- a/OpenRA.Mods.D2k/Traits/AttractsWorms.cs +++ b/OpenRA.Mods.D2k/Traits/AttractsWorms.cs @@ -8,12 +8,13 @@ */ #endregion +using OpenRA.Mods.Common.Traits; using OpenRA.Traits; namespace OpenRA.Mods.D2k.Traits { [Desc("This actor makes noise, which causes them to be targeted by actors with the Sandworm trait.")] - public class AttractsWormsInfo : ITraitInfo + public class AttractsWormsInfo : UpgradableTraitInfo, ITraitInfo { [Desc("How much noise this actor produces.")] public readonly int Intensity = 0; @@ -27,22 +28,23 @@ namespace OpenRA.Mods.D2k.Traits [Desc("Ranges at which each Falloff step is defined. Overrides Spread.")] public WRange[] Range = null; - public object Create(ActorInitializer init) { return new AttractsWorms(this); } + public object Create(ActorInitializer init) { return new AttractsWorms(init, this); } } - public class AttractsWorms + public class AttractsWorms : UpgradableTrait { - public readonly AttractsWormsInfo Info; + readonly Actor self; - public AttractsWorms(AttractsWormsInfo info) + public AttractsWorms(ActorInitializer init, AttractsWormsInfo info) + : base(info) { - Info = info; + self = init.Self; if (info.Range == null) info.Range = Exts.MakeArray(info.Falloff.Length, i => i * info.Spread); } - public int GetNoisePercentageAtDistance(int distance) + int GetNoisePercentageAtDistance(int distance) { var inner = Info.Range[0].Range; for (var i = 1; i < Info.Range.Length; i++) @@ -56,5 +58,23 @@ namespace OpenRA.Mods.D2k.Traits return 0; } + + public WVec AttractionAtPosition(WPos pos) + { + if (IsTraitDisabled) + return WVec.Zero; + + var distance = self.CenterPosition - pos; + var length = distance.Length; + + // Actor is too far to hear anything. + if (length > Info.Range[Info.Range.Length - 1].Range) + return WVec.Zero; + + var direction = 1024 * distance / length; + var percentage = GetNoisePercentageAtDistance(length); + + return direction * Info.Intensity * percentage / 100; + } } } \ No newline at end of file diff --git a/OpenRA.Mods.D2k/Traits/Sandworm.cs b/OpenRA.Mods.D2k/Traits/Sandworm.cs index d40d1fcfbb..6d8e0717bc 100644 --- a/OpenRA.Mods.D2k/Traits/Sandworm.cs +++ b/OpenRA.Mods.D2k/Traits/Sandworm.cs @@ -9,6 +9,7 @@ #endregion using System; +using System.Linq; using OpenRA.Mods.Common.Traits; using OpenRA.Traits; @@ -91,43 +92,28 @@ namespace OpenRA.Mods.D2k.Traits { targetCountdown = Info.TargetRescanInterval; - var actorsInRange = self.World.FindActorsInCircle(self.CenterPosition, Info.MaxSearchRadius); - var noiseDirection = WVec.Zero; - - foreach (var actor in actorsInRange) + // If close enough, we don't care about other actors. + var target = self.World.FindActorsInCircle(self.CenterPosition, Info.IgnoreNoiseAttackRange).FirstOrDefault(x => x.HasTrait()); + if (target != null) { - if (!actor.IsInWorld) - continue; - - // TODO: Test if we really want to ignore actors that are on rock - if (!mobile.Value.CanEnterCell(actor.Location, null, false)) - continue; - - var noise = actor.TraitOrDefault(); - if (noise == null) - continue; - - var distance = actor.CenterPosition - self.CenterPosition; - var length = distance.Length; - - // Actor is too far to be heard - if (noise.Info.Range[noise.Info.Range.Length - 1].Range < length) - continue; - - // If close enough, we don't care about other actors - if (length <= Info.IgnoreNoiseAttackRange.Range) - { - self.CancelActivity(); - attackTrait.Value.ResolveOrder(self, new Order("Attack", actor, true) { TargetActor = actor }); - return; - } - - var direction = 1024 * distance / length; - var percentage = noise.GetNoisePercentageAtDistance(length); - - noiseDirection += direction * noise.Info.Intensity * percentage / 100; + self.CancelActivity(); + attackTrait.Value.ResolveOrder(self, new Order("Attack", target, true) { TargetActor = target }); + return; } + Func isValidTarget = a => + { + if (!a.HasTrait()) + return false; + + return mobile.Value.CanEnterCell(a.Location, null, false); + }; + + var actorsInRange = self.World.FindActorsInCircle(self.CenterPosition, Info.MaxSearchRadius) + .Where(isValidTarget).SelectMany(a => a.TraitsImplementing()); + + var noiseDirection = actorsInRange.Aggregate(WVec.Zero, (a, b) => a + b.AttractionAtPosition(self.CenterPosition)); + // No target was found if (noiseDirection == WVec.Zero) return;