Introduce ScreenMap trait for caching screen-coord queries.
This commit is contained in:
@@ -36,7 +36,7 @@ namespace OpenRA.Mods.RA.Air
|
||||
public int GetInitialFacing() { return InitialFacing; }
|
||||
}
|
||||
|
||||
public class Aircraft : IFacing, IPositionable, ISync, INotifyKilled, IIssueOrder, IOrderVoice
|
||||
public class Aircraft : IFacing, IPositionable, ISync, INotifyKilled, IIssueOrder, IOrderVoice, INotifyAddedToWorld, INotifyRemovedFromWorld
|
||||
{
|
||||
static readonly Pair<CPos, SubCell>[] NoCells = new Pair<CPos, SubCell>[] { };
|
||||
|
||||
@@ -101,15 +101,28 @@ namespace OpenRA.Mods.RA.Air
|
||||
UnReserve();
|
||||
}
|
||||
|
||||
public void SetPosition(Actor self, CPos cell)
|
||||
public void SetPosition(Actor self, WPos pos)
|
||||
{
|
||||
// Changes position, but not altitude
|
||||
CenterPosition = cell.CenterPosition + new WVec(0, 0, CenterPosition.Z);
|
||||
CenterPosition = pos;
|
||||
|
||||
if (self.IsInWorld)
|
||||
self.World.ScreenMap.Update(self);
|
||||
}
|
||||
|
||||
public void SetPosition(Actor self, WPos pos) { CenterPosition = pos; }
|
||||
// Changes position, but not altitude
|
||||
public void SetPosition(Actor self, CPos cell) { SetPosition(self, cell.CenterPosition + new WVec(0, 0, CenterPosition.Z)); }
|
||||
public void SetVisualPosition(Actor self, WPos pos) { SetPosition(self, pos); }
|
||||
|
||||
public void AddedToWorld(Actor self)
|
||||
{
|
||||
self.World.ScreenMap.Add(self);
|
||||
}
|
||||
|
||||
public void RemovedFromWorld(Actor self)
|
||||
{
|
||||
self.World.ScreenMap.Remove(self);
|
||||
}
|
||||
|
||||
public bool AircraftCanEnter(Actor a)
|
||||
{
|
||||
if (self.AppearsHostileTo(a))
|
||||
|
||||
@@ -97,7 +97,7 @@ namespace OpenRA.Mods.RA.Buildings
|
||||
}
|
||||
}
|
||||
|
||||
public class Building : INotifyDamage, IOccupySpace, INotifyCapture, ISync, ITechTreePrerequisite
|
||||
public class Building : INotifyDamage, IOccupySpace, INotifyCapture, ISync, ITechTreePrerequisite, INotifyAddedToWorld, INotifyRemovedFromWorld
|
||||
{
|
||||
readonly Actor self;
|
||||
public readonly BuildingInfo Info;
|
||||
@@ -157,5 +157,15 @@ namespace OpenRA.Mods.RA.Buildings
|
||||
{
|
||||
PlayerPower = newOwner.PlayerActor.Trait<PowerManager>();
|
||||
}
|
||||
|
||||
public void AddedToWorld(Actor self)
|
||||
{
|
||||
self.World.ScreenMap.Add(self);
|
||||
}
|
||||
|
||||
public void RemovedFromWorld(Actor self)
|
||||
{
|
||||
self.World.ScreenMap.Remove(self);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace OpenRA.Mods.RA
|
||||
}
|
||||
|
||||
// ITeleportable is required for paradrop
|
||||
class Crate : ITick, IPositionable, ICrushable, ISync, INotifyParachuteLanded
|
||||
class Crate : ITick, IPositionable, ICrushable, ISync, INotifyParachuteLanded, INotifyAddedToWorld, INotifyRemovedFromWorld
|
||||
{
|
||||
readonly Actor self;
|
||||
readonly CrateInfo info;
|
||||
@@ -115,12 +115,25 @@ namespace OpenRA.Mods.RA
|
||||
rs.anim.PlayRepeating(seq);
|
||||
|
||||
if (self.IsInWorld)
|
||||
{
|
||||
self.World.ActorMap.Add(self, this);
|
||||
self.World.ScreenMap.Update(self);
|
||||
}
|
||||
}
|
||||
|
||||
public bool CrushableBy(string[] crushClasses, Player owner)
|
||||
{
|
||||
return crushClasses.Contains("crate");
|
||||
}
|
||||
|
||||
public void AddedToWorld(Actor self)
|
||||
{
|
||||
self.World.ScreenMap.Add(self);
|
||||
}
|
||||
|
||||
public void RemovedFromWorld(Actor self)
|
||||
{
|
||||
self.World.ScreenMap.Remove(self);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ namespace OpenRA.Mods.RA
|
||||
yield break;
|
||||
}
|
||||
|
||||
var target = FriendlyGuardableUnitsAtMouse(world, mi).FirstOrDefault();
|
||||
var target = FriendlyGuardableUnits(world, mi).FirstOrDefault();
|
||||
|
||||
if (target == null || subjects.All(s => s.IsDead()))
|
||||
yield break;
|
||||
@@ -79,19 +79,19 @@ namespace OpenRA.Mods.RA
|
||||
|
||||
public string GetCursor(World world, CPos xy, MouseInput mi)
|
||||
{
|
||||
if (world.Map.IsInMap(xy))
|
||||
{
|
||||
var targets = FriendlyGuardableUnitsAtMouse(world, mi);
|
||||
if (targets.Any() && (subjects.Count() > 1 || (subjects.Count() == 1 && subjects.First() != targets.First())))
|
||||
return "guard";
|
||||
}
|
||||
return "move-blocked";
|
||||
var multiple = subjects.Count() > 1;
|
||||
var canGuard = FriendlyGuardableUnits(world, mi)
|
||||
.Any(a => multiple || a != subjects.First());
|
||||
|
||||
return canGuard ? "guard" : "move-blocked";
|
||||
}
|
||||
|
||||
static IEnumerable<Actor> FriendlyGuardableUnitsAtMouse(World world, MouseInput mi)
|
||||
static IEnumerable<Actor> FriendlyGuardableUnits(World world, MouseInput mi)
|
||||
{
|
||||
return world.FindUnitsAtMouse(mi.Location)
|
||||
.Where(a => !a.IsDead() && a.AppearsFriendlyTo(world.LocalPlayer.PlayerActor) && a.HasTrait<Guardable>());
|
||||
return world.ScreenMap.ActorsAt(Game.viewport.ViewToWorldPx(mi.Location))
|
||||
.Where(a => !world.FogObscures(a) && !a.IsDead() &&
|
||||
a.AppearsFriendlyTo(world.LocalPlayer.PlayerActor) &&
|
||||
a.HasTrait<Guardable>());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace OpenRA.Mods.RA
|
||||
public int GetInitialFacing() { return 128; }
|
||||
}
|
||||
|
||||
class Husk : IPositionable, IFacing, ISync
|
||||
class Husk : IPositionable, IFacing, ISync, INotifyAddedToWorld, INotifyRemovedFromWorld
|
||||
{
|
||||
readonly HuskInfo info;
|
||||
readonly Actor self;
|
||||
@@ -64,7 +64,11 @@ namespace OpenRA.Mods.RA
|
||||
}
|
||||
|
||||
public void SetPosition(Actor self, CPos cell) { SetPosition(self, cell.CenterPosition); }
|
||||
public void SetVisualPosition(Actor self, WPos pos) { CenterPosition = pos; }
|
||||
public void SetVisualPosition(Actor self, WPos pos)
|
||||
{
|
||||
CenterPosition = pos;
|
||||
self.World.ScreenMap.Update(self);
|
||||
}
|
||||
|
||||
public void SetPosition(Actor self, WPos pos)
|
||||
{
|
||||
@@ -72,6 +76,17 @@ namespace OpenRA.Mods.RA
|
||||
CenterPosition = pos;
|
||||
TopLeft = pos.ToCPos();
|
||||
self.World.ActorMap.Add(self, this);
|
||||
self.World.ScreenMap.Update(self);
|
||||
}
|
||||
|
||||
public void AddedToWorld(Actor self)
|
||||
{
|
||||
self.World.ScreenMap.Add(self);
|
||||
}
|
||||
|
||||
public void RemovedFromWorld(Actor self)
|
||||
{
|
||||
self.World.ScreenMap.Remove(self);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace OpenRA.Mods.RA
|
||||
public object Create(ActorInitializer init) { return new Mine(init, this); }
|
||||
}
|
||||
|
||||
class Mine : ICrushable, IOccupySpace, ISync
|
||||
class Mine : ICrushable, IOccupySpace, ISync, INotifyAddedToWorld, INotifyRemovedFromWorld
|
||||
{
|
||||
readonly Actor self;
|
||||
readonly MineInfo info;
|
||||
@@ -62,6 +62,16 @@ namespace OpenRA.Mods.RA
|
||||
|
||||
public IEnumerable<Pair<CPos, SubCell>> OccupiedCells() { yield return Pair.New(TopLeft, SubCell.FullCell); }
|
||||
public WPos CenterPosition { get { return location.CenterPosition; } }
|
||||
|
||||
public void AddedToWorld(Actor self)
|
||||
{
|
||||
self.World.ScreenMap.Add(self);
|
||||
}
|
||||
|
||||
public void RemovedFromWorld(Actor self)
|
||||
{
|
||||
self.World.ScreenMap.Remove(self);
|
||||
}
|
||||
}
|
||||
|
||||
/* tag trait for stuff that shouldnt trigger mines */
|
||||
|
||||
@@ -106,7 +106,8 @@ namespace OpenRA.Mods.RA
|
||||
yield break;
|
||||
}
|
||||
|
||||
var underCursor = world.FindUnitsAtMouse(mi.Location)
|
||||
var underCursor = world.ScreenMap.ActorsAt(Game.viewport.ViewToWorldPx(mi.Location))
|
||||
.Where(a => !world.FogObscures(a))
|
||||
.OrderByDescending(a => a.Info.Traits.Contains<SelectableInfo>()
|
||||
? a.Info.Traits.Get<SelectableInfo>().Priority : int.MinValue)
|
||||
.FirstOrDefault();
|
||||
|
||||
@@ -144,7 +144,7 @@ namespace OpenRA.Mods.RA.Move
|
||||
public int GetInitialFacing() { return InitialFacing; }
|
||||
}
|
||||
|
||||
public class Mobile : IIssueOrder, IResolveOrder, IOrderVoice, IPositionable, IMove, IFacing, ISync
|
||||
public class Mobile : IIssueOrder, IResolveOrder, IOrderVoice, IPositionable, IMove, IFacing, ISync, INotifyAddedToWorld, INotifyRemovedFromWorld
|
||||
{
|
||||
public readonly Actor self;
|
||||
public readonly MobileInfo Info;
|
||||
@@ -231,6 +231,18 @@ namespace OpenRA.Mods.RA.Move
|
||||
public void SetVisualPosition(Actor self, WPos pos)
|
||||
{
|
||||
CenterPosition = pos;
|
||||
if (self.IsInWorld)
|
||||
self.World.ScreenMap.Update(self);
|
||||
}
|
||||
|
||||
public void AddedToWorld(Actor self)
|
||||
{
|
||||
self.World.ScreenMap.Add(self);
|
||||
}
|
||||
|
||||
public void RemovedFromWorld(Actor self)
|
||||
{
|
||||
self.World.ScreenMap.Remove(self);
|
||||
}
|
||||
|
||||
public IEnumerable<IOrderTargeter> Orders { get { yield return new MoveOrderTargeter(Info); } }
|
||||
|
||||
@@ -39,9 +39,8 @@ namespace OpenRA.Mods.RA.Orders
|
||||
{
|
||||
if (mi.Button == MouseButton.Left)
|
||||
{
|
||||
var underCursor = world.FindUnitsAtMouse(mi.Location)
|
||||
.Where(a => a.Owner == world.LocalPlayer
|
||||
&& a.HasTrait<T>()).FirstOrDefault();
|
||||
var underCursor = world.ScreenMap.ActorsAt(Game.viewport.ViewToWorldPx(mi.Location))
|
||||
.Where(a => a.Owner == world.LocalPlayer && a.HasTrait<T>()).FirstOrDefault();
|
||||
|
||||
if (underCursor != null)
|
||||
yield return new Order(order, underCursor, false);
|
||||
|
||||
@@ -30,8 +30,8 @@ namespace OpenRA.Mods.RA.Orders
|
||||
{
|
||||
if (mi.Button == MouseButton.Left)
|
||||
{
|
||||
var underCursor = world.FindUnitsAtMouse(mi.Location)
|
||||
.Where(a => a.AppearsFriendlyTo(world.LocalPlayer.PlayerActor) && a.HasTrait<RepairableBuilding>()).FirstOrDefault();
|
||||
var underCursor = world.ScreenMap.ActorsAt(Game.viewport.ViewToWorldPx(mi.Location))
|
||||
.Where(a => !world.FogObscures(a) && a.AppearsFriendlyTo(world.LocalPlayer.PlayerActor) && a.HasTrait<RepairableBuilding>()).FirstOrDefault();
|
||||
|
||||
if (underCursor == null)
|
||||
yield break;
|
||||
|
||||
Reference in New Issue
Block a user