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.Collections.Generic;
using System.Linq;
using OpenRA.Activities;
using OpenRA.Mods.Common.Activities;
using OpenRA.Mods.Common.Orders;
@@ -20,9 +19,13 @@ namespace OpenRA.Mods.Common.Traits
{
public class DeployToUpgradeInfo : ITraitInfo, Requires<UpgradeManagerInfo>
{
[UpgradeGrantedReference]
[Desc("The upgrades to grant while the actor is undeployed.")]
public readonly string[] UndeployedUpgrades = { };
[UpgradeGrantedReference, FieldLoader.Require]
[Desc("The upgrades to grant when deploying and revoke when undeploying.")]
public readonly string[] Upgrades = { };
[Desc("The upgrades to grant after deploying and revoke before undeploying.")]
public readonly string[] DeployedUpgrades = { };
[Desc("The terrain types that this actor can deploy on to receive these upgrades. " +
"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 class DeployToUpgrade : IResolveOrder, IIssueOrder
public class DeployToUpgrade : IResolveOrder, IIssueOrder, INotifyCreated
{
enum DeployState { Undeployed, Deploying, Deployed }
readonly Actor self;
readonly DeployToUpgradeInfo info;
readonly UpgradeManager manager;
@@ -61,7 +66,7 @@ namespace OpenRA.Mods.Common.Traits
readonly bool canTurn;
readonly Lazy<ISpriteBody> body;
bool isUpgraded;
DeployState deployState;
public DeployToUpgrade(Actor self, DeployToUpgradeInfo info)
{
@@ -73,6 +78,11 @@ namespace OpenRA.Mods.Common.Traits
body = Exts.Lazy(self.TraitOrDefault<ISpriteBody>);
}
public void Created(Actor self)
{
OnUndeployCompleted();
}
public IEnumerable<IOrderTargeter> Orders
{
get { yield return new DeployOrderTargeter("DeployToUpgrade", 5,
@@ -89,59 +99,24 @@ namespace OpenRA.Mods.Common.Traits
public void ResolveOrder(Actor self, Order order)
{
if (order.OrderString != "DeployToUpgrade")
if (order.OrderString != "DeployToUpgrade" || deployState == DeployState.Deploying)
return;
if (!IsOnValidTerrain())
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
{
if (!order.Queued)
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)
self.QueueActivity(new Turn(self, info.Facing));
// Grant the upgrade
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"));
}));
self.QueueActivity(new CallFunc(Deploy));
}
isUpgraded = !isUpgraded;
}
bool IsOnValidTerrain()
@@ -181,16 +156,80 @@ namespace OpenRA.Mods.Common.Traits
return ramp == 0;
}
void GrantUpgrades()
/// <summary>Play deploy sound and animation.</summary>
void Deploy()
{
foreach (var up in info.Upgrades)
manager.GrantUpgrade(self, up, this);
// Something went wrong, most likely due to deploy order spam and the fact that this is a delayed action.
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);
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;
}
}
}