Expose common actor Inits in the map editor.

This commit is contained in:
Paul Chote
2018-12-08 18:41:12 +00:00
committed by reaperrr
parent f6768fe624
commit 4723e5ddb9
11 changed files with 369 additions and 79 deletions

View File

@@ -23,7 +23,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
public class AircraftInfo : ITraitInfo, IPositionableInfo, IFacingInfo, IMoveInfo, ICruiseAltitudeInfo,
IActorPreviewInitInfo
IActorPreviewInitInfo, IEditorActorOptions
{
public readonly WDist CruiseAltitude = new WDist(1280);
@@ -111,6 +111,9 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Facing to use for actor previews (map editor, color picker, etc)")]
public readonly int PreviewFacing = 92;
[Desc("Display order for the facing slider in the map editor")]
public readonly int EditorFacingDisplayOrder = 3;
public int GetInitialFacing() { return InitialFacing; }
public WDist GetCruiseAltitude() { return CruiseAltitude; }
@@ -147,6 +150,17 @@ namespace OpenRA.Mods.Common.Traits
return !world.ActorMap.GetActorsAt(cell).Any(x => x != ignoreActor);
}
IEnumerable<EditorActorOption> IEditorActorOptions.ActorOptions(ActorInfo ai, World world)
{
yield return new EditorActorSlider("Facing", EditorFacingDisplayOrder, 0, 255, 8,
actor =>
{
var init = actor.Init<FacingInit>();
return init != null ? init.Value(world) : InitialFacing;
},
(actor, value) => actor.ReplaceInit(new FacingInit((int)value)));
}
}
public class Aircraft : ITick, ISync, IFacing, IPositionable, IMove, IIssueOrder, IResolveOrder, IOrderVoice, IDeathActorInitModifier,

View File

@@ -16,8 +16,10 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
public enum UnitStance { HoldFire, ReturnFire, Defend, AttackAnything }
[Desc("The actor will automatically engage the enemy when it is in range.")]
public class AutoTargetInfo : ConditionalTraitInfo, IRulesetLoaded, Requires<AttackBaseInfo>
public class AutoTargetInfo : ConditionalTraitInfo, Requires<AttackBaseInfo>, IEditorActorOptions
{
[Desc("It will try to hunt down the enemy if it is set to AttackAnything.")]
public readonly bool AllowMovement = true;
@@ -60,6 +62,9 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Ticks to wait until next AutoTarget: attempt.")]
public readonly int MaximumScanTimeInterval = 8;
[Desc("Display order for the stance dropdown in the map editor")]
public readonly int EditorStanceDisplayOrder = 1;
public override object Create(ActorInitializer init) { return new AutoTarget(init, this); }
public override void RulesetLoaded(Ruleset rules, ActorInfo info)
@@ -78,9 +83,30 @@ namespace OpenRA.Mods.Common.Traits
if (AttackAnythingCondition != null)
ConditionByStance[UnitStance.AttackAnything] = AttackAnythingCondition;
}
}
public enum UnitStance { HoldFire, ReturnFire, Defend, AttackAnything }
IEnumerable<EditorActorOption> IEditorActorOptions.ActorOptions(ActorInfo ai, World world)
{
// Indexed by UnitStance
var stances = new[] { "holdfire", "returnfire", "defend", "attackanything" };
var labels = new Dictionary<string, string>()
{
{ "holdfire", "Hold Fire" },
{ "returnfire", "Return Fire" },
{ "defend", "Defend" },
{ "attackanything", "Attack Anything" },
};
yield return new EditorActorDropdown("Stance", EditorStanceDisplayOrder, labels,
actor =>
{
var init = actor.Init<StanceInit>();
var stance = init != null ? init.Value(world) : InitialStance;
return stances[(int)stance];
},
(actor, value) => actor.ReplaceInit(new StanceInit((UnitStance)stances.IndexOf(value))));
}
}
public class AutoTarget : ConditionalTrait<AutoTargetInfo>, INotifyIdle, INotifyDamage, ITick, IResolveOrder, ISync, INotifyCreated
{

View File

@@ -9,13 +9,14 @@
*/
#endregion
using System.Collections.Generic;
using System.Linq;
using OpenRA.Primitives;
using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
public class HealthInfo : IHealthInfo, IRulesetLoaded
public class HealthInfo : IHealthInfo, IRulesetLoaded, IEditorActorOptions
{
[Desc("HitPoints")]
public readonly int HP = 0;
@@ -23,6 +24,9 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Trigger interfaces such as AnnounceOnKill?")]
public readonly bool NotifyAppliedDamage = true;
[Desc("Display order for the health slider in the map editor")]
public readonly int EditorHealthDisplayOrder = 2;
public virtual object Create(ActorInitializer init) { return new Health(init, this); }
public void RulesetLoaded(Ruleset rules, ActorInfo ai)
@@ -32,6 +36,17 @@ namespace OpenRA.Mods.Common.Traits
}
int IHealthInfo.MaxHP { get { return HP; } }
IEnumerable<EditorActorOption> IEditorActorOptions.ActorOptions(ActorInfo ai, World world)
{
yield return new EditorActorSlider("Health", EditorHealthDisplayOrder, 0, 100, 5,
actor =>
{
var init = actor.Init<HealthInit>();
return init != null ? init.Value(world) : 100;
},
(actor, value) => actor.ReplaceInit(new HealthInit((int)value)));
}
}
public class Health : IHealth, ISync, ITick, INotifyCreated, INotifyOwnerChanged

