moved helper functions out of Game, into WorldUtils
This commit is contained in:
@@ -89,7 +89,7 @@ namespace OpenRa
|
||||
return null;
|
||||
|
||||
var loc = mi.Location + Game.viewport.Location;
|
||||
var underCursor = Game.FindUnits(loc, loc).FirstOrDefault();
|
||||
var underCursor = Game.world.FindUnits(loc, loc).FirstOrDefault();
|
||||
|
||||
if (underCursor != null && !underCursor.traits.Contains<Selectable>())
|
||||
underCursor = null;
|
||||
|
||||
@@ -15,8 +15,8 @@ namespace OpenRa
|
||||
{
|
||||
var targetTile = ((1f / Game.CellSize) * loc.ToFloat2()).ToInt2();
|
||||
|
||||
var isWater = Game.IsWater(targetTile);
|
||||
var hitWater = Game.IsCellBuildable(targetTile, UnitMovementType.Float);
|
||||
var isWater = Game.world.IsWater(targetTile);
|
||||
var hitWater = Game.world.IsCellBuildable(targetTile, UnitMovementType.Float);
|
||||
|
||||
if (warhead.Explosion != 0)
|
||||
Game.world.AddFrameEndTask(
|
||||
@@ -31,7 +31,7 @@ namespace OpenRa
|
||||
if (warhead.Ore) Ore.Destroy(targetTile.X, targetTile.Y);
|
||||
|
||||
var maxSpread = GetMaximumSpread(weapon, warhead);
|
||||
var hitActors = Game.FindUnitsInCircle(loc, maxSpread);
|
||||
var hitActors = Game.world.FindUnitsInCircle(loc, maxSpread);
|
||||
|
||||
foreach (var victim in hitActors)
|
||||
victim.InflictDamage(firedBy, (int)GetDamageToInflict(victim, loc, weapon, warhead), warhead);
|
||||
|
||||
@@ -95,7 +95,7 @@ namespace OpenRa
|
||||
{
|
||||
if (orderGenerator is UnitOrderGenerator)
|
||||
{
|
||||
var newSelection = Game.SelectActorsInBox(Game.CellSize * dragStart, Game.CellSize * xy);
|
||||
var newSelection = Game.world.SelectActorsInBox(Game.CellSize * dragStart, Game.CellSize * xy);
|
||||
CombineSelection(newSelection, mi.Modifiers.HasModifier(Modifiers.Shift), dragStart == xy);
|
||||
}
|
||||
|
||||
|
||||
@@ -208,130 +208,9 @@ namespace OpenRa
|
||||
renderer.PaletteTexture = palette.Texture;
|
||||
}
|
||||
|
||||
public static bool IsCellBuildable(int2 a, UnitMovementType umt)
|
||||
{
|
||||
return IsCellBuildable(a, umt, null);
|
||||
}
|
||||
|
||||
public static bool IsCellBuildable(int2 a, UnitMovementType umt, Actor toIgnore)
|
||||
{
|
||||
if (Game.world.BuildingInfluence.GetBuildingAt(a) != null) return false;
|
||||
if (Game.world.UnitInfluence.GetUnitsAt(a).Any(b => b != toIgnore)) return false;
|
||||
|
||||
return Game.world.Map.IsInMap(a.X, a.Y) &&
|
||||
TerrainCosts.Cost(umt,
|
||||
Game.world.TileSet.GetWalkability(Game.world.Map.MapTiles[a.X, a.Y])) < double.PositiveInfinity;
|
||||
}
|
||||
|
||||
public static bool IsActorCrushableByActor(Actor a, Actor b)
|
||||
{
|
||||
return IsActorCrushableByMovementType(a, b.traits.GetOrDefault<IMovement>().GetMovementType());
|
||||
}
|
||||
|
||||
public static bool IsActorPathableToCrush(Actor a, UnitMovementType umt)
|
||||
{
|
||||
return a != null &&
|
||||
a.traits.WithInterface<ICrushable>()
|
||||
.Any(c => c.IsPathableCrush(umt, a.Owner));
|
||||
}
|
||||
|
||||
public static bool IsActorCrushableByMovementType(Actor a, UnitMovementType umt)
|
||||
{
|
||||
return a != null &&
|
||||
a.traits.WithInterface<ICrushable>()
|
||||
.Any(c => c.IsCrushableBy(umt, a.Owner));
|
||||
}
|
||||
|
||||
public static bool IsWater(int2 a)
|
||||
{
|
||||
return Game.world.Map.IsInMap(a.X, a.Y) &&
|
||||
TerrainCosts.Cost(UnitMovementType.Float,
|
||||
Game.world.TileSet.GetWalkability(Game.world.Map.MapTiles[a.X, a.Y])) < double.PositiveInfinity;
|
||||
}
|
||||
|
||||
public static IEnumerable<Actor> FindUnits(float2 a, float2 b)
|
||||
{
|
||||
var min = float2.Min(a, b);
|
||||
var max = float2.Max(a, b);
|
||||
|
||||
var rect = new RectangleF(min.X, min.Y, max.X - min.X, max.Y - min.Y);
|
||||
|
||||
return world.Actors
|
||||
.Where(x => x.GetBounds(true).IntersectsWith(rect));
|
||||
}
|
||||
|
||||
public static IEnumerable<Actor> FindUnitsInCircle(float2 a, float r)
|
||||
{
|
||||
var min = a - new float2(r, r);
|
||||
var max = a + new float2(r, r);
|
||||
|
||||
var rect = new RectangleF(min.X, min.Y, max.X - min.X, max.Y - min.Y);
|
||||
|
||||
var inBox = world.Actors.Where(x => x.GetBounds(false).IntersectsWith(rect));
|
||||
|
||||
return inBox.Where(x => (x.CenterLocation - a).LengthSquared < r * r);
|
||||
}
|
||||
|
||||
public static IEnumerable<int2> FindTilesInCircle(int2 a, int r)
|
||||
{
|
||||
var min = a - new int2(r, r);
|
||||
var max = a + new int2(r, r);
|
||||
if (min.X < 0) min.X = 0;
|
||||
if (min.Y < 0) min.Y = 0;
|
||||
if (max.X > 127) max.X = 127;
|
||||
if (max.Y > 127) max.Y = 127;
|
||||
|
||||
for (var j = min.Y; j <= max.Y; j++)
|
||||
for (var i = min.X; i <= max.X; i++)
|
||||
if (r * r >= (new int2(i, j) - a).LengthSquared)
|
||||
yield return new int2(i, j);
|
||||
}
|
||||
|
||||
public static IEnumerable<Actor> SelectActorsInBox(float2 a, float2 b)
|
||||
{
|
||||
return FindUnits(a, b)
|
||||
.Where( x => x.traits.Contains<Selectable>() )
|
||||
.GroupBy(x => (x.Owner == LocalPlayer) ? x.Info.Traits.Get<SelectableInfo>().Priority : 0)
|
||||
.OrderByDescending(g => g.Key)
|
||||
.Select( g => g.AsEnumerable() )
|
||||
.DefaultIfEmpty( new Actor[] {} )
|
||||
.FirstOrDefault();
|
||||
}
|
||||
|
||||
public static Random SharedRandom = new Random(0); /* for things that require sync */
|
||||
public static Random CosmeticRandom = new Random(); /* for things that are just fluff */
|
||||
|
||||
public static bool CanPlaceBuilding(string name, BuildingInfo building, int2 xy, Actor toIgnore, bool adjust)
|
||||
{
|
||||
return !Footprint.Tiles(name, building, xy, adjust).Any(
|
||||
t => !Game.world.Map.IsInMap(t.X, t.Y) || Game.world.Map.ContainsResource(t) || !Game.IsCellBuildable(t,
|
||||
building.WaterBound ? UnitMovementType.Float : UnitMovementType.Wheel,
|
||||
toIgnore));
|
||||
}
|
||||
|
||||
public static bool IsCloseEnoughToBase(Player p, string buildingName, BuildingInfo bi, int2 position)
|
||||
{
|
||||
var maxDistance = bi.Adjacent + 1;
|
||||
|
||||
var search = new PathSearch()
|
||||
{
|
||||
heuristic = loc =>
|
||||
{
|
||||
var b = Game.world.BuildingInfluence.GetBuildingAt(loc);
|
||||
if (b != null && b.Owner == p && b.Info.Traits.Get<BuildingInfo>().BaseNormal) return 0;
|
||||
if ((loc - position).Length > maxDistance)
|
||||
return float.PositiveInfinity; /* not quite right */
|
||||
return 1;
|
||||
},
|
||||
checkForBlocked = false,
|
||||
ignoreTerrain = true,
|
||||
};
|
||||
|
||||
foreach (var t in Footprint.Tiles(buildingName, bi, position)) search.AddInitialCell(t);
|
||||
|
||||
return Game.world.PathFinder.FindPath(search).Count != 0;
|
||||
}
|
||||
|
||||
public static void SyncLobbyInfo(string data)
|
||||
{
|
||||
var session = new Session();
|
||||
|
||||
@@ -102,7 +102,7 @@ namespace OpenRa.Graphics
|
||||
lineRenderer.DrawLine(a + b + c, a + c, Color.White, Color.White);
|
||||
lineRenderer.DrawLine(a, a + c, Color.White, Color.White);
|
||||
|
||||
foreach (var u in Game.SelectActorsInBox(selbox.Value.First, selbox.Value.Second))
|
||||
foreach (var u in Game.world.SelectActorsInBox(selbox.Value.First, selbox.Value.Second))
|
||||
DrawSelectionBox(u, Color.Yellow, false);
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<ProjectGuid>{0DFB103F-2962-400F-8C6D-E2C28CCBA633}</ProjectGuid>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>OpenRa.Game</RootNamespace>
|
||||
<RootNamespace>OpenRa</RootNamespace>
|
||||
<AssemblyName>OpenRa.Game</AssemblyName>
|
||||
<FileUpgradeFlags>
|
||||
</FileUpgradeFlags>
|
||||
@@ -274,6 +274,7 @@
|
||||
<Compile Include="UnitInfluenceMap.cs" />
|
||||
<Compile Include="Orders\UnitOrderGenerator.cs" />
|
||||
<Compile Include="World.cs" />
|
||||
<Compile Include="WorldUtils.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\OpenRa.FileFormats\OpenRa.FileFormats.csproj">
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace OpenRa.Orders
|
||||
if (mi.Button == MouseButton.Left)
|
||||
{
|
||||
var loc = mi.Location + Game.viewport.Location;
|
||||
var underCursor = Game.FindUnits(loc, loc)
|
||||
var underCursor = Game.world.FindUnits(loc, loc)
|
||||
.Where(a => a.Owner == Game.LocalPlayer
|
||||
&& a.traits.Contains<Chronoshiftable>()
|
||||
&& a.traits.Contains<Selectable>()).FirstOrDefault();
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace OpenRa.Orders
|
||||
if (mi.Button == MouseButton.Left)
|
||||
{
|
||||
var loc = mi.Location + Game.viewport.Location;
|
||||
var underCursor = Game.FindUnits(loc, loc)
|
||||
var underCursor = Game.world.FindUnits(loc, loc)
|
||||
.Where(a => a.Owner == Game.LocalPlayer
|
||||
&& a.traits.Contains<IronCurtainable>()
|
||||
&& a.traits.Contains<Selectable>()).FirstOrDefault();
|
||||
|
||||
@@ -28,8 +28,8 @@ namespace OpenRa.Orders
|
||||
{
|
||||
if (mi.Button == MouseButton.Left)
|
||||
{
|
||||
if (!Game.CanPlaceBuilding( Building, BuildingInfo, xy, null, true)
|
||||
|| !Game.IsCloseEnoughToBase(Producer.Owner, Building, BuildingInfo, xy))
|
||||
if (!Game.world.CanPlaceBuilding( Building, BuildingInfo, xy, null, true)
|
||||
|| !Game.world.IsCloseEnoughToBase(Producer.Owner, Building, BuildingInfo, xy))
|
||||
{
|
||||
Sound.Play("nodeply1.aud");
|
||||
yield break;
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace OpenRa.Orders
|
||||
if (mi.Button == MouseButton.Left)
|
||||
{
|
||||
var loc = mi.Location + Game.viewport.Location;
|
||||
var underCursor = Game.FindUnits(loc, loc)
|
||||
var underCursor = Game.world.FindUnits(loc, loc)
|
||||
.Where(a => a.Owner == Game.LocalPlayer
|
||||
&& a.traits.Contains<Building>()
|
||||
&& a.traits.Contains<Selectable>()).FirstOrDefault();
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace OpenRa.Orders
|
||||
if (mi.Button == MouseButton.Left)
|
||||
{
|
||||
var loc = mi.Location + Game.viewport.Location;
|
||||
var underCursor = Game.FindUnits(loc, loc)
|
||||
var underCursor = Game.world.FindUnits(loc, loc)
|
||||
.Where(a => a.Owner == Game.LocalPlayer
|
||||
&& a.traits.Contains<Building>()
|
||||
&& a.traits.Contains<Selectable>()).FirstOrDefault();
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace OpenRa.Orders
|
||||
if (mi.Button == MouseButton.Left)
|
||||
{
|
||||
var loc = mi.Location + Game.viewport.Location;
|
||||
var underCursor = Game.FindUnits(loc, loc)
|
||||
var underCursor = Game.world.FindUnits(loc, loc)
|
||||
.Where(a => a.Owner == Game.LocalPlayer
|
||||
&& a.traits.Contains<Building>()
|
||||
&& a.traits.Contains<Selectable>()).FirstOrDefault();
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace OpenRa.Orders
|
||||
.FirstOrDefault(a => a != null);
|
||||
|
||||
return c ??
|
||||
(Game.SelectActorsInBox(Game.CellSize * p,
|
||||
(Game.world.SelectActorsInBox(Game.CellSize * p,
|
||||
Game.CellSize * p).Any()
|
||||
? Cursor.Select : Cursor.Default);
|
||||
}
|
||||
@@ -70,7 +70,7 @@ namespace OpenRa.Orders
|
||||
return Cursor.MoveBlocked;
|
||||
case "DeployMcv":
|
||||
var factBuildingInfo = Rules.ActorInfo["fact"].Traits.Get<BuildingInfo>();
|
||||
if (Game.CanPlaceBuilding("fact", factBuildingInfo, a.Location - new int2(1, 1), a, false))
|
||||
if (Game.world.CanPlaceBuilding("fact", factBuildingInfo, a.Location - new int2(1, 1), a, false))
|
||||
return Cursor.Deploy;
|
||||
else
|
||||
return Cursor.DeployBlocked;
|
||||
|
||||
@@ -40,8 +40,8 @@ namespace OpenRa
|
||||
{
|
||||
using( new PerfSample( "find_unit_path_multiple_src" ) )
|
||||
{
|
||||
var tilesInRange = Game.FindTilesInCircle(target, range)
|
||||
.Where( t => Game.IsCellBuildable( t, umt ) );
|
||||
var tilesInRange = Game.world.FindTilesInCircle(target, range)
|
||||
.Where( t => Game.world.IsCellBuildable( t, umt ) );
|
||||
|
||||
var path = FindPath( PathSearch.FromPoints( tilesInRange, src, umt, false ).WithCustomBlocker(AvoidUnitsNear(src, 4)));
|
||||
path.Reverse();
|
||||
|
||||
@@ -64,7 +64,7 @@ namespace OpenRa
|
||||
}
|
||||
|
||||
// Replicate real-ra behavior of not being able to enter a cell if there is a mixture of crushable and uncrushable units
|
||||
if (checkForBlocked && (Game.world.UnitInfluence.GetUnitsAt(newHere).Any(a => !Game.IsActorPathableToCrush(a, umt))))
|
||||
if (checkForBlocked && (Game.world.UnitInfluence.GetUnitsAt(newHere).Any(a => !Game.world.IsActorPathableToCrush(a, umt))))
|
||||
continue;
|
||||
|
||||
if (customBlock != null && customBlock(newHere))
|
||||
|
||||
@@ -81,7 +81,7 @@ namespace OpenRa
|
||||
|
||||
public void Explore(Actor a)
|
||||
{
|
||||
foreach (var t in Game.FindTilesInCircle(
|
||||
foreach (var t in Game.world.FindTilesInCircle(
|
||||
(1f / Game.CellSize * a.CenterLocation).ToInt2(),
|
||||
a.Info.Traits.Get<OwnedActorInfo>().Sight))
|
||||
{
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace OpenRa.Traits.Activities
|
||||
if (unit.Altitude == 0)
|
||||
return NextActivity;
|
||||
|
||||
if (requireSpace && !Game.IsCellBuildable(self.Location, UnitMovementType.Foot))
|
||||
if (requireSpace && !Game.world.IsCellBuildable(self.Location, UnitMovementType.Foot))
|
||||
return this; // fail to land if no space
|
||||
|
||||
--unit.Altitude;
|
||||
|
||||
@@ -63,7 +63,7 @@ namespace OpenRa.Traits.Activities
|
||||
|
||||
// Cannot enter a cell if any unit inside is uncrushable
|
||||
// This will need to be updated for multiple-infantry-in-a-cell
|
||||
return (!Game.world.UnitInfluence.GetUnitsAt(c).Any(a => a != self && !Game.IsActorCrushableByActor(a, self)));
|
||||
return (!Game.world.UnitInfluence.GetUnitsAt(c).Any(a => a != self && !Game.world.IsActorCrushableByActor(a, self)));
|
||||
}
|
||||
|
||||
public IActivity Tick( Actor self )
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace OpenRa.Traits.Activities
|
||||
{
|
||||
if (!limitedAmmo.GiveAmmo()) return NextActivity;
|
||||
|
||||
var hostBuilding = Game.FindUnits(self.CenterLocation, self.CenterLocation)
|
||||
var hostBuilding = Game.world.FindUnits(self.CenterLocation, self.CenterLocation)
|
||||
.FirstOrDefault(a => a.traits.Contains<RenderBuilding>());
|
||||
|
||||
if (hostBuilding != null)
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace OpenRa.Traits.Activities
|
||||
if (self.Health == hp)
|
||||
return NextActivity;
|
||||
|
||||
var hostBuilding = Game.FindUnits(self.CenterLocation, self.CenterLocation)
|
||||
var hostBuilding = Game.world.FindUnits(self.CenterLocation, self.CenterLocation)
|
||||
.FirstOrDefault(a => a.traits.Contains<RenderBuilding>());
|
||||
|
||||
if (hostBuilding != null)
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace OpenRa.Traits.Activities
|
||||
for (var i = -1; i < 2; i++)
|
||||
for (var j = -1; j < 2; j++)
|
||||
if ((i != 0 || j != 0) &&
|
||||
Game.IsCellBuildable(self.Location + new int2(i, j),
|
||||
Game.world.IsCellBuildable(self.Location + new int2(i, j),
|
||||
UnitMovementType.Foot))
|
||||
return self.Location + new int2(i, j);
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace OpenRa.Traits
|
||||
|
||||
Actor ChooseTarget(Actor self, float range)
|
||||
{
|
||||
var inRange = Game.FindUnitsInCircle(self.CenterLocation, Game.CellSize * range);
|
||||
var inRange = Game.world.FindUnitsInCircle(self.CenterLocation, Game.CellSize * range);
|
||||
|
||||
return inRange
|
||||
.Where(a => a.Owner == self.Owner && a != self) /* todo: one day deal with friendly players */
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace OpenRa.Traits
|
||||
|
||||
Actor ChooseTarget(Actor self, float range)
|
||||
{
|
||||
var inRange = Game.FindUnitsInCircle(self.CenterLocation, Game.CellSize * range);
|
||||
var inRange = Game.world.FindUnitsInCircle(self.CenterLocation, Game.CellSize * range);
|
||||
|
||||
return inRange
|
||||
.Where(a => a.Owner != null && a.Owner != self.Owner) /* todo: one day deal with friendly players */
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace OpenRa.Traits
|
||||
{
|
||||
// force-move
|
||||
if (!mi.Modifiers.HasModifier(Modifiers.Alt)) return null;
|
||||
if (!Game.IsActorCrushableByActor(underCursor, self)) return null;
|
||||
if (!Game.world.IsActorCrushableByActor(underCursor, self)) return null;
|
||||
}
|
||||
|
||||
return new Order("Move", self, null, xy, null);
|
||||
@@ -57,7 +57,7 @@ namespace OpenRa.Traits
|
||||
{
|
||||
if (actor == self) continue;
|
||||
|
||||
if (!Game.IsActorCrushableByActor(actor, self))
|
||||
if (!Game.world.IsActorCrushableByActor(actor, self))
|
||||
{
|
||||
crushable = false;
|
||||
break;
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace OpenRa.Traits
|
||||
// Gap Generator building; powered down
|
||||
return (self.traits.Contains<Building>() && self.traits.Get<Building>().Disabled)
|
||||
? new int2[] {}
|
||||
: Game.FindTilesInCircle(self.Location, range);
|
||||
: Game.world.FindTilesInCircle(self.Location, range);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace OpenRa.Traits
|
||||
if( order.OrderString == "DeployMcv" )
|
||||
{
|
||||
var factBuildingInfo = Rules.ActorInfo[ "fact" ].Traits.Get<BuildingInfo>();
|
||||
if( Game.CanPlaceBuilding( "fact", factBuildingInfo, self.Location - new int2( 1, 1 ), self, false ) )
|
||||
if( Game.world.CanPlaceBuilding( "fact", factBuildingInfo, self.Location - new int2( 1, 1 ), self, false ) )
|
||||
{
|
||||
self.CancelActivity();
|
||||
self.QueueActivity( new Turn( 96 ) );
|
||||
|
||||
@@ -59,7 +59,7 @@ namespace OpenRa.Traits
|
||||
{
|
||||
// force-move
|
||||
if (!mi.Modifiers.HasModifier(Modifiers.Alt)) return null;
|
||||
if (!Game.IsActorCrushableByActor(underCursor, self)) return null;
|
||||
if (!Game.world.IsActorCrushableByActor(underCursor, self)) return null;
|
||||
}
|
||||
|
||||
if (Util.GetEffectiveSpeed(self) == 0) return null; /* allow disabling move orders from modifiers */
|
||||
@@ -97,7 +97,7 @@ namespace OpenRa.Traits
|
||||
{
|
||||
if (actor == self) continue;
|
||||
|
||||
if (!Game.IsActorCrushableByActor(actor, self))
|
||||
if (!Game.world.IsActorCrushableByActor(actor, self))
|
||||
{
|
||||
crushable = false;
|
||||
break;
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace OpenRa.Traits
|
||||
|
||||
for (var j = min.Y; j <= max.Y; j++)
|
||||
for (var i = min.X; i <= max.X; i++)
|
||||
if (Game.IsCellBuildable(new int2(i, j), umt))
|
||||
if (Game.world.IsCellBuildable(new int2(i, j), umt))
|
||||
return new int2(i, j);
|
||||
|
||||
return null;
|
||||
|
||||
@@ -46,10 +46,10 @@ namespace OpenRa
|
||||
public void DrawBuildingGrid( string name, BuildingInfo bi )
|
||||
{
|
||||
var position = Game.controller.MousePosition.ToInt2();
|
||||
var isCloseEnough = Game.IsCloseEnoughToBase(Game.LocalPlayer, name, bi, position);
|
||||
var isCloseEnough = Game.world.IsCloseEnoughToBase(Game.LocalPlayer, name, bi, position);
|
||||
|
||||
foreach( var t in Footprint.Tiles( name, bi, position ) )
|
||||
spriteRenderer.DrawSprite( ( isCloseEnough && Game.IsCellBuildable( t, bi.WaterBound
|
||||
spriteRenderer.DrawSprite( ( isCloseEnough && Game.world.IsCellBuildable( t, bi.WaterBound
|
||||
? UnitMovementType.Float : UnitMovementType.Wheel ) && !Game.world.Map.ContainsResource( t ) )
|
||||
? buildOk : buildBlocked, Game.CellSize * t, 0 );
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace OpenRa
|
||||
{
|
||||
// There should only be one (counterexample: An infantry and a tank try to pick up a crate at the same time.)
|
||||
// If there is more than one, do action on the first crusher
|
||||
var crusher = GetUnitsAt(cell).Where(b => a != b && Game.IsActorCrushableByActor(a, b)).FirstOrDefault();
|
||||
var crusher = GetUnitsAt(cell).Where(b => a != b && Game.world.IsActorCrushableByActor(a, b)).FirstOrDefault();
|
||||
if (crusher != null)
|
||||
{
|
||||
Log.Write("{0} crushes {1}", crusher.Info.Name, a.Info.Name);
|
||||
|
||||
133
OpenRa.Game/WorldUtils.cs
Executable file
133
OpenRa.Game/WorldUtils.cs
Executable file
@@ -0,0 +1,133 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRa.Traits;
|
||||
using System.Drawing;
|
||||
using OpenRa.GameRules;
|
||||
|
||||
namespace OpenRa
|
||||
{
|
||||
static class WorldUtils
|
||||
{
|
||||
public static bool IsCellBuildable(this World world, int2 a, UnitMovementType umt)
|
||||
{
|
||||
return world.IsCellBuildable(a, umt, null);
|
||||
}
|
||||
|
||||
public static bool IsCellBuildable(this World world, int2 a, UnitMovementType umt, Actor toIgnore)
|
||||
{
|
||||
if (world.BuildingInfluence.GetBuildingAt(a) != null) return false;
|
||||
if (world.UnitInfluence.GetUnitsAt(a).Any(b => b != toIgnore)) return false;
|
||||
|
||||
return world.Map.IsInMap(a.X, a.Y) &&
|
||||
TerrainCosts.Cost(umt,
|
||||
world.TileSet.GetWalkability(world.Map.MapTiles[a.X, a.Y])) < double.PositiveInfinity;
|
||||
}
|
||||
|
||||
public static bool IsActorCrushableByActor(this World world, Actor a, Actor b)
|
||||
{
|
||||
return world.IsActorCrushableByMovementType(a, b.traits.GetOrDefault<IMovement>().GetMovementType());
|
||||
}
|
||||
|
||||
public static bool IsActorPathableToCrush(this World world, Actor a, UnitMovementType umt)
|
||||
{
|
||||
return a != null &&
|
||||
a.traits.WithInterface<ICrushable>()
|
||||
.Any(c => c.IsPathableCrush(umt, a.Owner));
|
||||
}
|
||||
|
||||
public static bool IsActorCrushableByMovementType(this World world, Actor a, UnitMovementType umt)
|
||||
{
|
||||
return a != null &&
|
||||
a.traits.WithInterface<ICrushable>()
|
||||
.Any(c => c.IsCrushableBy(umt, a.Owner));
|
||||
}
|
||||
|
||||
public static bool IsWater(this World world, int2 a)
|
||||
{
|
||||
return world.Map.IsInMap(a.X, a.Y) &&
|
||||
TerrainCosts.Cost(UnitMovementType.Float,
|
||||
world.TileSet.GetWalkability(world.Map.MapTiles[a.X, a.Y])) < double.PositiveInfinity;
|
||||
}
|
||||
|
||||
public static IEnumerable<Actor> FindUnits(this World world, float2 a, float2 b)
|
||||
{
|
||||
var min = float2.Min(a, b);
|
||||
var max = float2.Max(a, b);
|
||||
|
||||
var rect = new RectangleF(min.X, min.Y, max.X - min.X, max.Y - min.Y);
|
||||
|
||||
return world.Actors
|
||||
.Where(x => x.GetBounds(true).IntersectsWith(rect));
|
||||
}
|
||||
|
||||
public static IEnumerable<Actor> FindUnitsInCircle(this World world, float2 a, float r)
|
||||
{
|
||||
var min = a - new float2(r, r);
|
||||
var max = a + new float2(r, r);
|
||||
|
||||
var rect = new RectangleF(min.X, min.Y, max.X - min.X, max.Y - min.Y);
|
||||
|
||||
var inBox = world.Actors.Where(x => x.GetBounds(false).IntersectsWith(rect));
|
||||
|
||||
return inBox.Where(x => (x.CenterLocation - a).LengthSquared < r * r);
|
||||
}
|
||||
|
||||
public static IEnumerable<int2> FindTilesInCircle(this World world, int2 a, int r)
|
||||
{
|
||||
var min = a - new int2(r, r);
|
||||
var max = a + new int2(r, r);
|
||||
if (min.X < 0) min.X = 0;
|
||||
if (min.Y < 0) min.Y = 0;
|
||||
if (max.X > 127) max.X = 127;
|
||||
if (max.Y > 127) max.Y = 127;
|
||||
|
||||
for (var j = min.Y; j <= max.Y; j++)
|
||||
for (var i = min.X; i <= max.X; i++)
|
||||
if (r * r >= (new int2(i, j) - a).LengthSquared)
|
||||
yield return new int2(i, j);
|
||||
}
|
||||
|
||||
public static IEnumerable<Actor> SelectActorsInBox(this World world, float2 a, float2 b)
|
||||
{
|
||||
return world.FindUnits(a, b)
|
||||
.Where( x => x.traits.Contains<Selectable>() )
|
||||
.GroupBy(x => (x.Owner == Game.LocalPlayer) ? x.Info.Traits.Get<SelectableInfo>().Priority : 0)
|
||||
.OrderByDescending(g => g.Key)
|
||||
.Select( g => g.AsEnumerable() )
|
||||
.DefaultIfEmpty( new Actor[] {} )
|
||||
.FirstOrDefault();
|
||||
}
|
||||
|
||||
public static bool CanPlaceBuilding(this World world, string name, BuildingInfo building, int2 xy, Actor toIgnore, bool adjust)
|
||||
{
|
||||
return !Footprint.Tiles(name, building, xy, adjust).Any(
|
||||
t => !world.Map.IsInMap(t.X, t.Y) || world.Map.ContainsResource(t) || !world.IsCellBuildable(t,
|
||||
building.WaterBound ? UnitMovementType.Float : UnitMovementType.Wheel,
|
||||
toIgnore));
|
||||
}
|
||||
|
||||
public static bool IsCloseEnoughToBase(this World world, Player p, string buildingName, BuildingInfo bi, int2 position)
|
||||
{
|
||||
var maxDistance = bi.Adjacent + 1;
|
||||
|
||||
var search = new PathSearch()
|
||||
{
|
||||
heuristic = loc =>
|
||||
{
|
||||
var b = world.BuildingInfluence.GetBuildingAt(loc);
|
||||
if (b != null && b.Owner == p && b.Info.Traits.Get<BuildingInfo>().BaseNormal) return 0;
|
||||
if ((loc - position).Length > maxDistance)
|
||||
return float.PositiveInfinity; /* not quite right */
|
||||
return 1;
|
||||
},
|
||||
checkForBlocked = false,
|
||||
ignoreTerrain = true,
|
||||
};
|
||||
|
||||
foreach (var t in Footprint.Tiles(buildingName, bi, position)) search.AddInitialCell(t);
|
||||
|
||||
return world.PathFinder.FindPath(search).Count != 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user