Merge pull request #12730 from abcdefg30/aircraftCrate
Fix GiveUnitCrateAction and SpawnMPUnits being limited to MobileInfo
This commit is contained in:
@@ -265,7 +265,11 @@ namespace OpenRA.Traits
|
|||||||
[RequireExplicitImplementation]
|
[RequireExplicitImplementation]
|
||||||
public interface ISelectionBar { float GetValue(); Color GetColor(); bool DisplayWhenEmpty { get; } }
|
public interface ISelectionBar { float GetValue(); Color GetColor(); bool DisplayWhenEmpty { get; } }
|
||||||
|
|
||||||
public interface IPositionableInfo : ITraitInfoInterface { }
|
public interface IPositionableInfo : IOccupySpaceInfo
|
||||||
|
{
|
||||||
|
bool CanEnterCell(World world, Actor self, CPos cell, Actor ignoreActor = null, bool checkTransientActors = true);
|
||||||
|
}
|
||||||
|
|
||||||
public interface IPositionable : IOccupySpace
|
public interface IPositionable : IOccupySpace
|
||||||
{
|
{
|
||||||
bool IsLeavingCell(CPos location, SubCell subCell = SubCell.Any);
|
bool IsLeavingCell(CPos location, SubCell subCell = SubCell.Any);
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ using OpenRA.Traits;
|
|||||||
|
|
||||||
namespace OpenRA.Mods.Common.Traits
|
namespace OpenRA.Mods.Common.Traits
|
||||||
{
|
{
|
||||||
public class AircraftInfo : ITraitInfo, IPositionableInfo, IFacingInfo, IOccupySpaceInfo, IMoveInfo, ICruiseAltitudeInfo,
|
public class AircraftInfo : ITraitInfo, IPositionableInfo, IFacingInfo, IMoveInfo, ICruiseAltitudeInfo,
|
||||||
UsesInit<LocationInit>, UsesInit<FacingInit>
|
UsesInit<LocationInit>, UsesInit<FacingInit>
|
||||||
{
|
{
|
||||||
public readonly WDist CruiseAltitude = new WDist(1280);
|
public readonly WDist CruiseAltitude = new WDist(1280);
|
||||||
@@ -94,6 +94,25 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
|
|
||||||
public IReadOnlyDictionary<CPos, SubCell> OccupiedCells(ActorInfo info, CPos location, SubCell subCell = SubCell.Any) { return new ReadOnlyDictionary<CPos, SubCell>(); }
|
public IReadOnlyDictionary<CPos, SubCell> OccupiedCells(ActorInfo info, CPos location, SubCell subCell = SubCell.Any) { return new ReadOnlyDictionary<CPos, SubCell>(); }
|
||||||
bool IOccupySpaceInfo.SharesCell { get { return false; } }
|
bool IOccupySpaceInfo.SharesCell { get { return false; } }
|
||||||
|
|
||||||
|
// Used to determine if an aircraft can spawn landed
|
||||||
|
public bool CanEnterCell(World world, Actor self, CPos cell, Actor ignoreActor = null, bool checkTransientActors = true)
|
||||||
|
{
|
||||||
|
if (!world.Map.Contains(cell))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var type = world.Map.GetTerrainInfo(cell).Type;
|
||||||
|
if (!LandableTerrainTypes.Contains(type))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (world.WorldActor.Trait<BuildingInfluence>().GetBuildingAt(cell) != null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!checkTransientActors)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return !world.ActorMap.GetActorsAt(cell).Any(x => x != ignoreActor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Aircraft : ITick, ISync, IFacing, IPositionable, IMove, IIssueOrder, IResolveOrder, IOrderVoice, IDeathActorInitModifier,
|
public class Aircraft : ITick, ISync, IFacing, IPositionable, IMove, IIssueOrder, IResolveOrder, IOrderVoice, IDeathActorInitModifier,
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ using OpenRA.Traits;
|
|||||||
|
|
||||||
namespace OpenRA.Mods.Common.Traits
|
namespace OpenRA.Mods.Common.Traits
|
||||||
{
|
{
|
||||||
class CrateInfo : ITraitInfo, IPositionableInfo, IOccupySpaceInfo, Requires<RenderSpritesInfo>
|
class CrateInfo : ITraitInfo, IPositionableInfo, Requires<RenderSpritesInfo>
|
||||||
{
|
{
|
||||||
[Desc("Length of time (in seconds) until the crate gets removed automatically. " +
|
[Desc("Length of time (in seconds) until the crate gets removed automatically. " +
|
||||||
"A value of zero disables auto-removal.")]
|
"A value of zero disables auto-removal.")]
|
||||||
@@ -38,6 +38,30 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool IOccupySpaceInfo.SharesCell { get { return false; } }
|
bool IOccupySpaceInfo.SharesCell { get { return false; } }
|
||||||
|
|
||||||
|
public bool CanEnterCell(World world, Actor self, CPos cell, Actor ignoreActor = null, bool checkTransientActors = true)
|
||||||
|
{
|
||||||
|
return GetAvailableSubCell(world, cell, ignoreActor, checkTransientActors) != SubCell.Invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SubCell GetAvailableSubCell(World world, CPos cell, Actor ignoreActor = null, bool checkTransientActors = true)
|
||||||
|
{
|
||||||
|
if (!world.Map.Contains(cell))
|
||||||
|
return SubCell.Invalid;
|
||||||
|
|
||||||
|
var type = world.Map.GetTerrainInfo(cell).Type;
|
||||||
|
if (!TerrainTypes.Contains(type))
|
||||||
|
return SubCell.Invalid;
|
||||||
|
|
||||||
|
if (world.WorldActor.Trait<BuildingInfluence>().GetBuildingAt(cell) != null)
|
||||||
|
return SubCell.Invalid;
|
||||||
|
|
||||||
|
if (!checkTransientActors)
|
||||||
|
return SubCell.FullCell;
|
||||||
|
|
||||||
|
return !world.ActorMap.GetActorsAt(cell).Any(x => x != ignoreActor)
|
||||||
|
? SubCell.FullCell : SubCell.Invalid;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Crate : ITick, IPositionable, ICrushable, ISync,
|
class Crate : ITick, IPositionable, ICrushable, ISync,
|
||||||
@@ -174,22 +198,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
public SubCell GetValidSubCell(SubCell preferred = SubCell.Any) { return SubCell.FullCell; }
|
public SubCell GetValidSubCell(SubCell preferred = SubCell.Any) { return SubCell.FullCell; }
|
||||||
public SubCell GetAvailableSubCell(CPos cell, SubCell preferredSubCell = SubCell.Any, Actor ignoreActor = null, bool checkTransientActors = true)
|
public SubCell GetAvailableSubCell(CPos cell, SubCell preferredSubCell = SubCell.Any, Actor ignoreActor = null, bool checkTransientActors = true)
|
||||||
{
|
{
|
||||||
if (!self.World.Map.Contains(cell))
|
return info.GetAvailableSubCell(self.World, cell, ignoreActor, checkTransientActors);
|
||||||
return SubCell.Invalid;
|
|
||||||
|
|
||||||
var type = self.World.Map.GetTerrainInfo(cell).Type;
|
|
||||||
if (!info.TerrainTypes.Contains(type))
|
|
||||||
return SubCell.Invalid;
|
|
||||||
|
|
||||||
if (self.World.WorldActor.Trait<BuildingInfluence>().GetBuildingAt(cell) != null)
|
|
||||||
return SubCell.Invalid;
|
|
||||||
|
|
||||||
if (!checkTransientActors)
|
|
||||||
return SubCell.FullCell;
|
|
||||||
|
|
||||||
return !self.World.ActorMap.GetActorsAt(cell)
|
|
||||||
.Any(x => x != ignoreActor)
|
|
||||||
? SubCell.FullCell : SubCell.Invalid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool CanEnterCell(CPos a, Actor ignoreActor = null, bool checkTransientActors = true)
|
public bool CanEnterCell(CPos a, Actor ignoreActor = null, bool checkTransientActors = true)
|
||||||
|
|||||||
@@ -97,11 +97,11 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
|
|
||||||
IEnumerable<CPos> GetSuitableCells(CPos near, string unitName)
|
IEnumerable<CPos> GetSuitableCells(CPos near, string unitName)
|
||||||
{
|
{
|
||||||
var mi = self.World.Map.Rules.Actors[unitName].TraitInfo<MobileInfo>();
|
var ip = self.World.Map.Rules.Actors[unitName].TraitInfo<IPositionableInfo>();
|
||||||
|
|
||||||
for (var i = -1; i < 2; i++)
|
for (var i = -1; i < 2; i++)
|
||||||
for (var j = -1; j < 2; j++)
|
for (var j = -1; j < 2; j++)
|
||||||
if (mi.CanEnterCell(self.World, self, near + new CVec(i, j)))
|
if (ip.CanEnterCell(self.World, self, near + new CVec(i, j)))
|
||||||
yield return near + new CVec(i, j);
|
yield return near + new CVec(i, j);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Desc("Unit is able to move.")]
|
[Desc("Unit is able to move.")]
|
||||||
public class MobileInfo : ConditionalTraitInfo, IMoveInfo, IPositionableInfo, IOccupySpaceInfo, IFacingInfo,
|
public class MobileInfo : ConditionalTraitInfo, IMoveInfo, IPositionableInfo, IFacingInfo,
|
||||||
UsesInit<FacingInit>, UsesInit<LocationInit>, UsesInit<SubCellInit>
|
UsesInit<FacingInit>, UsesInit<LocationInit>, UsesInit<SubCellInit>
|
||||||
{
|
{
|
||||||
[FieldLoader.LoadUsing("LoadSpeeds", true)]
|
[FieldLoader.LoadUsing("LoadSpeeds", true)]
|
||||||
@@ -263,11 +263,12 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
(current, terrainInfo) => unchecked(current * 31 + terrainInfo.Cost));
|
(current, terrainInfo) => unchecked(current * 31 + terrainInfo.Cost));
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool CanEnterCell(World world, Actor self, CPos cell, Actor ignoreActor = null, CellConditions check = CellConditions.All)
|
public bool CanEnterCell(World world, Actor self, CPos cell, Actor ignoreActor = null, bool checkTransientActors = true)
|
||||||
{
|
{
|
||||||
if (MovementCostForCell(world, cell) == int.MaxValue)
|
if (MovementCostForCell(world, cell) == int.MaxValue)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
var check = checkTransientActors ? CellConditions.All : CellConditions.BlockedByMovers;
|
||||||
return CanMoveFreelyInto(world, self, cell, ignoreActor, check);
|
return CanMoveFreelyInto(world, self, cell, ignoreActor, check);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -380,7 +381,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
}
|
}
|
||||||
|
|
||||||
public class Mobile : ConditionalTrait<MobileInfo>, INotifyCreated, IIssueOrder, IResolveOrder, IOrderVoice, IPositionable, IMove,
|
public class Mobile : ConditionalTrait<MobileInfo>, INotifyCreated, IIssueOrder, IResolveOrder, IOrderVoice, IPositionable, IMove,
|
||||||
IFacing, ISync, IDeathActorInitModifier, INotifyAddedToWorld, INotifyRemovedFromWorld, INotifyBlockingMove, IActorPreviewInitModifier
|
IFacing, IDeathActorInitModifier, INotifyAddedToWorld, INotifyRemovedFromWorld, INotifyBlockingMove, IActorPreviewInitModifier
|
||||||
{
|
{
|
||||||
const int AverageTicksBeforePathing = 5;
|
const int AverageTicksBeforePathing = 5;
|
||||||
const int SpreadTicksBeforePathing = 5;
|
const int SpreadTicksBeforePathing = 5;
|
||||||
@@ -699,7 +700,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
|
|
||||||
public bool CanEnterCell(CPos cell, Actor ignoreActor = null, bool checkTransientActors = true)
|
public bool CanEnterCell(CPos cell, Actor ignoreActor = null, bool checkTransientActors = true)
|
||||||
{
|
{
|
||||||
return Info.CanEnterCell(self.World, self, cell, ignoreActor, checkTransientActors ? CellConditions.All : CellConditions.BlockedByMovers);
|
return Info.CanEnterCell(self.World, self, cell, ignoreActor, checkTransientActors);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool CanMoveFreelyInto(CPos cell, Actor ignoreActor = null, bool checkTransientActors = true)
|
public bool CanMoveFreelyInto(CPos cell, Actor ignoreActor = null, bool checkTransientActors = true)
|
||||||
|
|||||||
@@ -86,8 +86,9 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
|
|
||||||
foreach (var s in unitGroup.SupportActors)
|
foreach (var s in unitGroup.SupportActors)
|
||||||
{
|
{
|
||||||
var mi = w.Map.Rules.Actors[s.ToLowerInvariant()].TraitInfo<MobileInfo>();
|
var actorRules = w.Map.Rules.Actors[s.ToLowerInvariant()];
|
||||||
var validCells = supportSpawnCells.Where(c => mi.CanEnterCell(w, null, c));
|
var ip = actorRules.TraitInfo<IPositionableInfo>();
|
||||||
|
var validCells = supportSpawnCells.Where(c => ip.CanEnterCell(w, null, c));
|
||||||
if (!validCells.Any())
|
if (!validCells.Any())
|
||||||
{
|
{
|
||||||
Log.Write("debug", "No cells available to spawn starting unit {0} for player {1}".F(s, p));
|
Log.Write("debug", "No cells available to spawn starting unit {0} for player {1}".F(s, p));
|
||||||
@@ -95,7 +96,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
}
|
}
|
||||||
|
|
||||||
var cell = validCells.Random(w.SharedRandom);
|
var cell = validCells.Random(w.SharedRandom);
|
||||||
var subCell = mi.SharesCell ? w.ActorMap.FreeSubCell(cell) : 0;
|
var subCell = ip.SharesCell ? w.ActorMap.FreeSubCell(cell) : 0;
|
||||||
|
|
||||||
w.CreateActor(s.ToLowerInvariant(), new TypeDictionary
|
w.CreateActor(s.ToLowerInvariant(), new TypeDictionary
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user