Add Map.DistanceAboveTerrain(WPos) and Actor.IsAtGroundLevel() extension method

This commit is contained in:
Taryn Hill
2015-08-01 07:53:14 -05:00
parent 7066254887
commit 6fa1f757b0
8 changed files with 36 additions and 13 deletions

View File

@@ -775,6 +775,13 @@ namespace OpenRA
return CenterOfCell(cell);
}
public WDist DistanceAboveTerrain(WPos pos)
{
var cell = CellContaining(pos);
var delta = pos - CenterOfCell(cell);
return new WDist(delta.Z);
}
public CPos CellContaining(WPos pos)
{
if (TileShape == TileShape.Rectangle)

View File

@@ -18,6 +18,25 @@ namespace OpenRA.Mods.Common
{
public static class ActorExts
{
public static bool IsAtGroundLevel(this Actor self)
{
if (self.IsDead)
return false;
if (!self.HasTrait<IPositionable>())
return false;
if (!self.IsInWorld)
return false;
var map = self.World.Map;
if (!map.Contains(self.Location))
return false;
return map.DistanceAboveTerrain(self.CenterPosition).Length == 0;
}
public static bool AppearsFriendlyTo(this Actor self, Actor toActor)
{
var stance = toActor.Owner.Stances[self.Owner];

View File

@@ -104,8 +104,7 @@ namespace OpenRA.Mods.Common.Graphics
public void Render(WorldRenderer wr)
{
// TODO: This is a temporary workaround until we have a proper ramp-aware height calculation
var groundPos = wr.World.Map.CenterOfCell(wr.World.Map.CellContaining(voxel.pos));
var groundPos = voxel.pos - new WVec(0, 0, wr.World.Map.DistanceAboveTerrain(voxel.pos).Length);
var ts = Game.ModData.Manifest.TileSize;
var groundZ = ts.Height * (groundPos.Z - voxel.pos.Z) / 1024f;

View File

@@ -171,7 +171,7 @@ namespace OpenRA.Mods.Common.Traits
public bool CanLoad(Actor self, Actor a)
{
return (reserves.Contains(a) || HasSpace(GetWeight(a))) && self.CenterPosition.Z == 0;
return (reserves.Contains(a) || HasSpace(GetWeight(a))) && self.IsAtGroundLevel();
}
internal bool ReserveSpace(Actor a)

View File

@@ -189,11 +189,8 @@ namespace OpenRA.Mods.Common.Traits
public bool CrushableBy(string[] crushClasses, Player owner)
{
// Crate can only be crushed if it is not in the air or underground
if (CenterPosition.Z != 0)
return false;
return crushClasses.Contains(info.CrushClass);
// Crate can only be crushed if it is not in the air.
return self.IsAtGroundLevel() && crushClasses.Contains(info.CrushClass);
}
public void AddedToWorld(Actor self)

View File

@@ -65,8 +65,8 @@ namespace OpenRA.Mods.Common.Traits
public bool CrushableBy(string[] crushClasses, Player crushOwner)
{
// Only make actor crushable if it is on the ground
if (self.CenterPosition.Z != 0)
// Only make actor crushable if it is on the ground.
if (!self.IsAtGroundLevel())
return false;
if (!info.CrushedByFriendlies && crushOwner.IsAlliedWith(self.Owner))

View File

@@ -65,7 +65,8 @@ namespace OpenRA.Mods.Common.Traits
return;
var cp = self.CenterPosition;
if ((cp.Z > 0 && !info.EjectInAir) || (cp.Z == 0 && !info.EjectOnGround))
var inAir = !self.IsAtGroundLevel();
if ((inAir && !info.EjectInAir) || (!inAir && !info.EjectOnGround))
return;
var pilot = self.World.CreateActor(false, info.PilotActor.ToLowerInvariant(),
@@ -73,7 +74,7 @@ namespace OpenRA.Mods.Common.Traits
if (info.AllowUnsuitableCell || IsSuitableCell(self, pilot))
{
if (cp.Z > 0)
if (inAir)
{
self.World.AddFrameEndTask(w =>
{

View File

@@ -565,7 +565,7 @@ namespace OpenRA.Mods.Common.Traits
public void FinishedMoving(Actor self)
{
// Only make actor crush if it is on the ground
if (self.CenterPosition.Z != 0)
if (!self.IsAtGroundLevel())
return;
var crushables = self.World.ActorMap.GetUnitsAt(ToCell).Where(a => a != self)