Add a lint check for cursor definitions.

This commit is contained in:
Matthias Mailänder
2021-03-14 16:01:33 +01:00
committed by reaperrr
parent cefb2e7cc6
commit bbbed49f82
40 changed files with 211 additions and 28 deletions

View File

@@ -63,6 +63,17 @@ namespace OpenRA.Traits
}
}
[AttributeUsage(AttributeTargets.Field)]
public sealed class CursorReferenceAttribute : Attribute
{
public readonly LintDictionaryReference DictionaryReference;
public CursorReferenceAttribute(LintDictionaryReference dictionaryReference = LintDictionaryReference.None)
{
DictionaryReference = dictionaryReference;
}
}
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public sealed class GrantedConditionReferenceAttribute : Attribute { }

View File

@@ -88,6 +88,7 @@ namespace OpenRA.Mods.Cnc.Traits
"A dictionary of [actor id]: [condition].")]
public readonly Dictionary<string, string> DisguisedAsConditions = new Dictionary<string, string>();
[CursorReference]
[Desc("Cursor to display when hovering over a valid actor to disguise as.")]
public readonly string Cursor = "ability";

View File

@@ -44,6 +44,7 @@ namespace OpenRA.Mods.Cnc.Traits
[Desc("Experience to grant to the infiltrating player.")]
public readonly int PlayerExperience = 0;
[CursorReference]
[Desc("Cursor to display when able to infiltrate the target actor.")]
public readonly string EnterCursor = "enter";

View File

