Fix WithDisguisingInfantryBody idle animation crash.

This commit is contained in:
Paul Chote
2020-03-01 12:36:21 +00:00
committed by Matthias Mailänder
parent e6314a944c
commit ce91c5a76f
2 changed files with 35 additions and 13 deletions

View File

@@ -9,6 +9,7 @@
*/ */
#endregion #endregion
using System.Linq;
using OpenRA.Mods.Common.Traits.Render; using OpenRA.Mods.Common.Traits.Render;
using OpenRA.Traits; using OpenRA.Traits;
@@ -21,39 +22,53 @@ namespace OpenRA.Mods.Cnc.Traits.Render
class WithDisguisingInfantryBody : WithInfantryBody class WithDisguisingInfantryBody : WithInfantryBody
{ {
readonly WithDisguisingInfantryBodyInfo info;
readonly Disguise disguise; readonly Disguise disguise;
readonly RenderSprites rs; readonly RenderSprites rs;
ActorInfo disguiseActor; ActorInfo disguiseActor;
Player disguisePlayer; Player disguisePlayer;
WithInfantryBodyInfo disguiseInfantryBody;
string disguiseImage; string disguiseImage;
public WithDisguisingInfantryBody(ActorInitializer init, WithDisguisingInfantryBodyInfo info) public WithDisguisingInfantryBody(ActorInitializer init, WithDisguisingInfantryBodyInfo info)
: base(init, info) : base(init, info)
{ {
this.info = info;
rs = init.Self.Trait<RenderSprites>(); rs = init.Self.Trait<RenderSprites>();
disguise = init.Self.Trait<Disguise>(); disguise = init.Self.Trait<Disguise>();
} }
protected override WithInfantryBodyInfo GetDisplayInfo()
{
return disguiseInfantryBody ?? Info;
}
protected override void Tick(Actor self) protected override void Tick(Actor self)
{ {
if (disguise.AsActor != disguiseActor || disguise.AsPlayer != disguisePlayer) if (disguise.AsActor != disguiseActor || disguise.AsPlayer != disguisePlayer)
{ {
// Force actor back to the stand state to avoid mismatched sequences
PlayStandAnimation(self);
disguiseActor = disguise.AsActor; disguiseActor = disguise.AsActor;
disguisePlayer = disguise.AsPlayer; disguisePlayer = disguise.AsPlayer;
disguiseImage = null; disguiseImage = null;
disguiseInfantryBody = null;
if (disguisePlayer != null) if (disguisePlayer != null)
{ {
var renderSprites = disguiseActor.TraitInfoOrDefault<RenderSpritesInfo>(); var renderSprites = disguiseActor.TraitInfoOrDefault<RenderSpritesInfo>();
if (renderSprites != null) var infantryBody = disguiseActor.TraitInfos<WithInfantryBodyInfo>()
.FirstOrDefault(t => t.EnabledByDefault);
if (renderSprites != null && infantryBody != null)
{
disguiseImage = renderSprites.GetImage(disguiseActor, self.World.Map.Rules.Sequences, disguisePlayer.InternalName); disguiseImage = renderSprites.GetImage(disguiseActor, self.World.Map.Rules.Sequences, disguisePlayer.InternalName);
disguiseInfantryBody = infantryBody;
}
} }
var sequence = DefaultAnimation.GetRandomExistingSequence(info.StandSequences, Game.CosmeticRandom); var sequence = DefaultAnimation.GetRandomExistingSequence(GetDisplayInfo().StandSequences, Game.CosmeticRandom);
if (sequence != null) if (sequence != null)
DefaultAnimation.ChangeImage(disguiseImage ?? rs.GetImage(self), sequence); DefaultAnimation.ChangeImage(disguiseImage ?? rs.GetImage(self), sequence);
rs.UpdatePalette(); rs.UpdatePalette();
} }

View File

@@ -55,7 +55,6 @@ namespace OpenRA.Mods.Common.Traits.Render
{ {
readonly IMove move; readonly IMove move;
protected readonly Animation DefaultAnimation; protected readonly Animation DefaultAnimation;
readonly bool hasIdleSequence;
bool dirty; bool dirty;
string idleSequence; string idleSequence;
@@ -66,6 +65,12 @@ namespace OpenRA.Mods.Common.Traits.Render
bool IsModifyingSequence { get { return rsm != null && rsm.IsModifyingSequence; } } bool IsModifyingSequence { get { return rsm != null && rsm.IsModifyingSequence; } }
bool wasModifying; bool wasModifying;
// Allow subclasses to override the info that we use for rendering
protected virtual WithInfantryBodyInfo GetDisplayInfo()
{
return Info;
}
public WithInfantryBody(ActorInitializer init, WithInfantryBodyInfo info) public WithInfantryBody(ActorInitializer init, WithInfantryBodyInfo info)
: base(info) : base(info)
{ {
@@ -75,7 +80,6 @@ namespace OpenRA.Mods.Common.Traits.Render
DefaultAnimation = new Animation(init.World, rs.GetImage(self), RenderSprites.MakeFacingFunc(self)); DefaultAnimation = new Animation(init.World, rs.GetImage(self), RenderSprites.MakeFacingFunc(self));
rs.Add(new AnimationWithOffset(DefaultAnimation, null, () => IsTraitDisabled)); rs.Add(new AnimationWithOffset(DefaultAnimation, null, () => IsTraitDisabled));
PlayStandAnimation(self); PlayStandAnimation(self);
hasIdleSequence = Info.IdleSequences.Length > 0;
move = init.Self.Trait<IMove>(); move = init.Self.Trait<IMove>();
} }
@@ -83,7 +87,8 @@ namespace OpenRA.Mods.Common.Traits.Render
protected override void Created(Actor self) protected override void Created(Actor self)
{ {
rsm = self.TraitOrDefault<IRenderInfantrySequenceModifier>(); rsm = self.TraitOrDefault<IRenderInfantrySequenceModifier>();
idleDelay = self.World.SharedRandom.Next(Info.MinIdleDelay, Info.MaxIdleDelay); var info = GetDisplayInfo();
idleDelay = self.World.SharedRandom.Next(info.MinIdleDelay, info.MaxIdleDelay);
base.Created(self); base.Created(self);
} }
@@ -100,7 +105,7 @@ namespace OpenRA.Mods.Common.Traits.Render
protected virtual bool AllowIdleAnimation(Actor self) protected virtual bool AllowIdleAnimation(Actor self)
{ {
return hasIdleSequence && !IsModifyingSequence; return GetDisplayInfo().IdleSequences.Length > 0 && !IsModifyingSequence;
} }
public void PlayStandAnimation(Actor self) public void PlayStandAnimation(Actor self)
@@ -118,8 +123,9 @@ namespace OpenRA.Mods.Common.Traits.Render
public void Attacking(Actor self, Target target, Armament a) public void Attacking(Actor self, Target target, Armament a)
{ {
string sequence; string sequence;
if (!Info.AttackSequences.TryGetValue(a.Info.Name, out sequence)) var info = GetDisplayInfo();
sequence = Info.DefaultAttackSequence; if (!info.AttackSequences.TryGetValue(a.Info.Name, out sequence))
sequence = info.DefaultAttackSequence;
if (!string.IsNullOrEmpty(sequence) && DefaultAnimation.HasSequence(NormalizeInfantrySequence(self, sequence))) if (!string.IsNullOrEmpty(sequence) && DefaultAnimation.HasSequence(NormalizeInfantrySequence(self, sequence)))
{ {
@@ -153,7 +159,7 @@ namespace OpenRA.Mods.Common.Traits.Render
if ((state != AnimationState.Moving || dirty) && move.CurrentMovementTypes.HasFlag(MovementType.Horizontal)) if ((state != AnimationState.Moving || dirty) && move.CurrentMovementTypes.HasFlag(MovementType.Horizontal))
{ {
state = AnimationState.Moving; state = AnimationState.Moving;
DefaultAnimation.PlayRepeating(NormalizeInfantrySequence(self, Info.MoveSequence)); DefaultAnimation.PlayRepeating(NormalizeInfantrySequence(self, GetDisplayInfo().MoveSequence));
} }
else if (((state == AnimationState.Moving || dirty) && !move.CurrentMovementTypes.HasFlag(MovementType.Horizontal)) else if (((state == AnimationState.Moving || dirty) && !move.CurrentMovementTypes.HasFlag(MovementType.Horizontal))
|| ((state == AnimationState.Idle || state == AnimationState.IdleAnimating) && !self.IsIdle)) || ((state == AnimationState.Idle || state == AnimationState.IdleAnimating) && !self.IsIdle))
@@ -170,8 +176,9 @@ namespace OpenRA.Mods.Common.Traits.Render
if (state == AnimationState.Waiting) if (state == AnimationState.Waiting)
{ {
state = AnimationState.Idle; state = AnimationState.Idle;
idleSequence = Info.IdleSequences.Random(self.World.SharedRandom); var info = GetDisplayInfo();
idleDelay = self.World.SharedRandom.Next(Info.MinIdleDelay, Info.MaxIdleDelay); idleSequence = info.IdleSequences.Random(self.World.SharedRandom);
idleDelay = self.World.SharedRandom.Next(info.MinIdleDelay, info.MaxIdleDelay);
} }
else if (state == AnimationState.Idle && idleDelay > 0 && --idleDelay == 0) else if (state == AnimationState.Idle && idleDelay > 0 && --idleDelay == 0)
{ {