Add support for deploy animations using a specific upgrade

Also ignore orders while playing a deploy/undeploy animation. Fixes 9242.

We grant a level 1 Undeployed upgrade(s) when the actor is created which enables the default behavior of the actor. When the actor receives a deploy order, the Undeployed upgrade(s) is(are) revoked, which may or may not be used to enable a trait to play a deploy animation. Once the deployment is complete, the Deployed upgrade(s) is(are) granted.
Then do the reverse when undeploying, disabling weapons and other systems first by revoking the Deployed upgrade(s), and granting the Undeployed upgrade(s) when the undeploy animation is done.
This commit is contained in:
Pavel Penev
2015-11-16 00:48:27 +02:00
parent be49435265
commit 7e4f0be7fb

View File

@@ -10,7 +10,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using OpenRA.Activities; using OpenRA.Activities;
using OpenRA.Mods.Common.Activities; using OpenRA.Mods.Common.Activities;
using OpenRA.Mods.Common.Orders; using OpenRA.Mods.Common.Orders;
@@ -20,9 +19,13 @@ namespace OpenRA.Mods.Common.Traits
{ {
public class DeployToUpgradeInfo : ITraitInfo, Requires<UpgradeManagerInfo> public class DeployToUpgradeInfo : ITraitInfo, Requires<UpgradeManagerInfo>
{ {
[UpgradeGrantedReference]
[Desc("The upgrades to grant while the actor is undeployed.")]
public readonly string[] UndeployedUpgrades = { };
[UpgradeGrantedReference, FieldLoader.Require] [UpgradeGrantedReference, FieldLoader.Require]
[Desc("The upgrades to grant when deploying and revoke when undeploying.")] [Desc("The upgrades to grant after deploying and revoke before undeploying.")]
public readonly string[] Upgrades = { }; public readonly string[] DeployedUpgrades = { };
[Desc("The terrain types that this actor can deploy on to receive these upgrades. " + [Desc("The terrain types that this actor can deploy on to receive these upgrades. " +
"Leave empty to allow any.")] "Leave empty to allow any.")]
@@ -52,8 +55,10 @@ namespace OpenRA.Mods.Common.Traits
public object Create(ActorInitializer init) { return new DeployToUpgrade(init.Self, this); } public object Create(ActorInitializer init) { return new DeployToUpgrade(init.Self, this); }
} }
public class DeployToUpgrade : IResolveOrder, IIssueOrder public class DeployToUpgrade : IResolveOrder, IIssueOrder, INotifyCreated
{ {
enum DeployState { Undeployed, Deploying, Deployed }
readonly Actor self; readonly Actor self;
readonly DeployToUpgradeInfo info; readonly DeployToUpgradeInfo info;
readonly UpgradeManager manager; readonly UpgradeManager manager;
@@ -61,7 +66,7 @@ namespace OpenRA.Mods.Common.Traits
readonly bool canTurn; readonly bool canTurn;
readonly Lazy<ISpriteBody> body; readonly Lazy<ISpriteBody> body;
bool isUpgraded; DeployState deployState;
public DeployToUpgrade(Actor self, DeployToUpgradeInfo info) public DeployToUpgrade(Actor self, DeployToUpgradeInfo info)
{ {
@@ -73,6 +78,11 @@ namespace OpenRA.Mods.Common.Traits
body = Exts.Lazy(self.TraitOrDefault<ISpriteBody>); body = Exts.Lazy(self.TraitOrDefault<ISpriteBody>);
} }
public void Created(Actor self)
{
OnUndeployCompleted();
}
public IEnumerable<IOrderTargeter> Orders public IEnumerable<IOrderTargeter> Orders
{ {
get { yield return new DeployOrderTargeter("DeployToUpgrade", 5, get { yield return new DeployOrderTargeter("DeployToUpgrade", 5,
@@ -89,59 +99,24 @@ namespace OpenRA.Mods.Common.Traits
public void ResolveOrder(Actor self, Order order) public void ResolveOrder(Actor self, Order order)
{ {
if (order.OrderString != "DeployToUpgrade") if (order.OrderString != "DeployToUpgrade" || deployState == DeployState.Deploying)
return; return;
if (!IsOnValidTerrain()) if (!order.Queued)
return;
if (isUpgraded)
{
// Play undeploy animation and after that revoke the upgrades
self.QueueActivity(false, new CallFunc(() =>
{
if (!string.IsNullOrEmpty(info.UndeploySound))
Game.Sound.Play(info.UndeploySound, self.CenterPosition);
if (string.IsNullOrEmpty(info.DeployAnimation))
{
RevokeUpgrades();
return;
}
if (body.Value != null)
body.Value.PlayCustomAnimationBackwards(self, info.DeployAnimation, RevokeUpgrades);
else
RevokeUpgrades();
}));
}
else
{
self.CancelActivity(); self.CancelActivity();
// Turn if (deployState == DeployState.Deployed)
{
self.QueueActivity(new CallFunc(Undeploy));
}
else if (deployState == DeployState.Undeployed)
{
// Turn to the required facing.
if (info.Facing != -1 && canTurn) if (info.Facing != -1 && canTurn)
self.QueueActivity(new Turn(self, info.Facing)); self.QueueActivity(new Turn(self, info.Facing));
// Grant the upgrade self.QueueActivity(new CallFunc(Deploy));
self.QueueActivity(new CallFunc(GrantUpgrades));
// Play deploy sound and animation
self.QueueActivity(new CallFunc(() =>
{
if (!string.IsNullOrEmpty(info.DeploySound))
Game.Sound.Play(info.DeploySound, self.CenterPosition);
if (string.IsNullOrEmpty(info.DeployAnimation))
return;
if (body.Value != null)
body.Value.PlayCustomAnimation(self, info.DeployAnimation,
() => body.Value.PlayCustomAnimationRepeating(self, "idle"));
}));
} }
isUpgraded = !isUpgraded;
} }
bool IsOnValidTerrain() bool IsOnValidTerrain()
@@ -181,16 +156,80 @@ namespace OpenRA.Mods.Common.Traits
return ramp == 0; return ramp == 0;
} }
void GrantUpgrades() /// <summary>Play deploy sound and animation.</summary>
void Deploy()
{ {
foreach (var up in info.Upgrades) // Something went wrong, most likely due to deploy order spam and the fact that this is a delayed action.
manager.GrantUpgrade(self, up, this); if (deployState != DeployState.Undeployed)
return;
if (!IsOnValidTerrain())
return;
if (!string.IsNullOrEmpty(info.DeploySound))
Game.Sound.Play(info.DeploySound, self.CenterPosition);
// Revoke upgrades that are used while undeployed.
OnDeployStarted();
// If there is no animation to play just grant the upgrades that are used while deployed.
// Alternatively, play the deploy animation and then grant the upgrades.
if (string.IsNullOrEmpty(info.DeployAnimation) || body.Value == null)
OnDeployCompleted();
else
body.Value.PlayCustomAnimation(self, info.DeployAnimation, OnDeployCompleted);
} }
void RevokeUpgrades() /// <summary>Play undeploy sound and animation and after that revoke the upgrades.</summary>
void Undeploy()
{ {
foreach (var up in info.Upgrades) // Something went wrong, most likely due to deploy order spam and the fact that this is a delayed action.
if (deployState != DeployState.Deployed)
return;
if (!string.IsNullOrEmpty(info.UndeploySound))
Game.Sound.Play(info.UndeploySound, self.CenterPosition);
OnUndeployStarted();
// If there is no animation to play just grant the upgrades that are used while undeployed.
// Alternatively, play the undeploy animation and then grant the upgrades.
if (string.IsNullOrEmpty(info.DeployAnimation) || body.Value == null)
OnUndeployCompleted();
else
body.Value.PlayCustomAnimationBackwards(self, info.DeployAnimation, OnUndeployCompleted);
}
void OnDeployStarted()
{
foreach (var up in info.UndeployedUpgrades)
manager.RevokeUpgrade(self, up, this); manager.RevokeUpgrade(self, up, this);
deployState = DeployState.Deploying;
}
void OnDeployCompleted()
{
foreach (var up in info.DeployedUpgrades)
manager.GrantUpgrade(self, up, this);
deployState = DeployState.Deployed;
}
void OnUndeployStarted()
{
foreach (var up in info.DeployedUpgrades)
manager.RevokeUpgrade(self, up, this);
deployState = DeployState.Deploying;
}
void OnUndeployCompleted()
{
foreach (var up in info.UndeployedUpgrades)
manager.GrantUpgrade(self, up, this);
deployState = DeployState.Undeployed;
} }
} }
} }