View File

@@ -22,7 +22,8 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
[Desc("Unit is able to move.")]
public class MobileInfo : ConditionalTraitInfo, IMoveInfo, IPositionableInfo, IFacingInfo, IActorPreviewInitInfo
public class MobileInfo : ConditionalTraitInfo, IMoveInfo, IPositionableInfo, IFacingInfo, IActorPreviewInitInfo,
IEditorActorOptions
{
[Desc("Which Locomotor does this trait use. Must be defined on the World actor.")]
[LocomotorReference, FieldLoader.Require]
@@ -46,6 +47,9 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Facing to use for actor previews (map editor, color picker, etc)")]
public readonly int PreviewFacing = 92;
[Desc("Display order for the facing slider in the map editor")]
public readonly int EditorFacingDisplayOrder = 3;
IEnumerable<object> IActorPreviewInitInfo.ActorPreviewInits(ActorInfo ai, ActorPreviewType type)
{
yield return new FacingInit(PreviewFacing);
@@ -84,6 +88,41 @@ namespace OpenRA.Mods.Common.Traits
}
bool IOccupySpaceInfo.SharesCell { get { return LocomotorInfo.SharesCell; } }
IEnumerable<EditorActorOption> IEditorActorOptions.ActorOptions(ActorInfo ai, World world)
{
yield return new EditorActorSlider("Facing", EditorFacingDisplayOrder, 0, 255, 8,
actor =>
{
var init = actor.Init<FacingInit>();
return init != null ? init.Value(world) : InitialFacing;
},
(actor, value) =>
{
// TODO: This can all go away once turrets are properly defined as a relative facing
var turretInit = actor.Init<TurretFacingInit>();
var turretsInit = actor.Init<TurretFacingsInit>();
var facingInit = actor.Init<FacingInit>();
var oldFacing = facingInit != null ? facingInit.Value(world) : InitialFacing;
var newFacing = (int)value;
if (turretInit != null)
{
var newTurretFacing = (turretInit.Value(world) + newFacing - oldFacing + 255) % 255;
actor.ReplaceInit(new TurretFacingInit(newTurretFacing));
}
if (turretsInit != null)
{
var newTurretFacings = turretsInit.Value(world)
.ToDictionary(kv => kv.Key, kv => (kv.Value + newFacing - oldFacing + 255) % 255);
actor.ReplaceInit(new TurretFacingsInit(newTurretFacings));
}
actor.ReplaceInit(new FacingInit(newFacing));
});
}
}
public class Mobile : ConditionalTrait<MobileInfo>, INotifyCreated, IIssueOrder, IResolveOrder, IOrderVoice, IPositionable, IMove,

View File

@@ -17,7 +17,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
public class TurretedInfo : PausableConditionalTraitInfo, Requires<BodyOrientationInfo>, IActorPreviewInitInfo
public class TurretedInfo : PausableConditionalTraitInfo, Requires<BodyOrientationInfo>, IActorPreviewInitInfo, IEditorActorOptions
{
public readonly string Turret = "primary";
[Desc("Speed at which the turret turns.")]
@@ -33,6 +33,9 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Facing to use for actor previews (map editor, color picker, etc)")]
public readonly int PreviewFacing = 92;
[Desc("Display order for the turret facing slider in the map editor")]
public readonly int EditorTurretFacingDisplayOrder = 4;
IEnumerable<object> IActorPreviewInitInfo.ActorPreviewInits(ActorInfo ai, ActorPreviewType type)
{
// HACK: The ActorInit system does not support multiple instances of the same type
@@ -41,6 +44,32 @@ namespace OpenRA.Mods.Common.Traits
yield return new TurretFacingInit(PreviewFacing);
}
IEnumerable<EditorActorOption> IEditorActorOptions.ActorOptions(ActorInfo ai, World world)
{
// TODO: Handle multiple turrets properly (will probably require a rewrite of the Init system)
if (ai.TraitInfos<TurretedInfo>().FirstOrDefault() != this)
yield break;
yield return new EditorActorSlider("Turret", EditorTurretFacingDisplayOrder, 0, 255, 8,
actor =>
{
var init = actor.Init<TurretFacingInit>();
if (init != null)
return init.Value(world);
var facingInit = actor.Init<FacingInit>();
if (facingInit != null)
return facingInit.Value(world);
return InitialFacing;
},
(actor, value) =>
{
actor.RemoveInit<TurretFacingsInit>();
actor.ReplaceInit(new TurretFacingInit((int)value));
});
}
public override object Create(ActorInitializer init) { return new Turreted(init, this); }
}

View File

@@ -134,6 +134,14 @@ namespace OpenRA.Mods.Common.Traits
GeneratePreviews();
}
public void RemoveInit<T>()
{
var original = actor.InitDict.GetOrDefault<T>();
if (original != null)
actor.InitDict.Remove(original);
GeneratePreviews();
}
public T Init<T>()
{
return actor.InitDict.GetOrDefault<T>();