@@ -61,7 +61,15 @@ namespace OpenRA.Mods.Cnc.Traits
[Desc("Types of damage that this trait causes to self while self-destructing. Leave empty for no damage types.")]
public readonly BitSet<DamageType> DamageTypes = default(BitSet<DamageType>);
public override object Create(ActorInitializer init) { return new MadTank(init.Self, this); }
[CursorReference]
[Desc("Cursor to display when targetting.")]
public readonly string AttackCursor = "attack";
[CursorReference]
[Desc("Cursor to display when able to set up the detonation sequence.")]
public readonly string DeployCursor = "deploy";
public override object Create(ActorInitializer init) { return new MadTank(this); }
public void RulesetLoaded(Ruleset rules, ActorInfo ai)
{
@@ -83,7 +91,9 @@ namespace OpenRA.Mods.Cnc.Traits
{
readonly MadTankInfo info;
public MadTank(Actor self, MadTankInfo info)
bool initiated;
public MadTank(MadTankInfo info)
{
this.info = info;
}
@@ -92,8 +102,10 @@ namespace OpenRA.Mods.Cnc.Traits
{
get
{
yield return new TargetTypeOrderTargeter(new BitSet<TargetableType>("DetonateAttack"), "DetonateAttack", 5, "attack", true, false) { ForceAttack = false };
yield return new DeployOrderTargeter("Detonate", 5);
yield return new TargetTypeOrderTargeter(new BitSet<TargetableType>("DetonateAttack"), "DetonateAttack", 5, info.AttackCursor, true, false) { ForceAttack = false };
if (!initiated)
yield return new DeployOrderTargeter("Detonate", 5, () => info.DeployCursor);
}
}
@@ -140,7 +152,6 @@ namespace OpenRA.Mods.Cnc.Traits
readonly bool assignTargetOnFirstRun;
int ticks;
bool initiated;
Target target;
public DetonationSequence(Actor self, MadTank mad)
@@ -176,7 +187,7 @@ namespace OpenRA.Mods.Cnc.Traits
return false;
}
if (!initiated)
if (!mad.initiated)
{
// If the target has died while we were moving, we should abort detonation.
if (target.Type == TargetType.Invalid)
@@ -189,7 +200,7 @@ namespace OpenRA.Mods.Cnc.Traits
wfsb.PlayCustomAnimationRepeating(self, mad.info.ThumpSequence);
IsInterruptible = false;
initiated = true;
mad.initiated = true;
}
if (++ticks % mad.info.ThumpInterval == 0)
@@ -209,7 +220,7 @@ namespace OpenRA.Mods.Cnc.Traits
protected override void OnLastRun(Actor self)
{
if (!initiated)
if (!mad.initiated)
return;
Game.Sound.Play(SoundType.World, mad.info.DetonationSound, self.CenterPosition);

View File

@@ -50,12 +50,18 @@ namespace OpenRA.Mods.Cnc.Traits
[Desc("Only allow laying mines on listed terrain types. Leave empty to allow all terrain types.")]
public readonly HashSet<string> TerrainTypes = new HashSet<string>();
[CursorReference]
[Desc("Cursor to display when able to lay a mine.")]
public readonly string DeployCursor = "deploy";
[CursorReference]
[Desc("Cursor to display when unable to lay a mine.")]
public readonly string DeployBlockedCursor = "deploy-blocked";
[CursorReference]
[Desc("Cursor to display when able to lay a mine.")]
public readonly string AbilityCursor = "ability";
public override object Create(ActorInitializer init) { return new Minelayer(init.Self, this); }
}
@@ -85,7 +91,7 @@ namespace OpenRA.Mods.Cnc.Traits
{
get
{
yield return new BeginMinefieldOrderTargeter();
yield return new BeginMinefieldOrderTargeter(Info.AbilityCursor);
yield return new DeployOrderTargeter("PlaceMine", 5, () => IsCellAcceptable(self, self.Location) ? Info.DeployCursor : Info.DeployBlockedCursor);
}
}
@@ -97,7 +103,7 @@ namespace OpenRA.Mods.Cnc.Traits
case "BeginMinefield":
var start = self.World.Map.CellContaining(target.CenterPosition);
if (self.World.OrderGenerator is MinefieldOrderGenerator)
((MinefieldOrderGenerator)self.World.OrderGenerator).AddMinelayer(self, start);
((MinefieldOrderGenerator)self.World.OrderGenerator).AddMinelayer(self);
else
self.World.OrderGenerator = new MinefieldOrderGenerator(self, start, queued);
@@ -204,6 +210,7 @@ namespace OpenRA.Mods.Cnc.Traits
readonly float validAlpha, unknownAlpha, blockedAlpha;
readonly CPos minefieldStart;
readonly bool queued;
readonly string cursor;
public MinefieldOrderGenerator(Actor a, CPos xy, bool queued)
{
@@ -251,9 +258,11 @@ namespace OpenRA.Mods.Cnc.Traits
blockedTile = blockedSequence.GetSprite(0);
blockedAlpha = blockedSequence.GetAlpha(0);
}
cursor = minelayer.Info.AbilityCursor;
}
public void AddMinelayer(Actor a, CPos xy)
public void AddMinelayer(Actor a)
{
minelayers.Add(a);
}
@@ -331,7 +340,7 @@ namespace OpenRA.Mods.Cnc.Traits
protected override string GetCursor(World world, CPos cell, int2 worldPixel, MouseInput mi)
{
return "ability";
return cursor;
}
}
@@ -339,6 +348,14 @@ namespace OpenRA.Mods.Cnc.Traits
{
public string OrderID => "BeginMinefield";
public int OrderPriority => 5;
readonly string cursor;
public BeginMinefieldOrderTargeter(string cursor)
{
this.cursor = cursor;
}
public bool TargetOverridesSelection(Actor self, in Target target, List<Actor> actorsAt, CPos xy, TargetModifiers modifiers) { return true; }
public bool CanTarget(Actor self, in Target target, List<Actor> othersAtTarget, ref TargetModifiers modifiers, ref string cursor)
@@ -350,7 +367,8 @@ namespace OpenRA.Mods.Cnc.Traits
if (!self.World.Map.Contains(location))
return false;
cursor = "ability";
cursor = this.cursor;
IsQueued = modifiers.HasModifier(TargetModifiers.ForceQueue);
return modifiers.HasModifier(TargetModifiers.ForceAttack);

View File

@@ -35,15 +35,19 @@ namespace OpenRA.Mods.Cnc.Traits
[Desc("Sound to play when teleporting.")]
public readonly string ChronoshiftSound = "chrotnk1.aud";
[CursorReference]
[Desc("Cursor to display when able to deploy the actor.")]
public readonly string DeployCursor = "deploy";
[CursorReference]
[Desc("Cursor to display when unable to deploy the actor.")]
public readonly string DeployBlockedCursor = "deploy-blocked";
[CursorReference]
[Desc("Cursor to display when targeting a teleport location.")]
public readonly string TargetCursor = "chrono-target";
[CursorReference]
[Desc("Cursor to display when the targeted location is blocked.")]
public readonly string TargetBlockedCursor = "move-blocked";

View File

@@ -48,12 +48,15 @@ namespace OpenRA.Mods.Cnc.Traits
public readonly bool KillCargo = true;
[CursorReference]
[Desc("Cursor to display when selecting targets for the chronoshift.")]
public readonly string SelectionCursor = "chrono-select";
[CursorReference]
[Desc("Cursor to display when targeting an area for the chronoshift.")]
public readonly string TargetCursor = "chrono-target";
[CursorReference]
[Desc("Cursor to display when the targeted area is blocked.")]
public readonly string TargetBlockedCursor = "move-blocked";

View File

@@ -0,0 +1,55 @@
#region Copyright & License Information
/*
* Copyright 2007-2020 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version. For more
* information, see COPYING.
*/
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using OpenRA.Traits;
namespace OpenRA.Mods.Common.Lint
{
class CheckCursors : ILintRulesPass
{
public void Run(Action<string> emitError, Action<string> emitWarning, ModData modData, Ruleset rules)
{
var fileSystem = modData.DefaultFileSystem;
var sequenceYaml = MiniYaml.Merge(modData.Manifest.Cursors.Select(s => MiniYaml.FromStream(fileSystem.Open(s), s)));
var nodesDict = new MiniYaml(null, sequenceYaml).ToDictionary();
// Avoid using CursorProvider as it attempts to load palettes from the file system.
var cursors = new List<string>();
foreach (var s in nodesDict["Cursors"].Nodes)
foreach (var sequence in s.Value.Nodes)
cursors.Add(sequence.Key);
foreach (var actorInfo in rules.Actors)
{
foreach (var traitInfo in actorInfo.Value.TraitInfos<TraitInfo>())
{
var fields = traitInfo.GetType().GetFields();
foreach (var field in fields)
{
var cursorReference = field.GetCustomAttributes<CursorReferenceAttribute>(true).FirstOrDefault();
if (cursorReference == null)
continue;
var cursor = LintExts.GetFieldValues(traitInfo, field, emitError, cursorReference.DictionaryReference).FirstOrDefault();
if (string.IsNullOrEmpty(cursor))
continue;
if (!cursors.Contains(cursor))
emitError("Undefined cursor {0} for actor {1} with trait {2}.".F(cursor, actorInfo.Value.Name, traitInfo));
}
}
}
}
}
}

View File

@@ -30,7 +30,7 @@ namespace OpenRA.Mods.Common.Orders
protected override IEnumerable<IRenderable> RenderAnnotations(WorldRenderer wr, World world) { yield break; }
protected override string GetCursor(World world, CPos cell, int2 worldPixel, MouseInput mi)
{
return "ability";
return "ability"; // TODO: [CursorReference]
}
}
}

