Allow queued structure rallypoints.

This commit is contained in:
tovl
2019-08-31 19:55:11 +02:00
committed by abcdefg30
parent 3236499fb7
commit 203fff0ab7
9 changed files with 65 additions and 40 deletions

View File

@@ -188,7 +188,8 @@ namespace OpenRA.Mods.Common.Activities
if (wasRepaired || isHostInvalid || (!stayOnResupplier && aircraft.Info.TakeOffOnResupply)) if (wasRepaired || isHostInvalid || (!stayOnResupplier && aircraft.Info.TakeOffOnResupply))
{ {
if (self.CurrentActivity.NextActivity == null && rp != null) if (self.CurrentActivity.NextActivity == null && rp != null)
QueueChild(move.MoveTo(rp.Location, ignoreActor: repairableNear != null ? null : host.Actor, targetLineColor: Color.Green)); foreach (var cell in rp.Path)
QueueChild(move.MoveTo(cell, 1, ignoreActor: repairableNear != null ? null : host.Actor, targetLineColor: Color.Green));
else else
QueueChild(new TakeOff(self)); QueueChild(new TakeOff(self));
@@ -208,7 +209,8 @@ namespace OpenRA.Mods.Common.Activities
if (self.CurrentActivity.NextActivity == null) if (self.CurrentActivity.NextActivity == null)
{ {
if (rp != null) if (rp != null)
QueueChild(move.MoveTo(rp.Location, ignoreActor: repairableNear != null ? null : host.Actor)); foreach (var cell in rp.Path)
QueueChild(move.MoveTo(cell, 1, repairableNear != null ? null : host.Actor, true));
else if (repairableNear == null) else if (repairableNear == null)
QueueChild(move.MoveToTarget(self, host)); QueueChild(move.MoveToTarget(self, host));
} }

View File

@@ -25,8 +25,8 @@ namespace OpenRA.Mods.Common.Effects
readonly Animation circles; readonly Animation circles;
readonly ExitInfo[] exits; readonly ExitInfo[] exits;
readonly WPos[] targetLine = new WPos[2]; List<WPos> targetLineNodes = new List<WPos> { };
CPos cachedLocation; List<CPos> cachedLocations;
public RallyPointIndicator(Actor building, RallyPoint rp, ExitInfo[] exits) public RallyPointIndicator(Actor building, RallyPoint rp, ExitInfo[] exits)
{ {
@@ -52,11 +52,13 @@ namespace OpenRA.Mods.Common.Effects
if (circles != null) if (circles != null)
circles.Tick(); circles.Tick();
if (cachedLocation != rp.Location) if (cachedLocations == null || !cachedLocations.SequenceEqual(rp.Path))
{ {
cachedLocation = rp.Location; cachedLocations = new List<CPos>(rp.Path);
targetLineNodes.Clear();
foreach (var c in cachedLocations)
targetLineNodes.Add(world.Map.CenterOfCell(c));
var rallyPos = world.Map.CenterOfCell(cachedLocation);
var exitPos = building.CenterPosition; var exitPos = building.CenterPosition;
// Find closest exit // Find closest exit
@@ -64,7 +66,7 @@ namespace OpenRA.Mods.Common.Effects
foreach (var exit in exits) foreach (var exit in exits)
{ {
var ep = building.CenterPosition + exit.SpawnOffset; var ep = building.CenterPosition + exit.SpawnOffset;
var len = (rallyPos - ep).Length; var len = (targetLineNodes[0] - ep).Length;
if (len < dist) if (len < dist)
{ {
dist = len; dist = len;
@@ -72,8 +74,7 @@ namespace OpenRA.Mods.Common.Effects
} }
} }
targetLine[0] = exitPos; targetLineNodes.Insert(0, exitPos);
targetLine[1] = rallyPos;
if (circles != null) if (circles != null)
circles.Play(rp.Info.CirclesSequence); circles.Play(rp.Info.CirclesSequence);
@@ -98,10 +99,10 @@ namespace OpenRA.Mods.Common.Effects
{ {
var palette = wr.Palette(rp.PaletteName); var palette = wr.Palette(rp.PaletteName);
if (circles != null) if (circles != null)
renderables = renderables.Concat(circles.Render(targetLine[1], palette)); renderables = renderables.Concat(circles.Render(targetLineNodes.Last(), palette));
if (flag != null) if (flag != null)
renderables = renderables.Concat(flag.Render(targetLine[1], palette)); renderables = renderables.Concat(flag.Render(targetLineNodes.Last(), palette));
} }
return renderables; return renderables;
@@ -118,7 +119,18 @@ namespace OpenRA.Mods.Common.Effects
if (!building.World.Selection.Contains(building)) if (!building.World.Selection.Contains(building))
return SpriteRenderable.None; return SpriteRenderable.None;
return new IRenderable[] { new TargetLineRenderable(targetLine, building.Owner.Color, rp.Info.LineWidth) }; return RenderInner(wr);
}
IEnumerable<IRenderable> RenderInner(WorldRenderer wr)
{
var prev = targetLineNodes[0];
foreach (var pos in targetLineNodes.Skip(1))
{
var targetLine = new[] { prev, pos };
prev = pos;
yield return new TargetLineRenderable(targetLine, building.Owner.Color, rp.Info.LineWidth);
}
} }
} }
} }

