Move any mobile actors that block the building's desired footprint when placing a building

This commit is contained in:
Pavel Penev
2015-09-03 13:06:07 +03:00
parent 02be188d14
commit f942ab1389

View File

@@ -12,9 +12,12 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using OpenRA.Graphics; using OpenRA.Graphics;
using OpenRA.Mods.Common.Activities;
using OpenRA.Mods.Common.Graphics; using OpenRA.Mods.Common.Graphics;
using OpenRA.Mods.Common.Traits; using OpenRA.Mods.Common.Traits;
using OpenRA.Primitives; using OpenRA.Primitives;
using OpenRA.Traits;
using Util = OpenRA.Traits.Util;
namespace OpenRA.Mods.Common.Orders namespace OpenRA.Mods.Common.Orders
{ {
@@ -65,7 +68,11 @@ namespace OpenRA.Mods.Common.Orders
world.CancelInputMode(); world.CancelInputMode();
var ret = InnerOrder(world, xy, mi).ToArray(); var ret = InnerOrder(world, xy, mi).ToArray();
if (ret.Length > 0)
// If there was a successful placement order
if (ret.Any(o => o.OrderString == "PlaceBuilding"
|| o.OrderString == "LineBuild"
|| o.OrderString == "PlacePlug"))
world.CancelInputMode(); world.CancelInputMode();
return ret; return ret;
@@ -96,6 +103,9 @@ namespace OpenRA.Mods.Common.Orders
if (!world.CanPlaceBuilding(building, buildingInfo, topLeft, null) if (!world.CanPlaceBuilding(building, buildingInfo, topLeft, null)
|| !buildingInfo.IsCloseEnoughToBase(world, producer.Owner, building, topLeft)) || !buildingInfo.IsCloseEnoughToBase(world, producer.Owner, building, topLeft))
{ {
foreach (var order in ClearBlockersOrders(world, topLeft))
yield return order;
Game.Sound.PlayNotification(world.Map.Rules, producer.Owner, "Speech", "BuildingCannotPlaceAudio", producer.Owner.Faction.InternalName); Game.Sound.PlayNotification(world.Map.Rules, producer.Owner, "Speech", "BuildingCannotPlaceAudio", producer.Owner.Faction.InternalName);
yield break; yield break;
} }
@@ -210,5 +220,28 @@ namespace OpenRA.Mods.Common.Orders
} }
public string GetCursor(World world, CPos xy, MouseInput mi) { return "default"; } public string GetCursor(World world, CPos xy, MouseInput mi) { return "default"; }
IEnumerable<Order> ClearBlockersOrders(World world, CPos topLeft)
{
var allTiles = FootprintUtils.Tiles(world.Map.Rules, building, buildingInfo, topLeft).ToArray();
var neightborTiles = Util.ExpandFootprint(allTiles, true).Except(allTiles)
.Where(world.Map.Contains).ToList();
var blockers = allTiles.SelectMany(world.ActorMap.GetUnitsAt)
.Where(a => a.Owner == producer.Owner && a.IsIdle)
.Select(a => new TraitPair<Mobile> { Actor = a, Trait = a.TraitOrDefault<Mobile>() });
foreach (var blocker in blockers.Where(x => x.Trait != null))
{
var availableCells = neightborTiles.Where(t => blocker.Trait.CanEnterCell(t)).ToList();
if (availableCells.Count == 0)
continue;
yield return new Order("Move", blocker.Actor, false)
{
TargetLocation = blocker.Actor.ClosestCell(availableCells)
};
}
}
} }
} }