Allow ActorInits to target a specific trait by matching the @ suffix.

This commit is contained in:
Paul Chote
2020-06-02 19:39:32 +01:00
committed by teinarss
parent b38018af9c
commit 0eb0041f90
6 changed files with 61 additions and 11 deletions

View File

@@ -44,7 +44,17 @@ namespace OpenRA.Mods.Common.Graphics
public T GetOrDefault<T>(TraitInfo info) where T : ActorInit
{
return dict.GetOrDefault<T>();
var inits = dict.WithInterface<T>();
// Traits tagged with an instance name prefer inits with the same name.
// If a more specific init is not available, fall back to an unnamed init.
// If duplicate inits are defined, take the last to match standard yaml override expectations
if (info != null && !string.IsNullOrEmpty(info.InstanceName))
return inits.LastOrDefault(i => i.InstanceName == info.InstanceName) ??
inits.LastOrDefault(i => string.IsNullOrEmpty(i.InstanceName));
// Untagged traits will only use untagged inits
return inits.LastOrDefault(i => string.IsNullOrEmpty(i.InstanceName));
}
public T Get<T>(TraitInfo info) where T : ActorInit

View File

@@ -30,12 +30,16 @@ namespace OpenRA.Mods.Common.Scripting
ActorInit CreateInit(string initName, LuaValue value)
{
// Find the requested type
var initType = Game.ModData.ObjectCreator.FindType(initName + "Init");
var initInstance = initName.Split(ActorInfo.TraitInstanceSeparator);
var initType = Game.ModData.ObjectCreator.FindType(initInstance[0] + "Init");
if (initType == null)
throw new LuaException("Unknown initializer type '{0}'".F(initName));
throw new LuaException("Unknown initializer type '{0}'".F(initInstance[0]));
// Construct the ActorInit.
var init = (ActorInit)FormatterServices.GetUninitializedObject(initType);
if (initInstance.Length > 1)
initType.GetField("InstanceName").SetValue(init, initInstance[1]);
var initializers = initType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
.Where(m => m.Name == "Initialize" && m.GetParameters().Length == 1);
@@ -55,7 +59,7 @@ namespace OpenRA.Mods.Common.Scripting
}
var types = initializers.Select(y => y.GetParameters()[0].ParameterType.Name).JoinWith(", ");
throw new LuaException("Invalid data type for '{0}' (expected one of {1})".F(initName, types));
throw new LuaException("Invalid data type for '{0}' (expected one of {1})".F(initInstance[0], types));
}
[Desc("Create a new actor. initTable specifies a list of key-value pairs that defines the initial parameters for the actor's traits.")]