View File

@@ -79,8 +79,8 @@ namespace OpenRA.Mods.Common.Scripting
[Desc("Query or set a factory's rally point.")] [Desc("Query or set a factory's rally point.")]
public CPos RallyPoint public CPos RallyPoint
{ {
get { return rp.Location; } get { return rp.Path.Last(); }
set { rp.Location = value; } set { rp.Path = new List<CPos> { value }; }
} }
} }

View File

@@ -229,7 +229,7 @@ namespace OpenRA.Mods.Common.Traits
foreach (var rp in world.ActorsWithTrait<RallyPoint>()) foreach (var rp in world.ActorsWithTrait<RallyPoint>())
{ {
if (rp.Actor.Owner == player && if (rp.Actor.Owner == player &&
!IsRallyPointValid(rp.Trait.Location, rp.Actor.Info.TraitInfoOrDefault<BuildingInfo>())) !IsRallyPointValid(rp.Trait.Path[0], rp.Actor.Info.TraitInfoOrDefault<BuildingInfo>()))
{ {
bot.QueueOrder(new Order("SetRallyPoint", rp.Actor, Target.FromCell(world, ChooseRallyLocationNear(rp.Actor)), false) bot.QueueOrder(new Order("SetRallyPoint", rp.Actor, Target.FromCell(world, ChooseRallyLocationNear(rp.Actor)), false)
{ {

View File

@@ -48,23 +48,22 @@ namespace OpenRA.Mods.Common.Traits
{ {
const string OrderID = "SetRallyPoint"; const string OrderID = "SetRallyPoint";
[Sync] public List<CPos> Path;
public CPos Location;
public RallyPointInfo Info; public RallyPointInfo Info;
public string PaletteName { get; private set; } public string PaletteName { get; private set; }
const uint ForceSet = 1; const uint ForceSet = 1;
public void ResetLocation(Actor self) public void ResetPath(Actor self)
{ {
Location = self.Location + Info.Offset; Path = new List<CPos> { self.Location + Info.Offset };
} }
public RallyPoint(Actor self, RallyPointInfo info) public RallyPoint(Actor self, RallyPointInfo info)
{ {
Info = info; Info = info;
ResetLocation(self); ResetPath(self);
PaletteName = info.IsPlayerPalette ? info.Palette + self.Owner.InternalName : info.Palette; PaletteName = info.IsPlayerPalette ? info.Palette + self.Owner.InternalName : info.Palette;
} }
@@ -84,7 +83,7 @@ namespace OpenRA.Mods.Common.Traits
if (Info.IsPlayerPalette) if (Info.IsPlayerPalette)
PaletteName = Info.Palette + newOwner.InternalName; PaletteName = Info.Palette + newOwner.InternalName;
ResetLocation(self); ResetPath(self);
} }
public IEnumerable<IOrderTargeter> Orders public IEnumerable<IOrderTargeter> Orders
@@ -96,7 +95,7 @@ namespace OpenRA.Mods.Common.Traits
{ {
if (order.OrderID == OrderID) if (order.OrderID == OrderID)
{ {
return new Order(order.OrderID, self, target, false) return new Order(order.OrderID, self, target, queued)
{ {
SuppressVisualFeedback = true, SuppressVisualFeedback = true,
ExtraData = ((RallyPointOrderTargeter)order).ForceSet ? ForceSet : 0 ExtraData = ((RallyPointOrderTargeter)order).ForceSet ? ForceSet : 0
@@ -108,8 +107,13 @@ namespace OpenRA.Mods.Common.Traits
public void ResolveOrder(Actor self, Order order) public void ResolveOrder(Actor self, Order order)
{ {
if (order.OrderString == OrderID) if (order.OrderString != OrderID)
Location = self.World.Map.CellContaining(order.Target.CenterPosition); return;
if (!order.Queued)
Path.Clear();
Path.Add(self.World.Map.CellContaining(order.Target.CenterPosition));
} }
public static bool IsForceSet(Order order) public static bool IsForceSet(Order order)
@@ -130,12 +134,15 @@ namespace OpenRA.Mods.Common.Traits
public int OrderPriority { get { return 0; } } public int OrderPriority { get { return 0; } }
public bool TargetOverridesSelection(Actor self, Target target, List<Actor> actorsAt, CPos xy, TargetModifiers modifiers) { return true; } public bool TargetOverridesSelection(Actor self, Target target, List<Actor> actorsAt, CPos xy, TargetModifiers modifiers) { return true; }
public bool ForceSet { get; private set; } public bool ForceSet { get; private set; }
public bool IsQueued { get; protected set; }
public bool CanTarget(Actor self, Target target, List<Actor> othersAtTarget, ref TargetModifiers modifiers, ref string cursor) public bool CanTarget(Actor self, Target target, List<Actor> othersAtTarget, ref TargetModifiers modifiers, ref string cursor)
{ {
if (target.Type != TargetType.Terrain) if (target.Type != TargetType.Terrain)
return false; return false;
IsQueued = modifiers.HasModifier(TargetModifiers.ForceQueue);
var location = self.World.Map.CellContaining(target.CenterPosition); var location = self.World.Map.CellContaining(target.CenterPosition);
if (self.World.Map.Contains(location)) if (self.World.Map.Contains(location))
{ {
@@ -154,8 +161,6 @@ namespace OpenRA.Mods.Common.Traits
return false; return false;
} }
public bool IsQueued { get { return false; } } // unused
} }
} }
} }

View File

@@ -85,7 +85,8 @@ namespace OpenRA.Mods.Common.Traits
if (reservedForAircraft.GetActorBelow() == self) if (reservedForAircraft.GetActorBelow() == self)
{ {
if (rallyPoint != null) if (rallyPoint != null)
reservedFor.QueueActivity(reservedForAircraft.MoveTo(rallyPoint.Location, null, targetLineColor: Color.Green)); foreach (var cell in rallyPoint.Path)
reservedFor.QueueActivity(reservedForAircraft.MoveTo(cell, 1, targetLineColor: Color.Green));
else else
reservedFor.QueueActivity(new TakeOff(reservedFor)); reservedFor.QueueActivity(new TakeOff(reservedFor));
} }

View File

@@ -10,6 +10,7 @@
#endregion #endregion
using System; using System;
using System.Collections.Generic;
using OpenRA.Mods.Common.Activities; using OpenRA.Mods.Common.Activities;
using OpenRA.Primitives; using OpenRA.Primitives;
using OpenRA.Traits; using OpenRA.Traits;
@@ -42,7 +43,7 @@ namespace OpenRA.Mods.Common.Traits
public virtual void DoProduction(Actor self, ActorInfo producee, ExitInfo exitinfo, string productionType, TypeDictionary inits) public virtual void DoProduction(Actor self, ActorInfo producee, ExitInfo exitinfo, string productionType, TypeDictionary inits)
{ {
var exit = CPos.Zero; var exit = CPos.Zero;
var exitLocation = CPos.Zero; var exitLocations = new List<CPos>();
// Clone the initializer dictionary for the new actor // Clone the initializer dictionary for the new actor
var td = new TypeDictionary(); var td = new TypeDictionary();
@@ -68,7 +69,7 @@ namespace OpenRA.Mods.Common.Traits
initialFacing = delta.Yaw.Facing; initialFacing = delta.Yaw.Facing;
} }
exitLocation = rp.Value != null ? rp.Value.Location : exit; exitLocations = rp.Value != null ? rp.Value.Path : new List<CPos> { exit };
td.Add(new LocationInit(exit)); td.Add(new LocationInit(exit));
td.Add(new CenterPositionInit(spawn)); td.Add(new CenterPositionInit(spawn));
@@ -83,7 +84,8 @@ namespace OpenRA.Mods.Common.Traits
var move = newUnit.TraitOrDefault<IMove>(); var move = newUnit.TraitOrDefault<IMove>();
if (exitinfo != null && move != null) if (exitinfo != null && move != null)
newUnit.QueueActivity(new AttackMoveActivity(newUnit, () => move.MoveTo(exitLocation, 1, targetLineColor: Color.OrangeRed))); foreach (var cell in exitLocations)
newUnit.QueueActivity(new AttackMoveActivity(newUnit, () => move.MoveTo(cell, 1, evaluateNearestMovableCell: true, targetLineColor: Color.OrangeRed)));
if (!self.IsDead) if (!self.IsDead)
foreach (var t in self.TraitsImplementing<INotifyProduction>()) foreach (var t in self.TraitsImplementing<INotifyProduction>())

View File

@@ -9,8 +9,8 @@
*/ */
#endregion #endregion
using System.Collections.Generic;
using OpenRA.Primitives; using OpenRA.Primitives;
using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
{ {
@@ -49,7 +49,7 @@ namespace OpenRA.Mods.Common.Traits
var aircraftInfo = producee.TraitInfoOrDefault<AircraftInfo>(); var aircraftInfo = producee.TraitInfoOrDefault<AircraftInfo>();
var mobileInfo = producee.TraitInfoOrDefault<MobileInfo>(); var mobileInfo = producee.TraitInfoOrDefault<MobileInfo>();
var destination = rp != null ? rp.Location : self.Location; var destinations = rp != null ? rp.Path : new List<CPos> { self.Location };
var location = spawnLocation; var location = spawnLocation;
if (!location.HasValue) if (!location.HasValue)
@@ -61,7 +61,7 @@ namespace OpenRA.Mods.Common.Traits
{ {
var locomotorInfo = mobileInfo.LocomotorInfo; var locomotorInfo = mobileInfo.LocomotorInfo;
location = self.World.Map.ChooseClosestMatchingEdgeCell(self.Location, location = self.World.Map.ChooseClosestMatchingEdgeCell(self.Location,
c => mobileInfo.CanEnterCell(self.World, null, c) && domainIndex.IsPassable(c, destination, locomotorInfo)); c => mobileInfo.CanEnterCell(self.World, null, c) && domainIndex.IsPassable(c, destinations[0], locomotorInfo));
} }
} }
@@ -75,7 +75,7 @@ namespace OpenRA.Mods.Common.Traits
if (aircraftInfo != null) if (aircraftInfo != null)
pos += new WVec(0, 0, aircraftInfo.CruiseAltitude.Length); pos += new WVec(0, 0, aircraftInfo.CruiseAltitude.Length);
var initialFacing = self.World.Map.FacingBetween(location.Value, destination, 0); var initialFacing = self.World.Map.FacingBetween(location.Value, destinations[0], 0);
self.World.AddFrameEndTask(w => self.World.AddFrameEndTask(w =>
{ {
@@ -91,11 +91,12 @@ namespace OpenRA.Mods.Common.Traits
var move = newUnit.TraitOrDefault<IMove>(); var move = newUnit.TraitOrDefault<IMove>();
if (move != null) if (move != null)
newUnit.QueueActivity(move.MoveTo(destination, 2)); foreach (var cell in destinations)
newUnit.QueueActivity(move.MoveTo(cell, 2, evaluateNearestMovableCell: true));
if (!self.IsDead) if (!self.IsDead)
foreach (var t in self.TraitsImplementing<INotifyProduction>()) foreach (var t in self.TraitsImplementing<INotifyProduction>())
t.UnitProduced(self, newUnit, destination); t.UnitProduced(self, newUnit, destinations[0]);
var notifyOthers = self.World.ActorsWithTrait<INotifyOtherProduction>(); var notifyOthers = self.World.ActorsWithTrait<INotifyOtherProduction>();
foreach (var notify in notifyOthers) foreach (var notify in notifyOthers)

View File

@@ -10,6 +10,7 @@
#endregion #endregion
using System; using System;
using System.Collections.Generic;
using OpenRA.Activities; using OpenRA.Activities;
using OpenRA.Mods.Common.Activities; using OpenRA.Mods.Common.Activities;
using OpenRA.Primitives; using OpenRA.Primitives;
@@ -102,7 +103,7 @@ namespace OpenRA.Mods.Common.Traits
public override void DoProduction(Actor self, ActorInfo producee, ExitInfo exitinfo, string productionType, TypeDictionary inits) public override void DoProduction(Actor self, ActorInfo producee, ExitInfo exitinfo, string productionType, TypeDictionary inits)
{ {
var exit = CPos.Zero; var exit = CPos.Zero;
var exitLocation = CPos.Zero; var exitLocations = new List<CPos>();
var info = (ProductionParadropInfo)Info; var info = (ProductionParadropInfo)Info;
var actorType = info.ActorType; var actorType = info.ActorType;
@@ -122,7 +123,7 @@ namespace OpenRA.Mods.Common.Traits
var initialFacing = exitinfo.Facing < 0 ? (to - spawn).Yaw.Facing : exitinfo.Facing; var initialFacing = exitinfo.Facing < 0 ? (to - spawn).Yaw.Facing : exitinfo.Facing;
exitLocation = rp.Value != null ? rp.Value.Location : exit; exitLocations = rp.Value != null ? rp.Value.Path : new List<CPos> { exit };
td.Add(new LocationInit(exit)); td.Add(new LocationInit(exit));
td.Add(new CenterPositionInit(spawn)); td.Add(new CenterPositionInit(spawn));
@@ -137,7 +138,8 @@ namespace OpenRA.Mods.Common.Traits
var move = newUnit.TraitOrDefault<IMove>(); var move = newUnit.TraitOrDefault<IMove>();
if (move != null) if (move != null)
newUnit.QueueActivity(new AttackMoveActivity(newUnit, () => move.MoveTo(exitLocation, 1, targetLineColor: Color.OrangeRed))); foreach (var cell in exitLocations)
newUnit.QueueActivity(new AttackMoveActivity(newUnit, () => move.MoveTo(cell, 1, evaluateNearestMovableCell: true, targetLineColor: Color.OrangeRed)));
if (!self.IsDead) if (!self.IsDead)
foreach (var t in self.TraitsImplementing<INotifyProduction>()) foreach (var t in self.TraitsImplementing<INotifyProduction>())