Add a lint check for trait placement on hardcoded actor names.

This commit is contained in:
Matthias Mailänder
2021-04-11 14:30:00 +01:00
committed by reaperrr
parent 0d3c624bbc
commit 5a0bcc01a6
129 changed files with 266 additions and 67 deletions

View File

@@ -24,6 +24,15 @@ using OpenRA.Traits;
namespace OpenRA
{
[Flags]
public enum SystemActors
{
Player = 0,
EditorPlayer = 1,
World = 2,
EditorWorld = 4
}
public sealed class Actor : IScriptBindable, IScriptNotifyBind, ILuaTableBinding, ILuaEqualityBinding, ILuaToStringBinding, IEquatable<Actor>, IDisposable
{
internal readonly struct SyncHash

View File

@@ -22,7 +22,7 @@ namespace OpenRA
{
public class Ruleset
{
public readonly IReadOnlyDictionary<string, ActorInfo> Actors;
public readonly ActorInfoDictionary Actors;
public readonly IReadOnlyDictionary<string, WeaponInfo> Weapons;
public readonly IReadOnlyDictionary<string, SoundInfo> Voices;
public readonly IReadOnlyDictionary<string, SoundInfo> Notifications;
@@ -41,7 +41,7 @@ namespace OpenRA
SequenceProvider sequences,
IReadOnlyDictionary<string, MiniYamlNode> modelSequences)
{
Actors = actors;
Actors = new ActorInfoDictionary(actors);
Weapons = weapons;
Voices = voices;
Notifications = notifications;

View File

@@ -31,7 +31,7 @@ namespace OpenRA.Graphics
// Overwrite previous definitions if there are duplicates
var pals = new Dictionary<string, IProvidesCursorPaletteInfo>();
foreach (var p in modData.DefaultRules.Actors["world"].TraitInfos<IProvidesCursorPaletteInfo>())
foreach (var p in modData.DefaultRules.Actors[SystemActors.World].TraitInfos<IProvidesCursorPaletteInfo>())
if (p.Palette != null)
pals[p.Palette] = p;

View File

@@ -708,7 +708,7 @@ namespace OpenRA
}
// ResourceLayer is on world actor, which isn't caught above, so an extra check for it.
var worldActorInfo = Rules.Actors["world"];
var worldActorInfo = Rules.Actors[SystemActors.World];
var worldimpsis = worldActorInfo.TraitInfos<IMapPreviewSignatureInfo>();
foreach (var worldimpsi in worldimpsis)
worldimpsi.PopulateMapPreviewSignatureCells(this, worldActorInfo, null, positions);

View File

@@ -30,7 +30,7 @@ namespace OpenRA
public MapPlayers(Ruleset rules, int playerCount)
{
var firstFaction = rules.Actors["world"].TraitInfos<FactionInfo>()
var firstFaction = rules.Actors[SystemActors.World].TraitInfos<FactionInfo>()
.First(f => f.Selectable).InternalName;
Players = new Dictionary<string, PlayerReference>

View File

@@ -37,9 +37,6 @@ namespace OpenRA
public class Player : IScriptBindable, IScriptNotifyBind, ILuaTableBinding, ILuaEqualityBinding, ILuaToStringBinding
{
public const string PlayerActorType = "Player";
public const string EditorPlayerActorType = "EditorPlayer";
struct StanceColors
{
public Color Self;
@@ -129,13 +126,13 @@ namespace OpenRA
static FactionInfo ResolveFaction(World world, string factionName, MersenneTwister playerRandom, bool requireSelectable)
{
var factionInfos = world.Map.Rules.Actors["world"].TraitInfos<FactionInfo>();
var factionInfos = world.Map.Rules.Actors[SystemActors.World].TraitInfos<FactionInfo>();
return ResolveFaction(factionName, factionInfos, playerRandom, requireSelectable);
}
static FactionInfo ResolveDisplayFaction(World world, string factionName)
{
var factions = world.Map.Rules.Actors["world"].TraitInfos<FactionInfo>().ToArray();
var factions = world.Map.Rules.Actors[SystemActors.World].TraitInfos<FactionInfo>().ToArray();
return factions.FirstOrDefault(f => f.InternalName == factionName) ?? factions.First();
}
@@ -165,7 +162,7 @@ namespace OpenRA
{
ClientIndex = client.Index;
Color = client.Color;
PlayerName = ResolvePlayerName(client, world.LobbyInfo.Clients, world.Map.Rules.Actors["player"].TraitInfos<IBotInfo>());
PlayerName = ResolvePlayerName(client, world.LobbyInfo.Clients, world.Map.Rules.Actors[SystemActors.Player].TraitInfos<IBotInfo>());
BotType = client.Bot;
Faction = ResolveFaction(world, client.Faction, playerRandom, !pr.LockFaction);
@@ -206,8 +203,8 @@ namespace OpenRA
// querying player traits in INotifyCreated.Created would crash.
// Therefore assign the uninitialized actor and run the Created callbacks
// by calling Initialize ourselves.
var playerActorType = world.Type == WorldType.Editor ? EditorPlayerActorType : PlayerActorType;
PlayerActor = new Actor(world, playerActorType, new TypeDictionary { new OwnerInit(this) });
var playerActorType = world.Type == WorldType.Editor ? SystemActors.EditorPlayer : SystemActors.Player;
PlayerActor = new Actor(world, playerActorType.ToString(), new TypeDictionary { new OwnerInit(this) });
PlayerActor.Initialize(true);
Shroud = PlayerActor.Trait<Shroud>();

View File

@@ -0,0 +1,48 @@
#region Copyright & License Information
/*
* Copyright 2007-2021 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;
using System.Collections.Generic;
namespace OpenRA
{
public class ActorInfoDictionary : IReadOnlyDictionary<string, ActorInfo>
{
readonly Dictionary<string, ActorInfo> dict;
public ActorInfoDictionary(IReadOnlyDictionary<string, ActorInfo> dict)
{
if (dict == null)
throw new ArgumentNullException(nameof(dict));
this.dict = new Dictionary<string, ActorInfo>(dict);
}
public bool ContainsKey(string key) => dict.ContainsKey(key);
public bool TryGetValue(string key, out ActorInfo value) => dict.TryGetValue(key, out value);
public int Count => dict.Count;
public ActorInfo this[string key] => dict[key];
public ActorInfo this[SystemActors key] => dict[key.ToString().ToLowerInvariant()];
IEnumerable<string> IReadOnlyDictionary<string, ActorInfo>.Keys => dict.Keys;
IEnumerable<ActorInfo> IReadOnlyDictionary<string, ActorInfo>.Values => dict.Values;
public ICollection<string> Keys => dict.Keys;
public ICollection<ActorInfo> Values => dict.Values;
public IEnumerator<KeyValuePair<string, ActorInfo>> GetEnumerator() => dict.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => dict.GetEnumerator();
}
}

View File

@@ -159,7 +159,7 @@ namespace OpenRA.Scripting
var knownPlayerCommands = Game.ModData.ObjectCreator
.GetTypesImplementing<ScriptPlayerProperties>()
.ToArray();
PlayerCommands = FilterCommands(world.Map.Rules.Actors["player"], knownPlayerCommands);
PlayerCommands = FilterCommands(world.Map.Rules.Actors[SystemActors.Player], knownPlayerCommands);
runtime.Globals["EngineDir"] = Platform.EngineDir;
runtime.DoBuffer(File.Open(Path.Combine(Platform.EngineDir, "lua", "scriptwrapper.lua"), FileMode.Open, FileAccess.Read).ReadAllText(), "scriptwrapper.lua").Dispose();

View File

@@ -1209,7 +1209,7 @@ namespace OpenRA.Server
// The null padding is needed to keep the player indexes in sync with world.Players on the clients
// This will need to change if future code wants to use worldPlayers for other purposes
var playerRandom = new MersenneTwister(LobbyInfo.GlobalSettings.RandomSeed);
foreach (var cmpi in Map.Rules.Actors["world"].TraitInfos<ICreatePlayersInfo>())
foreach (var cmpi in Map.Rules.Actors[SystemActors.World].TraitInfos<ICreatePlayersInfo>())
cmpi.CreateServerPlayers(Map, LobbyInfo, worldPlayers, playerRandom);
if (recorder != null)

View File

@@ -403,7 +403,7 @@ namespace OpenRA
public static string SanitizedPlayerName(string dirty)
{
var forbiddenNames = new string[] { "Open", "Closed" };
var botNames = OpenRA.Game.ModData.DefaultRules.Actors["player"].TraitInfos<IBotInfo>().Select(t => t.Name);
var botNames = OpenRA.Game.ModData.DefaultRules.Actors[SystemActors.Player].TraitInfos<IBotInfo>().Select(t => t.Name);
var clean = SanitizedName(dirty);

View File

@@ -11,6 +11,7 @@
namespace OpenRA.Traits
{
[TraitLocation(SystemActors.World)]
[Desc("Checks for pause related desyncs. Attach this to the world actor.")]
public class DebugPauseStateInfo : TraitInfo
{

View File

@@ -105,4 +105,14 @@ namespace OpenRA.Traits
PlayerPaletteReferenceSwitch = playerPaletteReferenceSwitch;
}
}
[AttributeUsage(AttributeTargets.Class)]
public sealed class TraitLocationAttribute : Attribute
{
public readonly SystemActors SystemActors;
public TraitLocationAttribute(SystemActors systemActors)
{
SystemActors = systemActors;
}
}
}

View File

@@ -22,6 +22,7 @@ namespace OpenRA.Traits
void OnVisibilityChanged(FrozenActor frozen);
}
[TraitLocation(SystemActors.Player)]
[Desc("Required for FrozenUnderFog to work. Attach this to the player actor.")]
public class FrozenActorLayerInfo : TraitInfo, Requires<ShroudInfo>
{

View File

@@ -14,7 +14,8 @@ using OpenRA.Primitives;
namespace OpenRA.Traits
{
[Desc("Add this to the Player actor definition.")]
[TraitLocation(SystemActors.World | SystemActors.EditorWorld)]
[Desc("Add this to the World actor definition.")]
public class PlayerColorPaletteInfo : TraitInfo
{
[PaletteReference]

View File

@@ -14,6 +14,7 @@ using System.Collections.Generic;
namespace OpenRA.Traits
{
[TraitLocation(SystemActors.Player | SystemActors.EditorPlayer)]
[Desc("Required for shroud and fog visibility checks. Add this to the player actor.")]
public class ShroudInfo : TraitInfo, ILobbyOptions
{

View File

@@ -11,6 +11,7 @@
namespace OpenRA.Traits
{
[TraitLocation(SystemActors.World | SystemActors.EditorWorld)]
[Desc("Enables visualization commands. Attach this to the world actor.")]
public class DebugVisualizationsInfo : TraitInfo<DebugVisualizations> { }

View File

@@ -14,6 +14,7 @@ using System.Collections.Generic;
namespace OpenRA.Traits
{
[Desc("Attach this to the `World` actor.")]
[TraitLocation(SystemActors.World | SystemActors.EditorWorld)]
public class FactionInfo : TraitInfo<Faction>
{
[Desc("This is the name exposed to the players.")]

View File

@@ -30,6 +30,7 @@ namespace OpenRA.Traits
public override string ToString() { return "{0}->{1}".F(Actor.Info.Name, Bounds.GetType().Name); }
}
[TraitLocation(SystemActors.World | SystemActors.EditorWorld)]
public class ScreenMapInfo : TraitInfo
{
[Desc("Size of partition bins (world pixels)")]

View File

@@ -16,6 +16,7 @@ using OpenRA.Graphics;
namespace OpenRA.Traits
{
[TraitLocation(SystemActors.World)]
public class ScreenShakerInfo : TraitInfo
{
public readonly float2 MinMultiplier = new float2(-3, -3);

View File

@@ -202,8 +202,8 @@ namespace OpenRA
ModelCache = modData.ModelSequenceLoader.CacheModels(map, modData, map.Rules.ModelSequences);
var worldActorType = type == WorldType.Editor ? "EditorWorld" : "World";
WorldActor = CreateActor(worldActorType, new TypeDictionary());
var worldActorType = type == WorldType.Editor ? SystemActors.EditorWorld : SystemActors.World;
WorldActor = CreateActor(worldActorType.ToString(), new TypeDictionary());
ActorMap = WorldActor.Trait<IActorMap>();
ScreenMap = WorldActor.Trait<ScreenMap>();
Selection = WorldActor.Trait<ISelection>();

View File

@@ -16,6 +16,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Cnc.Traits
{
[TraitLocation(SystemActors.Player)]
[Desc("Required for `GpsPower`. Attach this to the player actor.")]
class GpsWatcherInfo : TraitInfo
{

View File

@@ -16,6 +16,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Cnc.Traits
{
[TraitLocation(SystemActors.World | SystemActors.EditorWorld)]
[Desc("Apply palette full screen rotations during chronoshifts. Add this to the world actor.")]
public class ChronoshiftPaletteEffectInfo : TraitInfo
{

View File

@@ -15,6 +15,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Cnc.Traits
{
[TraitLocation(SystemActors.World | SystemActors.EditorWorld)]
[Desc("Palette effect used for blinking \"animations\" on actors.")]
class LightPaletteRotatorInfo : TraitInfo
{

View File

@@ -18,6 +18,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Cnc.Traits
{
[TraitLocation(SystemActors.World | SystemActors.EditorWorld)]
[Desc("Adds the hard-coded shroud palette to the game")]
class ShroudPaletteInfo : TraitInfo
{

View File

@@ -18,6 +18,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Cnc.Traits
{
[TraitLocation(SystemActors.World | SystemActors.EditorWorld)]
[Desc("Adds the hard-coded shroud palette to the game")]
class TSShroudPaletteInfo : TraitInfo
{

View File

@@ -42,13 +42,13 @@ namespace OpenRA.Mods.Cnc.UtilityCommands
var srcModData = new ModData(utility.Mods[srcMod], utility.Mods);
Game.ModData = srcModData;
var srcPaletteInfo = srcModData.DefaultRules.Actors["player"].TraitInfo<PlayerColorPaletteInfo>();
var srcPaletteInfo = srcModData.DefaultRules.Actors[SystemActors.Player].TraitInfo<PlayerColorPaletteInfo>();
var srcRemapIndex = srcPaletteInfo.RemapIndex;
var destMod = args[2].Split(':')[0];
var destModData = new ModData(utility.Mods[destMod], utility.Mods);
Game.ModData = destModData;
var destPaletteInfo = destModData.DefaultRules.Actors["player"].TraitInfo<PlayerColorPaletteInfo>();
var destPaletteInfo = destModData.DefaultRules.Actors[SystemActors.Player].TraitInfo<PlayerColorPaletteInfo>();
var destRemapIndex = destPaletteInfo.RemapIndex;
var shadowIndex = new int[] { };

View File

@@ -16,6 +16,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Commands
{
[TraitLocation(SystemActors.World)]
[Desc("Enables commands triggered by typing them into the chatbox. Attach this to the world actor.")]
public class ChatCommandsInfo : TraitInfo<ChatCommands> { }

View File

@@ -16,6 +16,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Commands
{
[TraitLocation(SystemActors.World)]
[Desc("Enables visualization commands via the chatbox. Attach this to the world actor.")]
public class DebugVisualizationCommandsInfo : TraitInfo<DebugVisualizationCommands> { }

View File

@@ -17,6 +17,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Commands
{
[TraitLocation(SystemActors.World)]
[Desc("Enables developer cheats via the chatbox. Attach this to the world actor.")]
public class DevCommandsInfo : TraitInfo<DevCommands> { }

View File

@@ -15,6 +15,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Commands
{
[TraitLocation(SystemActors.World)]
[Desc("Shows a list of available commands in the chatbox. Attach this to the world actor.")]
public class HelpCommandInfo : TraitInfo<HelpCommand> { }

View File

@@ -14,6 +14,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Commands
{
[TraitLocation(SystemActors.World)]
[Desc("Allows the player to pause or surrender the game via the chatbox. Attach this to the world actor.")]
public class PlayerCommandsInfo : TraitInfo<PlayerCommands> { }

View File

@@ -20,7 +20,7 @@ namespace OpenRA.Mods.Common.Lint
{
public void Run(Action<string> emitError, Action<string> emitWarning, ModData modData, Ruleset rules)
{
var worldActor = rules.Actors["world"];
var worldActor = rules.Actors[SystemActors.World];
var locomotorInfos = worldActor.TraitInfos<LocomotorInfo>().ToArray();
foreach (var li in locomotorInfos)
foreach (var otherLocomotor in locomotorInfos)

View File

@@ -56,7 +56,7 @@ namespace OpenRA.Mods.Common.Lint
if (!worldOwnerFound)
emitError("Found no player owning the world.");
var worldActor = map.Rules.Actors["world"];
var worldActor = map.Rules.Actors[SystemActors.World];
var factions = worldActor.TraitInfos<FactionInfo>().Select(f => f.InternalName).ToHashSet();
foreach (var player in players.Values)
if (!string.IsNullOrWhiteSpace(player.Faction) && !factions.Contains(player.Faction))

View File

@@ -38,7 +38,7 @@ namespace OpenRA.Mods.Common.Lint
void Run(Action<string> emitError, Action<string> emitWarning, Ruleset rules, SequenceProvider sequences)
{
var factions = rules.Actors["world"].TraitInfos<FactionInfo>().Select(f => f.InternalName).ToArray();
var factions = rules.Actors[SystemActors.World].TraitInfos<FactionInfo>().Select(f => f.InternalName).ToArray();
foreach (var actorInfo in rules.Actors)
{
// Actors may have 0 or 1 RenderSprites traits

View File

@@ -0,0 +1,43 @@
#region Copyright & License Information
/*
* Copyright 2007-2021 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.Linq;
using DiscordRPC.Helper;
using OpenRA.Traits;
namespace OpenRA.Mods.Common.Lint
{
public class CheckTraitLocation : ILintRulesPass
{
void ILintRulesPass.Run(Action<string> emitError, Action<string> emitWarning, ModData modData, Ruleset rules)
{
foreach (var actorInfo in rules.Actors)
{
foreach (var traitInfo in actorInfo.Value.TraitInfos<TraitInfo>())
{
var traitLocation = traitInfo.GetType().GetCustomAttributes<TraitLocationAttribute>(true).FirstOrDefault();
if (traitLocation == null)
continue;
if (!Enum.TryParse(actorInfo.Key, true, out SystemActors systemActor) || !traitLocation.SystemActors.HasFlag(systemActor))
{
// Remove the "Info" suffix
var traitName = traitInfo.GetType().Name;
traitName = traitName.Remove(traitName.Length - 4);
var locations = traitLocation.SystemActors.ToString().Replace(", ", " or ");
emitError("{0} does not belong on {1}. It is a system trait meant for {2}.".F(traitName, actorInfo.Key, locations));
}
}
}
}
}
}

View File

@@ -357,7 +357,7 @@ namespace OpenRA.Mods.Common.Server
}
var botType = parts[2];
var botInfo = server.Map.Rules.Actors["player"].TraitInfos<IBotInfo>()
var botInfo = server.Map.Rules.Actors[SystemActors.Player].TraitInfos<IBotInfo>()
.FirstOrDefault(b => b.Type == botType);
if (botInfo == null)
@@ -440,7 +440,7 @@ namespace OpenRA.Mods.Common.Server
LoadMapSettings(server, server.LobbyInfo.GlobalSettings, server.Map.Rules);
// Reset client states
var selectableFactions = server.Map.Rules.Actors["world"].TraitInfos<FactionInfo>()
var selectableFactions = server.Map.Rules.Actors[SystemActors.World].TraitInfos<FactionInfo>()
.Where(f => f.Selectable)
.Select(f => f.InternalName)
.ToList();
@@ -457,7 +457,7 @@ namespace OpenRA.Mods.Common.Server
// - Players who now lack a slot are made observers
// - Bots who now lack a slot are dropped
// - Bots who are not defined in the map rules are dropped
var botTypes = server.Map.Rules.Actors["player"].TraitInfos<IBotInfo>().Select(t => t.Type);
var botTypes = server.Map.Rules.Actors[SystemActors.Player].TraitInfos<IBotInfo>().Select(t => t.Type);
var slots = server.LobbyInfo.Slots.Keys.ToArray();
var i = 0;
foreach (var os in oldSlots)
@@ -534,8 +534,8 @@ namespace OpenRA.Mods.Common.Server
return true;
}
var allOptions = server.Map.Rules.Actors["player"].TraitInfos<ILobbyOptions>()
.Concat(server.Map.Rules.Actors["world"].TraitInfos<ILobbyOptions>())
var allOptions = server.Map.Rules.Actors[SystemActors.Player].TraitInfos<ILobbyOptions>()
.Concat(server.Map.Rules.Actors[SystemActors.World].TraitInfos<ILobbyOptions>())
.SelectMany(t => t.LobbyOptions(server.Map.Rules));
// Overwrite keys with duplicate ids
@@ -775,7 +775,7 @@ namespace OpenRA.Mods.Common.Server
if (server.LobbyInfo.Slots[targetClient.Slot].LockFaction)
return true;
var factions = server.Map.Rules.Actors["world"].TraitInfos<FactionInfo>()
var factions = server.Map.Rules.Actors[SystemActors.World].TraitInfos<FactionInfo>()
.Where(f => f.Selectable).Select(f => f.InternalName);
if (!factions.Contains(parts[1]))
@@ -1045,8 +1045,8 @@ namespace OpenRA.Mods.Common.Server
{
lock (server.LobbyInfo)
{
var options = rules.Actors["player"].TraitInfos<ILobbyOptions>()
.Concat(rules.Actors["world"].TraitInfos<ILobbyOptions>())
var options = rules.Actors[SystemActors.Player].TraitInfos<ILobbyOptions>()
.Concat(rules.Actors[SystemActors.World].TraitInfos<ILobbyOptions>())
.SelectMany(t => t.LobbyOptions(rules));
foreach (var o in options)
@@ -1100,7 +1100,7 @@ namespace OpenRA.Mods.Common.Server
static string MissionBriefingOrDefault(S server)
{
var missionData = server.Map.Rules.Actors["world"].TraitInfoOrDefault<MissionDataInfo>();
var missionData = server.Map.Rules.Actors[SystemActors.World].TraitInfoOrDefault<MissionDataInfo>();
if (missionData != null && !string.IsNullOrEmpty(missionData.Briefing))
return missionData.Briefing.Replace("\\n", "\n");

View File

@@ -25,8 +25,8 @@ namespace OpenRA.Mods.Common.Server
var defaults = new Session.Global();
LobbyCommands.LoadMapSettings(server, defaults, server.Map.Rules);
var options = server.Map.Rules.Actors["player"].TraitInfos<ILobbyOptions>()
.Concat(server.Map.Rules.Actors["world"].TraitInfos<ILobbyOptions>())
var options = server.Map.Rules.Actors[SystemActors.Player].TraitInfos<ILobbyOptions>()
.Concat(server.Map.Rules.Actors[SystemActors.World].TraitInfos<ILobbyOptions>())
.SelectMany(t => t.LobbyOptions(server.Map.Rules))
.ToDictionary(o => o.Id, o => o);

View File

@@ -55,7 +55,7 @@ namespace OpenRA.Mods.Common.Traits
public void RulesetLoaded(Ruleset rules, ActorInfo ai)
{
if (!rules.Actors["world"].HasTraitInfo<ITiledTerrainRendererInfo>())
if (!rules.Actors[SystemActors.World].HasTraitInfo<ITiledTerrainRendererInfo>())
throw new YamlException("Bridge requires a tile-based terrain renderer.");
if (string.IsNullOrEmpty(DemolishWeapon))

View File

@@ -14,6 +14,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[TraitLocation(SystemActors.World)]
[Desc("A dictionary of buildings placed on the map. Attach this to the world actor.")]
public class BuildingInfluenceInfo : TraitInfo
{

View File

@@ -48,7 +48,7 @@ namespace OpenRA.Mods.Common.Traits
public override void RulesetLoaded(Ruleset rules, ActorInfo ai)
{
var locomotorInfos = rules.Actors["world"].TraitInfos<LocomotorInfo>();
var locomotorInfos = rules.Actors[SystemActors.World].TraitInfos<LocomotorInfo>();
LocomotorInfo = locomotorInfos.FirstOrDefault(li => li.Name == Locomotor);
if (LocomotorInfo == null)
throw new YamlException("A locomotor named '{0}' doesn't exist.".F(Locomotor));

View File

@@ -82,7 +82,7 @@ namespace OpenRA.Mods.Common.Traits
public override void RulesetLoaded(Ruleset rules, ActorInfo ai)
{
var locomotorInfos = rules.Actors["world"].TraitInfos<LocomotorInfo>();
var locomotorInfos = rules.Actors[SystemActors.World].TraitInfos<LocomotorInfo>();
LocomotorInfo = locomotorInfos.FirstOrDefault(li => li.Name == Locomotor);
if (LocomotorInfo == null)
throw new YamlException("A locomotor named '{0}' doesn't exist.".F(Locomotor));

View File

@@ -56,7 +56,7 @@ namespace OpenRA.Mods.Common.Traits
var map = init.World.Map;
// Explore map-placed actors if the "Explore Map" option is enabled
var shroudInfo = init.World.Map.Rules.Actors["player"].TraitInfo<ShroudInfo>();
var shroudInfo = init.World.Map.Rules.Actors[SystemActors.Player].TraitInfo<ShroudInfo>();
var exploredMap = init.World.LobbyInfo.GlobalSettings.OptionOrDefault("explored", shroudInfo.ExploredMapCheckboxEnabled);
startsRevealed = exploredMap && init.Contains<SpawnedByMapInit>() && !init.Contains<HiddenUnderFogInit>();
var buildingInfo = init.Self.Info.TraitInfoOrDefault<BuildingInfo>();

View File

@@ -18,6 +18,7 @@ namespace OpenRA.Mods.Common.Traits
{
using GUtil = OpenRA.Graphics.Util;
[TraitLocation(SystemActors.World | SystemActors.EditorWorld)]
[Desc("Used for bursted one-colored whole screen effects. Add this to the world actor.")]
public class FlashPaletteEffectInfo : TraitInfo
{

View File

@@ -17,6 +17,7 @@ using OpenRA.Widgets;
namespace OpenRA.Mods.Common.Traits
{
[TraitLocation(SystemActors.World | SystemActors.EditorWorld)]
[Desc("Fades the world from/to black at the start/end of the game, and can (optionally) desaturate the world")]
public class MenuPaletteEffectInfo : TraitInfo
{

View File

@@ -15,6 +15,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[TraitLocation(SystemActors.World | SystemActors.EditorWorld)]
[Desc("Palette effect used for sprinkle \"animations\".")]
class RotationPaletteEffectInfo : TraitInfo
{

View File

@@ -13,6 +13,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[TraitLocation(SystemActors.Player)]
[Desc("Attach this to the player actor to allow building repair by team mates.")]
class AllyRepairInfo : TraitInfo<AllyRepair> { }

View File

@@ -14,6 +14,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[TraitLocation(SystemActors.Player)]
[Desc("Plays an audio notification and shows a radar ping when a building is attacked.",
"Attach this to the player actor.")]
public class BaseAttackNotifierInfo : TraitInfo

View File

@@ -21,6 +21,7 @@ namespace OpenRA.Mods.Common.Traits
"Will only work together with the Production: trait on the actor that actually does the production.",
"You will also want to add PrimaryBuildings: to let the user choose where new units should exit.",
"The production speed depends on the number of production buildings and units queued at the same time.")]
[TraitLocation(SystemActors.Player)]
public class ClassicParallelProductionQueueInfo : ProductionQueueInfo, Requires<TechTreeInfo>, Requires<PlayerResourcesInfo>
{
[Desc("If you build more actors of the same type,", "the same queue will get its build time lowered for every actor produced there.")]

View File

@@ -16,6 +16,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[TraitLocation(SystemActors.Player)]
[Desc("Attach this to the player actor (not a building!) to define a new shared build queue.",
"Will only work together with the Production: trait on the actor that actually does the production.",
"You will also want to add PrimaryBuildings: to let the user choose where new units should exit.")]

View File

@@ -11,11 +11,11 @@
using System.Linq;
using OpenRA.Network;
using OpenRA.Primitives;
using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[TraitLocation(SystemActors.Player)]
public class ConquestVictoryConditionsInfo : TraitInfo, Requires<MissionObjectivesInfo>
{
[Desc("Delay for the end game notification in milliseconds.")]

View File

@@ -16,6 +16,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[TraitLocation(SystemActors.Player)]
[Desc("Attach this to the player actor.")]
public class DeveloperModeInfo : TraitInfo, ILobbyOptions
{

View File

@@ -15,6 +15,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[TraitLocation(SystemActors.Player)]
[Desc("Tracks neutral and enemy actors' visibility and notifies the player.",
"Attach this to the player actor. The actors to track need the 'AnnounceOnSeen' trait.")]
class EnemyWatcherInfo : TraitInfo

View File

@@ -11,11 +11,11 @@
using System.Collections.Generic;
using System.Linq;
using OpenRA.Primitives;
using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[TraitLocation(SystemActors.Player)]
[Desc("Attach this to the player actor.")]
public class GrantConditionOnPrerequisiteManagerInfo : TraitInfo, Requires<TechTreeInfo>
{

View File

@@ -16,6 +16,7 @@ namespace OpenRA.Mods.Common.Traits
{
[Desc("Plays an audio notification and shows a radar ping when a harvester is attacked.",
"Attach this to the player actor.")]
[TraitLocation(SystemActors.Player)]
public class HarvesterAttackNotifierInfo : TraitInfo
{
[Desc("Minimum duration (in seconds) between notification events.")]

View File

@@ -35,6 +35,7 @@ namespace OpenRA.Mods.Common.Traits
}
}
[TraitLocation(SystemActors.Player)]
public class MissionObjectivesInfo : TraitInfo
{
[Desc("Set this to true if multiple cooperative players have a distinct set of " +
@@ -258,6 +259,7 @@ namespace OpenRA.Mods.Common.Traits
}
}
[TraitLocation(SystemActors.World)]
[Desc("Provides game mode progress information for players.",
"Goes on WorldActor - observers don't have a player it can live on.",
"Current options for PanelName are 'SKIRMISH_STATS' and 'MISSION_OBJECTIVES'.")]
@@ -271,6 +273,7 @@ namespace OpenRA.Mods.Common.Traits
public override object Create(ActorInitializer init) { return new ObjectivesPanel(this); }
}
[TraitLocation(SystemActors.World)]
public class ObjectivesPanel : IObjectivesPanel
{
readonly ObjectivesPanelInfo info;

View File

@@ -14,6 +14,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[TraitLocation(SystemActors.Player)]
[Desc("A beacon that is constructed from a circle sprite that is animated once and a moving arrow sprite.")]
public class PlaceBeaconInfo : TraitInfo
{

View File

@@ -18,6 +18,7 @@ namespace OpenRA.Mods.Common.Traits
// Allows third party mods to detect whether an actor was created by PlaceBuilding.
public class PlaceBuildingInit : RuntimeFlagInit { }
[TraitLocation(SystemActors.Player)]
[Desc("Allows the player to execute build orders.", " Attach this to the player actor.")]
public class PlaceBuildingInfo : TraitInfo
{

View File

@@ -13,6 +13,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[TraitLocation(SystemActors.Player)]
[Desc("This trait can be used to track player experience based on units killed with the `GivesExperience` trait.",
"It can also be used as a point score system in scripted maps, for example.",
"Attach this to the player actor.")]

View File

@@ -11,11 +11,11 @@
using System;
using OpenRA.Graphics;
using OpenRA.Primitives;
using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[TraitLocation(SystemActors.Player)]
public class PlayerRadarTerrainInfo : TraitInfo, Requires<ShroudInfo>
{
public override object Create(ActorInitializer init)

View File

@@ -16,6 +16,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[TraitLocation(SystemActors.Player | SystemActors.EditorPlayer)]
public class PlayerResourcesInfo : TraitInfo, ILobbyOptions
{
[Desc("Descriptive label for the starting cash option in the lobby.")]

View File

@@ -18,6 +18,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[TraitLocation(SystemActors.Player)]
[Desc("Attach this to the player actor to collect observer stats.")]
public class PlayerStatisticsInfo : TraitInfo
{

View File

@@ -14,6 +14,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[TraitLocation(SystemActors.Player)]
public class ProvidesTechPrerequisiteInfo : TraitInfo, ITechTreePrerequisiteInfo
{
[Desc("Internal id for this tech level.")]

View File

@@ -13,6 +13,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[TraitLocation(SystemActors.Player)]
[Desc("Provides the player with an audible warning when their storage is nearing full.")]
public class ResourceStorageWarningInfo : TraitInfo, Requires<PlayerResourcesInfo>
{

View File

@@ -17,6 +17,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[TraitLocation(SystemActors.Player)]
[Desc("Manages build limits and pre-requisites.", " Attach this to the player actor.")]
public class TechTreeInfo : TraitInfo
{

View File

@@ -17,6 +17,7 @@ using OpenRA.Widgets;
namespace OpenRA.Mods.Common.Traits
{
[TraitLocation(SystemActors.World)]
[Desc("This trait allows setting a time limit on matches. Attach this to the World actor.")]
public class TimeLimitManagerInfo : TraitInfo, ILobbyOptions, IRulesetLoaded
{

View File

@@ -15,6 +15,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[TraitLocation(SystemActors.Player)]
[Desc("Attach this to the player actor.")]
public class PowerManagerInfo : TraitInfo, Requires<DeveloperModeInfo>
{

View File

@@ -17,6 +17,7 @@ using OpenRA.Widgets;
namespace OpenRA.Mods.Common.Traits
{
[TraitLocation(SystemActors.World)]
class ProductionQueueFromSelectionInfo : TraitInfo
{
public string ProductionTabsWidget = null;

View File

@@ -38,7 +38,7 @@ namespace OpenRA.Mods.Common.Traits
public void RulesetLoaded(Ruleset rules, ActorInfo info)
{
var pci = rules.Actors["player"].TraitInfoOrDefault<ProximityCaptorInfo>();
var pci = rules.Actors[SystemActors.Player].TraitInfoOrDefault<ProximityCaptorInfo>();
if (pci == null)
throw new YamlException("ProximityCapturable requires the `Player` actor to have the ProximityCaptor trait.");
}

View File

@@ -17,6 +17,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[TraitLocation(SystemActors.World)]
[Desc("Displays custom terrain types.")]
class CustomTerrainDebugOverlayInfo : TraitInfo
{

View File

@@ -31,7 +31,7 @@ namespace OpenRA.Mods.Common.Traits.Render
// No queues available - check for classic production queues
if (queue == null)
queue = rules.Actors["player"].TraitInfos<ProductionQueueInfo>().FirstOrDefault(q => ProductionType == q.Type);
queue = rules.Actors[SystemActors.Player].TraitInfos<ProductionQueueInfo>().FirstOrDefault(q => ProductionType == q.Type);
if (queue == null)
throw new YamlException("Can't find a queue with ProductionType '{0}'".F(ProductionType));

View File

@@ -15,6 +15,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits.Render
{
[TraitLocation(SystemActors.Player)]
[Desc("Attach this to the player actor. When attached, enables all actors possessing the ProducibleWithLevel ",
"trait to have their production queue icons render with an overlay defined in this trait. ",
"The icon change occurs when ProducibleWithLevel.Prerequisites are met.")]

View File

@@ -18,6 +18,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[TraitLocation(SystemActors.Player)]
[Desc("Attach this to the player actor.")]
public class SupportPowerManagerInfo : TraitInfo, Requires<DeveloperModeInfo>, Requires<TechTreeInfo>
{

View File

@@ -35,7 +35,7 @@ namespace OpenRA.Mods.Common.Traits
public void RulesetLoaded(Ruleset rules, ActorInfo ai)
{
if (!rules.Actors["world"].HasTraitInfo<TerrainLightingInfo>())
if (!rules.Actors[SystemActors.World].HasTraitInfo<TerrainLightingInfo>())
throw new YamlException("TerrainLightSource can only be used with the world TerrainLighting trait.");
}

View File

@@ -18,6 +18,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[TraitLocation(SystemActors.World | SystemActors.EditorWorld)]
public class ActorMapInfo : TraitInfo
{
[Desc("Size of partition bins (cells)")]

View File

@@ -18,6 +18,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[Desc("Controls the spawning of specified actor types. Attach this to the world actor.")]
[TraitLocation(SystemActors.World)]
public class ActorSpawnManagerInfo : ConditionalTraitInfo, Requires<MapCreepsInfo>
{
[Desc("Minimum number of actors.")]

View File

@@ -18,6 +18,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[TraitLocation(SystemActors.World)]
public class CrateSpawnerInfo : TraitInfo, ILobbyOptions
{
[Desc("Descriptive label for the crates checkbox in the lobby.")]

View File

@@ -18,6 +18,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[TraitLocation(SystemActors.World)]
[Desc("Attach this to the world actor.")]
public class CreateMapPlayersInfo : TraitInfo<CreateMapPlayers>, ICreatePlayersInfo
{
@@ -27,7 +28,7 @@ namespace OpenRA.Mods.Common.Traits
/// </summary>
void ICreatePlayersInfo.CreateServerPlayers(MapPreview map, Session lobbyInfo, List<GameInformation.Player> players, MersenneTwister playerRandom)
{
var worldInfo = map.Rules.Actors["world"];
var worldInfo = map.Rules.Actors[SystemActors.World];
var factions = worldInfo.TraitInfos<FactionInfo>().ToArray();
var assignSpawnLocations = worldInfo.TraitInfoOrDefault<IAssignSpawnPointsInfo>();
var spawnState = assignSpawnLocations?.InitializeState(map, lobbyInfo);
@@ -41,7 +42,7 @@ namespace OpenRA.Mods.Common.Traits
}
// Create the regular playable players.
var bots = map.Rules.Actors["player"].TraitInfos<IBotInfo>().ToArray();
var bots = map.Rules.Actors[SystemActors.Player].TraitInfos<IBotInfo>().ToArray();
foreach (var kv in lobbyInfo.Slots)
{

View File

@@ -17,6 +17,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[TraitLocation(SystemActors.World)]
[Desc("Identify untraversable regions of the map for faster pathfinding, especially with AI.",
"This trait is required. Every mod needs it attached to the world actor.")]
class DomainIndexInfo : TraitInfo<DomainIndex> { }

View File

@@ -16,6 +16,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[TraitLocation(SystemActors.EditorWorld)]
public class EditorActionManagerInfo : TraitInfo<EditorActionManager> { }
public class EditorActionManager : IWorldLoaded

View File

@@ -21,6 +21,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[TraitLocation(SystemActors.EditorWorld)]
[Desc("Required for the map editor to work. Attach this to the world actor.")]
public class EditorActorLayerInfo : TraitInfo, ICreatePlayersInfo
{

View File

@@ -19,6 +19,7 @@ namespace OpenRA.Mods.Common.Traits
{
public enum EditorCursorType { None, Actor, TerrainTemplate, Resource }
[TraitLocation(SystemActors.EditorWorld)]
[Desc("Required for the map editor to work. Attach this to the world actor.")]
public class EditorCursorLayerInfo : TraitInfo, Requires<EditorActorLayerInfo>, Requires<ITiledTerrainRendererInfo>
{

View File

@@ -18,6 +18,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[TraitLocation(SystemActors.EditorWorld)]
[Desc("Required for the map editor to work. Attach this to the world actor.")]
public class EditorResourceLayerInfo : TraitInfo, IResourceLayerInfo, IMapPreviewSignatureInfo
{
@@ -94,7 +95,7 @@ namespace OpenRA.Mods.Common.Traits
if (w.Type != WorldType.Editor)
return;
var playerResourcesInfo = w.Map.Rules.Actors["player"].TraitInfoOrDefault<PlayerResourcesInfo>();
var playerResourcesInfo = w.Map.Rules.Actors[SystemActors.Player].TraitInfoOrDefault<PlayerResourcesInfo>();
resourceValues = playerResourcesInfo?.ResourceValues ?? new Dictionary<string, int>();
foreach (var cell in Map.AllCells)

View File

@@ -15,6 +15,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[TraitLocation(SystemActors.EditorWorld)]
[Desc("Required for the map editor to work. Attach this to the world actor.")]
public class EditorSelectionLayerInfo : TraitInfo
{

View File

@@ -16,6 +16,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[TraitLocation(SystemActors.Player)]
public class GameSaveViewportManagerInfo : TraitInfo
{
public override object Create(ActorInitializer init) { return new GameSaveViewportManager(); }

View File

@@ -17,6 +17,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common
{
[TraitLocation(SystemActors.World | SystemActors.EditorWorld)]
[Desc("Define a palette by swapping palette indices.")]
public class IndexedPaletteInfo : TraitInfo, IRulesetLoaded
{

View File

@@ -19,6 +19,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[TraitLocation(SystemActors.World)]
class LegacyBridgeLayerInfo : TraitInfo
{
[ActorReference]

View File

@@ -16,6 +16,7 @@ using OpenRA.Widgets;
namespace OpenRA.Mods.Common.Traits
{
[TraitLocation(SystemActors.World | SystemActors.EditorWorld)]
public class LoadWidgetAtGameStartInfo : TraitInfo
{
[Desc("The widget tree to open when a shellmap is loaded (i.e. the main menu).")]

View File

@@ -14,6 +14,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[TraitLocation(SystemActors.Player)]
[Desc("Enables defined prerequisites at game start for all players if the checkbox is enabled.")]
public class LobbyPrerequisiteCheckboxInfo : TraitInfo, ILobbyOptions, ITechTreePrerequisiteInfo
{

View File

@@ -54,6 +54,7 @@ namespace OpenRA.Mods.Common.Traits
public const byte ElevatedBridge = 4;
}
[TraitLocation(SystemActors.World | SystemActors.EditorWorld)]
[Desc("Used by Mobile. Attach these to the world actor. You can have multiple variants by adding @suffixes.")]
public class LocomotorInfo : TraitInfo
{

View File

@@ -14,6 +14,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[TraitLocation(SystemActors.World)]
[Desc("Controls the build radius checkboxes in the lobby options.")]
public class MapBuildRadiusInfo : TraitInfo, ILobbyOptions
{

View File

@@ -15,6 +15,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[Desc("Controls the 'Creeps' checkbox in the lobby options.")]
[TraitLocation(SystemActors.World)]
public class MapCreepsInfo : TraitInfo, ILobbyOptions
{
[Desc("Descriptive label for the creeps checkbox in the lobby.")]

View File

@@ -15,6 +15,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[TraitLocation(SystemActors.World)]
[Desc("Controls the game speed, tech level, and short game lobby options.")]
public class MapOptionsInfo : TraitInfo, ILobbyOptions, IRulesetLoaded
{
@@ -77,7 +78,7 @@ namespace OpenRA.Mods.Common.Traits
yield return new LobbyBooleanOption("shortgame", ShortGameCheckboxLabel, ShortGameCheckboxDescription,
ShortGameCheckboxVisible, ShortGameCheckboxDisplayOrder, ShortGameCheckboxEnabled, ShortGameCheckboxLocked);
var techLevels = rules.Actors["player"].TraitInfos<ProvidesTechPrerequisiteInfo>()
var techLevels = rules.Actors[SystemActors.Player].TraitInfos<ProvidesTechPrerequisiteInfo>()
.ToDictionary(t => t.Id, t => t.Name);
if (techLevels.Any())

View File

@@ -19,6 +19,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[TraitLocation(SystemActors.World)]
[Desc("Allows the map to have working spawnpoints. Also controls the 'Separate Team Spawns' checkbox in the lobby options.")]
public class MapStartingLocationsInfo : TraitInfo, ILobbyOptions, IAssignSpawnPointsInfo
{

View File

@@ -14,6 +14,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[TraitLocation(SystemActors.World)]
[Desc("Used by SpawnStartingUnits. Attach these to the world actor. You can have multiple variants by adding @suffixes.")]
public class StartingUnitsInfo : TraitInfo<StartingUnits>
{

View File

@@ -17,6 +17,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[TraitLocation(SystemActors.World | SystemActors.EditorWorld)]
[Desc("Trait for music handling. Attach this to the world actor.")]
public class MusicPlaylistInfo : TraitInfo
{

View File

@@ -16,6 +16,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[TraitLocation(SystemActors.World | SystemActors.EditorWorld)]
[Desc("Load VGA palette (.pal) registers.")]
class PaletteFromFileInfo : TraitInfo, IProvidesCursorPaletteInfo
{

View File

@@ -19,6 +19,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[TraitLocation(SystemActors.World | SystemActors.EditorWorld)]
[Desc("Load a GIMP .gpl or JASC .pal palette file. Supports per-color alpha.")]
class PaletteFromGimpOrJascFileInfo : TraitInfo, IProvidesCursorPaletteInfo
{

View File

@@ -16,6 +16,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[TraitLocation(SystemActors.World | SystemActors.EditorWorld)]
[Desc("Create a palette by applying alpha transparency to another palette.")]
class PaletteFromPaletteWithAlphaInfo : TraitInfo
{

View File

@@ -15,6 +15,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[TraitLocation(SystemActors.World | SystemActors.EditorWorld)]
[Desc("Create player palettes by applying alpha transparency to another player palette.")]
class PaletteFromPlayerPaletteWithAlphaInfo : TraitInfo
{

View File

@@ -18,6 +18,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[TraitLocation(SystemActors.World | SystemActors.EditorWorld)]
[Desc("Load a PNG and use its embedded palette.")]
class PaletteFromPngInfo : TraitInfo, IProvidesCursorPaletteInfo
{

Some files were not shown because too many files have changed in this diff Show More