#region Copyright & License Information /* * Copyright 2007-2018 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.Diagnostics.CodeAnalysis; using System.Drawing; using OpenRA.Activities; using OpenRA.FileSystem; using OpenRA.Graphics; using OpenRA.Network; using OpenRA.Primitives; namespace OpenRA.Traits { public sealed class RequireExplicitImplementationAttribute : Attribute { } [Flags] public enum DamageState { Undamaged = 1, Light = 2, Medium = 4, Heavy = 8, Critical = 16, Dead = 32 } /// /// Type tag for DamageTypes . /// public sealed class DamageType { DamageType() { } } public interface IHealthInfo : ITraitInfo { int MaxHP { get; } } public interface IHealth { DamageState DamageState { get; } int HP { get; } int MaxHP { get; } int DisplayHP { get; } bool IsDead { get; } void InflictDamage(Actor self, Actor attacker, Damage damage, bool ignoreModifiers); void Kill(Actor self, Actor attacker, BitSet damageTypes); } // depends on the order of pips in WorldRenderer.cs! public enum PipType { Transparent, Green, Yellow, Red, Gray, Blue, Ammo, AmmoEmpty } [Flags] public enum Stance { None = 0, Enemy = 1, Neutral = 2, Ally = 4, } public static class StanceExts { public static bool HasStance(this Stance s, Stance stance) { // PERF: Enum.HasFlag is slower and requires allocations. return (s & stance) == stance; } } public class AttackInfo { public Damage Damage; public Actor Attacker; public DamageState DamageState; public DamageState PreviousDamageState; } public class Damage { public readonly int Value; public readonly BitSet DamageTypes; public Damage(int damage, BitSet damageTypes) { Value = damage; DamageTypes = damageTypes; } public Damage(int damage) { Value = damage; DamageTypes = default(BitSet); } } [RequireExplicitImplementation] public interface ITick { void Tick(Actor self); } [RequireExplicitImplementation] public interface ITickRender { void TickRender(WorldRenderer wr, Actor self); } public interface IRender { IEnumerable Render(Actor self, WorldRenderer wr); IEnumerable ScreenBounds(Actor self, WorldRenderer wr); } // TODO: Replace Rectangle with an int2[] polygon public interface IMouseBounds { Rectangle MouseoverBounds(Actor self, WorldRenderer wr); } public interface IMouseBoundsInfo : ITraitInfoInterface { } public interface IAutoMouseBounds { Rectangle AutoMouseoverBounds(Actor self, WorldRenderer wr); } // HACK: This provides a shim for legacy code until it can be rewritten public interface IDecorationBounds { Rectangle DecorationBounds(Actor self, WorldRenderer wr); } public interface IDecorationBoundsInfo : ITraitInfoInterface { } public static class DecorationBoundsExtensions { public static Rectangle FirstNonEmptyBounds(this IEnumerable decorationBounds, Actor self, WorldRenderer wr) { // PERF: Avoid LINQ. foreach (var decoration in decorationBounds) { var bounds = decoration.DecorationBounds(self, wr); if (!bounds.IsEmpty) return bounds; } return Rectangle.Empty; } public static Rectangle FirstNonEmptyBounds(this IDecorationBounds[] decorationBounds, Actor self, WorldRenderer wr) { // PERF: Avoid LINQ. foreach (var decoration in decorationBounds) { var bounds = decoration.DecorationBounds(self, wr); if (!bounds.IsEmpty) return bounds; } return Rectangle.Empty; } } public interface IIssueOrder { IEnumerable Orders { get; } Order IssueOrder(Actor self, IOrderTargeter order, Target target, bool queued); } [Flags] public enum TargetModifiers { None = 0, ForceAttack = 1, ForceQueue = 2, ForceMove = 4 } public static class TargetModifiersExts { public static bool HasModifier(this TargetModifiers self, TargetModifiers m) { // PERF: Enum.HasFlag is slower and requires allocations. return (self & m) == m; } } public interface IOrderTargeter { string OrderID { get; } int OrderPriority { get; } bool CanTarget(Actor self, Target target, List othersAtTarget, ref TargetModifiers modifiers, ref string cursor); bool IsQueued { get; } bool TargetOverridesSelection(TargetModifiers modifiers); } public interface IResolveOrder { void ResolveOrder(Actor self, Order order); } public interface IValidateOrder { bool OrderValidation(OrderManager orderManager, World world, int clientId, Order order); } public interface IOrderVoice { string VoicePhraseForOrder(Actor self, Order order); } [RequireExplicitImplementation] public interface INotifyCreated { void Created(Actor self); } [RequireExplicitImplementation] public interface INotifyAddedToWorld { void AddedToWorld(Actor self); } [RequireExplicitImplementation] public interface INotifyRemovedFromWorld { void RemovedFromWorld(Actor self); } [RequireExplicitImplementation] public interface INotifyActorDisposing { void Disposing(Actor self); } public interface INotifyOwnerChanged { void OnOwnerChanged(Actor self, Player oldOwner, Player newOwner); } public interface INotifyEffectiveOwnerChanged { void OnEffectiveOwnerChanged(Actor self, Player oldEffectiveOwner, Player newEffectiveOwner); } public interface INotifyOwnerLost { void OnOwnerLost(Actor self); } [RequireExplicitImplementation] public interface IVoiced { string VoiceSet { get; } bool PlayVoice(Actor self, string phrase, string variant); bool PlayVoiceLocal(Actor self, string phrase, string variant, float volume); bool HasVoice(Actor self, string voice); } [RequireExplicitImplementation] public interface IStoreResources { int Capacity { get; } } public interface IEffectiveOwner { bool Disguised { get; } Player Owner { get; } } public interface ITooltip { ITooltipInfo TooltipInfo { get; } Player Owner { get; } } public interface ITooltipInfo : ITraitInfoInterface { string TooltipForPlayerStance(Stance stance); bool IsOwnerRowVisible { get; } } public interface IProvideTooltipInfo { bool IsTooltipVisible(Player forPlayer); string TooltipText { get; } } public interface IDisabledTrait { bool IsTraitDisabled { get; } } public interface IDefaultVisibilityInfo : ITraitInfoInterface { } public interface IDefaultVisibility { bool IsVisible(Actor self, Player byPlayer); } public interface IVisibilityModifier { bool IsVisible(Actor self, Player byPlayer); } public interface IActorMap { IEnumerable GetActorsAt(CPos a); IEnumerable GetActorsAt(CPos a, SubCell sub); bool HasFreeSubCell(CPos cell, bool checkTransient = true); SubCell FreeSubCell(CPos cell, SubCell preferredSubCell = SubCell.Any, bool checkTransient = true); SubCell FreeSubCell(CPos cell, SubCell preferredSubCell, Func checkIfBlocker); bool AnyActorsAt(CPos a); bool AnyActorsAt(CPos a, SubCell sub, bool checkTransient = true); bool AnyActorsAt(CPos a, SubCell sub, Func withCondition); void AddInfluence(Actor self, IOccupySpace ios); void RemoveInfluence(Actor self, IOccupySpace ios); int AddCellTrigger(CPos[] cells, Action onEntry, Action onExit); void RemoveCellTrigger(int id); int AddProximityTrigger(WPos pos, WDist range, WDist vRange, Action onEntry, Action onExit); void RemoveProximityTrigger(int id); void UpdateProximityTrigger(int id, WPos newPos, WDist newRange, WDist newVRange); void AddPosition(Actor a, IOccupySpace ios); void RemovePosition(Actor a, IOccupySpace ios); void UpdatePosition(Actor a, IOccupySpace ios); IEnumerable ActorsInBox(WPos a, WPos b); WDist LargestActorRadius { get; } WDist LargestBlockingActorRadius { get; } } [RequireExplicitImplementation] public interface IRenderModifier { IEnumerable ModifyRender(Actor self, WorldRenderer wr, IEnumerable r); // HACK: This is here to support the WithShadow trait. // That trait should be rewritten using standard techniques, and then this interface method removed IEnumerable ModifyScreenBounds(Actor self, WorldRenderer wr, IEnumerable r); } [RequireExplicitImplementation] public interface IProvidesCursorPaletteInfo : ITraitInfoInterface { string Palette { get; } ImmutablePalette ReadPalette(IReadOnlyFileSystem fileSystem); } public interface ILoadsPalettes { void LoadPalettes(WorldRenderer wr); } public interface ILoadsPlayerPalettes { void LoadPlayerPalettes(WorldRenderer wr, string playerName, HSLColor playerColor, bool replaceExisting); } public interface IPaletteModifier { void AdjustPalette(IReadOnlyDictionary b); } public interface IPips { IEnumerable GetPips(Actor self); } [RequireExplicitImplementation] public interface ISelectionBar { float GetValue(); Color GetColor(); bool DisplayWhenEmpty { get; } } public interface IOccupySpaceInfo : ITraitInfoInterface { IReadOnlyDictionary OccupiedCells(ActorInfo info, CPos location, SubCell subCell = SubCell.Any); bool SharesCell { get; } } public interface IOccupySpace { WPos CenterPosition { get; } CPos TopLeft { get; } Pair[] OccupiedCells(); } public enum SubCell : byte { Invalid = byte.MaxValue, Any = byte.MaxValue - 1, FullCell = 0, First = 1 } public interface IPositionableInfo : IOccupySpaceInfo { bool CanEnterCell(World world, Actor self, CPos cell, Actor ignoreActor = null, bool checkTransientActors = true); } public interface IPositionable : IOccupySpace { bool CanExistInCell(CPos location); bool IsLeavingCell(CPos location, SubCell subCell = SubCell.Any); bool CanEnterCell(CPos location, Actor ignoreActor = null, bool checkTransientActors = true); SubCell GetValidSubCell(SubCell preferred = SubCell.Any); SubCell GetAvailableSubCell(CPos location, SubCell preferredSubCell = SubCell.Any, Actor ignoreActor = null, bool checkTransientActors = true); void SetPosition(Actor self, CPos cell, SubCell subCell = SubCell.Any); void SetPosition(Actor self, WPos pos); void SetVisualPosition(Actor self, WPos pos); } public interface ITemporaryBlockerInfo : ITraitInfoInterface { } [RequireExplicitImplementation] public interface ITemporaryBlocker { bool CanRemoveBlockage(Actor self, Actor blocking); bool IsBlocking(Actor self, CPos cell); } public interface IFacing { int TurnSpeed { get; } int Facing { get; set; } } public interface IFacingInfo : ITraitInfoInterface { int GetInitialFacing(); } public interface ITraitInfoInterface { } public interface ITraitInfo : ITraitInfoInterface { object Create(ActorInitializer init); } public class TraitInfo : ITraitInfo where T : new() { public virtual object Create(ActorInitializer init) { return new T(); } } public interface ILobbyCustomRulesIgnore { } [SuppressMessage("StyleCop.CSharp.NamingRules", "SA1302:InterfaceNamesMustBeginWithI", Justification = "Not a real interface, but more like a tag.")] public interface Requires where T : class, ITraitInfoInterface { } [SuppressMessage("StyleCop.CSharp.NamingRules", "SA1302:InterfaceNamesMustBeginWithI", Justification = "Not a real interface, but more like a tag.")] public interface UsesInit : ITraitInfo where T : IActorInit { } [RequireExplicitImplementation] public interface INotifySelected { void Selected(Actor self); } [RequireExplicitImplementation] public interface INotifySelection { void SelectionChanged(); } public interface IWorldLoaded { void WorldLoaded(World w, WorldRenderer wr); } [RequireExplicitImplementation] public interface ICreatePlayers { void CreatePlayers(World w); } public interface IBotInfo : ITraitInfoInterface { string Type { get; } string Name { get; } } public interface IBot { void Activate(Player p); IBotInfo Info { get; } } [RequireExplicitImplementation] public interface IRenderOverlay { void Render(WorldRenderer wr); } [RequireExplicitImplementation] public interface INotifyBecomingIdle { void OnBecomingIdle(Actor self); } [RequireExplicitImplementation] public interface INotifyIdle { void TickIdle(Actor self); } public interface IRenderAboveWorld { void RenderAboveWorld(Actor self, WorldRenderer wr); } public interface IRenderShroud { void RenderShroud(Shroud shroud, WorldRenderer wr); } [RequireExplicitImplementation] public interface IRenderTerrain { void RenderTerrain(WorldRenderer wr, Viewport viewport); } public interface IRenderAboveShroud { IEnumerable RenderAboveShroud(Actor self, WorldRenderer wr); bool SpatiallyPartitionable { get; } } public interface IRenderAboveShroudWhenSelected { IEnumerable RenderAboveShroud(Actor self, WorldRenderer wr); bool SpatiallyPartitionable { get; } } /// /// Indicates target types as defined on are present in a . /// public sealed class TargetableType { TargetableType() { } } public interface ITargetableInfo : ITraitInfoInterface { BitSet GetTargetTypes(); } public interface ITargetable { // Check IsTraitEnabled or !IsTraitDisabled first BitSet TargetTypes { get; } bool TargetableBy(Actor self, Actor byActor); bool RequiresForceFire { get; } } [RequireExplicitImplementation] public interface ITargetablePositions { IEnumerable TargetablePositions(Actor self); bool AlwaysEnabled { get; } } public interface IMoveInfo : ITraitInfoInterface { } [RequireExplicitImplementation] public interface IGameOver { void GameOver(World world); } public interface IWarhead { int Delay { get; } bool IsValidAgainst(Actor victim, Actor firedBy); bool IsValidAgainst(FrozenActor victim, Actor firedBy); void DoImpact(Target target, Actor firedBy, IEnumerable damageModifiers); } public interface IRulesetLoaded { void RulesetLoaded(Ruleset rules, TInfo info); } public interface IRulesetLoaded : IRulesetLoaded, ITraitInfoInterface { } [RequireExplicitImplementation] public interface ILobbyOptions : ITraitInfoInterface { IEnumerable LobbyOptions(Ruleset rules); } public class LobbyOption { public readonly string Id; public readonly string Name; public readonly string Description; public readonly IReadOnlyDictionary Values; public readonly string DefaultValue; public readonly bool IsLocked; public readonly bool IsVisible; public readonly int DisplayOrder; public LobbyOption(string id, string name, string description, bool visible, int displayorder, IReadOnlyDictionary values, string defaultValue, bool locked) { Id = id; Name = name; Description = description; IsVisible = visible; DisplayOrder = displayorder; Values = values; DefaultValue = defaultValue; IsLocked = locked; } public virtual string ValueChangedMessage(string playerName, string newValue) { return playerName + " changed " + Name + " to " + Values[newValue] + "."; } } public class LobbyBooleanOption : LobbyOption { static readonly Dictionary BoolValues = new Dictionary() { { true.ToString(), "enabled" }, { false.ToString(), "disabled" } }; public LobbyBooleanOption(string id, string name, string description, bool visible, int displayorder, bool defaultValue, bool locked) : base(id, name, description, visible, displayorder, new ReadOnlyDictionary(BoolValues), defaultValue.ToString(), locked) { } public override string ValueChangedMessage(string playerName, string newValue) { return playerName + " " + BoolValues[newValue] + " " + Name + "."; } } [RequireExplicitImplementation] public interface IUnlocksRenderPlayer { bool RenderPlayerUnlocked { get; } } }