Fix CA1851
This commit is contained in:
@@ -834,6 +834,12 @@ dotnet_diagnostic.CA1849.severity = warning
|
|||||||
# Prefer static HashData method over ComputeHash. (Not available on mono)
|
# Prefer static HashData method over ComputeHash. (Not available on mono)
|
||||||
dotnet_diagnostic.CA1850.severity = none
|
dotnet_diagnostic.CA1850.severity = none
|
||||||
|
|
||||||
|
# Possible multiple enumerations of IEnumerable collection.
|
||||||
|
#dotnet_code_quality.CA1851.enumeration_methods =
|
||||||
|
#dotnet_code_quality.CA1851.linq_chain_methods =
|
||||||
|
#dotnet_code_quality.CA1851.assume_method_enumerates_parameters = false
|
||||||
|
dotnet_diagnostic.CA1851.severity = warning
|
||||||
|
|
||||||
# Seal internal types.
|
# Seal internal types.
|
||||||
dotnet_diagnostic.CA1852.severity = warning
|
dotnet_diagnostic.CA1852.severity = warning
|
||||||
|
|
||||||
|
|||||||
@@ -185,7 +185,7 @@ namespace OpenRA
|
|||||||
public bool HasTraitInfo<T>() where T : ITraitInfoInterface { return traits.Contains<T>(); }
|
public bool HasTraitInfo<T>() where T : ITraitInfoInterface { return traits.Contains<T>(); }
|
||||||
public T TraitInfo<T>() where T : ITraitInfoInterface { return traits.Get<T>(); }
|
public T TraitInfo<T>() where T : ITraitInfoInterface { return traits.Get<T>(); }
|
||||||
public T TraitInfoOrDefault<T>() where T : ITraitInfoInterface { return traits.GetOrDefault<T>(); }
|
public T TraitInfoOrDefault<T>() where T : ITraitInfoInterface { return traits.GetOrDefault<T>(); }
|
||||||
public IEnumerable<T> TraitInfos<T>() where T : ITraitInfoInterface { return traits.WithInterface<T>(); }
|
public IReadOnlyCollection<T> TraitInfos<T>() where T : ITraitInfoInterface { return traits.WithInterface<T>(); }
|
||||||
|
|
||||||
public BitSet<TargetableType> GetAllTargetTypes()
|
public BitSet<TargetableType> GetAllTargetTypes()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -234,7 +234,7 @@ namespace OpenRA.Graphics
|
|||||||
{
|
{
|
||||||
// PERF: We don't need to search for images if there are no definitions.
|
// PERF: We don't need to search for images if there are no definitions.
|
||||||
// PERF: It's more efficient to send an empty array rather than an array of 9 nulls.
|
// PERF: It's more efficient to send an empty array rather than an array of 9 nulls.
|
||||||
if (!collection.Regions.Any())
|
if (collection.Regions.Count == 0)
|
||||||
return Array.Empty<Sprite>();
|
return Array.Empty<Sprite>();
|
||||||
|
|
||||||
// Support manual definitions for unusual dialog layouts
|
// Support manual definitions for unusual dialog layouts
|
||||||
|
|||||||
@@ -139,7 +139,7 @@ namespace OpenRA
|
|||||||
return removed;
|
return removed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<T> GetAll<T>() where T : ActorInit
|
public IReadOnlyCollection<T> GetAll<T>() where T : ActorInit
|
||||||
{
|
{
|
||||||
return initDict.Value.WithInterface<T>();
|
return initDict.Value.WithInterface<T>();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace OpenRA
|
namespace OpenRA
|
||||||
{
|
{
|
||||||
@@ -64,9 +63,9 @@ namespace OpenRA
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Returns the minimal region that covers at least the specified cells.</summary>
|
/// <summary>Returns the minimal region that covers at least the specified cells.</summary>
|
||||||
public static CellRegion BoundingRegion(MapGridType shape, IEnumerable<CPos> cells)
|
public static CellRegion BoundingRegion(MapGridType shape, IReadOnlyCollection<CPos> cells)
|
||||||
{
|
{
|
||||||
if (cells == null || !cells.Any())
|
if (cells == null || cells.Count == 0)
|
||||||
throw new ArgumentException("cells must not be null or empty.", nameof(cells));
|
throw new ArgumentException("cells must not be null or empty.", nameof(cells));
|
||||||
|
|
||||||
var minU = int.MaxValue;
|
var minU = int.MaxValue;
|
||||||
|
|||||||
@@ -201,8 +201,12 @@ namespace OpenRA.Network
|
|||||||
public TypeInfo(Type type)
|
public TypeInfo(Type type)
|
||||||
{
|
{
|
||||||
const BindingFlags Flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
|
const BindingFlags Flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
|
||||||
var fields = type.GetFields(Flags).Where(fi => !fi.IsLiteral && !fi.IsStatic && fi.HasAttribute<SyncAttribute>());
|
var fields = type.GetFields(Flags)
|
||||||
var properties = type.GetProperties(Flags).Where(pi => pi.HasAttribute<SyncAttribute>());
|
.Where(fi => !fi.IsLiteral && !fi.IsStatic && fi.HasAttribute<SyncAttribute>())
|
||||||
|
.ToList();
|
||||||
|
var properties = type.GetProperties(Flags)
|
||||||
|
.Where(pi => pi.HasAttribute<SyncAttribute>())
|
||||||
|
.ToList();
|
||||||
|
|
||||||
foreach (var prop in properties)
|
foreach (var prop in properties)
|
||||||
if (!prop.CanRead || prop.GetIndexParameters().Length > 0)
|
if (!prop.CanRead || prop.GetIndexParameters().Length > 0)
|
||||||
|
|||||||
@@ -134,8 +134,8 @@ namespace OpenRA
|
|||||||
public ConstructorInfo GetCtor(Type type)
|
public ConstructorInfo GetCtor(Type type)
|
||||||
{
|
{
|
||||||
var flags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance;
|
var flags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance;
|
||||||
var ctors = type.GetConstructors(flags).Where(x => x.HasAttribute<UseCtorAttribute>());
|
var ctors = type.GetConstructors(flags).Where(x => x.HasAttribute<UseCtorAttribute>()).ToList();
|
||||||
if (ctors.Count() > 1)
|
if (ctors.Count > 1)
|
||||||
throw new InvalidOperationException("ObjectCreator: UseCtor on multiple constructors; invalid.");
|
throw new InvalidOperationException("ObjectCreator: UseCtor on multiple constructors; invalid.");
|
||||||
return ctors.FirstOrDefault();
|
return ctors.FirstOrDefault();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ namespace OpenRA
|
|||||||
|
|
||||||
static FactionInfo ResolveDisplayFaction(World world, string factionName)
|
static FactionInfo ResolveDisplayFaction(World world, string factionName)
|
||||||
{
|
{
|
||||||
var factions = world.Map.Rules.Actors[SystemActors.World].TraitInfos<FactionInfo>().ToArray();
|
var factions = world.Map.Rules.Actors[SystemActors.World].TraitInfos<FactionInfo>();
|
||||||
|
|
||||||
return factions.FirstOrDefault(f => f.InternalName == factionName) ?? factions.First();
|
return factions.FirstOrDefault(f => f.InternalName == factionName) ?? factions.First();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,14 +12,20 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace OpenRA.Primitives
|
namespace OpenRA.Primitives
|
||||||
{
|
{
|
||||||
public class TypeDictionary : IEnumerable<object>
|
public class TypeDictionary : IEnumerable<object>
|
||||||
{
|
{
|
||||||
static readonly Func<Type, List<object>> CreateList = type => new List<object>();
|
static readonly Func<Type, ITypeContainer> CreateTypeContainer = t =>
|
||||||
readonly Dictionary<Type, List<object>> data = new();
|
(ITypeContainer)typeof(TypeContainer<>).MakeGenericType(t).GetConstructor(Type.EmptyTypes).Invoke(null);
|
||||||
|
|
||||||
|
readonly Dictionary<Type, ITypeContainer> data = new();
|
||||||
|
|
||||||
|
ITypeContainer InnerGet(Type t)
|
||||||
|
{
|
||||||
|
return data.GetOrAdd(t, CreateTypeContainer);
|
||||||
|
}
|
||||||
|
|
||||||
public void Add(object val)
|
public void Add(object val)
|
||||||
{
|
{
|
||||||
@@ -33,7 +39,7 @@ namespace OpenRA.Primitives
|
|||||||
|
|
||||||
void InnerAdd(Type t, object val)
|
void InnerAdd(Type t, object val)
|
||||||
{
|
{
|
||||||
data.GetOrAdd(t, CreateList).Add(val);
|
InnerGet(t).Add(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Contains<T>()
|
public bool Contains<T>()
|
||||||
@@ -48,35 +54,33 @@ namespace OpenRA.Primitives
|
|||||||
|
|
||||||
public T Get<T>()
|
public T Get<T>()
|
||||||
{
|
{
|
||||||
return (T)Get(typeof(T), true);
|
return Get<T>(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public T GetOrDefault<T>()
|
public T GetOrDefault<T>()
|
||||||
{
|
{
|
||||||
var result = Get(typeof(T), false);
|
return Get<T>(false);
|
||||||
if (result == null)
|
|
||||||
return default;
|
|
||||||
return (T)result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
object Get(Type t, bool throwsIfMissing)
|
T Get<T>(bool throwsIfMissing)
|
||||||
{
|
{
|
||||||
if (!data.TryGetValue(t, out var ret))
|
if (!data.TryGetValue(typeof(T), out var container))
|
||||||
{
|
{
|
||||||
if (throwsIfMissing)
|
if (throwsIfMissing)
|
||||||
throw new InvalidOperationException($"TypeDictionary does not contain instance of type `{t}`");
|
throw new InvalidOperationException($"TypeDictionary does not contain instance of type `{typeof(T)}`");
|
||||||
return null;
|
return default;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret.Count > 1)
|
var list = ((TypeContainer<T>)container).Objects;
|
||||||
throw new InvalidOperationException($"TypeDictionary contains multiple instances of type `{t}`");
|
if (list.Count > 1)
|
||||||
return ret[0];
|
throw new InvalidOperationException($"TypeDictionary contains multiple instances of type `{typeof(T)}`");
|
||||||
|
return list[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<T> WithInterface<T>()
|
public IReadOnlyCollection<T> WithInterface<T>()
|
||||||
{
|
{
|
||||||
if (data.TryGetValue(typeof(T), out var objs))
|
if (data.TryGetValue(typeof(T), out var container))
|
||||||
return objs.Cast<T>();
|
return ((TypeContainer<T>)container).Objects;
|
||||||
return Array.Empty<T>();
|
return Array.Empty<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,18 +96,19 @@ namespace OpenRA.Primitives
|
|||||||
|
|
||||||
void InnerRemove(Type t, object val)
|
void InnerRemove(Type t, object val)
|
||||||
{
|
{
|
||||||
if (!data.TryGetValue(t, out var objs))
|
if (!data.TryGetValue(t, out var container))
|
||||||
return;
|
return;
|
||||||
objs.Remove(val);
|
|
||||||
if (objs.Count == 0)
|
container.Remove(val);
|
||||||
|
if (container.Count == 0)
|
||||||
data.Remove(t);
|
data.Remove(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void TrimExcess()
|
public void TrimExcess()
|
||||||
{
|
{
|
||||||
data.TrimExcess();
|
data.TrimExcess();
|
||||||
foreach (var objs in data.Values)
|
foreach (var t in data.Keys)
|
||||||
objs.TrimExcess();
|
InnerGet(t).TrimExcess();
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerator<object> GetEnumerator()
|
public IEnumerator<object> GetEnumerator()
|
||||||
@@ -115,6 +120,36 @@ namespace OpenRA.Primitives
|
|||||||
{
|
{
|
||||||
return GetEnumerator();
|
return GetEnumerator();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface ITypeContainer
|
||||||
|
{
|
||||||
|
int Count { get; }
|
||||||
|
void Add(object value);
|
||||||
|
void Remove(object value);
|
||||||
|
void TrimExcess();
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class TypeContainer<T> : ITypeContainer
|
||||||
|
{
|
||||||
|
public List<T> Objects { get; } = new List<T>();
|
||||||
|
|
||||||
|
public int Count => Objects.Count;
|
||||||
|
|
||||||
|
public void Add(object value)
|
||||||
|
{
|
||||||
|
Objects.Add((T)value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Remove(object value)
|
||||||
|
{
|
||||||
|
Objects.Remove((T)value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TrimExcess()
|
||||||
|
{
|
||||||
|
Objects.TrimExcess();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class TypeExts
|
public static class TypeExts
|
||||||
|
|||||||
@@ -11,7 +11,6 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
using Eluant;
|
using Eluant;
|
||||||
using Eluant.ObjectBinding;
|
using Eluant.ObjectBinding;
|
||||||
using OpenRA.Scripting;
|
using OpenRA.Scripting;
|
||||||
@@ -139,20 +138,21 @@ namespace OpenRA
|
|||||||
{
|
{
|
||||||
public static WPos Average(this IEnumerable<WPos> source)
|
public static WPos Average(this IEnumerable<WPos> source)
|
||||||
{
|
{
|
||||||
var length = source.Count();
|
var length = 0;
|
||||||
if (length == 0)
|
|
||||||
return WPos.Zero;
|
|
||||||
|
|
||||||
var x = 0L;
|
var x = 0L;
|
||||||
var y = 0L;
|
var y = 0L;
|
||||||
var z = 0L;
|
var z = 0L;
|
||||||
foreach (var pos in source)
|
foreach (var pos in source)
|
||||||
{
|
{
|
||||||
|
length++;
|
||||||
x += pos.X;
|
x += pos.X;
|
||||||
y += pos.Y;
|
y += pos.Y;
|
||||||
z += pos.Z;
|
z += pos.Z;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (length == 0)
|
||||||
|
return WPos.Zero;
|
||||||
|
|
||||||
x /= length;
|
x /= length;
|
||||||
y /= length;
|
y /= length;
|
||||||
z /= length;
|
z /= length;
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
|
||||||
using OpenRA.Activities;
|
using OpenRA.Activities;
|
||||||
using OpenRA.Mods.Cnc.Traits;
|
using OpenRA.Mods.Cnc.Traits;
|
||||||
using OpenRA.Mods.Common.Traits;
|
using OpenRA.Mods.Common.Traits;
|
||||||
@@ -120,7 +119,7 @@ namespace OpenRA.Mods.Cnc.Activities
|
|||||||
if (teleporter == null)
|
if (teleporter == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
var restrictTo = maximumDistance == null ? null : self.World.Map.FindTilesInCircle(self.Location, maximumDistance.Value);
|
var restrictTo = maximumDistance == null ? null : self.World.Map.FindTilesInCircle(self.Location, maximumDistance.Value).ToHashSet();
|
||||||
|
|
||||||
if (maximumDistance != null)
|
if (maximumDistance != null)
|
||||||
destination = restrictTo.MinBy(x => (x - destination).LengthSquared);
|
destination = restrictTo.MinBy(x => (x - destination).LengthSquared);
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ namespace OpenRA.Mods.Cnc.Traits
|
|||||||
{
|
{
|
||||||
var wasGranted = Granted;
|
var wasGranted = Granted;
|
||||||
var wasGrantedAllies = GrantedAllies;
|
var wasGrantedAllies = GrantedAllies;
|
||||||
var allyWatchers = owner.World.ActorsWithTrait<GpsWatcher>().Where(kv => kv.Actor.Owner.IsAlliedWith(owner));
|
var allyWatchers = owner.World.ActorsWithTrait<GpsWatcher>().Where(kv => kv.Actor.Owner.IsAlliedWith(owner)).ToList();
|
||||||
|
|
||||||
Granted = actors.Count > 0 && Launched;
|
Granted = actors.Count > 0 && Launched;
|
||||||
GrantedAllies = allyWatchers.Any(w => w.Trait.Granted);
|
GrantedAllies = allyWatchers.Any(w => w.Trait.Granted);
|
||||||
|
|||||||
@@ -358,14 +358,11 @@ namespace OpenRA.Mods.Cnc.Traits
|
|||||||
|
|
||||||
bool IsValidTarget(CPos xy)
|
bool IsValidTarget(CPos xy)
|
||||||
{
|
{
|
||||||
// Don't teleport if there are no units in range (either all moved out of range, or none yet moved into range)
|
|
||||||
var unitsInRange = power.UnitsInRange(sourceLocation);
|
|
||||||
if (!unitsInRange.Any())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
var canTeleport = false;
|
var canTeleport = false;
|
||||||
foreach (var unit in unitsInRange)
|
var anyUnitsInRange = false;
|
||||||
|
foreach (var unit in power.UnitsInRange(sourceLocation))
|
||||||
{
|
{
|
||||||
|
anyUnitsInRange = true;
|
||||||
var targetCell = unit.Location + (xy - sourceLocation);
|
var targetCell = unit.Location + (xy - sourceLocation);
|
||||||
if (manager.Self.Owner.Shroud.IsExplored(targetCell) && unit.Trait<Chronoshiftable>().CanChronoshiftTo(unit, targetCell))
|
if (manager.Self.Owner.Shroud.IsExplored(targetCell) && unit.Trait<Chronoshiftable>().CanChronoshiftTo(unit, targetCell))
|
||||||
{
|
{
|
||||||
@@ -374,6 +371,10 @@ namespace OpenRA.Mods.Cnc.Traits
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Don't teleport if there are no units in range (either all moved out of range, or none yet moved into range)
|
||||||
|
if (!anyUnitsInRange)
|
||||||
|
return false;
|
||||||
|
|
||||||
if (!canTeleport)
|
if (!canTeleport)
|
||||||
{
|
{
|
||||||
// Check the terrain types. This will allow chronoshifts to occur on empty terrain to terrain of
|
// Check the terrain types. This will allow chronoshifts to occur on empty terrain to terrain of
|
||||||
|
|||||||
@@ -196,8 +196,8 @@ namespace OpenRA.Mods.Common.Activities
|
|||||||
|
|
||||||
// Update ranges. Exclude paused armaments except when ALL weapons are paused
|
// Update ranges. Exclude paused armaments except when ALL weapons are paused
|
||||||
// (e.g. out of ammo), in which case use the paused, valid weapon with highest range.
|
// (e.g. out of ammo), in which case use the paused, valid weapon with highest range.
|
||||||
var activeArmaments = armaments.Where(x => !x.IsTraitPaused);
|
var activeArmaments = armaments.Where(x => !x.IsTraitPaused).ToList();
|
||||||
if (activeArmaments.Any())
|
if (activeArmaments.Count != 0)
|
||||||
{
|
{
|
||||||
minRange = activeArmaments.Max(a => a.Weapon.MinRange);
|
minRange = activeArmaments.Max(a => a.Weapon.MinRange);
|
||||||
maxRange = activeArmaments.Min(a => a.MaxRange());
|
maxRange = activeArmaments.Min(a => a.MaxRange());
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
|
||||||
using OpenRA.Mods.Common.Traits;
|
using OpenRA.Mods.Common.Traits;
|
||||||
|
|
||||||
namespace OpenRA.Mods.Common.Lint
|
namespace OpenRA.Mods.Common.Lint
|
||||||
@@ -21,8 +20,8 @@ namespace OpenRA.Mods.Common.Lint
|
|||||||
{
|
{
|
||||||
foreach (var actorInfo in rules.Actors)
|
foreach (var actorInfo in rules.Actors)
|
||||||
{
|
{
|
||||||
var selectable = actorInfo.Value.TraitInfos<SelectableInfo>().Count();
|
var selectable = actorInfo.Value.TraitInfos<SelectableInfo>().Count;
|
||||||
var interactable = actorInfo.Value.TraitInfos<InteractableInfo>().Count();
|
var interactable = actorInfo.Value.TraitInfos<InteractableInfo>().Count;
|
||||||
if (selectable > 0 && selectable != interactable)
|
if (selectable > 0 && selectable != interactable)
|
||||||
emitWarning($"Actor `{actorInfo.Value.Name}` defines both Interactable and Selectable traits. This may cause unexpected results.");
|
emitWarning($"Actor `{actorInfo.Value.Name}` defines both Interactable and Selectable traits. This may cause unexpected results.");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ namespace OpenRA.Mods.Common.Lint
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var visibilityTypes = actorInfo.Value.TraitInfos<IDefaultVisibilityInfo>();
|
var visibilityTypes = actorInfo.Value.TraitInfos<IDefaultVisibilityInfo>();
|
||||||
var count = visibilityTypes.Count();
|
var count = visibilityTypes.Count;
|
||||||
|
|
||||||
if (count == 0)
|
if (count == 0)
|
||||||
emitError($"Actor type `{actorInfo.Key}` does not define a default visibility type.");
|
emitError($"Actor type `{actorInfo.Key}` does not define a default visibility type.");
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
|
||||||
using OpenRA.Mods.Common.Traits;
|
using OpenRA.Mods.Common.Traits;
|
||||||
using OpenRA.Server;
|
using OpenRA.Server;
|
||||||
using OpenRA.Traits;
|
using OpenRA.Traits;
|
||||||
@@ -41,7 +40,7 @@ namespace OpenRA.Mods.Common.Lint
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
var hitShapes = actorInfo.Value.TraitInfos<HitShapeInfo>();
|
var hitShapes = actorInfo.Value.TraitInfos<HitShapeInfo>();
|
||||||
if (!hitShapes.Any())
|
if (hitShapes.Count == 0)
|
||||||
emitError($"Actor type `{actorInfo.Key}` has a Health trait but no HitShape trait.");
|
emitError($"Actor type `{actorInfo.Key}` has a Health trait but no HitShape trait.");
|
||||||
}
|
}
|
||||||
catch (InvalidOperationException e)
|
catch (InvalidOperationException e)
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using OpenRA.Mods.Common.Traits;
|
using OpenRA.Mods.Common.Traits;
|
||||||
using OpenRA.Server;
|
using OpenRA.Server;
|
||||||
@@ -32,12 +33,15 @@ namespace OpenRA.Mods.Common.Lint
|
|||||||
static void Run(Action<string> emitError, Ruleset rules)
|
static void Run(Action<string> emitError, Ruleset rules)
|
||||||
{
|
{
|
||||||
var worldActor = rules.Actors[SystemActors.World];
|
var worldActor = rules.Actors[SystemActors.World];
|
||||||
var locomotorInfos = worldActor.TraitInfos<LocomotorInfo>().ToArray();
|
var locomotorNames = worldActor.TraitInfos<LocomotorInfo>().Select(li => li.Name).ToList();
|
||||||
foreach (var li in locomotorInfos)
|
var duplicateNames = locomotorNames
|
||||||
foreach (var otherLocomotor in locomotorInfos)
|
.GroupBy(name => name)
|
||||||
if (li != otherLocomotor && li.Name == otherLocomotor.Name)
|
.Where(g => g.Count() > 1)
|
||||||
emitError($"More than one Locomotor exists with the name `{li.Name}`.");
|
.Select(g => g.Key);
|
||||||
|
foreach (var duplicateName in duplicateNames)
|
||||||
|
emitError($"More than one Locomotor exists with the name `{duplicateName}`.");
|
||||||
|
|
||||||
|
var locomotorNamesSet = locomotorNames.ToHashSet();
|
||||||
foreach (var actorInfo in rules.Actors)
|
foreach (var actorInfo in rules.Actors)
|
||||||
{
|
{
|
||||||
foreach (var traitInfo in actorInfo.Value.TraitInfos<TraitInfo>())
|
foreach (var traitInfo in actorInfo.Value.TraitInfos<TraitInfo>())
|
||||||
@@ -51,16 +55,16 @@ namespace OpenRA.Mods.Common.Lint
|
|||||||
if (string.IsNullOrEmpty(locomotor))
|
if (string.IsNullOrEmpty(locomotor))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
CheckLocomotors(actorInfo.Value, emitError, locomotorInfos, locomotor);
|
CheckLocomotors(actorInfo.Value, emitError, locomotorNamesSet, locomotor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void CheckLocomotors(ActorInfo actorInfo, Action<string> emitError, LocomotorInfo[] locomotorInfos, string locomotor)
|
static void CheckLocomotors(ActorInfo actorInfo, Action<string> emitError, HashSet<string> locomotorNames, string locomotor)
|
||||||
{
|
{
|
||||||
if (!locomotorInfos.Any(l => l.Name == locomotor))
|
if (!locomotorNames.Contains(locomotor))
|
||||||
emitError($"Actor `{actorInfo.Name}` defines Locomotor `{locomotor}` not found on World actor.");
|
emitError($"Actor `{actorInfo.Name}` defines Locomotor `{locomotor}` not found on World actor.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,10 +32,12 @@ namespace OpenRA.Mods.Common.Lint
|
|||||||
{
|
{
|
||||||
foreach (var actorInfo in rules.Actors)
|
foreach (var actorInfo in rules.Actors)
|
||||||
{
|
{
|
||||||
var wsbs = actorInfo.Value.TraitInfos<WithSpriteBodyInfo>();
|
var duplicateNames = actorInfo.Value.TraitInfos<WithSpriteBodyInfo>()
|
||||||
foreach (var wsb in wsbs)
|
.GroupBy(wsb => wsb.Name)
|
||||||
if (wsbs.Any(w => w != wsb && w.Name == wsb.Name))
|
.Where(g => g.Count() > 1)
|
||||||
emitError($"Actor type `{actorInfo.Key}` has more than one *SpriteBody with Name: {wsb.Name}.");
|
.Select(g => g.Key);
|
||||||
|
foreach (var duplicateName in duplicateNames)
|
||||||
|
emitError($"Actor type `{actorInfo.Key}` has more than one *SpriteBody with Name: {duplicateName}.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,13 +50,13 @@ namespace OpenRA.Mods.Common.Orders
|
|||||||
.Where(o => o != null)
|
.Where(o => o != null)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
var actorsInvolved = orders.Select(o => o.Actor).Distinct();
|
var actorsInvolved = orders.Select(o => o.Actor).Distinct().ToArray();
|
||||||
if (!actorsInvolved.Any())
|
if (actorsInvolved.Length == 0)
|
||||||
yield break;
|
yield break;
|
||||||
|
|
||||||
// HACK: This is required by the hacky player actions-per-minute calculation
|
// HACK: This is required by the hacky player actions-per-minute calculation
|
||||||
// TODO: Reimplement APM properly and then remove this
|
// TODO: Reimplement APM properly and then remove this
|
||||||
yield return new Order("CreateGroup", actorsInvolved.First().Owner.PlayerActor, false, actorsInvolved.ToArray());
|
yield return new Order("CreateGroup", actorsInvolved.First().Owner.PlayerActor, false, actorsInvolved);
|
||||||
|
|
||||||
foreach (var o in orders)
|
foreach (var o in orders)
|
||||||
yield return CheckSameOrder(o.Order, o.Trait.IssueOrder(o.Actor, o.Order, o.Target, mi.Modifiers.HasModifier(Modifiers.Shift)));
|
yield return CheckSameOrder(o.Order, o.Trait.IssueOrder(o.Actor, o.Order, o.Target, mi.Modifiers.HasModifier(Modifiers.Shift)));
|
||||||
@@ -165,7 +165,8 @@ namespace OpenRA.Mods.Common.Orders
|
|||||||
var orders = self.TraitsImplementing<IIssueOrder>()
|
var orders = self.TraitsImplementing<IIssueOrder>()
|
||||||
.SelectMany(trait => trait.Orders.Select(x => new { Trait = trait, Order = x }))
|
.SelectMany(trait => trait.Orders.Select(x => new { Trait = trait, Order = x }))
|
||||||
.Select(x => x)
|
.Select(x => x)
|
||||||
.OrderByDescending(x => x.Order.OrderPriority);
|
.OrderByDescending(x => x.Order.OrderPriority)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
for (var i = 0; i < 2; i++)
|
for (var i = 0; i < 2; i++)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -245,7 +245,7 @@ namespace OpenRA.Mods.Common.Scripting
|
|||||||
foreach (var actorType in actorTypes.Distinct())
|
foreach (var actorType in actorTypes.Distinct())
|
||||||
typeToQueueMap.Add(actorType, GetBuildableInfo(actorType).Queue.First());
|
typeToQueueMap.Add(actorType, GetBuildableInfo(actorType).Queue.First());
|
||||||
|
|
||||||
var queueTypes = typeToQueueMap.Values.Distinct();
|
var queueTypes = typeToQueueMap.Values.Distinct().ToList();
|
||||||
|
|
||||||
if (queueTypes.Any(t => !queues.ContainsKey(t) || productionHandlers.ContainsKey(t)))
|
if (queueTypes.Any(t => !queues.ContainsKey(t) || productionHandlers.ContainsKey(t)))
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -748,10 +748,11 @@ namespace OpenRA.Mods.Common.Server
|
|||||||
teamCount = teamCount.Clamp(0, maxTeams);
|
teamCount = teamCount.Clamp(0, maxTeams);
|
||||||
var clients = server.LobbyInfo.Slots
|
var clients = server.LobbyInfo.Slots
|
||||||
.Select(slot => server.LobbyInfo.ClientInSlot(slot.Key))
|
.Select(slot => server.LobbyInfo.ClientInSlot(slot.Key))
|
||||||
.Where(c => c != null && !server.LobbyInfo.Slots[c.Slot].LockTeam);
|
.Where(c => c != null && !server.LobbyInfo.Slots[c.Slot].LockTeam)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
var assigned = 0;
|
var assigned = 0;
|
||||||
var clientCount = clients.Count();
|
var clientCount = clients.Count;
|
||||||
foreach (var player in clients)
|
foreach (var player in clients)
|
||||||
{
|
{
|
||||||
// Free for all
|
// Free for all
|
||||||
|
|||||||
@@ -41,8 +41,8 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
var owner = map.PlayerDefinitions.Single(p => s.Get<OwnerInit>().InternalName == p.Value.Nodes.Last(k => k.Key == "Name").Value.Value);
|
var owner = map.PlayerDefinitions.Single(p => s.Get<OwnerInit>().InternalName == p.Value.Nodes.Last(k => k.Key == "Name").Value.Value);
|
||||||
var colorValue = owner.Value.Nodes.Where(n => n.Key == "Color");
|
var colorValue = owner.Value.Nodes.FirstOrDefault(n => n.Key == "Color");
|
||||||
var ownerColor = colorValue.Any() ? colorValue.First().Value.Value : "FFFFFF";
|
var ownerColor = colorValue?.Value.Value ?? "FFFFFF";
|
||||||
Color.TryParse(ownerColor, out color);
|
Color.TryParse(ownerColor, out color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -445,15 +445,15 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
modifiers |= TargetModifiers.ForceAttack;
|
modifiers |= TargetModifiers.ForceAttack;
|
||||||
|
|
||||||
var forceAttack = modifiers.HasModifier(TargetModifiers.ForceAttack);
|
var forceAttack = modifiers.HasModifier(TargetModifiers.ForceAttack);
|
||||||
var armaments = ab.ChooseArmamentsForTarget(target, forceAttack);
|
|
||||||
if (!armaments.Any())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Use valid armament with highest range out of those that have ammo
|
// Use valid armament with highest range out of those that have ammo
|
||||||
// If all are out of ammo, just use valid armament with highest range
|
// If all are out of ammo, just use valid armament with highest range
|
||||||
armaments = armaments.OrderByDescending(x => x.MaxRange());
|
var a = ab.ChooseArmamentsForTarget(target, forceAttack)
|
||||||
var a = armaments.FirstOrDefault(x => !x.IsTraitPaused);
|
.OrderBy(x => x.IsTraitPaused)
|
||||||
a ??= armaments.First();
|
.ThenByDescending(x => x.MaxRange())
|
||||||
|
.FirstOrDefault();
|
||||||
|
if (a == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
var outOfRange = !target.IsInRange(self.CenterPosition, a.MaxRange()) ||
|
var outOfRange = !target.IsInRange(self.CenterPosition, a.MaxRange()) ||
|
||||||
(!forceAttack && target.Type == TargetType.FrozenActor && !ab.Info.TargetFrozenActors);
|
(!forceAttack && target.Type == TargetType.FrozenActor && !ab.Info.TargetFrozenActors);
|
||||||
@@ -482,15 +482,15 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
var target = Target.FromCell(self.World, location);
|
var target = Target.FromCell(self.World, location);
|
||||||
var armaments = ab.ChooseArmamentsForTarget(target, true);
|
|
||||||
if (!armaments.Any())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Use valid armament with highest range out of those that have ammo
|
// Use valid armament with highest range out of those that have ammo
|
||||||
// If all are out of ammo, just use valid armament with highest range
|
// If all are out of ammo, just use valid armament with highest range
|
||||||
armaments = armaments.OrderByDescending(x => x.MaxRange());
|
var a = ab.ChooseArmamentsForTarget(target, true)
|
||||||
var a = armaments.FirstOrDefault(x => !x.IsTraitPaused);
|
.OrderBy(x => x.IsTraitPaused)
|
||||||
a ??= armaments.First();
|
.ThenByDescending(x => x.MaxRange())
|
||||||
|
.FirstOrDefault();
|
||||||
|
if (a == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
cursor = !target.IsInRange(self.CenterPosition, a.MaxRange())
|
cursor = !target.IsInRange(self.CenterPosition, a.MaxRange())
|
||||||
? ab.Info.OutsideRangeCursor ?? a.Info.OutsideRangeCursor
|
? ab.Info.OutsideRangeCursor ?? a.Info.OutsideRangeCursor
|
||||||
|
|||||||
@@ -163,7 +163,7 @@ namespace OpenRA.Mods.Common.Traits.BotModules.Squads
|
|||||||
fuzzyEngine.Rules.Add(fuzzyEngine.ParseRule(rule));
|
fuzzyEngine.Rules.Add(fuzzyEngine.ParseRule(rule));
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool CanAttack(IEnumerable<Actor> ownUnits, IEnumerable<Actor> enemyUnits)
|
public bool CanAttack(IReadOnlyCollection<Actor> ownUnits, IReadOnlyCollection<Actor> enemyUnits)
|
||||||
{
|
{
|
||||||
double attackChance;
|
double attackChance;
|
||||||
var inputValues = new Dictionary<FuzzyVariable, double>();
|
var inputValues = new Dictionary<FuzzyVariable, double>();
|
||||||
@@ -201,7 +201,7 @@ namespace OpenRA.Mods.Common.Traits.BotModules.Squads
|
|||||||
return (int)((long)sumOfHp * normalizeByValue / sumOfMaxHp);
|
return (int)((long)sumOfHp * normalizeByValue / sumOfMaxHp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static float RelativePower(IEnumerable<Actor> own, IEnumerable<Actor> enemy)
|
static float RelativePower(IReadOnlyCollection<Actor> own, IReadOnlyCollection<Actor> enemy)
|
||||||
{
|
{
|
||||||
return RelativeValue(own, enemy, 100, SumOfValues<AttackBaseInfo>, a =>
|
return RelativeValue(own, enemy, 100, SumOfValues<AttackBaseInfo>, a =>
|
||||||
{
|
{
|
||||||
@@ -225,18 +225,18 @@ namespace OpenRA.Mods.Common.Traits.BotModules.Squads
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static float RelativeSpeed(IEnumerable<Actor> own, IEnumerable<Actor> enemy)
|
static float RelativeSpeed(IReadOnlyCollection<Actor> own, IReadOnlyCollection<Actor> enemy)
|
||||||
{
|
{
|
||||||
return RelativeValue(own, enemy, 100, Average<MobileInfo>, (Actor a) => a.Info.TraitInfo<MobileInfo>().Speed);
|
return RelativeValue(own, enemy, 100, Average<MobileInfo>, (Actor a) => a.Info.TraitInfo<MobileInfo>().Speed);
|
||||||
}
|
}
|
||||||
|
|
||||||
static float RelativeValue(IEnumerable<Actor> own, IEnumerable<Actor> enemy, float normalizeByValue,
|
static float RelativeValue(IReadOnlyCollection<Actor> own, IReadOnlyCollection<Actor> enemy, float normalizeByValue,
|
||||||
Func<IEnumerable<Actor>, Func<Actor, int>, float> relativeFunc, Func<Actor, int> getValue)
|
Func<IReadOnlyCollection<Actor>, Func<Actor, int>, float> relativeFunc, Func<Actor, int> getValue)
|
||||||
{
|
{
|
||||||
if (!enemy.Any())
|
if (enemy.Count == 0)
|
||||||
return 999.0f;
|
return 999.0f;
|
||||||
|
|
||||||
if (!own.Any())
|
if (own.Count == 0)
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
|
|
||||||
var relative = relativeFunc(own, getValue) / relativeFunc(enemy, getValue) * normalizeByValue;
|
var relative = relativeFunc(own, getValue) / relativeFunc(enemy, getValue) * normalizeByValue;
|
||||||
|
|||||||
@@ -22,9 +22,9 @@ namespace OpenRA.Mods.Common.Traits.BotModules.Squads
|
|||||||
|
|
||||||
protected const int MissileUnitMultiplier = 3;
|
protected const int MissileUnitMultiplier = 3;
|
||||||
|
|
||||||
protected static int CountAntiAirUnits(IEnumerable<Actor> units)
|
protected static int CountAntiAirUnits(IReadOnlyCollection<Actor> units)
|
||||||
{
|
{
|
||||||
if (!units.Any())
|
if (units.Count == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
var missileUnitsCount = 0;
|
var missileUnitsCount = 0;
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ namespace OpenRA.Mods.Common.Traits.BotModules.Squads
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual bool ShouldFlee(Squad squad, Func<IEnumerable<Actor>, bool> flee)
|
protected virtual bool ShouldFlee(Squad squad, Func<IReadOnlyCollection<Actor>, bool> flee)
|
||||||
{
|
{
|
||||||
if (!squad.IsValid)
|
if (!squad.IsValid)
|
||||||
return false;
|
return false;
|
||||||
@@ -95,8 +95,10 @@ namespace OpenRA.Mods.Common.Traits.BotModules.Squads
|
|||||||
if (u.Owner == squad.Bot.Player && u.Info.HasTraitInfo<BuildingInfo>())
|
if (u.Owner == squad.Bot.Player && u.Info.HasTraitInfo<BuildingInfo>())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
var enemyAroundUnit = units.Where(unit => squad.SquadManager.IsPreferredEnemyUnit(unit) && unit.Info.HasTraitInfo<AttackBaseInfo>());
|
var enemyAroundUnit = units
|
||||||
if (!enemyAroundUnit.Any())
|
.Where(unit => squad.SquadManager.IsPreferredEnemyUnit(unit) && unit.Info.HasTraitInfo<AttackBaseInfo>())
|
||||||
|
.ToList();
|
||||||
|
if (enemyAroundUnit.Count == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return flee(enemyAroundUnit);
|
return flee(enemyAroundUnit);
|
||||||
|
|||||||
@@ -172,17 +172,18 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
|
|
||||||
ActorInfo ChooseUnitToBuild(ProductionQueue queue)
|
ActorInfo ChooseUnitToBuild(ProductionQueue queue)
|
||||||
{
|
{
|
||||||
var buildableThings = queue.BuildableItems();
|
var buildableThings = queue.BuildableItems().Select(b => b.Name).ToHashSet();
|
||||||
if (!buildableThings.Any())
|
if (buildableThings.Count == 0)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
var myUnits = player.World
|
var myUnits = player.World
|
||||||
.ActorsHavingTrait<IPositionable>()
|
.ActorsHavingTrait<IPositionable>()
|
||||||
.Where(a => a.Owner == player)
|
.Where(a => a.Owner == player)
|
||||||
.Select(a => a.Info.Name).ToList();
|
.Select(a => a.Info.Name)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
foreach (var unit in Info.UnitsToBuild.Shuffle(world.LocalRandom))
|
foreach (var unit in Info.UnitsToBuild.Shuffle(world.LocalRandom))
|
||||||
if (buildableThings.Any(b => b.Name == unit.Key))
|
if (buildableThings.Contains(unit.Key))
|
||||||
if (myUnits.Count(a => a == unit.Key) * 100 < unit.Value * myUnits.Count)
|
if (myUnits.Count(a => a == unit.Key) * 100 < unit.Value * myUnits.Count)
|
||||||
if (HasAdequateAirUnitReloadBuildings(world.Map.Rules.Actors[unit.Key]))
|
if (HasAdequateAirUnitReloadBuildings(world.Map.Rules.Actors[unit.Key]))
|
||||||
return world.Map.Rules.Actors[unit.Key];
|
return world.Map.Rules.Actors[unit.Key];
|
||||||
|
|||||||
@@ -80,9 +80,6 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
return null;
|
return null;
|
||||||
|
|
||||||
var allOfType = Exits(actor, productionType);
|
var allOfType = Exits(actor, productionType);
|
||||||
if (!allOfType.Any())
|
|
||||||
return null;
|
|
||||||
|
|
||||||
foreach (var g in allOfType.GroupBy(e => e.Info.Priority))
|
foreach (var g in allOfType.GroupBy(e => e.Info.Priority))
|
||||||
{
|
{
|
||||||
var shuffled = g.Shuffle(world.SharedRandom);
|
var shuffled = g.Shuffle(world.SharedRandom);
|
||||||
|
|||||||
@@ -54,13 +54,15 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
|
|
||||||
public override void RulesetLoaded(Ruleset rules, ActorInfo ai)
|
public override void RulesetLoaded(Ruleset rules, ActorInfo ai)
|
||||||
{
|
{
|
||||||
var locomotorInfos = rules.Actors[SystemActors.World].TraitInfos<LocomotorInfo>();
|
var locomotorInfos = rules.Actors[SystemActors.World].TraitInfos<LocomotorInfo>()
|
||||||
LocomotorInfo = locomotorInfos.FirstOrDefault(li => li.Name == Locomotor);
|
.Where(li => li.Name == Locomotor).ToList();
|
||||||
if (LocomotorInfo == null)
|
if (locomotorInfos.Count == 0)
|
||||||
throw new YamlException($"A locomotor named '{Locomotor}' doesn't exist.");
|
throw new YamlException($"A locomotor named '{Locomotor}' doesn't exist.");
|
||||||
else if (locomotorInfos.Count(li => li.Name == Locomotor) > 1)
|
else if (locomotorInfos.Count > 1)
|
||||||
throw new YamlException($"There is more than one locomotor named '{Locomotor}'.");
|
throw new YamlException($"There is more than one locomotor named '{Locomotor}'.");
|
||||||
|
|
||||||
|
LocomotorInfo = locomotorInfos[0];
|
||||||
|
|
||||||
base.RulesetLoaded(rules, ai);
|
base.RulesetLoaded(rules, ai);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -113,23 +113,32 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
void INotifyParachute.OnLanded(Actor self)
|
void INotifyParachute.OnLanded(Actor self)
|
||||||
{
|
{
|
||||||
// Check whether the crate landed on anything
|
// Check whether the crate landed on anything
|
||||||
var landedOn = self.World.ActorMap.GetActorsAt(self.Location)
|
var anyOtherActors = false;
|
||||||
.Where(a => a != self);
|
Actor collector = null;
|
||||||
|
foreach (var otherActor in self.World.ActorMap.GetActorsAt(self.Location))
|
||||||
if (!landedOn.Any())
|
|
||||||
return;
|
|
||||||
|
|
||||||
var collector = landedOn.FirstOrDefault(a =>
|
|
||||||
{
|
{
|
||||||
|
if (self == otherActor)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
anyOtherActors = true;
|
||||||
|
|
||||||
// Mobile is (currently) the only trait that supports crushing
|
// Mobile is (currently) the only trait that supports crushing
|
||||||
var mi = a.Info.TraitInfoOrDefault<MobileInfo>();
|
var mi = otherActor.Info.TraitInfoOrDefault<MobileInfo>();
|
||||||
if (mi == null)
|
if (mi == null)
|
||||||
return false;
|
continue;
|
||||||
|
|
||||||
// Make sure that the actor can collect this crate type
|
// Make sure that the actor can collect this crate type
|
||||||
// Crate can only be crushed if it is not in the air.
|
// Crate can only be crushed if it is not in the air.
|
||||||
return self.IsAtGroundLevel() && mi.LocomotorInfo.Crushes.Contains(info.CrushClass);
|
if (self.IsAtGroundLevel() && mi.LocomotorInfo.Crushes.Contains(info.CrushClass))
|
||||||
});
|
{
|
||||||
|
collector = otherActor;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The crate can land unhindered.
|
||||||
|
if (!anyOtherActors)
|
||||||
|
return;
|
||||||
|
|
||||||
// Destroy the crate if none of the units in the cell are valid collectors
|
// Destroy the crate if none of the units in the cell are valid collectors
|
||||||
if (collector != null)
|
if (collector != null)
|
||||||
@@ -148,10 +157,11 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
self.Dispose();
|
self.Dispose();
|
||||||
collected = true;
|
collected = true;
|
||||||
|
|
||||||
if (crateActions.Any())
|
var shares = crateActions
|
||||||
|
.Select(a => (Action: a, Shares: a.GetSelectionSharesOuter(crusher)))
|
||||||
|
.ToList();
|
||||||
|
if (shares.Count != 0)
|
||||||
{
|
{
|
||||||
var shares = crateActions.Select(a => (Action: a, Shares: a.GetSelectionSharesOuter(crusher)));
|
|
||||||
|
|
||||||
var totalShares = shares.Sum(a => a.Shares);
|
var totalShares = shares.Sum(a => a.Shares);
|
||||||
var n = self.World.SharedRandom.Next(totalShares);
|
var n = self.World.SharedRandom.Next(totalShares);
|
||||||
|
|
||||||
|
|||||||
@@ -76,7 +76,8 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
void GrantCondition(Actor actor)
|
void GrantCondition(Actor actor)
|
||||||
{
|
{
|
||||||
var externals = actor.TraitsImplementing<ExternalCondition>()
|
var externals = actor.TraitsImplementing<ExternalCondition>()
|
||||||
.Where(t => t.Info.Condition == info.Condition);
|
.Where(t => t.Info.Condition == info.Condition)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
ExternalCondition external = null;
|
ExternalCondition external = null;
|
||||||
for (var n = 0; n < info.Levels; n++)
|
for (var n = 0; n < info.Levels; n++)
|
||||||
|
|||||||
@@ -104,13 +104,15 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
|
|
||||||
public override void RulesetLoaded(Ruleset rules, ActorInfo ai)
|
public override void RulesetLoaded(Ruleset rules, ActorInfo ai)
|
||||||
{
|
{
|
||||||
var locomotorInfos = rules.Actors[SystemActors.World].TraitInfos<LocomotorInfo>();
|
var locomotorInfos = rules.Actors[SystemActors.World].TraitInfos<LocomotorInfo>()
|
||||||
LocomotorInfo = locomotorInfos.FirstOrDefault(li => li.Name == Locomotor);
|
.Where(li => li.Name == Locomotor).ToList();
|
||||||
if (LocomotorInfo == null)
|
if (locomotorInfos.Count == 0)
|
||||||
throw new YamlException($"A locomotor named '{Locomotor}' doesn't exist.");
|
throw new YamlException($"A locomotor named '{Locomotor}' doesn't exist.");
|
||||||
else if (locomotorInfos.Count(li => li.Name == Locomotor) > 1)
|
else if (locomotorInfos.Count > 1)
|
||||||
throw new YamlException($"There is more than one locomotor named '{Locomotor}'.");
|
throw new YamlException($"There is more than one locomotor named '{Locomotor}'.");
|
||||||
|
|
||||||
|
LocomotorInfo = locomotorInfos[0];
|
||||||
|
|
||||||
// We need to reset the reference to the locomotor between each worlds, otherwise we are reference the previous state.
|
// We need to reset the reference to the locomotor between each worlds, otherwise we are reference the previous state.
|
||||||
locomotor = null;
|
locomotor = null;
|
||||||
|
|
||||||
|
|||||||
@@ -133,15 +133,15 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
|
|
||||||
public override TraitPair<Production> MostLikelyProducer()
|
public override TraitPair<Production> MostLikelyProducer()
|
||||||
{
|
{
|
||||||
var productionActors = self.World.ActorsWithTrait<Production>()
|
var productionActor = self.World.ActorsWithTrait<Production>()
|
||||||
.Where(x => x.Actor.Owner == self.Owner
|
.Where(x => x.Actor.Owner == self.Owner
|
||||||
&& !x.Trait.IsTraitDisabled && x.Trait.Info.Produces.Contains(Info.Type))
|
&& !x.Trait.IsTraitDisabled && x.Trait.Info.Produces.Contains(Info.Type))
|
||||||
.OrderByDescending(x => x.Actor.IsPrimaryBuilding())
|
.OrderBy(x => x.Trait.IsTraitPaused)
|
||||||
|
.ThenByDescending(x => x.Actor.IsPrimaryBuilding())
|
||||||
.ThenByDescending(x => x.Actor.ActorID)
|
.ThenByDescending(x => x.Actor.ActorID)
|
||||||
.ToList();
|
.FirstOrDefault();
|
||||||
|
|
||||||
var unpaused = productionActors.FirstOrDefault(a => !a.Trait.IsTraitPaused);
|
return productionActor;
|
||||||
return unpaused.Trait != null ? unpaused : productionActors.FirstOrDefault();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool BuildUnit(ActorInfo unit)
|
protected override bool BuildUnit(ActorInfo unit)
|
||||||
@@ -159,14 +159,10 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
.OrderByDescending(x => x.Actor.IsPrimaryBuilding())
|
.OrderByDescending(x => x.Actor.IsPrimaryBuilding())
|
||||||
.ThenByDescending(x => x.Actor.ActorID);
|
.ThenByDescending(x => x.Actor.ActorID);
|
||||||
|
|
||||||
if (!producers.Any())
|
var anyProducers = false;
|
||||||
{
|
|
||||||
CancelProduction(unit.Name, 1);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var p in producers)
|
foreach (var p in producers)
|
||||||
{
|
{
|
||||||
|
anyProducers = true;
|
||||||
if (p.Trait.IsTraitPaused)
|
if (p.Trait.IsTraitPaused)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -184,6 +180,12 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!anyProducers)
|
||||||
|
{
|
||||||
|
CancelProduction(unit.Name, 1);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -83,15 +83,15 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
|
|
||||||
public override TraitPair<Production> MostLikelyProducer()
|
public override TraitPair<Production> MostLikelyProducer()
|
||||||
{
|
{
|
||||||
var productionActors = self.World.ActorsWithTrait<Production>()
|
var productionActor = self.World.ActorsWithTrait<Production>()
|
||||||
.Where(x => x.Actor.Owner == self.Owner
|
.Where(x => x.Actor.Owner == self.Owner
|
||||||
&& !x.Trait.IsTraitDisabled && x.Trait.Info.Produces.Contains(Info.Type))
|
&& !x.Trait.IsTraitDisabled && x.Trait.Info.Produces.Contains(Info.Type))
|
||||||
.OrderByDescending(x => x.Actor.IsPrimaryBuilding())
|
.OrderBy(x => x.Trait.IsTraitPaused)
|
||||||
|
.ThenByDescending(x => x.Actor.IsPrimaryBuilding())
|
||||||
.ThenByDescending(x => x.Actor.ActorID)
|
.ThenByDescending(x => x.Actor.ActorID)
|
||||||
.ToList();
|
.FirstOrDefault();
|
||||||
|
|
||||||
var unpaused = productionActors.FirstOrDefault(a => !a.Trait.IsTraitPaused);
|
return productionActor;
|
||||||
return unpaused.Trait != null ? unpaused : productionActors.FirstOrDefault();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool BuildUnit(ActorInfo unit)
|
protected override bool BuildUnit(ActorInfo unit)
|
||||||
@@ -109,14 +109,10 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
.OrderByDescending(x => x.Actor.IsPrimaryBuilding())
|
.OrderByDescending(x => x.Actor.IsPrimaryBuilding())
|
||||||
.ThenByDescending(x => x.Actor.ActorID);
|
.ThenByDescending(x => x.Actor.ActorID);
|
||||||
|
|
||||||
if (!producers.Any())
|
var anyProducers = false;
|
||||||
{
|
|
||||||
CancelProduction(unit.Name, 1);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var p in producers)
|
foreach (var p in producers)
|
||||||
{
|
{
|
||||||
|
anyProducers = true;
|
||||||
if (p.Trait.IsTraitPaused)
|
if (p.Trait.IsTraitPaused)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -134,6 +130,12 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!anyProducers)
|
||||||
|
{
|
||||||
|
CancelProduction(unit.Name, 1);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -81,13 +81,14 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
var myTeam = self.World.LobbyInfo.ClientWithIndex(self.Owner.ClientIndex).Team;
|
var myTeam = self.World.LobbyInfo.ClientWithIndex(self.Owner.ClientIndex).Team;
|
||||||
var teams = self.World.Players.Where(p => !p.NonCombatant && p.Playable)
|
var victoriousTeam = self.World.Players.Where(p => !p.NonCombatant && p.Playable)
|
||||||
.Select(p => (Player: p, PlayerStatistics: p.PlayerActor.TraitOrDefault<PlayerStatistics>()))
|
.Select(p => (Player: p, PlayerStatistics: p.PlayerActor.TraitOrDefault<PlayerStatistics>()))
|
||||||
.OrderByDescending(p => p.PlayerStatistics?.Experience ?? 0)
|
.OrderByDescending(p => p.PlayerStatistics?.Experience ?? 0)
|
||||||
.GroupBy(p => (self.World.LobbyInfo.ClientWithIndex(p.Player.ClientIndex) ?? new Session.Client()).Team)
|
.GroupBy(p => (self.World.LobbyInfo.ClientWithIndex(p.Player.ClientIndex) ?? new Session.Client()).Team)
|
||||||
.OrderByDescending(g => g.Sum(gg => gg.PlayerStatistics?.Experience ?? 0));
|
.OrderByDescending(g => g.Sum(gg => gg.PlayerStatistics?.Experience ?? 0))
|
||||||
|
.First();
|
||||||
|
|
||||||
if (teams.First().Key == myTeam && (myTeam != 0 || teams.First().First().Player == self.Owner))
|
if (victoriousTeam.Key == myTeam && (myTeam != 0 || victoriousTeam.First().Player == self.Owner))
|
||||||
{
|
{
|
||||||
mo.MarkCompleted(self.Owner, objectiveID);
|
mo.MarkCompleted(self.Owner, objectiveID);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -594,9 +594,11 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
// Returns the actor/trait that is most likely (but not necessarily guaranteed) to produce something in this queue
|
// Returns the actor/trait that is most likely (but not necessarily guaranteed) to produce something in this queue
|
||||||
public virtual TraitPair<Production> MostLikelyProducer()
|
public virtual TraitPair<Production> MostLikelyProducer()
|
||||||
{
|
{
|
||||||
var traits = productionTraits.Where(p => !p.IsTraitDisabled && p.Info.Produces.Contains(Info.Type));
|
var trait = productionTraits
|
||||||
var unpaused = traits.FirstOrDefault(a => !a.IsTraitPaused);
|
.Where(p => !p.IsTraitDisabled && p.Info.Produces.Contains(Info.Type))
|
||||||
return new TraitPair<Production>(Actor, unpaused ?? traits.FirstOrDefault());
|
.OrderBy(p => p.IsTraitPaused)
|
||||||
|
.FirstOrDefault();
|
||||||
|
return new TraitPair<Production>(Actor, trait);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Builds a unit from the actor that holds this queue (1 queue per building)
|
// Builds a unit from the actor that holds this queue (1 queue per building)
|
||||||
|
|||||||
@@ -89,13 +89,21 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
if (!self.Owner.NonCombatant && self.Owner.HasNoRequiredUnits(shortGame))
|
if (!self.Owner.NonCombatant && self.Owner.HasNoRequiredUnits(shortGame))
|
||||||
mo.MarkFailed(self.Owner, objectiveID);
|
mo.MarkFailed(self.Owner, objectiveID);
|
||||||
|
|
||||||
var others = self.World.Players.Where(p => !p.NonCombatant
|
var allOthersLost = true;
|
||||||
&& !p.IsAlliedWith(self.Owner));
|
var anyOtherWon = false;
|
||||||
|
foreach (var other in self.World.Players)
|
||||||
|
{
|
||||||
|
if (other.NonCombatant || other.IsAlliedWith(self.Owner))
|
||||||
|
continue;
|
||||||
|
|
||||||
if (others.All(p => p.WinState == WinState.Lost))
|
allOthersLost = allOthersLost && other.WinState == WinState.Lost;
|
||||||
|
anyOtherWon = anyOtherWon || other.WinState == WinState.Won;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (allOthersLost)
|
||||||
mo.MarkCompleted(player, objectiveID);
|
mo.MarkCompleted(player, objectiveID);
|
||||||
|
|
||||||
if (others.Any(p => p.WinState == WinState.Won))
|
if (anyOtherWon)
|
||||||
mo.MarkFailed(player, objectiveID);
|
mo.MarkFailed(player, objectiveID);
|
||||||
|
|
||||||
// See if any of the conditions are met to increase the count
|
// See if any of the conditions are met to increase the count
|
||||||
@@ -119,13 +127,14 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
var myTeam = self.World.LobbyInfo.ClientWithIndex(self.Owner.ClientIndex).Team;
|
var myTeam = self.World.LobbyInfo.ClientWithIndex(self.Owner.ClientIndex).Team;
|
||||||
var teams = self.World.Players.Where(p => !p.NonCombatant && p.Playable)
|
var victoriousTeam = self.World.Players.Where(p => !p.NonCombatant && p.Playable)
|
||||||
.Select(p => (Player: p, PlayerStatistics: p.PlayerActor.TraitOrDefault<PlayerStatistics>()))
|
.Select(p => (Player: p, PlayerStatistics: p.PlayerActor.TraitOrDefault<PlayerStatistics>()))
|
||||||
.OrderByDescending(p => p.PlayerStatistics?.Experience ?? 0)
|
.OrderByDescending(p => p.PlayerStatistics?.Experience ?? 0)
|
||||||
.GroupBy(p => (self.World.LobbyInfo.ClientWithIndex(p.Player.ClientIndex) ?? new Session.Client()).Team)
|
.GroupBy(p => (self.World.LobbyInfo.ClientWithIndex(p.Player.ClientIndex) ?? new Session.Client()).Team)
|
||||||
.OrderByDescending(g => g.Sum(gg => gg.PlayerStatistics?.Experience ?? 0));
|
.OrderByDescending(g => g.Sum(gg => gg.PlayerStatistics?.Experience ?? 0))
|
||||||
|
.First();
|
||||||
|
|
||||||
if (teams.First().Key == myTeam && (myTeam != 0 || teams.First().First().Player == self.Owner))
|
if (victoriousTeam.Key == myTeam && (myTeam != 0 || victoriousTeam.First().Player == self.Owner))
|
||||||
{
|
{
|
||||||
mo.MarkCompleted(self.Owner, objectiveID);
|
mo.MarkCompleted(self.Owner, objectiveID);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -44,10 +44,19 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
if (rejectsOrdersTraits.Length == 0)
|
if (rejectsOrdersTraits.Length == 0)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
var reject = rejectsOrdersTraits.SelectMany(t => t.Reject);
|
foreach (var rejectsOrdersTrait in rejectsOrdersTraits)
|
||||||
var except = rejectsOrdersTraits.SelectMany(t => t.Except);
|
if (rejectsOrdersTrait.Except.Contains(orderString))
|
||||||
|
return true;
|
||||||
|
|
||||||
return except.Contains(orderString) || (reject.Any() && !reject.Contains(orderString));
|
var anyRejects = false;
|
||||||
|
foreach (var rejectsOrdersTrait in rejectsOrdersTraits)
|
||||||
|
{
|
||||||
|
anyRejects = anyRejects || rejectsOrdersTrait.Reject.Count > 0;
|
||||||
|
if (rejectsOrdersTrait.Reject.Contains(orderString))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return anyRejects;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,29 +51,27 @@ namespace OpenRA.Mods.Common.Traits.Render
|
|||||||
if (IsTraitDisabled)
|
if (IsTraitDisabled)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
var renderables = r.ToList();
|
||||||
var height = self.World.Map.DistanceAboveTerrain(self.CenterPosition).Length;
|
var height = self.World.Map.DistanceAboveTerrain(self.CenterPosition).Length;
|
||||||
var shadowSprites = r.Where(s => !s.IsDecoration && s is IModifyableRenderable)
|
var shadowSprites = renderables.Where(s => !s.IsDecoration && s is IModifyableRenderable)
|
||||||
.Select(ma => ((IModifyableRenderable)ma).WithTint(shadowColor, ((IModifyableRenderable)ma).TintModifiers | TintModifiers.ReplaceColor)
|
.Select(ma => ((IModifyableRenderable)ma).WithTint(shadowColor, ((IModifyableRenderable)ma).TintModifiers | TintModifiers.ReplaceColor)
|
||||||
.WithAlpha(shadowAlpha)
|
.WithAlpha(shadowAlpha)
|
||||||
.OffsetBy(info.Offset - new WVec(0, 0, height))
|
.OffsetBy(info.Offset - new WVec(0, 0, height))
|
||||||
.WithZOffset(ma.ZOffset + height + info.ZOffset)
|
.WithZOffset(ma.ZOffset + height + info.ZOffset)
|
||||||
.AsDecoration());
|
.AsDecoration());
|
||||||
|
|
||||||
return shadowSprites.Concat(r);
|
return shadowSprites.Concat(renderables);
|
||||||
}
|
}
|
||||||
|
|
||||||
IEnumerable<Rectangle> IRenderModifier.ModifyScreenBounds(Actor self, WorldRenderer wr, IEnumerable<Rectangle> bounds)
|
IEnumerable<Rectangle> IRenderModifier.ModifyScreenBounds(Actor self, WorldRenderer wr, IEnumerable<Rectangle> bounds)
|
||||||
{
|
{
|
||||||
foreach (var r in bounds)
|
|
||||||
yield return r;
|
|
||||||
|
|
||||||
if (IsTraitDisabled)
|
if (IsTraitDisabled)
|
||||||
yield break;
|
return bounds;
|
||||||
|
|
||||||
|
var boundsList = bounds.ToList();
|
||||||
var height = self.World.Map.DistanceAboveTerrain(self.CenterPosition).Length;
|
var height = self.World.Map.DistanceAboveTerrain(self.CenterPosition).Length;
|
||||||
var offset = wr.ScreenPxOffset(info.Offset - new WVec(0, 0, height));
|
var offset = wr.ScreenPxOffset(info.Offset - new WVec(0, 0, height));
|
||||||
foreach (var r in bounds)
|
return boundsList.Concat(boundsList.Select(r => new Rectangle(r.X + offset.X, r.Y + offset.Y, r.Width, r.Height)));
|
||||||
yield return new Rectangle(r.X + offset.X, r.Y + offset.Y, r.Width, r.Height);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -205,8 +205,8 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
actorShouldBeRemoved = removeActorPosition.Contains;
|
actorShouldBeRemoved = removeActorPosition.Contains;
|
||||||
|
|
||||||
LargestActorRadius = map.Rules.Actors.SelectMany(a => a.Value.TraitInfos<HitShapeInfo>()).Max(h => h.Type.OuterRadius);
|
LargestActorRadius = map.Rules.Actors.SelectMany(a => a.Value.TraitInfos<HitShapeInfo>()).Max(h => h.Type.OuterRadius);
|
||||||
var blockers = map.Rules.Actors.Where(a => a.Value.HasTraitInfo<IBlocksProjectilesInfo>());
|
var blockers = map.Rules.Actors.Where(a => a.Value.HasTraitInfo<IBlocksProjectilesInfo>()).ToList();
|
||||||
LargestBlockingActorRadius = blockers.Any() ? blockers.SelectMany(a => a.Value.TraitInfos<HitShapeInfo>()).Max(h => h.Type.OuterRadius) : WDist.Zero;
|
LargestBlockingActorRadius = blockers.Count != 0 ? blockers.SelectMany(a => a.Value.TraitInfos<HitShapeInfo>()).Max(h => h.Type.OuterRadius) : WDist.Zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
void INotifyCreated.Created(Actor self)
|
void INotifyCreated.Created(Actor self)
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
void ICreatePlayersInfo.CreateServerPlayers(MapPreview map, Session lobbyInfo, List<GameInformation.Player> players, MersenneTwister playerRandom)
|
void ICreatePlayersInfo.CreateServerPlayers(MapPreview map, Session lobbyInfo, List<GameInformation.Player> players, MersenneTwister playerRandom)
|
||||||
{
|
{
|
||||||
var factions = map.WorldActorInfo.TraitInfos<FactionInfo>().ToArray();
|
var factions = map.WorldActorInfo.TraitInfos<FactionInfo>();
|
||||||
var assignSpawnLocations = map.WorldActorInfo.TraitInfoOrDefault<IAssignSpawnPointsInfo>();
|
var assignSpawnLocations = map.WorldActorInfo.TraitInfoOrDefault<IAssignSpawnPointsInfo>();
|
||||||
var spawnState = assignSpawnLocations?.InitializeState(map, lobbyInfo);
|
var spawnState = assignSpawnLocations?.InitializeState(map, lobbyInfo);
|
||||||
|
|
||||||
@@ -41,7 +41,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create the regular playable players.
|
// Create the regular playable players.
|
||||||
var bots = map.PlayerActorInfo.TraitInfos<IBotInfo>().ToArray();
|
var bots = map.PlayerActorInfo.TraitInfos<IBotInfo>();
|
||||||
|
|
||||||
foreach (var kv in lobbyInfo.Slots)
|
foreach (var kv in lobbyInfo.Slots)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -178,7 +178,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
return reference.GetOrDefault<T>(info);
|
return reference.GetOrDefault<T>(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<T> GetInits<T>() where T : ActorInit
|
public IReadOnlyCollection<T> GetInits<T>() where T : ActorInit
|
||||||
{
|
{
|
||||||
return reference.GetAll<T>();
|
return reference.GetAll<T>();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -136,7 +136,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
public readonly LongBitSet<PlayerBitMask> Crushable;
|
public readonly LongBitSet<PlayerBitMask> Crushable;
|
||||||
public readonly CellFlag CellFlag;
|
public readonly CellFlag CellFlag;
|
||||||
|
|
||||||
public CellCache(LongBitSet<PlayerBitMask> immovable, CellFlag cellFlag, LongBitSet<PlayerBitMask> crushable = default)
|
public CellCache(LongBitSet<PlayerBitMask> immovable, CellFlag cellFlag, LongBitSet<PlayerBitMask> crushable)
|
||||||
{
|
{
|
||||||
Immovable = immovable;
|
Immovable = immovable;
|
||||||
Crushable = crushable;
|
Crushable = crushable;
|
||||||
@@ -459,26 +459,17 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
using (new PerfSample("locomotor_cache"))
|
using (new PerfSample("locomotor_cache"))
|
||||||
{
|
{
|
||||||
var cache = blockingCache[cell.Layer];
|
var cache = blockingCache[cell.Layer];
|
||||||
|
|
||||||
var actors = actorMap.GetActorsAt(cell);
|
|
||||||
var cellFlag = CellFlag.HasFreeSpace;
|
var cellFlag = CellFlag.HasFreeSpace;
|
||||||
|
|
||||||
if (!actors.Any())
|
|
||||||
{
|
|
||||||
cache[cell] = new CellCache(default, cellFlag);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sharesCell && actorMap.HasFreeSubCell(cell))
|
|
||||||
{
|
|
||||||
cache[cell] = new CellCache(default, cellFlag);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var cellImmovablePlayers = default(LongBitSet<PlayerBitMask>);
|
var cellImmovablePlayers = default(LongBitSet<PlayerBitMask>);
|
||||||
var cellCrushablePlayers = world.AllPlayersMask;
|
var cellCrushablePlayers = world.AllPlayersMask;
|
||||||
|
|
||||||
foreach (var actor in actors)
|
if (sharesCell && actorMap.HasFreeSubCell(cell))
|
||||||
|
{
|
||||||
|
cache[cell] = new CellCache(cellImmovablePlayers, cellFlag, cellCrushablePlayers);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var actor in actorMap.GetActorsAt(cell))
|
||||||
{
|
{
|
||||||
var actorImmovablePlayers = world.AllPlayersMask;
|
var actorImmovablePlayers = world.AllPlayersMask;
|
||||||
var actorCrushablePlayers = world.NoPlayersMask;
|
var actorCrushablePlayers = world.NoPlayersMask;
|
||||||
@@ -493,11 +484,10 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
if (isTransitOnly)
|
if (isTransitOnly)
|
||||||
cellFlag |= CellFlag.HasTransitOnlyActor;
|
cellFlag |= CellFlag.HasTransitOnlyActor;
|
||||||
|
|
||||||
if (crushables.Any())
|
foreach (var crushable in crushables)
|
||||||
{
|
{
|
||||||
cellFlag |= CellFlag.HasCrushableActor;
|
cellFlag |= CellFlag.HasCrushableActor;
|
||||||
foreach (var crushable in crushables)
|
actorCrushablePlayers = actorCrushablePlayers.Union(crushable.CrushableBy(actor, Info.Crushes));
|
||||||
actorCrushablePlayers = actorCrushablePlayers.Union(crushable.CrushableBy(actor, Info.Crushes));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isMoving)
|
if (isMoving)
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||||
{
|
{
|
||||||
@@ -24,7 +23,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
|
|||||||
|
|
||||||
public override IEnumerable<string> AfterUpdate(ModData modData)
|
public override IEnumerable<string> AfterUpdate(ModData modData)
|
||||||
{
|
{
|
||||||
if (locations.Any())
|
if (locations.Count != 0)
|
||||||
yield return "Icon overlay logic has been split from ProducibleWithLevel to WithProductionIconOverlay trait.\n" +
|
yield return "Icon overlay logic has been split from ProducibleWithLevel to WithProductionIconOverlay trait.\n" +
|
||||||
"If you have been using VeteranProductionIconOverlay trait, add WithProductionIconOverlay to following actors:\n" +
|
"If you have been using VeteranProductionIconOverlay trait, add WithProductionIconOverlay to following actors:\n" +
|
||||||
UpdateUtils.FormatMessageList(locations);
|
UpdateUtils.FormatMessageList(locations);
|
||||||
|
|||||||
@@ -45,16 +45,16 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
|
|||||||
foreach (var sequenceNode in imageNode.Value.Nodes)
|
foreach (var sequenceNode in imageNode.Value.Nodes)
|
||||||
{
|
{
|
||||||
var useTilesetExtensionNode = sequenceNode.LastChildMatching("UseTilesetExtension");
|
var useTilesetExtensionNode = sequenceNode.LastChildMatching("UseTilesetExtension");
|
||||||
if (useTilesetExtensionNode != null && !tilesetExtensions.Any())
|
if (useTilesetExtensionNode != null && tilesetExtensions.Count == 0)
|
||||||
requiredMetadata.Add("TilesetExtensions");
|
requiredMetadata.Add("TilesetExtensions");
|
||||||
|
|
||||||
var useTilesetCodeNode = sequenceNode.LastChildMatching("UseTilesetCode");
|
var useTilesetCodeNode = sequenceNode.LastChildMatching("UseTilesetCode");
|
||||||
if (useTilesetCodeNode != null && !tilesetCodes.Any())
|
if (useTilesetCodeNode != null && tilesetCodes.Count == 0)
|
||||||
requiredMetadata.Add("TilesetCodes");
|
requiredMetadata.Add("TilesetCodes");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (requiredMetadata.Any())
|
if (requiredMetadata.Count != 0)
|
||||||
{
|
{
|
||||||
yield return $"The ExplicitSequenceFilenames rule requires {requiredMetadata.JoinWith(", ")}\n" +
|
yield return $"The ExplicitSequenceFilenames rule requires {requiredMetadata.JoinWith(", ")}\n" +
|
||||||
"to be defined under the SpriteSequenceFormat definition in mod.yaml.\n" +
|
"to be defined under the SpriteSequenceFormat definition in mod.yaml.\n" +
|
||||||
@@ -317,7 +317,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
|
|||||||
if (allSequencesHaveTilesetFilenames)
|
if (allSequencesHaveTilesetFilenames)
|
||||||
sequenceNode.RemoveNodes("TilesetFilenames");
|
sequenceNode.RemoveNodes("TilesetFilenames");
|
||||||
|
|
||||||
if (!sequenceNode.Value.Nodes.Any())
|
if (sequenceNode.Value.Nodes.Count == 0)
|
||||||
imageNode.RemoveNode(sequenceNode);
|
imageNode.RemoveNode(sequenceNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -328,13 +328,13 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
|
|||||||
sequenceNode.RemoveNodes("TilesetFilenames");
|
sequenceNode.RemoveNodes("TilesetFilenames");
|
||||||
|
|
||||||
var tilesetFilenamesNode = sequenceNode.LastChildMatching("TilesetFilenames");
|
var tilesetFilenamesNode = sequenceNode.LastChildMatching("TilesetFilenames");
|
||||||
if (allSequencesHaveTilesetFilenames && tilesetFilenamesNode != null && !tilesetFilenamesNode.Value.Nodes.Any())
|
if (allSequencesHaveTilesetFilenames && tilesetFilenamesNode != null && tilesetFilenamesNode.Value.Nodes.Count == 0)
|
||||||
sequenceNode.RemoveNode(tilesetFilenamesNode);
|
sequenceNode.RemoveNode(tilesetFilenamesNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var sequenceNode in imageNode.Value.Nodes.ToList())
|
foreach (var sequenceNode in imageNode.Value.Nodes.ToList())
|
||||||
if (implicitInheritedSequences.Contains(sequenceNode.Key) && !sequenceNode.Value.Nodes.Any())
|
if (implicitInheritedSequences.Contains(sequenceNode.Key) && sequenceNode.Value.Nodes.Count == 0)
|
||||||
imageNode.RemoveNode(sequenceNode);
|
imageNode.RemoveNode(sequenceNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -424,7 +424,7 @@ namespace OpenRA.Mods.Common.UpdateRules.Rules
|
|||||||
if (overrideNode.Value.Value == filenameNode.Value.Value)
|
if (overrideNode.Value.Value == filenameNode.Value.Value)
|
||||||
tilesetFilenamesNode.Value.Nodes.Remove(overrideNode);
|
tilesetFilenamesNode.Value.Nodes.Remove(overrideNode);
|
||||||
|
|
||||||
if (!tilesetFilenamesNode.Value.Nodes.Any())
|
if (tilesetFilenamesNode.Value.Nodes.Count == 0)
|
||||||
sequenceNode.RemoveNode(tilesetFilenamesNode);
|
sequenceNode.RemoveNode(tilesetFilenamesNode);
|
||||||
|
|
||||||
sequenceNode.Value.Nodes.Insert(0, filenameNode);
|
sequenceNode.Value.Nodes.Insert(0, filenameNode);
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ namespace OpenRA.Mods.Common.UpdateRules
|
|||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
public static IEnumerable<UpdateRule> FromSource(ObjectCreator objectCreator, string source, bool chain = true)
|
public static IReadOnlyCollection<UpdateRule> FromSource(ObjectCreator objectCreator, string source, bool chain = true)
|
||||||
{
|
{
|
||||||
// Use reflection to identify types
|
// Use reflection to identify types
|
||||||
var namedType = objectCreator.FindType(source);
|
var namedType = objectCreator.FindType(source);
|
||||||
@@ -143,12 +143,12 @@ namespace OpenRA.Mods.Common.UpdateRules
|
|||||||
this.chainToSource = chainToSource;
|
this.chainToSource = chainToSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
IEnumerable<UpdateRule> Rules(bool chain = true)
|
IReadOnlyCollection<UpdateRule> Rules(bool chain = true)
|
||||||
{
|
{
|
||||||
if (chainToSource != null && chain)
|
if (chainToSource != null && chain)
|
||||||
{
|
{
|
||||||
var child = Paths.First(p => p.source == chainToSource);
|
var child = Paths.First(p => p.source == chainToSource);
|
||||||
return rules.Concat(child.Rules(chain));
|
return rules.Concat(child.Rules(chain)).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
return rules;
|
return rules;
|
||||||
|
|||||||
@@ -271,7 +271,7 @@ namespace OpenRA.Mods.Common.UtilityCommands
|
|||||||
if (isActivity)
|
if (isActivity)
|
||||||
Console.WriteLine(" --- *Queued Activity*");
|
Console.WriteLine(" --- *Queued Activity*");
|
||||||
|
|
||||||
if (requiredTraits.Any())
|
if (requiredTraits.Length != 0)
|
||||||
Console.WriteLine($" --- **Requires {(requiredTraits.Length == 1 ? "Trait" : "Traits")}:** {requiredTraits.Select(GetDocumentationUrl).JoinWith(", ")}");
|
Console.WriteLine($" --- **Requires {(requiredTraits.Length == 1 ? "Trait" : "Traits")}:** {requiredTraits.Select(GetDocumentationUrl).JoinWith(", ")}");
|
||||||
|
|
||||||
if (memberInfo is MethodInfo methodInfo)
|
if (memberInfo is MethodInfo methodInfo)
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ namespace OpenRA.Mods.Common.UtilityCommands
|
|||||||
if (folder.OpenPackage(args[1], modData.ModFiles) is not IReadWritePackage package)
|
if (folder.OpenPackage(args[1], modData.ModFiles) is not IReadWritePackage package)
|
||||||
throw new FileNotFoundException(args[1]);
|
throw new FileNotFoundException(args[1]);
|
||||||
|
|
||||||
IEnumerable<UpdateRule> rules = null;
|
IReadOnlyCollection<UpdateRule> rules = null;
|
||||||
if (args.Length > 2)
|
if (args.Length > 2)
|
||||||
rules = UpdatePath.FromSource(modData.ObjectCreator, args[2]);
|
rules = UpdatePath.FromSource(modData.ObjectCreator, args[2]);
|
||||||
|
|
||||||
@@ -77,9 +77,10 @@ namespace OpenRA.Mods.Common.UtilityCommands
|
|||||||
}
|
}
|
||||||
|
|
||||||
var other = UpdatePath.KnownRules(modData.ObjectCreator)
|
var other = UpdatePath.KnownRules(modData.ObjectCreator)
|
||||||
.Where(r => !ruleGroups.Values.Any(g => g.Contains(r)));
|
.Where(r => !ruleGroups.Values.Any(g => g.Contains(r)))
|
||||||
|
.ToList();
|
||||||
|
|
||||||
if (other.Any())
|
if (other.Count != 0)
|
||||||
{
|
{
|
||||||
Console.WriteLine(" Other:");
|
Console.WriteLine(" Other:");
|
||||||
foreach (var r in other)
|
foreach (var r in other)
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ namespace OpenRA.Mods.Common.UtilityCommands
|
|||||||
// HACK: The engine code assumes that Game.modData is set.
|
// HACK: The engine code assumes that Game.modData is set.
|
||||||
var modData = Game.ModData = utility.ModData;
|
var modData = Game.ModData = utility.ModData;
|
||||||
|
|
||||||
IEnumerable<UpdateRule> rules = null;
|
IReadOnlyCollection<UpdateRule> rules = null;
|
||||||
if (args.Length > 1)
|
if (args.Length > 1)
|
||||||
rules = UpdatePath.FromSource(modData.ObjectCreator, args[1]);
|
rules = UpdatePath.FromSource(modData.ObjectCreator, args[1]);
|
||||||
|
|
||||||
@@ -71,9 +71,10 @@ namespace OpenRA.Mods.Common.UtilityCommands
|
|||||||
}
|
}
|
||||||
|
|
||||||
var other = UpdatePath.KnownRules(modData.ObjectCreator)
|
var other = UpdatePath.KnownRules(modData.ObjectCreator)
|
||||||
.Where(r => !ruleGroups.Values.Any(g => g.Contains(r)));
|
.Where(r => !ruleGroups.Values.Any(g => g.Contains(r)))
|
||||||
|
.ToList();
|
||||||
|
|
||||||
if (other.Any())
|
if (other.Count != 0)
|
||||||
{
|
{
|
||||||
Console.WriteLine(" Other:");
|
Console.WriteLine(" Other:");
|
||||||
foreach (var r in other)
|
foreach (var r in other)
|
||||||
@@ -111,9 +112,9 @@ namespace OpenRA.Mods.Common.UtilityCommands
|
|||||||
PrintSummary(rules, args.Contains("--detailed"));
|
PrintSummary(rules, args.Contains("--detailed"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void PrintSummary(IEnumerable<UpdateRule> rules, bool detailed)
|
public static void PrintSummary(IReadOnlyCollection<UpdateRule> rules, bool detailed)
|
||||||
{
|
{
|
||||||
var count = rules.Count();
|
var count = rules.Count;
|
||||||
if (count == 1)
|
if (count == 1)
|
||||||
Console.WriteLine("Found 1 API change:");
|
Console.WriteLine("Found 1 API change:");
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -60,9 +60,9 @@ namespace OpenRA.Mods.Common.Warheads
|
|||||||
|
|
||||||
if (RandomClusterCount != 0)
|
if (RandomClusterCount != 0)
|
||||||
{
|
{
|
||||||
var randomTargetCells = CellsMatching(targetCell, true);
|
var randomTargetCells = CellsMatching(targetCell, true).ToList();
|
||||||
var clusterCount = RandomClusterCount < 0 ? randomTargetCells.Count() : RandomClusterCount;
|
var clusterCount = RandomClusterCount < 0 ? randomTargetCells.Count : RandomClusterCount;
|
||||||
if (randomTargetCells.Any())
|
if (randomTargetCells.Count != 0)
|
||||||
for (var i = 0; i < clusterCount; i++)
|
for (var i = 0; i < clusterCount; i++)
|
||||||
FireProjectileAtCell(map, firedBy, target, randomTargetCells.Random(firedBy.World.SharedRandom), args);
|
FireProjectileAtCell(map, firedBy, target, randomTargetCells.Random(firedBy.World.SharedRandom), args);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
var actors = new List<KeyValuePair<ActorInfo, EncyclopediaInfo>>();
|
var actors = new List<KeyValuePair<ActorInfo, EncyclopediaInfo>>();
|
||||||
foreach (var actor in modData.DefaultRules.Actors.Values)
|
foreach (var actor in modData.DefaultRules.Actors.Values)
|
||||||
{
|
{
|
||||||
if (!actor.TraitInfos<IRenderActorPreviewSpritesInfo>().Any())
|
if (actor.TraitInfos<IRenderActorPreviewSpritesInfo>().Count == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var statistics = actor.TraitInfoOrDefault<UpdatesPlayerStatisticsInfo>();
|
var statistics = actor.TraitInfoOrDefault<UpdatesPlayerStatisticsInfo>();
|
||||||
|
|||||||
@@ -113,7 +113,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
.Select(p => (Player: p, PlayerStatistics: p.PlayerActor.TraitOrDefault<PlayerStatistics>()))
|
.Select(p => (Player: p, PlayerStatistics: p.PlayerActor.TraitOrDefault<PlayerStatistics>()))
|
||||||
.OrderByDescending(p => p.PlayerStatistics?.Experience ?? 0)
|
.OrderByDescending(p => p.PlayerStatistics?.Experience ?? 0)
|
||||||
.GroupBy(p => (world.LobbyInfo.ClientWithIndex(p.Player.ClientIndex) ?? new Session.Client()).Team)
|
.GroupBy(p => (world.LobbyInfo.ClientWithIndex(p.Player.ClientIndex) ?? new Session.Client()).Team)
|
||||||
.OrderByDescending(g => g.Sum(gg => gg.PlayerStatistics?.Experience ?? 0));
|
.OrderByDescending(g => g.Sum(gg => gg.PlayerStatistics?.Experience ?? 0))
|
||||||
|
.ToList();
|
||||||
|
|
||||||
void KickAction(Session.Client client)
|
void KickAction(Session.Client client)
|
||||||
{
|
{
|
||||||
@@ -133,7 +134,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
|
|
||||||
foreach (var t in teams)
|
foreach (var t in teams)
|
||||||
{
|
{
|
||||||
if (teams.Count() > 1)
|
if (teams.Count > 1)
|
||||||
{
|
{
|
||||||
var teamHeader = ScrollItemWidget.Setup(teamTemplate, () => false, () => { });
|
var teamHeader = ScrollItemWidget.Setup(teamTemplate, () => false, () => { });
|
||||||
var team = t.Key > 0
|
var team = t.Key > 0
|
||||||
|
|||||||
@@ -114,9 +114,10 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
.GroupBy(p => (world.LobbyInfo.ClientWithIndex(p.Player.ClientIndex) ?? new Session.Client()).Team)
|
.GroupBy(p => (world.LobbyInfo.ClientWithIndex(p.Player.ClientIndex) ?? new Session.Client()).Team)
|
||||||
.OrderBy(g => g.Key);
|
.OrderBy(g => g.Key);
|
||||||
|
|
||||||
var noTeams = teams.Count() == 1;
|
var teamsList = teams.ToList();
|
||||||
|
var noTeams = teamsList.Count == 1;
|
||||||
var totalPlayers = 0;
|
var totalPlayers = 0;
|
||||||
foreach (var t in teams)
|
foreach (var t in teamsList)
|
||||||
{
|
{
|
||||||
totalPlayers += t.Count();
|
totalPlayers += t.Count();
|
||||||
var label = noTeams ? TranslationProvider.GetString(Players) : t.Key > 0
|
var label = noTeams ? TranslationProvider.GetString(Players) : t.Key > 0
|
||||||
@@ -209,12 +210,12 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
if (e.Key >= Keycode.NUMBER_0 && e.Key <= Keycode.NUMBER_9)
|
if (e.Key >= Keycode.NUMBER_0 && e.Key <= Keycode.NUMBER_9)
|
||||||
{
|
{
|
||||||
var key = (int)e.Key - (int)Keycode.NUMBER_0;
|
var key = (int)e.Key - (int)Keycode.NUMBER_0;
|
||||||
var team = teams.Where(t => t.Key == key).SelectMany(s => s);
|
var team = teams.Where(t => t.Key == key).SelectMany(s => s).ToList();
|
||||||
if (!team.Any())
|
if (team.Count == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (e.Modifiers == Modifiers.Shift)
|
if (e.Modifiers == Modifiers.Shift)
|
||||||
team = team.Reverse();
|
team.Reverse();
|
||||||
|
|
||||||
selected = team.SkipWhile(t => t.Player != selected.Player).Skip(1).FirstOrDefault() ?? team.FirstOrDefault();
|
selected = team.SkipWhile(t => t.Player != selected.Player).Skip(1).FirstOrDefault() ?? team.FirstOrDefault();
|
||||||
selected.OnClick();
|
selected.OnClick();
|
||||||
|
|||||||
@@ -183,7 +183,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
selectedPackages = availablePackages.ToDictionary(x => x.Identifier, y => y.Required);
|
selectedPackages = availablePackages.ToDictionary(x => x.Identifier, y => y.Required);
|
||||||
|
|
||||||
// Ignore source if content is already installed
|
// Ignore source if content is already installed
|
||||||
if (availablePackages.Any())
|
if (availablePackages.Length != 0)
|
||||||
{
|
{
|
||||||
Game.RunAfterTick(() =>
|
Game.RunAfterTick(() =>
|
||||||
{
|
{
|
||||||
@@ -218,10 +218,10 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
|
|
||||||
var options = new Dictionary<string, IEnumerable<string>>();
|
var options = new Dictionary<string, IEnumerable<string>>();
|
||||||
|
|
||||||
if (gameSources.Any())
|
if (gameSources.Count != 0)
|
||||||
options.Add(TranslationProvider.GetString(GameSources), gameSources);
|
options.Add(TranslationProvider.GetString(GameSources), gameSources);
|
||||||
|
|
||||||
if (digitalInstalls.Any())
|
if (digitalInstalls.Count != 0)
|
||||||
options.Add(TranslationProvider.GetString(DigitalInstalls), digitalInstalls);
|
options.Add(TranslationProvider.GetString(DigitalInstalls), digitalInstalls);
|
||||||
|
|
||||||
Game.RunAfterTick(() =>
|
Game.RunAfterTick(() =>
|
||||||
|
|||||||
@@ -322,18 +322,19 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
if (!int.TryParse(mapFilter, out var playerCountFilter))
|
if (!int.TryParse(mapFilter, out var playerCountFilter))
|
||||||
playerCountFilter = -1;
|
playerCountFilter = -1;
|
||||||
|
|
||||||
var validMaps = tabMaps[tab]
|
var maps = tabMaps[tab]
|
||||||
.Where(m => category == null || m.Categories.Contains(category))
|
.Where(m => category == null || m.Categories.Contains(category))
|
||||||
.Where(m => mapFilter == null ||
|
.Where(m => mapFilter == null ||
|
||||||
(m.Title != null && m.Title.Contains(mapFilter, StringComparison.CurrentCultureIgnoreCase)) ||
|
(m.Title != null && m.Title.Contains(mapFilter, StringComparison.CurrentCultureIgnoreCase)) ||
|
||||||
(m.Author != null && m.Author.Contains(mapFilter, StringComparison.CurrentCultureIgnoreCase)) ||
|
(m.Author != null && m.Author.Contains(mapFilter, StringComparison.CurrentCultureIgnoreCase)) ||
|
||||||
m.PlayerCount == playerCountFilter);
|
m.PlayerCount == playerCountFilter);
|
||||||
|
|
||||||
IOrderedEnumerable<MapPreview> maps;
|
|
||||||
if (orderByFunc == null)
|
if (orderByFunc == null)
|
||||||
maps = validMaps.OrderBy(m => m.Title);
|
maps = maps.OrderBy(m => m.Title);
|
||||||
else
|
else
|
||||||
maps = validMaps.OrderBy(orderByFunc).ThenBy(m => m.Title);
|
maps = maps.OrderBy(orderByFunc).ThenBy(m => m.Title);
|
||||||
|
|
||||||
|
maps = maps.ToList();
|
||||||
|
|
||||||
scrollpanels[tab].RemoveChildren();
|
scrollpanels[tab].RemoveChildren();
|
||||||
foreach (var loop in maps)
|
foreach (var loop in maps)
|
||||||
|
|||||||
@@ -715,10 +715,11 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
|
|
||||||
var players = replay.GameInfo.Players
|
var players = replay.GameInfo.Players
|
||||||
.GroupBy(p => p.Team)
|
.GroupBy(p => p.Team)
|
||||||
.OrderBy(g => g.Key);
|
.OrderBy(g => g.Key)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
var teams = new Dictionary<string, IEnumerable<GameInformation.Player>>();
|
var teams = new Dictionary<string, IEnumerable<GameInformation.Player>>();
|
||||||
var noTeams = players.Count() == 1;
|
var noTeams = players.Count == 1;
|
||||||
foreach (var p in players)
|
foreach (var p in players)
|
||||||
{
|
{
|
||||||
var label = noTeams ? TranslationProvider.GetString(Players) : p.Key > 0
|
var label = noTeams ? TranslationProvider.GetString(Players) : p.Key > 0
|
||||||
|
|||||||
@@ -572,10 +572,11 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
var players = server.Clients
|
var players = server.Clients
|
||||||
.Where(c => !c.IsSpectator)
|
.Where(c => !c.IsSpectator)
|
||||||
.GroupBy(p => p.Team)
|
.GroupBy(p => p.Team)
|
||||||
.OrderBy(g => g.Key);
|
.OrderBy(g => g.Key)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
var teams = new Dictionary<string, IEnumerable<GameClient>>();
|
var teams = new Dictionary<string, IEnumerable<GameClient>>();
|
||||||
var noTeams = players.Count() == 1;
|
var noTeams = players.Count == 1;
|
||||||
foreach (var p in players)
|
foreach (var p in players)
|
||||||
{
|
{
|
||||||
var label = noTeams ? TranslationProvider.GetString(Players) : p.Key > 0
|
var label = noTeams ? TranslationProvider.GetString(Players) : p.Key > 0
|
||||||
|
|||||||
@@ -183,9 +183,10 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
{
|
{
|
||||||
var typesInGroup = hg.Value;
|
var typesInGroup = hg.Value;
|
||||||
var keysInGroup = modData.Hotkeys.Definitions
|
var keysInGroup = modData.Hotkeys.Definitions
|
||||||
.Where(hd => IsHotkeyVisibleInFilter(hd) && hd.Types.Overlaps(typesInGroup));
|
.Where(hd => IsHotkeyVisibleInFilter(hd) && hd.Types.Overlaps(typesInGroup))
|
||||||
|
.ToList();
|
||||||
|
|
||||||
if (!keysInGroup.Any())
|
if (keysInGroup.Count == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var header = headerTemplate.Clone();
|
var header = headerTemplate.Clone();
|
||||||
|
|||||||
@@ -102,14 +102,15 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
|
|
||||||
var queues = world.ActorsWithTrait<ProductionQueue>()
|
var queues = world.ActorsWithTrait<ProductionQueue>()
|
||||||
.Where(a => a.Actor.Owner == player)
|
.Where(a => a.Actor.Owner == player)
|
||||||
.Select((a, i) => new { a.Trait, i });
|
.Select(a => a.Trait)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
foreach (var queue in queues)
|
foreach (var queue in queues)
|
||||||
if (!clocks.ContainsKey(queue.Trait))
|
if (!clocks.ContainsKey(queue))
|
||||||
clocks.Add(queue.Trait, new Animation(world, ClockAnimation));
|
clocks.Add(queue, new Animation(world, ClockAnimation));
|
||||||
|
|
||||||
var currentItemsByItem = queues
|
var currentItemsByItem = queues
|
||||||
.Select(a => a.Trait.CurrentItem())
|
.Select(q => q.CurrentItem())
|
||||||
.Where(pi => pi != null)
|
.Where(pi => pi != null)
|
||||||
.GroupBy(pr => pr.Item)
|
.GroupBy(pr => pr.Item)
|
||||||
.OrderBy(g => g.First().Queue.Info.DisplayOrder)
|
.OrderBy(g => g.First().Queue.Info.DisplayOrder)
|
||||||
|
|||||||
@@ -183,9 +183,9 @@ namespace OpenRA.Mods.Common.Widgets
|
|||||||
|
|
||||||
public override void Draw()
|
public override void Draw()
|
||||||
{
|
{
|
||||||
var tabs = Groups[queueGroup].Tabs.Where(t => t.Queue.BuildableItems().Any());
|
var tabs = Groups[queueGroup].Tabs.Where(t => t.Queue.BuildableItems().Any()).ToList();
|
||||||
|
|
||||||
if (!tabs.Any())
|
if (tabs.Count == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var rb = RenderBounds;
|
var rb = RenderBounds;
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ namespace OpenRA.Mods.D2k.Activities
|
|||||||
swallow = self.Trait<AttackSwallow>();
|
swallow = self.Trait<AttackSwallow>();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AttackTargets(Actor self, IEnumerable<Actor> targets)
|
bool AttackTargets(Actor self, IReadOnlyCollection<Actor> targets)
|
||||||
{
|
{
|
||||||
var targetLocation = target.Actor.Location;
|
var targetLocation = target.Actor.Location;
|
||||||
foreach (var t in targets)
|
foreach (var t in targets)
|
||||||
@@ -129,9 +129,10 @@ namespace OpenRA.Mods.D2k.Activities
|
|||||||
}
|
}
|
||||||
|
|
||||||
var targets = self.World.ActorMap.GetActorsAt(targetLocation)
|
var targets = self.World.ActorMap.GetActorsAt(targetLocation)
|
||||||
.Where(t => !t.Equals(self) && weapon.IsValidAgainst(t, self));
|
.Where(t => !t.Equals(self) && weapon.IsValidAgainst(t, self))
|
||||||
|
.ToList();
|
||||||
|
|
||||||
if (!targets.Any())
|
if (targets.Count == 0)
|
||||||
{
|
{
|
||||||
RevokeCondition(self);
|
RevokeCondition(self);
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -509,17 +509,12 @@ namespace OpenRA.Mods.D2k.UtilityCommands
|
|||||||
|
|
||||||
// HACK: The arrakis.yaml tileset file seems to be missing some tiles, so just get a replacement for them
|
// HACK: The arrakis.yaml tileset file seems to be missing some tiles, so just get a replacement for them
|
||||||
// Also used for duplicate tiles that are taken from only tileset
|
// Also used for duplicate tiles that are taken from only tileset
|
||||||
if (template == null)
|
// Just get a template that contains a tile with the same ID as requested
|
||||||
|
template ??= terrainInfo.Templates.FirstOrDefault(t =>
|
||||||
{
|
{
|
||||||
// Just get a template that contains a tile with the same ID as requested
|
var templateInfo = (DefaultTerrainTemplateInfo)t.Value;
|
||||||
var templates = terrainInfo.Templates.Where(t =>
|
return templateInfo.Frames != null && templateInfo.Frames.Contains(tileIndex);
|
||||||
{
|
}).Value;
|
||||||
var templateInfo = (DefaultTerrainTemplateInfo)t.Value;
|
|
||||||
return templateInfo.Frames != null && templateInfo.Frames.Contains(tileIndex);
|
|
||||||
});
|
|
||||||
if (templates.Any())
|
|
||||||
template = templates.First().Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (template == null)
|
if (template == null)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user