107 lines
3.4 KiB
C#
107 lines
3.4 KiB
C#
#region Copyright & License Information
|
|
/*
|
|
* Copyright 2007-2021 The OpenRA Developers (see AUTHORS)
|
|
* This file is part of OpenRA, which is free software. It is made
|
|
* available to you under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation, either version 3 of
|
|
* the License, or (at your option) any later version. For more
|
|
* information, see COPYING.
|
|
*/
|
|
#endregion
|
|
|
|
using System;
|
|
using OpenRA.Mods.Common.Activities;
|
|
using OpenRA.Primitives;
|
|
using OpenRA.Traits;
|
|
|
|
namespace OpenRA.Mods.Common.Traits
|
|
{
|
|
[Desc("Reserve landing places for aircraft.")]
|
|
class ReservableInfo : TraitInfo<Reservable> { }
|
|
|
|
public class Reservable : ITick, INotifyOwnerChanged, INotifySold, INotifyActorDisposing, INotifyCreated
|
|
{
|
|
Actor reservedFor;
|
|
Aircraft reservedForAircraft;
|
|
RallyPoint rallyPoint;
|
|
|
|
void INotifyCreated.Created(Actor self)
|
|
{
|
|
rallyPoint = self.TraitOrDefault<RallyPoint>();
|
|
}
|
|
|
|
void ITick.Tick(Actor self)
|
|
{
|
|
// Nothing to do.
|
|
if (reservedFor == null)
|
|
return;
|
|
|
|
if (!Target.FromActor(reservedFor).IsValidFor(self))
|
|
{
|
|
// Not likely to arrive now.
|
|
reservedForAircraft.UnReserve();
|
|
reservedFor = null;
|
|
reservedForAircraft = null;
|
|
}
|
|
}
|
|
|
|
public IDisposable Reserve(Actor self, Actor forActor, Aircraft forAircraft)
|
|
{
|
|
if (reservedForAircraft != null && reservedForAircraft.MayYieldReservation)
|
|
UnReserve(self);
|
|
|
|
reservedFor = forActor;
|
|
reservedForAircraft = forAircraft;
|
|
|
|
// NOTE: we really don't care about the GC eating DisposableActions that apply to a world *other* than
|
|
// the one we're playing in.
|
|
return new DisposableAction(
|
|
() => { reservedFor = null; reservedForAircraft = null; },
|
|
() => Game.RunAfterTick(() =>
|
|
{
|
|
if (Game.IsCurrentWorld(self.World))
|
|
throw new InvalidOperationException(
|
|
$"Attempted to finalize an undisposed DisposableAction. {forActor.Info.Name} ({forActor.ActorID}) reserved {self.Info.Name} ({self.ActorID})");
|
|
}));
|
|
}
|
|
|
|
public static bool IsReserved(Actor a)
|
|
{
|
|
var res = a.TraitOrDefault<Reservable>();
|
|
return res != null && res.reservedForAircraft != null && !res.reservedForAircraft.MayYieldReservation;
|
|
}
|
|
|
|
public static bool IsAvailableFor(Actor reservable, Actor forActor)
|
|
{
|
|
var res = reservable.TraitOrDefault<Reservable>();
|
|
return res == null || res.reservedForAircraft == null || res.reservedForAircraft.MayYieldReservation || res.reservedFor == forActor;
|
|
}
|
|
|
|
void UnReserve(Actor self)
|
|
{
|
|
if (reservedForAircraft != null)
|
|
{
|
|
if (reservedForAircraft.GetActorBelow() == self)
|
|
{
|
|
// HACK: Cache this in a local var, such that the inner activity of AttackMoveActivity can access the trait easily after reservedForAircraft was nulled
|
|
var aircraft = reservedForAircraft;
|
|
if (rallyPoint != null && rallyPoint.Path.Count > 0)
|
|
foreach (var cell in rallyPoint.Path)
|
|
reservedFor.QueueActivity(new AttackMoveActivity(reservedFor, () => aircraft.MoveTo(cell, 1, targetLineColor: Color.OrangeRed)));
|
|
else
|
|
reservedFor.QueueActivity(new TakeOff(reservedFor));
|
|
}
|
|
|
|
reservedForAircraft.UnReserve();
|
|
}
|
|
}
|
|
|
|
void INotifyActorDisposing.Disposing(Actor self) { UnReserve(self); }
|
|
|
|
void INotifyOwnerChanged.OnOwnerChanged(Actor self, Player oldOwner, Player newOwner) { UnReserve(self); }
|
|
|
|
void INotifySold.Selling(Actor self) { UnReserve(self); }
|
|
void INotifySold.Sold(Actor self) { UnReserve(self); }
|
|
}
|
|
}
|