moved helper functions out of Game, into WorldUtils
This commit is contained in:
@@ -89,7 +89,7 @@ namespace OpenRa
|
|||||||
return null;
|
return null;
|
||||||
|
|
||||||
var loc = mi.Location + Game.viewport.Location;
|
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>())
|
if (underCursor != null && !underCursor.traits.Contains<Selectable>())
|
||||||
underCursor = null;
|
underCursor = null;
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ namespace OpenRa
|
|||||||
{
|
{
|
||||||
var targetTile = ((1f / Game.CellSize) * loc.ToFloat2()).ToInt2();
|
var targetTile = ((1f / Game.CellSize) * loc.ToFloat2()).ToInt2();
|
||||||
|
|
||||||
var isWater = Game.IsWater(targetTile);
|
var isWater = Game.world.IsWater(targetTile);
|
||||||
var hitWater = Game.IsCellBuildable(targetTile, UnitMovementType.Float);
|
var hitWater = Game.world.IsCellBuildable(targetTile, UnitMovementType.Float);
|
||||||
|
|
||||||
if (warhead.Explosion != 0)
|
if (warhead.Explosion != 0)
|
||||||
Game.world.AddFrameEndTask(
|
Game.world.AddFrameEndTask(
|
||||||
@@ -31,7 +31,7 @@ namespace OpenRa
|
|||||||
if (warhead.Ore) Ore.Destroy(targetTile.X, targetTile.Y);
|
if (warhead.Ore) Ore.Destroy(targetTile.X, targetTile.Y);
|
||||||
|
|
||||||
var maxSpread = GetMaximumSpread(weapon, warhead);
|
var maxSpread = GetMaximumSpread(weapon, warhead);
|
||||||
var hitActors = Game.FindUnitsInCircle(loc, maxSpread);
|
var hitActors = Game.world.FindUnitsInCircle(loc, maxSpread);
|
||||||
|
|
||||||
foreach (var victim in hitActors)
|
foreach (var victim in hitActors)
|
||||||
victim.InflictDamage(firedBy, (int)GetDamageToInflict(victim, loc, weapon, warhead), warhead);
|
victim.InflictDamage(firedBy, (int)GetDamageToInflict(victim, loc, weapon, warhead), warhead);
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ namespace OpenRa
|
|||||||
{
|
{
|
||||||
if (orderGenerator is UnitOrderGenerator)
|
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);
|
CombineSelection(newSelection, mi.Modifiers.HasModifier(Modifiers.Shift), dragStart == xy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -208,130 +208,9 @@ namespace OpenRa
|
|||||||
renderer.PaletteTexture = palette.Texture;
|
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 SharedRandom = new Random(0); /* for things that require sync */
|
||||||
public static Random CosmeticRandom = new Random(); /* for things that are just fluff */
|
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)
|
public static void SyncLobbyInfo(string data)
|
||||||
{
|
{
|
||||||
var session = new Session();
|
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 + b + c, a + c, Color.White, Color.White);
|
||||||
lineRenderer.DrawLine(a, 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);
|
DrawSelectionBox(u, Color.Yellow, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<ProjectGuid>{0DFB103F-2962-400F-8C6D-E2C28CCBA633}</ProjectGuid>
|
<ProjectGuid>{0DFB103F-2962-400F-8C6D-E2C28CCBA633}</ProjectGuid>
|
||||||
<OutputType>WinExe</OutputType>
|
<OutputType>WinExe</OutputType>
|
||||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
<RootNamespace>OpenRa.Game</RootNamespace>
|
<RootNamespace>OpenRa</RootNamespace>
|
||||||
<AssemblyName>OpenRa.Game</AssemblyName>
|
<AssemblyName>OpenRa.Game</AssemblyName>
|
||||||
<FileUpgradeFlags>
|
<FileUpgradeFlags>
|
||||||
</FileUpgradeFlags>
|
</FileUpgradeFlags>
|
||||||
@@ -274,6 +274,7 @@
|
|||||||
<Compile Include="UnitInfluenceMap.cs" />
|
<Compile Include="UnitInfluenceMap.cs" />
|
||||||
<Compile Include="Orders\UnitOrderGenerator.cs" />
|
<Compile Include="Orders\UnitOrderGenerator.cs" />
|
||||||
<Compile Include="World.cs" />
|
<Compile Include="World.cs" />
|
||||||
|
<Compile Include="WorldUtils.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\OpenRa.FileFormats\OpenRa.FileFormats.csproj">
|
<ProjectReference Include="..\OpenRa.FileFormats\OpenRa.FileFormats.csproj">
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ namespace OpenRa.Orders
|
|||||||
if (mi.Button == MouseButton.Left)
|
if (mi.Button == MouseButton.Left)
|
||||||
{
|
{
|
||||||
var loc = mi.Location + Game.viewport.Location;
|
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
|
.Where(a => a.Owner == Game.LocalPlayer
|
||||||
&& a.traits.Contains<Chronoshiftable>()
|
&& a.traits.Contains<Chronoshiftable>()
|
||||||
&& a.traits.Contains<Selectable>()).FirstOrDefault();
|
&& a.traits.Contains<Selectable>()).FirstOrDefault();
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ namespace OpenRa.Orders
|
|||||||
if (mi.Button == MouseButton.Left)
|
if (mi.Button == MouseButton.Left)
|
||||||
{
|
{
|
||||||
var loc = mi.Location + Game.viewport.Location;
|
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
|
.Where(a => a.Owner == Game.LocalPlayer
|
||||||
&& a.traits.Contains<IronCurtainable>()
|
&& a.traits.Contains<IronCurtainable>()
|
||||||
&& a.traits.Contains<Selectable>()).FirstOrDefault();
|
&& a.traits.Contains<Selectable>()).FirstOrDefault();
|
||||||
|
|||||||
@@ -28,8 +28,8 @@ namespace OpenRa.Orders
|
|||||||
{
|
{
|
||||||
if (mi.Button == MouseButton.Left)
|
if (mi.Button == MouseButton.Left)
|
||||||
{
|
{
|
||||||
if (!Game.CanPlaceBuilding( Building, BuildingInfo, xy, null, true)
|
if (!Game.world.CanPlaceBuilding( Building, BuildingInfo, xy, null, true)
|
||||||
|| !Game.IsCloseEnoughToBase(Producer.Owner, Building, BuildingInfo, xy))
|
|| !Game.world.IsCloseEnoughToBase(Producer.Owner, Building, BuildingInfo, xy))
|
||||||
{
|
{
|
||||||
Sound.Play("nodeply1.aud");
|
Sound.Play("nodeply1.aud");
|
||||||
yield break;
|
yield break;
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ namespace OpenRa.Orders
|
|||||||
if (mi.Button == MouseButton.Left)
|
if (mi.Button == MouseButton.Left)
|
||||||
{
|
{
|
||||||
var loc = mi.Location + Game.viewport.Location;
|
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
|
.Where(a => a.Owner == Game.LocalPlayer
|
||||||
&& a.traits.Contains<Building>()
|
&& a.traits.Contains<Building>()
|
||||||
&& a.traits.Contains<Selectable>()).FirstOrDefault();
|
&& a.traits.Contains<Selectable>()).FirstOrDefault();
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ namespace OpenRa.Orders
|
|||||||
if (mi.Button == MouseButton.Left)
|
if (mi.Button == MouseButton.Left)
|
||||||
{
|
{
|
||||||
var loc = mi.Location + Game.viewport.Location;
|
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
|
.Where(a => a.Owner == Game.LocalPlayer
|
||||||
&& a.traits.Contains<Building>()
|
&& a.traits.Contains<Building>()
|
||||||
&& a.traits.Contains<Selectable>()).FirstOrDefault();
|
&& a.traits.Contains<Selectable>()).FirstOrDefault();
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ namespace OpenRa.Orders
|
|||||||
if (mi.Button == MouseButton.Left)
|
if (mi.Button == MouseButton.Left)
|
||||||
{
|
{
|
||||||
var loc = mi.Location + Game.viewport.Location;
|
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
|
.Where(a => a.Owner == Game.LocalPlayer
|
||||||
&& a.traits.Contains<Building>()
|
&& a.traits.Contains<Building>()
|
||||||
&& a.traits.Contains<Selectable>()).FirstOrDefault();
|
&& a.traits.Contains<Selectable>()).FirstOrDefault();
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ namespace OpenRa.Orders
|
|||||||
.FirstOrDefault(a => a != null);
|
.FirstOrDefault(a => a != null);
|
||||||
|
|
||||||
return c ??
|
return c ??
|
||||||
(Game.SelectActorsInBox(Game.CellSize * p,
|
(Game.world.SelectActorsInBox(Game.CellSize * p,
|
||||||
Game.CellSize * p).Any()
|
Game.CellSize * p).Any()
|
||||||
? Cursor.Select : Cursor.Default);
|
? Cursor.Select : Cursor.Default);
|
||||||
}
|
}
|
||||||
@@ -70,7 +70,7 @@ namespace OpenRa.Orders
|
|||||||
return Cursor.MoveBlocked;
|
return Cursor.MoveBlocked;
|
||||||
case "DeployMcv":
|
case "DeployMcv":
|
||||||
var factBuildingInfo = Rules.ActorInfo["fact"].Traits.Get<BuildingInfo>();
|
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;
|
return Cursor.Deploy;
|
||||||
else
|
else
|
||||||
return Cursor.DeployBlocked;
|
return Cursor.DeployBlocked;
|
||||||
|
|||||||
@@ -40,8 +40,8 @@ namespace OpenRa
|
|||||||
{
|
{
|
||||||
using( new PerfSample( "find_unit_path_multiple_src" ) )
|
using( new PerfSample( "find_unit_path_multiple_src" ) )
|
||||||
{
|
{
|
||||||
var tilesInRange = Game.FindTilesInCircle(target, range)
|
var tilesInRange = Game.world.FindTilesInCircle(target, range)
|
||||||
.Where( t => Game.IsCellBuildable( t, umt ) );
|
.Where( t => Game.world.IsCellBuildable( t, umt ) );
|
||||||
|
|
||||||
var path = FindPath( PathSearch.FromPoints( tilesInRange, src, umt, false ).WithCustomBlocker(AvoidUnitsNear(src, 4)));
|
var path = FindPath( PathSearch.FromPoints( tilesInRange, src, umt, false ).WithCustomBlocker(AvoidUnitsNear(src, 4)));
|
||||||
path.Reverse();
|
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
|
// 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;
|
continue;
|
||||||
|
|
||||||
if (customBlock != null && customBlock(newHere))
|
if (customBlock != null && customBlock(newHere))
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ namespace OpenRa
|
|||||||
|
|
||||||
public void Explore(Actor a)
|
public void Explore(Actor a)
|
||||||
{
|
{
|
||||||
foreach (var t in Game.FindTilesInCircle(
|
foreach (var t in Game.world.FindTilesInCircle(
|
||||||
(1f / Game.CellSize * a.CenterLocation).ToInt2(),
|
(1f / Game.CellSize * a.CenterLocation).ToInt2(),
|
||||||
a.Info.Traits.Get<OwnedActorInfo>().Sight))
|
a.Info.Traits.Get<OwnedActorInfo>().Sight))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ namespace OpenRa.Traits.Activities
|
|||||||
if (unit.Altitude == 0)
|
if (unit.Altitude == 0)
|
||||||
return NextActivity;
|
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
|
return this; // fail to land if no space
|
||||||
|
|
||||||
--unit.Altitude;
|
--unit.Altitude;
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ namespace OpenRa.Traits.Activities
|
|||||||
|
|
||||||
// Cannot enter a cell if any unit inside is uncrushable
|
// Cannot enter a cell if any unit inside is uncrushable
|
||||||
// This will need to be updated for multiple-infantry-in-a-cell
|
// 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 )
|
public IActivity Tick( Actor self )
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ namespace OpenRa.Traits.Activities
|
|||||||
{
|
{
|
||||||
if (!limitedAmmo.GiveAmmo()) return NextActivity;
|
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>());
|
.FirstOrDefault(a => a.traits.Contains<RenderBuilding>());
|
||||||
|
|
||||||
if (hostBuilding != null)
|
if (hostBuilding != null)
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ namespace OpenRa.Traits.Activities
|
|||||||
if (self.Health == hp)
|
if (self.Health == hp)
|
||||||
return NextActivity;
|
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>());
|
.FirstOrDefault(a => a.traits.Contains<RenderBuilding>());
|
||||||
|
|
||||||
if (hostBuilding != null)
|
if (hostBuilding != null)
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ namespace OpenRa.Traits.Activities
|
|||||||
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 ((i != 0 || j != 0) &&
|
if ((i != 0 || j != 0) &&
|
||||||
Game.IsCellBuildable(self.Location + new int2(i, j),
|
Game.world.IsCellBuildable(self.Location + new int2(i, j),
|
||||||
UnitMovementType.Foot))
|
UnitMovementType.Foot))
|
||||||
return self.Location + new int2(i, j);
|
return self.Location + new int2(i, j);
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ namespace OpenRa.Traits
|
|||||||
|
|
||||||
Actor ChooseTarget(Actor self, float range)
|
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
|
return inRange
|
||||||
.Where(a => a.Owner == self.Owner && a != self) /* todo: one day deal with friendly players */
|
.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)
|
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
|
return inRange
|
||||||
.Where(a => a.Owner != null && a.Owner != self.Owner) /* todo: one day deal with friendly players */
|
.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
|
// force-move
|
||||||
if (!mi.Modifiers.HasModifier(Modifiers.Alt)) return null;
|
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);
|
return new Order("Move", self, null, xy, null);
|
||||||
@@ -57,7 +57,7 @@ namespace OpenRa.Traits
|
|||||||
{
|
{
|
||||||
if (actor == self) continue;
|
if (actor == self) continue;
|
||||||
|
|
||||||
if (!Game.IsActorCrushableByActor(actor, self))
|
if (!Game.world.IsActorCrushableByActor(actor, self))
|
||||||
{
|
{
|
||||||
crushable = false;
|
crushable = false;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ namespace OpenRa.Traits
|
|||||||
// Gap Generator building; powered down
|
// Gap Generator building; powered down
|
||||||
return (self.traits.Contains<Building>() && self.traits.Get<Building>().Disabled)
|
return (self.traits.Contains<Building>() && self.traits.Get<Building>().Disabled)
|
||||||
? new int2[] {}
|
? new int2[] {}
|
||||||
: Game.FindTilesInCircle(self.Location, range);
|
: Game.world.FindTilesInCircle(self.Location, range);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ namespace OpenRa.Traits
|
|||||||
if( order.OrderString == "DeployMcv" )
|
if( order.OrderString == "DeployMcv" )
|
||||||
{
|
{
|
||||||
var factBuildingInfo = Rules.ActorInfo[ "fact" ].Traits.Get<BuildingInfo>();
|
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.CancelActivity();
|
||||||
self.QueueActivity( new Turn( 96 ) );
|
self.QueueActivity( new Turn( 96 ) );
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ namespace OpenRa.Traits
|
|||||||
{
|
{
|
||||||
// force-move
|
// force-move
|
||||||
if (!mi.Modifiers.HasModifier(Modifiers.Alt)) return null;
|
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 */
|
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 (actor == self) continue;
|
||||||
|
|
||||||
if (!Game.IsActorCrushableByActor(actor, self))
|
if (!Game.world.IsActorCrushableByActor(actor, self))
|
||||||
{
|
{
|
||||||
crushable = false;
|
crushable = false;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ namespace OpenRa.Traits
|
|||||||
|
|
||||||
for (var j = min.Y; j <= max.Y; j++)
|
for (var j = min.Y; j <= max.Y; j++)
|
||||||
for (var i = min.X; i <= max.X; i++)
|
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 new int2(i, j);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -46,10 +46,10 @@ namespace OpenRa
|
|||||||
public void DrawBuildingGrid( string name, BuildingInfo bi )
|
public void DrawBuildingGrid( string name, BuildingInfo bi )
|
||||||
{
|
{
|
||||||
var position = Game.controller.MousePosition.ToInt2();
|
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 ) )
|
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 ) )
|
? UnitMovementType.Float : UnitMovementType.Wheel ) && !Game.world.Map.ContainsResource( t ) )
|
||||||
? buildOk : buildBlocked, Game.CellSize * t, 0 );
|
? 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.)
|
// 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
|
// 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)
|
if (crusher != null)
|
||||||
{
|
{
|
||||||
Log.Write("{0} crushes {1}", crusher.Info.Name, a.Info.Name);
|
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