View File

@@ -19,11 +19,6 @@ namespace OpenRA.Mods.Common.Orders
{
readonly Func<string> cursor;
public DeployOrderTargeter(string order, int priority)
: this(order, priority, () => "deploy")
{
}
public DeployOrderTargeter(string order, int priority, Func<string> cursor)
{
OrderID = order;

View File

@@ -160,9 +160,11 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Boolean expression defining the condition under which the regular (non-force) move cursor is disabled.")]
public readonly BooleanExpression RequireForceMoveCondition = null;
[CursorReference]
[Desc("Cursor to display when able to land at target building.")]
public readonly string EnterCursor = "enter";
[CursorReference]
[Desc("Cursor to display when unable to land at target building.")]
public readonly string EnterBlockedCursor = "enter-blocked";

View File

@@ -74,10 +74,12 @@ namespace OpenRA.Mods.Common.Traits
// TODO: instead of having multiple Armaments and unique AttackBase,
// an actor should be able to have multiple AttackBases with
// a single corresponding Armament each
[CursorReference]
[Desc("Cursor to display when hovering over a valid target.")]
public readonly string Cursor = "attack";
// TODO: same as above
[CursorReference]
[Desc("Cursor to display when hovering over a valid target that is outside of range.")]
public readonly string OutsideRangeCursor = "attackoutsiderange";

View File

@@ -27,9 +27,11 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Armament names")]
public readonly string[] Armaments = { "primary", "secondary" };
[CursorReference]
[Desc("Cursor to display when hovering over a valid target.")]
public readonly string Cursor = null;
[CursorReference]
[Desc("Cursor to display when hovering over a valid target that is outside of range.")]
public readonly string OutsideRangeCursor = null;

View File

@@ -38,6 +38,18 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Can the actor be ordered to move in to shroud?")]
public readonly bool MoveIntoShroud = true;
[CursorReference]
public readonly string AttackMoveCursor = "attackmove";
[CursorReference]
public readonly string AttackMoveBlockedCursor = "attackmove-blocked";
[CursorReference]
public readonly string AssaultMoveCursor = "assaultmove";
[CursorReference]
public readonly string AssaultMoveBlockedCursor = "assaultmove-blocked";
public override object Create(ActorInitializer init) { return new AttackMove(init.Self, this); }
}
@@ -137,16 +149,31 @@ namespace OpenRA.Mods.Common.Traits
public override string GetCursor(World world, CPos cell, int2 worldPixel, MouseInput mi)
{
var prefix = mi.Modifiers.HasModifier(Modifiers.Ctrl) ? "assaultmove" : "attackmove";
var isAssaultMove = mi.Modifiers.HasModifier(Modifiers.Ctrl);
if (world.Map.Contains(cell) && subjects.Any())
var subject = subjects.FirstOrDefault();
if (subject.Actor != null)
{
var explored = subjects.First().Actor.Owner.Shroud.IsExplored(cell);
var blocked = !explored && subjects.Any(a => !a.Trait.Info.MoveIntoShroud);
return blocked ? prefix + "-blocked" : prefix;
var info = subject.Trait.Info;
if (world.Map.Contains(cell))
{
var explored = subject.Actor.Owner.Shroud.IsExplored(cell);
var cannotMove = subjects.FirstOrDefault(a => !a.Trait.Info.MoveIntoShroud).Trait;
var blocked = !explored && cannotMove != null;
if (isAssaultMove)
return blocked ? cannotMove.Info.AssaultMoveBlockedCursor : info.AssaultMoveCursor;
return blocked ? cannotMove.Info.AttackMoveBlockedCursor : info.AttackMoveCursor;
}
return prefix + "-blocked";
if (isAssaultMove)
return info.AssaultMoveBlockedCursor;
else
return info.AttackMoveBlockedCursor;
}
return null;
}
public override bool InputOverridesSelection(World world, int2 xy, MouseInput mi)

View File

@@ -40,7 +40,11 @@ namespace OpenRA.Mods.Common.Traits
"If empty, the list given in the `Produces` property of the `Production` trait will be used.")]
public readonly string[] ProductionQueues = { };
public override object Create(ActorInitializer init) { return new PrimaryBuilding(init.Self, this); }
[CursorReference]
[Desc("Cursor to display when setting the primary building.")]
public readonly string Cursor = "deploy";
public override object Create(ActorInitializer init) { return new PrimaryBuilding(this); }
}
public class PrimaryBuilding : ConditionalTrait<PrimaryBuildingInfo>, IIssueOrder, IResolveOrder
@@ -51,7 +55,7 @@ namespace OpenRA.Mods.Common.Traits
public bool IsPrimary { get; private set; }
public PrimaryBuilding(Actor self, PrimaryBuildingInfo info)
public PrimaryBuilding(PrimaryBuildingInfo info)
: base(info) { }
IEnumerable<IOrderTargeter> IIssueOrder.Orders
@@ -61,7 +65,7 @@ namespace OpenRA.Mods.Common.Traits
if (IsTraitDisabled)
yield break;
yield return new DeployOrderTargeter(OrderID, 1);
yield return new DeployOrderTargeter(OrderID, 1, () => Info.Cursor);
}
}

