New crush code, now with less bs

This commit is contained in:
Paul Chote
2010-06-25 20:57:06 +12:00
parent 00b91bd7ad
commit 7c3a10396c
16 changed files with 70 additions and 94 deletions

View File

@@ -35,7 +35,6 @@ namespace OpenRA
public PathFinder( World world )
{
this.world = world;
var map = world.Map;
}
class CachedPath

View File

@@ -306,6 +306,7 @@ namespace OpenRA.Traits.Activities
{
self.CenterLocation = Util.CenterOfCell( mobile.toCell );
mobile.fromCell = mobile.toCell;
mobile.FinishedMoving(self);
return null;
}
}

View File

@@ -30,6 +30,7 @@ namespace OpenRA.Traits
{
public readonly TerrainType[] TerrainTypes;
public readonly float[] TerrainSpeeds;
public readonly string[] Crushes;
public readonly int WaitAverage = 60;
public readonly int WaitSpread = 20;
@@ -39,6 +40,7 @@ namespace OpenRA.Traits
public class Mobile : IIssueOrder, IResolveOrder, IOccupySpace, IMove
{
public readonly Actor self;
public readonly MobileInfo Info;
public readonly Dictionary<TerrainType,float> TerrainCost;
public readonly Dictionary<TerrainType,float> TerrainSpeed;
@@ -67,6 +69,7 @@ namespace OpenRA.Traits
public Mobile(ActorInitializer init, MobileInfo info)
{
this.self = init.self;
this.Info = info;
this.__fromCell = this.__toCell = init.location;
AddInfluence();
@@ -137,9 +140,19 @@ namespace OpenRA.Traits
public virtual bool CanEnterCell(int2 cell, Actor ignoreActor, bool checkTransientActors)
{
if (!self.World.WorldActor.traits.Get<BuildingInfluence>().CanMoveHere(cell, ignoreActor))
return false;
// Check for buildings
var building = self.World.WorldActor.traits.Get<BuildingInfluence>().GetBuildingBlocking(cell);
if (building != null && building != ignoreActor)
{
var crushable = building.traits.WithInterface<ICrushable>();
if (crushable.Count() == 0)
return false;
if (!crushable.Any(b => b.CrushClasses.Intersect(Info.Crushes).Any()))
return false;
}
// Check mobile actors
if (checkTransientActors)
{
var canShare = self.traits.Contains<SharesCell>();
@@ -150,16 +163,27 @@ namespace OpenRA.Traits
// only allow 5 in a cell
if (shareable.Count() >= 5)
return false;
// We can enter a cell with nonshareable units if we can crush all of them
if (nonshareable.Any(
a => !self.World.IsActorCrushableByActor(a, self)))
if (nonshareable.Any(a => !(a.traits.Contains<ICrushable>() &&
a.traits.WithInterface<ICrushable>().Any(b => b.CrushClasses.Intersect(Info.Crushes).Any()))))
return false;
}
return MovementCostForCell(self, cell) < float.PositiveInfinity;
}
public virtual void FinishedMoving(Actor self)
{
var crushable = self.World.WorldActor.traits.Get<UnitInfluence>().GetUnitsAt(self.Location).Where(a => a != self && a.traits.Contains<ICrushable>());
foreach (var a in crushable)
{
var crushActions = a.traits.WithInterface<ICrushable>().Where(b => b.CrushClasses.Intersect(Info.Crushes).Any());
foreach (var b in crushActions)
b.OnCrush(self);
}
}
public virtual float MovementCostForCell(Actor self, int2 cell)
{
if (!self.World.Map.IsInMap(cell.X,cell.Y))

View File

@@ -115,8 +115,7 @@ namespace OpenRA.Traits
public interface ICrushable
{
void OnCrush(Actor crusher);
bool IsCrushableBy(UnitMovementType umt, Player player);
bool IsPathableCrush(UnitMovementType umt, Player player);
IEnumerable<string> CrushClasses { get; }
}
public struct Renderable

View File

@@ -65,6 +65,12 @@ namespace OpenRA.Traits
if (!map.IsInMap(cell)) return null;
return influence[cell.X, cell.Y];
}
public Actor GetBuildingBlocking(int2 cell)
{
if (!map.IsInMap(cell) || !blocked[cell.X, cell.Y]) return null;
return influence[cell.X, cell.Y];
}
public bool CanMoveHere(int2 cell)
{

View File

@@ -38,7 +38,6 @@ namespace OpenRA.Traits
public HazardLayer( World world )
{
map = world.Map;
hazards = new List<Pair<Actor, Hazard>>[world.Map.MapSize.X, world.Map.MapSize.Y];
for (int i = 0; i < world.Map.MapSize.X; i++)
for (int j = 0; j < world.Map.MapSize.Y; j++)

View File

@@ -49,27 +49,6 @@ namespace OpenRA.Traits
public void Tick( Actor self )
{
// Does this belong here? NO, but it's your mess.
// Get the crushable actors
foreach (var aa in self.World.Queries.WithTrait<ICrushable>())
{
var a = aa.Actor;
// Are there any units in the same cell that can crush this?
foreach( var ios in a.traits.WithInterface<IOccupySpace>() )
foreach( var cell in ios.OccupiedCells() )
{
// 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 && self.World.IsActorCrushableByActor(a, b)).FirstOrDefault();
if (crusher != null)
{
// Apply the crush action
foreach (var crush in a.traits.WithInterface<ICrushable>())
crush.OnCrush(crusher);
}
}
}
SanityCheck( self );
}

View File

@@ -49,29 +49,6 @@ namespace OpenRA
.Buildable;
}
public static bool IsActorCrushableByActor(this World world, Actor a, Actor b)
{
return false;
//var movement = b.traits.GetOrDefault<IMove>();
//return movement != null && world.IsActorCrushableByMovementType(a, movement.GetMovementType());
}
// Todo: Reenable crushing based on actor, not umt
/*
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 IEnumerable<Actor> FindUnitsAtMouse(this World world, int2 mouseLocation)
{
var loc = mouseLocation + Game.viewport.Location;