1 #region Copyright & License Information 2 /* 3 * Copyright 2007-2020 The OpenRA Developers (see AUTHORS) 4 * This file is part of OpenRA, which is free software. It is made 5 * available to you under the terms of the GNU General Public License 6 * as published by the Free Software Foundation, either version 3 of 7 * the License, or (at your option) any later version. For more 8 * information, see COPYING. 9 */ 10 #endregion 11 12 using System; 13 using System.Collections.Generic; 14 using System.Diagnostics.CodeAnalysis; 15 using OpenRA.Activities; 16 using OpenRA.FileSystem; 17 using OpenRA.GameRules; 18 using OpenRA.Graphics; 19 using OpenRA.Network; 20 using OpenRA.Primitives; 21 22 namespace OpenRA.Traits 23 { 24 public sealed class RequireExplicitImplementationAttribute : Attribute { } 25 26 [Flags] 27 public enum DamageState 28 { 29 Undamaged = 1, 30 Light = 2, 31 Medium = 4, 32 Heavy = 8, 33 Critical = 16, 34 Dead = 32 35 } 36 37 // NOTE: Each subsequent category is a superset of the previous categories 38 // and categories are mutually exclusive. 39 public enum BlockedByActor 40 { 41 None, 42 Immovable, 43 Stationary, 44 All 45 } 46 47 /// <summary> 48 /// Type tag for DamageTypes <see cref="Primitives.BitSet{T}"/>. 49 /// </summary> DamageType()50 public sealed class DamageType { DamageType() { } } 51 52 public interface IHealthInfo : ITraitInfo 53 { 54 int MaxHP { get; } 55 } 56 57 public interface IHealth 58 { 59 DamageState DamageState { get; } 60 int HP { get; } 61 int MaxHP { get; } 62 int DisplayHP { get; } 63 bool IsDead { get; } 64 InflictDamage(Actor self, Actor attacker, Damage damage, bool ignoreModifiers)65 void InflictDamage(Actor self, Actor attacker, Damage damage, bool ignoreModifiers); Kill(Actor self, Actor attacker, BitSet<DamageType> damageTypes)66 void Kill(Actor self, Actor attacker, BitSet<DamageType> damageTypes); 67 } 68 69 // depends on the order of pips in WorldRenderer.cs! 70 public enum PipType { Transparent, Green, Yellow, Red, Gray, Blue, Ammo, AmmoEmpty } 71 72 [Flags] 73 public enum Stance 74 { 75 None = 0, 76 Enemy = 1, 77 Neutral = 2, 78 Ally = 4, 79 } 80 81 public static class StanceExts 82 { HasStance(this Stance s, Stance stance)83 public static bool HasStance(this Stance s, Stance stance) 84 { 85 // PERF: Enum.HasFlag is slower and requires allocations. 86 return (s & stance) == stance; 87 } 88 } 89 90 public class AttackInfo 91 { 92 public Damage Damage; 93 public Actor Attacker; 94 public DamageState DamageState; 95 public DamageState PreviousDamageState; 96 } 97 98 public class Damage 99 { 100 public readonly int Value; 101 public readonly BitSet<DamageType> DamageTypes; 102 Damage(int damage, BitSet<DamageType> damageTypes)103 public Damage(int damage, BitSet<DamageType> damageTypes) 104 { 105 Value = damage; 106 DamageTypes = damageTypes; 107 } 108 Damage(int damage)109 public Damage(int damage) 110 { 111 Value = damage; 112 DamageTypes = default(BitSet<DamageType>); 113 } 114 } 115 116 [RequireExplicitImplementation] Tick(Actor self)117 public interface ITick { void Tick(Actor self); } 118 [RequireExplicitImplementation] TickRender(WorldRenderer wr, Actor self)119 public interface ITickRender { void TickRender(WorldRenderer wr, Actor self); } 120 public interface IRender 121 { Render(Actor self, WorldRenderer wr)122 IEnumerable<IRenderable> Render(Actor self, WorldRenderer wr); ScreenBounds(Actor self, WorldRenderer wr)123 IEnumerable<Rectangle> ScreenBounds(Actor self, WorldRenderer wr); 124 } 125 126 // TODO: Replace Rectangle with an int2[] polygon MouseoverBounds(Actor self, WorldRenderer wr)127 public interface IMouseBounds { Rectangle MouseoverBounds(Actor self, WorldRenderer wr); } 128 public interface IMouseBoundsInfo : ITraitInfoInterface { } AutoMouseoverBounds(Actor self, WorldRenderer wr)129 public interface IAutoMouseBounds { Rectangle AutoMouseoverBounds(Actor self, WorldRenderer wr); } 130 131 // HACK: This provides a shim for legacy code until it can be rewritten DecorationBounds(Actor self, WorldRenderer wr)132 public interface IDecorationBounds { Rectangle DecorationBounds(Actor self, WorldRenderer wr); } 133 public interface IDecorationBoundsInfo : ITraitInfoInterface { } 134 public static class DecorationBoundsExtensions 135 { FirstNonEmptyBounds(this IEnumerable<IDecorationBounds> decorationBounds, Actor self, WorldRenderer wr)136 public static Rectangle FirstNonEmptyBounds(this IEnumerable<IDecorationBounds> decorationBounds, Actor self, WorldRenderer wr) 137 { 138 // PERF: Avoid LINQ. 139 foreach (var decoration in decorationBounds) 140 { 141 var bounds = decoration.DecorationBounds(self, wr); 142 if (!bounds.IsEmpty) 143 return bounds; 144 } 145 146 return Rectangle.Empty; 147 } 148 FirstNonEmptyBounds(this IDecorationBounds[] decorationBounds, Actor self, WorldRenderer wr)149 public static Rectangle FirstNonEmptyBounds(this IDecorationBounds[] decorationBounds, Actor self, WorldRenderer wr) 150 { 151 // PERF: Avoid LINQ. 152 foreach (var decoration in decorationBounds) 153 { 154 var bounds = decoration.DecorationBounds(self, wr); 155 if (!bounds.IsEmpty) 156 return bounds; 157 } 158 159 return Rectangle.Empty; 160 } 161 } 162 163 public interface IIssueOrder 164 { 165 IEnumerable<IOrderTargeter> Orders { get; } IssueOrder(Actor self, IOrderTargeter order, Target target, bool queued)166 Order IssueOrder(Actor self, IOrderTargeter order, Target target, bool queued); 167 } 168 169 [Flags] 170 public enum TargetModifiers { None = 0, ForceAttack = 1, ForceQueue = 2, ForceMove = 4 } 171 172 public static class TargetModifiersExts 173 { HasModifier(this TargetModifiers self, TargetModifiers m)174 public static bool HasModifier(this TargetModifiers self, TargetModifiers m) 175 { 176 // PERF: Enum.HasFlag is slower and requires allocations. 177 return (self & m) == m; 178 } 179 } 180 181 public interface IOrderTargeter 182 { 183 string OrderID { get; } 184 int OrderPriority { get; } CanTarget(Actor self, Target target, List<Actor> othersAtTarget, ref TargetModifiers modifiers, ref string cursor)185 bool CanTarget(Actor self, Target target, List<Actor> othersAtTarget, ref TargetModifiers modifiers, ref string cursor); 186 bool IsQueued { get; } TargetOverridesSelection(Actor self, Target target, List<Actor> actorsAt, CPos xy, TargetModifiers modifiers)187 bool TargetOverridesSelection(Actor self, Target target, List<Actor> actorsAt, CPos xy, TargetModifiers modifiers); 188 } 189 ResolveOrder(Actor self, Order order)190 public interface IResolveOrder { void ResolveOrder(Actor self, Order order); } OrderValidation(OrderManager orderManager, World world, int clientId, Order order)191 public interface IValidateOrder { bool OrderValidation(OrderManager orderManager, World world, int clientId, Order order); } VoicePhraseForOrder(Actor self, Order order)192 public interface IOrderVoice { string VoicePhraseForOrder(Actor self, Order order); } 193 194 [RequireExplicitImplementation] Created(Actor self)195 public interface INotifyCreated { void Created(Actor self); } 196 197 [RequireExplicitImplementation] AddedToWorld(Actor self)198 public interface INotifyAddedToWorld { void AddedToWorld(Actor self); } 199 [RequireExplicitImplementation] RemovedFromWorld(Actor self)200 public interface INotifyRemovedFromWorld { void RemovedFromWorld(Actor self); } 201 202 [RequireExplicitImplementation] Disposing(Actor self)203 public interface INotifyActorDisposing { void Disposing(Actor self); } OnOwnerChanged(Actor self, Player oldOwner, Player newOwner)204 public interface INotifyOwnerChanged { void OnOwnerChanged(Actor self, Player oldOwner, Player newOwner); } OnEffectiveOwnerChanged(Actor self, Player oldEffectiveOwner, Player newEffectiveOwner)205 public interface INotifyEffectiveOwnerChanged { void OnEffectiveOwnerChanged(Actor self, Player oldEffectiveOwner, Player newEffectiveOwner); } OnOwnerLost(Actor self)206 public interface INotifyOwnerLost { void OnOwnerLost(Actor self); } 207 208 [RequireExplicitImplementation] 209 public interface IVoiced 210 { 211 string VoiceSet { get; } PlayVoice(Actor self, string phrase, string variant)212 bool PlayVoice(Actor self, string phrase, string variant); PlayVoiceLocal(Actor self, string phrase, string variant, float volume)213 bool PlayVoiceLocal(Actor self, string phrase, string variant, float volume); HasVoice(Actor self, string voice)214 bool HasVoice(Actor self, string voice); 215 } 216 217 [RequireExplicitImplementation] 218 public interface IStoreResources { int Capacity { get; } } 219 220 public interface IEffectiveOwner 221 { 222 bool Disguised { get; } 223 Player Owner { get; } 224 } 225 226 public interface ITooltip 227 { 228 ITooltipInfo TooltipInfo { get; } 229 Player Owner { get; } 230 } 231 232 public interface ITooltipInfo : ITraitInfoInterface 233 { TooltipForPlayerStance(Stance stance)234 string TooltipForPlayerStance(Stance stance); 235 bool IsOwnerRowVisible { get; } 236 } 237 238 public interface IProvideTooltipInfo 239 { IsTooltipVisible(Player forPlayer)240 bool IsTooltipVisible(Player forPlayer); 241 string TooltipText { get; } 242 } 243 244 public interface IDisabledTrait { bool IsTraitDisabled { get; } } 245 246 public interface IDefaultVisibilityInfo : ITraitInfoInterface { } IsVisible(Actor self, Player byPlayer)247 public interface IDefaultVisibility { bool IsVisible(Actor self, Player byPlayer); } IsVisible(Actor self, Player byPlayer)248 public interface IVisibilityModifier { bool IsVisible(Actor self, Player byPlayer); } 249 250 public interface IActorMap 251 { GetActorsAt(CPos a)252 IEnumerable<Actor> GetActorsAt(CPos a); GetActorsAt(CPos a, SubCell sub)253 IEnumerable<Actor> GetActorsAt(CPos a, SubCell sub); HasFreeSubCell(CPos cell, bool checkTransient = true)254 bool HasFreeSubCell(CPos cell, bool checkTransient = true); FreeSubCell(CPos cell, SubCell preferredSubCell = SubCell.Any, bool checkTransient = true)255 SubCell FreeSubCell(CPos cell, SubCell preferredSubCell = SubCell.Any, bool checkTransient = true); FreeSubCell(CPos cell, SubCell preferredSubCell, Func<Actor, bool> checkIfBlocker)256 SubCell FreeSubCell(CPos cell, SubCell preferredSubCell, Func<Actor, bool> checkIfBlocker); AnyActorsAt(CPos a)257 bool AnyActorsAt(CPos a); AnyActorsAt(CPos a, SubCell sub, bool checkTransient = true)258 bool AnyActorsAt(CPos a, SubCell sub, bool checkTransient = true); AnyActorsAt(CPos a, SubCell sub, Func<Actor, bool> withCondition)259 bool AnyActorsAt(CPos a, SubCell sub, Func<Actor, bool> withCondition); AddInfluence(Actor self, IOccupySpace ios)260 void AddInfluence(Actor self, IOccupySpace ios); RemoveInfluence(Actor self, IOccupySpace ios)261 void RemoveInfluence(Actor self, IOccupySpace ios); AddCellTrigger(CPos[] cells, Action<Actor> onEntry, Action<Actor> onExit)262 int AddCellTrigger(CPos[] cells, Action<Actor> onEntry, Action<Actor> onExit); RemoveCellTrigger(int id)263 void RemoveCellTrigger(int id); AddProximityTrigger(WPos pos, WDist range, WDist vRange, Action<Actor> onEntry, Action<Actor> onExit)264 int AddProximityTrigger(WPos pos, WDist range, WDist vRange, Action<Actor> onEntry, Action<Actor> onExit); RemoveProximityTrigger(int id)265 void RemoveProximityTrigger(int id); UpdateProximityTrigger(int id, WPos newPos, WDist newRange, WDist newVRange)266 void UpdateProximityTrigger(int id, WPos newPos, WDist newRange, WDist newVRange); AddPosition(Actor a, IOccupySpace ios)267 void AddPosition(Actor a, IOccupySpace ios); RemovePosition(Actor a, IOccupySpace ios)268 void RemovePosition(Actor a, IOccupySpace ios); UpdatePosition(Actor a, IOccupySpace ios)269 void UpdatePosition(Actor a, IOccupySpace ios); ActorsInBox(WPos a, WPos b)270 IEnumerable<Actor> ActorsInBox(WPos a, WPos b); 271 272 WDist LargestActorRadius { get; } 273 WDist LargestBlockingActorRadius { get; } 274 UpdateOccupiedCells(IOccupySpace ios)275 void UpdateOccupiedCells(IOccupySpace ios); 276 event Action<CPos> CellUpdated; 277 } 278 279 [RequireExplicitImplementation] 280 public interface IRenderModifier 281 { ModifyRender(Actor self, WorldRenderer wr, IEnumerable<IRenderable> r)282 IEnumerable<IRenderable> ModifyRender(Actor self, WorldRenderer wr, IEnumerable<IRenderable> r); 283 284 // HACK: This is here to support the WithShadow trait. 285 // That trait should be rewritten using standard techniques, and then this interface method removed ModifyScreenBounds(Actor self, WorldRenderer wr, IEnumerable<Rectangle> r)286 IEnumerable<Rectangle> ModifyScreenBounds(Actor self, WorldRenderer wr, IEnumerable<Rectangle> r); 287 } 288 289 [RequireExplicitImplementation] 290 public interface IProvidesCursorPaletteInfo : ITraitInfoInterface 291 { 292 string Palette { get; } ReadPalette(IReadOnlyFileSystem fileSystem)293 ImmutablePalette ReadPalette(IReadOnlyFileSystem fileSystem); 294 } 295 LoadPalettes(WorldRenderer wr)296 public interface ILoadsPalettes { void LoadPalettes(WorldRenderer wr); } LoadPlayerPalettes(WorldRenderer wr, string playerName, Color playerColor, bool replaceExisting)297 public interface ILoadsPlayerPalettes { void LoadPlayerPalettes(WorldRenderer wr, string playerName, Color playerColor, bool replaceExisting); } AdjustPalette(IReadOnlyDictionary<string, MutablePalette> b)298 public interface IPaletteModifier { void AdjustPalette(IReadOnlyDictionary<string, MutablePalette> b); } GetPips(Actor self)299 public interface IPips { IEnumerable<PipType> GetPips(Actor self); } 300 301 [RequireExplicitImplementation] GetColor()302 public interface ISelectionBar { float GetValue(); Color GetColor(); bool DisplayWhenEmpty { get; } } 303 DrawRollover(Actor self, WorldRenderer worldRenderer)304 public interface ISelectionDecorations { void DrawRollover(Actor self, WorldRenderer worldRenderer); } 305 306 public interface IMapPreviewSignatureInfo : ITraitInfoInterface 307 { PopulateMapPreviewSignatureCells(Map map, ActorInfo ai, ActorReference s, List<Pair<MPos, Color>> destinationBuffer)308 void PopulateMapPreviewSignatureCells(Map map, ActorInfo ai, ActorReference s, List<Pair<MPos, Color>> destinationBuffer); 309 } 310 311 public interface IOccupySpaceInfo : ITraitInfoInterface 312 { OccupiedCells(ActorInfo info, CPos location, SubCell subCell = SubCell.Any)313 IReadOnlyDictionary<CPos, SubCell> OccupiedCells(ActorInfo info, CPos location, SubCell subCell = SubCell.Any); 314 bool SharesCell { get; } 315 } 316 317 public interface IOccupySpace 318 { 319 WPos CenterPosition { get; } 320 CPos TopLeft { get; } OccupiedCells()321 Pair<CPos, SubCell>[] OccupiedCells(); 322 } 323 324 public enum SubCell : byte { Invalid = byte.MaxValue, Any = byte.MaxValue - 1, FullCell = 0, First = 1 } 325 326 public interface IPositionableInfo : IOccupySpaceInfo 327 { CanEnterCell(World world, Actor self, CPos cell, SubCell subCell = SubCell.FullCell, Actor ignoreActor = null, BlockedByActor check = BlockedByActor.All)328 bool CanEnterCell(World world, Actor self, CPos cell, SubCell subCell = SubCell.FullCell, Actor ignoreActor = null, BlockedByActor check = BlockedByActor.All); 329 } 330 331 public interface IPositionable : IOccupySpace 332 { CanExistInCell(CPos location)333 bool CanExistInCell(CPos location); IsLeavingCell(CPos location, SubCell subCell = SubCell.Any)334 bool IsLeavingCell(CPos location, SubCell subCell = SubCell.Any); CanEnterCell(CPos location, Actor ignoreActor = null, BlockedByActor check = BlockedByActor.All)335 bool CanEnterCell(CPos location, Actor ignoreActor = null, BlockedByActor check = BlockedByActor.All); GetValidSubCell(SubCell preferred = SubCell.Any)336 SubCell GetValidSubCell(SubCell preferred = SubCell.Any); GetAvailableSubCell(CPos location, SubCell preferredSubCell = SubCell.Any, Actor ignoreActor = null, BlockedByActor check = BlockedByActor.All)337 SubCell GetAvailableSubCell(CPos location, SubCell preferredSubCell = SubCell.Any, Actor ignoreActor = null, BlockedByActor check = BlockedByActor.All); SetPosition(Actor self, CPos cell, SubCell subCell = SubCell.Any)338 void SetPosition(Actor self, CPos cell, SubCell subCell = SubCell.Any); SetPosition(Actor self, WPos pos)339 void SetPosition(Actor self, WPos pos); SetVisualPosition(Actor self, WPos pos)340 void SetVisualPosition(Actor self, WPos pos); 341 } 342 343 public interface ITemporaryBlockerInfo : ITraitInfoInterface { } 344 345 [RequireExplicitImplementation] 346 public interface ITemporaryBlocker 347 { CanRemoveBlockage(Actor self, Actor blocking)348 bool CanRemoveBlockage(Actor self, Actor blocking); IsBlocking(Actor self, CPos cell)349 bool IsBlocking(Actor self, CPos cell); 350 } 351 352 public interface IFacing 353 { 354 int TurnSpeed { get; } 355 int Facing { get; set; } 356 } 357 GetInitialFacing()358 public interface IFacingInfo : ITraitInfoInterface { int GetInitialFacing(); } 359 360 public interface ITraitInfoInterface { } Create(ActorInitializer init)361 public interface ITraitInfo : ITraitInfoInterface { object Create(ActorInitializer init); } 362 Create(ActorInitializer init)363 public class TraitInfo<T> : ITraitInfo where T : new() { public virtual object Create(ActorInitializer init) { return new T(); } } 364 public interface ILobbyCustomRulesIgnore { } 365 366 [SuppressMessage("StyleCop.CSharp.NamingRules", "SA1302:InterfaceNamesMustBeginWithI", Justification = "Not a real interface, but more like a tag.")] 367 public interface Requires<T> where T : class, ITraitInfoInterface { } 368 369 public interface IActivityInterface { } 370 371 [RequireExplicitImplementation] Selected(Actor self)372 public interface INotifySelected { void Selected(Actor self); } 373 [RequireExplicitImplementation] SelectionChanged()374 public interface INotifySelection { void SelectionChanged(); } 375 WorldLoaded(World w, WorldRenderer wr)376 public interface IWorldLoaded { void WorldLoaded(World w, WorldRenderer wr); } GameLoading(World w)377 public interface INotifyGameLoading { void GameLoading(World w); } GameLoaded(World w)378 public interface INotifyGameLoaded { void GameLoaded(World w); } GameSaved(World w)379 public interface INotifyGameSaved { void GameSaved(World w); } 380 381 public interface IGameSaveTraitData 382 { IssueTraitData(Actor self)383 List<MiniYamlNode> IssueTraitData(Actor self); ResolveTraitData(Actor self, List<MiniYamlNode> data)384 void ResolveTraitData(Actor self, List<MiniYamlNode> data); 385 } 386 387 [RequireExplicitImplementation] CreatePlayers(World w)388 public interface ICreatePlayers { void CreatePlayers(World w); } 389 390 public interface IBotInfo : ITraitInfoInterface 391 { 392 string Type { get; } 393 string Name { get; } 394 } 395 396 public interface IBot 397 { Activate(Player p)398 void Activate(Player p); QueueOrder(Order order)399 void QueueOrder(Order order); 400 IBotInfo Info { get; } 401 Player Player { get; } 402 } 403 404 [RequireExplicitImplementation] Render(WorldRenderer wr)405 public interface IRenderOverlay { void Render(WorldRenderer wr); } 406 407 [RequireExplicitImplementation] OnBecomingIdle(Actor self)408 public interface INotifyBecomingIdle { void OnBecomingIdle(Actor self); } 409 410 [RequireExplicitImplementation] TickIdle(Actor self)411 public interface INotifyIdle { void TickIdle(Actor self); } 412 RenderAboveWorld(Actor self, WorldRenderer wr)413 public interface IRenderAboveWorld { void RenderAboveWorld(Actor self, WorldRenderer wr); } RenderShroud(WorldRenderer wr)414 public interface IRenderShroud { void RenderShroud(WorldRenderer wr); } 415 416 [RequireExplicitImplementation] RenderTerrain(WorldRenderer wr, Viewport viewport)417 public interface IRenderTerrain { void RenderTerrain(WorldRenderer wr, Viewport viewport); } 418 419 public interface IRenderAboveShroud 420 { RenderAboveShroud(Actor self, WorldRenderer wr)421 IEnumerable<IRenderable> RenderAboveShroud(Actor self, WorldRenderer wr); 422 bool SpatiallyPartitionable { get; } 423 } 424 425 public interface IRenderAboveShroudWhenSelected 426 { RenderAboveShroud(Actor self, WorldRenderer wr)427 IEnumerable<IRenderable> RenderAboveShroud(Actor self, WorldRenderer wr); 428 bool SpatiallyPartitionable { get; } 429 } 430 431 public interface IRenderAnnotations 432 { RenderAnnotations(Actor self, WorldRenderer wr)433 IEnumerable<IRenderable> RenderAnnotations(Actor self, WorldRenderer wr); 434 bool SpatiallyPartitionable { get; } 435 } 436 437 public interface IRenderAnnotationsWhenSelected 438 { RenderAnnotations(Actor self, WorldRenderer wr)439 IEnumerable<IRenderable> RenderAnnotations(Actor self, WorldRenderer wr); 440 bool SpatiallyPartitionable { get; } 441 } 442 443 public interface ISelection 444 { 445 int Hash { get; } 446 IEnumerable<Actor> Actors { get; } 447 Add(Actor a)448 void Add(Actor a); Remove(Actor a)449 void Remove(Actor a); Contains(Actor a)450 bool Contains(Actor a); Combine(World world, IEnumerable<Actor> newSelection, bool isCombine, bool isClick)451 void Combine(World world, IEnumerable<Actor> newSelection, bool isCombine, bool isClick); Clear()452 void Clear(); DoControlGroup(World world, WorldRenderer worldRenderer, int group, Modifiers mods, int multiTapCount)453 void DoControlGroup(World world, WorldRenderer worldRenderer, int group, Modifiers mods, int multiTapCount); AddToControlGroup(Actor a, int group)454 void AddToControlGroup(Actor a, int group); RemoveFromControlGroup(Actor a)455 void RemoveFromControlGroup(Actor a); GetControlGroupForActor(Actor a)456 int? GetControlGroupForActor(Actor a); 457 } 458 459 /// <summary> 460 /// Indicates target types as defined on <see cref="Traits.ITargetable"/> are present in a <see cref="Primitives.BitSet{T}"/>. 461 /// </summary> TargetableType()462 public sealed class TargetableType { TargetableType() { } } 463 464 public interface ITargetableInfo : ITraitInfoInterface 465 { GetTargetTypes()466 BitSet<TargetableType> GetTargetTypes(); 467 } 468 469 public interface ITargetable 470 { 471 // Check IsTraitEnabled or !IsTraitDisabled first 472 BitSet<TargetableType> TargetTypes { get; } TargetableBy(Actor self, Actor byActor)473 bool TargetableBy(Actor self, Actor byActor); 474 bool RequiresForceFire { get; } 475 } 476 477 [RequireExplicitImplementation] 478 public interface ITargetablePositions 479 { TargetablePositions(Actor self)480 IEnumerable<WPos> TargetablePositions(Actor self); 481 bool AlwaysEnabled { get; } 482 } 483 484 public interface IMoveInfo : ITraitInfoInterface { } 485 486 [RequireExplicitImplementation] GameOver(World world)487 public interface IGameOver { void GameOver(World world); } 488 489 public interface IWarhead 490 { 491 int Delay { get; } IsValidAgainst(Actor victim, Actor firedBy)492 bool IsValidAgainst(Actor victim, Actor firedBy); IsValidAgainst(FrozenActor victim, Actor firedBy)493 bool IsValidAgainst(FrozenActor victim, Actor firedBy); DoImpact(Target target, WarheadArgs args)494 void DoImpact(Target target, WarheadArgs args); 495 } 496 RulesetLoaded(Ruleset rules, TInfo info)497 public interface IRulesetLoaded<TInfo> { void RulesetLoaded(Ruleset rules, TInfo info); } 498 public interface IRulesetLoaded : IRulesetLoaded<ActorInfo>, ITraitInfoInterface { } 499 500 [RequireExplicitImplementation] 501 public interface ILobbyOptions : ITraitInfoInterface 502 { LobbyOptions(Ruleset rules)503 IEnumerable<LobbyOption> LobbyOptions(Ruleset rules); 504 } 505 506 public class LobbyOption 507 { 508 public readonly string Id; 509 public readonly string Name; 510 public readonly string Description; 511 public readonly IReadOnlyDictionary<string, string> Values; 512 public readonly string DefaultValue; 513 public readonly bool IsLocked; 514 public readonly bool IsVisible; 515 public readonly int DisplayOrder; 516 LobbyOption(string id, string name, string description, bool visible, int displayorder, IReadOnlyDictionary<string, string> values, string defaultValue, bool locked)517 public LobbyOption(string id, string name, string description, bool visible, int displayorder, 518 IReadOnlyDictionary<string, string> values, string defaultValue, bool locked) 519 { 520 Id = id; 521 Name = name; 522 Description = description; 523 IsVisible = visible; 524 DisplayOrder = displayorder; 525 Values = values; 526 DefaultValue = defaultValue; 527 IsLocked = locked; 528 } 529 ValueChangedMessage(string playerName, string newValue)530 public virtual string ValueChangedMessage(string playerName, string newValue) 531 { 532 return playerName + " changed " + Name + " to " + Values[newValue] + "."; 533 } 534 } 535 536 public class LobbyBooleanOption : LobbyOption 537 { 538 static readonly Dictionary<string, string> BoolValues = new Dictionary<string, string>() 539 { 540 { true.ToString(), "enabled" }, 541 { false.ToString(), "disabled" } 542 }; 543 LobbyBooleanOption(string id, string name, string description, bool visible, int displayorder, bool defaultValue, bool locked)544 public LobbyBooleanOption(string id, string name, string description, bool visible, int displayorder, bool defaultValue, bool locked) 545 : base(id, name, description, visible, displayorder, new ReadOnlyDictionary<string, string>(BoolValues), defaultValue.ToString(), locked) { } 546 ValueChangedMessage(string playerName, string newValue)547 public override string ValueChangedMessage(string playerName, string newValue) 548 { 549 return playerName + " " + BoolValues[newValue] + " " + Name + "."; 550 } 551 } 552 553 [RequireExplicitImplementation] 554 public interface IUnlocksRenderPlayer { bool RenderPlayerUnlocked { get; } } 555 556 [RequireExplicitImplementation] GetCreationActivity()557 public interface ICreationActivity { Activity GetCreationActivity(); } 558 } 559