View File

@@ -30,6 +30,7 @@ namespace OpenRA.Mods.Common.Traits
[SequenceReference(nameof(Image), allowNullImage: true)]
public readonly string CirclesSequence = "circles";
[CursorReference]
[Desc("Cursor to display when rally point can be set.")]
public readonly string Cursor = "ability";

View File

@@ -34,9 +34,11 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Require the force-move modifier to display the move cursor.")]
public readonly bool RequiresForceMove = false;
[CursorReference]
[Desc("Cursor to display when able to land at target building.")]
public readonly string EnterCursor = "enter";
[CursorReference]
[Desc("Cursor to display when unable to land at target building.")]
public readonly string EnterBlockedCursor = "enter-blocked";

View File

@@ -20,9 +20,11 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Add to a building to expose a move cursor that triggers Transforms and issues an enter tunnel order to the transformed actor.")]
public class TransformsIntoEntersTunnelsInfo : ConditionalTraitInfo, Requires<TransformsInfo>
{
[CursorReference]
[Desc("Cursor to display when able to enter target tunnel.")]
public readonly string EnterCursor = "enter";
[CursorReference]
[Desc("Cursor to display when unable to enter target tunnel.")]
public readonly string EnterBlockedCursor = "enter-blocked";

View File

@@ -25,9 +25,11 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Locomotor used by the transformed actor. Must be defined on the World actor.")]
public readonly string Locomotor = null;
[CursorReference]
[Desc("Cursor to display when a move order can be issued at target location.")]
public readonly string Cursor = "move";
[CursorReference]
[Desc("Cursor to display when a move order cannot be issued at target location.")]
public readonly string BlockedCursor = "move-blocked";

View File

@@ -33,9 +33,11 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Require the force-move modifier to display the enter cursor.")]
public readonly bool RequiresForceMove = false;
[CursorReference]
[Desc("Cursor to display when able to enter target actor.")]
public readonly string EnterCursor = "enter";
[CursorReference]
[Desc("Cursor to display when unable to enter target actor.")]
public readonly string EnterBlockedCursor = "enter-blocked";

View File

@@ -34,9 +34,11 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Require the force-move modifier to display the enter cursor.")]
public readonly bool RequiresForceMove = false;
[CursorReference]
[Desc("Cursor to display when able to be repaired at target actor.")]
public readonly string EnterCursor = "enter";
[CursorReference]
[Desc("Cursor to display when unable to be repaired at target actor.")]
public readonly string EnterBlockedCursor = "enter-blocked";

View File

@@ -46,12 +46,15 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Relationships that the structure's previous owner needs to have for the capturing player to receive Experience.")]
public readonly PlayerRelationship PlayerExperienceRelationships = PlayerRelationship.Enemy;
[CursorReference]
[Desc("Cursor to display when the health of the target actor is above the sabotage threshold.")]
public readonly string SabotageCursor = "capture";
[CursorReference]
[Desc("Cursor to display when able to capture the target actor.")]
public readonly string EnterCursor = "enter";
[CursorReference]
[Desc("Cursor to display when unable to capture the target actor.")]
public readonly string EnterBlockedCursor = "enter-blocked";

View File

@@ -60,9 +60,11 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Delay (in ticks) before continuing after unloading a passenger.")]
public readonly int AfterUnloadDelay = 25;
[CursorReference]
[Desc("Cursor to display when able to unload the passengers.")]
public readonly string UnloadCursor = "deploy";
[CursorReference]
[Desc("Cursor to display when unable to unload the passengers.")]
public readonly string UnloadBlockedCursor = "deploy-blocked";

View File

@@ -39,21 +39,26 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Radius around the target drop location that are considered if the target tile is blocked.")]
public readonly WDist DropRange = WDist.FromCells(5);
[CursorReference]
[Desc("Cursor to display when able to unload the passengers.")]
public readonly string UnloadCursor = "deploy";
[CursorReference]
[Desc("Cursor to display when unable to unload the passengers.")]
public readonly string UnloadBlockedCursor = "deploy-blocked";
[Desc("Allow moving and unloading with one order using force-move")]
public readonly bool AllowDropOff = false;
[CursorReference]
[Desc("Cursor to display when able to drop off the passengers at location.")]
public readonly string DropOffCursor = "ability";
[CursorReference]
[Desc("Cursor to display when unable to drop off the passengers at location.")]
public readonly string DropOffBlockedCursor = "move-blocked";
[CursorReference]
[Desc("Cursor to display when picking up the passengers.")]
public readonly string PickUpCursor = "ability";

View File

@@ -37,9 +37,11 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Can this actor deploy on slopes?")]
public readonly bool CanDeployOnRamps = false;
[CursorReference]
[Desc("Cursor to display when able to (un)deploy the actor.")]
public readonly string DeployCursor = "deploy";
[CursorReference]
[Desc("Cursor to display when unable to (un)deploy the actor.")]
public readonly string DeployBlockedCursor = "deploy-blocked";

View File

@@ -32,6 +32,7 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Sound to play when delivering cash")]
public readonly string[] Sounds = { };
[CursorReference]
[Desc("Cursor to display when hovering over a valid actor to deliver cash to.")]
public readonly string Cursor = "enter";

View File

@@ -26,6 +26,7 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Identifier checked against AcceptsDeliveredExperience.ValidTypes. Only needed if the latter is not empty.")]
public readonly string Type = null;
[CursorReference]
[Desc("Cursor to display when hovering over a valid actor to deliver experience to.")]
public readonly string Cursor = "enter";

View File

@@ -50,6 +50,7 @@ namespace OpenRA.Mods.Common.Traits
public readonly PlayerRelationship TargetRelationships = PlayerRelationship.Enemy | PlayerRelationship.Neutral;
public readonly PlayerRelationship ForceTargetRelationships = PlayerRelationship.Enemy | PlayerRelationship.Neutral | PlayerRelationship.Ally;
[CursorReference]
[Desc("Cursor to display when hovering over a demolishable target.")]
public readonly string Cursor = "c4";

View File

@@ -39,9 +39,11 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Sound to play when repairing is done.")]
public readonly string RepairSound = null;
[CursorReference]
[Desc("Cursor to display when hovering over a valid actor to repair.")]
public readonly string Cursor = "goldwrench";
[CursorReference]
[Desc("Cursor to display when target actor has full health so it can't be repaired.")]
public readonly string RepairBlockedCursor = "goldwrench-blocked";

View File

@@ -22,9 +22,11 @@ namespace OpenRA.Mods.Common.Traits
[Desc("This actor can interact with TunnelEntrances to move through TerrainTunnels.")]
public class EntersTunnelsInfo : TraitInfo, Requires<IMoveInfo>, IObservesVariablesInfo
{
[CursorReference]
[Desc("Cursor to display when able to enter target tunnel.")]
public readonly string EnterCursor = "enter";
[CursorReference]
[Desc("Cursor to display when unable to enter target tunnel.")]
public readonly string EnterBlockedCursor = "enter-blocked";

View File

@@ -90,9 +90,11 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Color to use for the target line of harvest orders.")]
public readonly Color DeliverLineColor = Color.Green;
[CursorReference]
[Desc("Cursor to display when able to unload at target actor.")]
public readonly string EnterCursor = "enter";
[CursorReference]
[Desc("Cursor to display when unable to unload at target actor.")]
public readonly string EnterBlockedCursor = "enter-blocked";

View File

@@ -40,9 +40,11 @@ namespace OpenRA.Mods.Common.Traits
[Desc("If set to true, this unit will always turn in place instead of following a curved trajectory (like infantry).")]
public readonly bool AlwaysTurnInPlace = false;
[CursorReference]
[Desc("Cursor to display when a move order can be issued at target location.")]
public readonly string Cursor = "move";
[CursorReference]
[Desc("Cursor to display when a move order cannot be issued at target location.")]
public readonly string BlockedCursor = "move-blocked";

View File

@@ -50,9 +50,11 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Boolean expression defining the condition under which the regular (non-force) enter cursor is disabled.")]
public readonly BooleanExpression RequireForceMoveCondition = null;
[CursorReference]
[Desc("Cursor to display when able to enter target actor.")]
public readonly string EnterCursor = "enter";
[CursorReference]
[Desc("Cursor to display when unable to enter target actor.")]
public readonly string EnterBlockedCursor = "enter-blocked";

View File

@@ -35,9 +35,11 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Boolean expression defining the condition under which the regular (non-force) enter cursor is disabled.")]
public readonly BooleanExpression RequireForceMoveCondition = null;
[CursorReference]
[Desc("Cursor to display when able to be repaired at target actor.")]
public readonly string EnterCursor = "enter";
[CursorReference]
[Desc("Cursor to display when unable to be repaired at target actor.")]
public readonly string EnterBlockedCursor = "enter-blocked";

View File

@@ -33,9 +33,11 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Boolean expression defining the condition under which the regular (non-force) enter cursor is disabled.")]
public readonly BooleanExpression RequireForceMoveCondition = null;
[CursorReference]
[Desc("Cursor to display when able to be repaired near target actor.")]
public readonly string EnterCursor = "enter";
[CursorReference]
[Desc("Cursor to display when unable to be repaired near target actor.")]
public readonly string EnterBlockedCursor = "enter-blocked";

View File

@@ -30,9 +30,11 @@ namespace OpenRA.Mods.Common.Traits
"Possible values are Exit, Suicide, Dispose.")]
public readonly EnterBehaviour EnterBehaviour = EnterBehaviour.Dispose;
[CursorReference]
[Desc("Cursor to display when targeting an unrepaired bridge.")]
public readonly string TargetCursor = "goldwrench";
[CursorReference]
[Desc("Cursor to display when repairing is denied.")]
public readonly string TargetBlockedCursor = "goldwrench-blocked";

View File

@@ -39,6 +39,7 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Skip playing (reversed) make animation.")]
public readonly bool SkipMakeAnimation = false;
[CursorReference]
[Desc("Cursor to display when the sell order generator hovers over this actor.")]
public readonly string Cursor = "sell";

View File

@@ -47,6 +47,7 @@ namespace OpenRA.Mods.Common.Traits
"This requires the actor to have the WithSpriteBody trait or one of its derivatives.")]
public readonly string Sequence = "active";
[CursorReference]
[Desc("Cursor to display when there are no units to apply the condition in range.")]
public readonly string BlockedCursor = "move-blocked";

View File

@@ -38,6 +38,7 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Allow this to be used only once.")]
public readonly bool OneShot = false;
[CursorReference]
[Desc("Cursor to display for using this support power.")]
public readonly string Cursor = "ability";

View File

@@ -45,9 +45,11 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Notification to play when the transformation is blocked.")]
public readonly string NoTransformNotification = null;
[CursorReference]
[Desc("Cursor to display when able to (un)deploy the actor.")]
public readonly string DeployCursor = "deploy";
[CursorReference]
[Desc("Cursor to display when unable to (un)deploy the actor.")]
public readonly string DeployBlockedCursor = "deploy-blocked";