Move everything Capture-related + Transform activity to Mods.Common
This commit is contained in:
77
OpenRA.Mods.Common/Activities/CaptureActor.cs
Normal file
77
OpenRA.Mods.Common/Activities/CaptureActor.cs
Normal file
@@ -0,0 +1,77 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2014 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. For more information,
|
||||
* see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using OpenRA.Mods.Common.Traits;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common.Activities
|
||||
{
|
||||
public class CaptureActor : Enter
|
||||
{
|
||||
readonly Actor actor;
|
||||
readonly Capturable capturable;
|
||||
readonly CapturesInfo capturesInfo;
|
||||
|
||||
public CaptureActor(Actor self, Actor target)
|
||||
: base(self, target)
|
||||
{
|
||||
actor = target;
|
||||
capturesInfo = self.Info.Traits.Get<CapturesInfo>();
|
||||
capturable = target.Trait<Capturable>();
|
||||
}
|
||||
|
||||
protected override bool CanReserve(Actor self)
|
||||
{
|
||||
return !capturable.BeingCaptured && capturable.Info.CanBeTargetedBy(self, actor.Owner);
|
||||
}
|
||||
|
||||
protected override void OnInside(Actor self)
|
||||
{
|
||||
if (actor.IsDead || capturable.BeingCaptured)
|
||||
return;
|
||||
|
||||
var b = actor.TraitOrDefault<Building>();
|
||||
if (b != null && !b.Lock())
|
||||
return;
|
||||
|
||||
self.World.AddFrameEndTask(w =>
|
||||
{
|
||||
if (b != null && b.Locked)
|
||||
b.Unlock();
|
||||
|
||||
if (actor.IsDead || capturable.BeingCaptured)
|
||||
return;
|
||||
|
||||
var health = actor.Trait<Health>();
|
||||
|
||||
var lowEnoughHealth = health.HP <= capturable.Info.CaptureThreshold * health.MaxHP;
|
||||
if (!capturesInfo.Sabotage || lowEnoughHealth || actor.Owner.NonCombatant)
|
||||
{
|
||||
var oldOwner = actor.Owner;
|
||||
|
||||
actor.ChangeOwner(self.Owner);
|
||||
|
||||
foreach (var t in actor.TraitsImplementing<INotifyCapture>())
|
||||
t.OnCapture(actor, self, oldOwner, self.Owner);
|
||||
|
||||
if (b != null && b.Locked)
|
||||
b.Unlock();
|
||||
}
|
||||
else
|
||||
{
|
||||
var damage = (int)(health.MaxHP * capturesInfo.SabotageHPRemoval);
|
||||
actor.InflictDamage(self, damage, null);
|
||||
}
|
||||
|
||||
self.Destroy();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
94
OpenRA.Mods.Common/Activities/Transform.cs
Normal file
94
OpenRA.Mods.Common/Activities/Transform.cs
Normal file
@@ -0,0 +1,94 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2014 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. For more information,
|
||||
* see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Linq;
|
||||
using OpenRA.Activities;
|
||||
using OpenRA.Mods.Common.Traits;
|
||||
using OpenRA.Primitives;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common.Activities
|
||||
{
|
||||
public class Transform : Activity
|
||||
{
|
||||
public readonly string ToActor;
|
||||
public CVec Offset = CVec.Zero;
|
||||
public int Facing = 96;
|
||||
public string[] Sounds = { };
|
||||
public int ForceHealthPercentage = 0;
|
||||
public bool SkipMakeAnims = false;
|
||||
public string Race = null;
|
||||
|
||||
public Transform(Actor self, string toActor)
|
||||
{
|
||||
ToActor = toActor;
|
||||
}
|
||||
|
||||
public override Activity Tick(Actor self)
|
||||
{
|
||||
if (IsCanceled)
|
||||
return NextActivity;
|
||||
|
||||
self.World.AddFrameEndTask(w =>
|
||||
{
|
||||
if (self.IsDead)
|
||||
return;
|
||||
|
||||
foreach (var nt in self.TraitsImplementing<INotifyTransform>())
|
||||
nt.OnTransform(self);
|
||||
|
||||
var selected = w.Selection.Contains(self);
|
||||
var controlgroup = w.Selection.GetControlGroupForActor(self);
|
||||
|
||||
self.Destroy();
|
||||
foreach (var s in Sounds)
|
||||
Sound.PlayToPlayer(self.Owner, s, self.CenterPosition);
|
||||
|
||||
var init = new TypeDictionary
|
||||
{
|
||||
new LocationInit(self.Location + Offset),
|
||||
new OwnerInit(self.Owner),
|
||||
new FacingInit(Facing),
|
||||
};
|
||||
|
||||
if (SkipMakeAnims)
|
||||
init.Add(new SkipMakeAnimsInit());
|
||||
|
||||
if (Race != null)
|
||||
init.Add(new RaceInit(Race));
|
||||
|
||||
var health = self.TraitOrDefault<Health>();
|
||||
if (health != null)
|
||||
{
|
||||
var newHP = (ForceHealthPercentage > 0)
|
||||
? ForceHealthPercentage / 100f
|
||||
: (float)health.HP / health.MaxHP;
|
||||
|
||||
init.Add(new HealthInit(newHP));
|
||||
}
|
||||
|
||||
var cargo = self.TraitOrDefault<Cargo>();
|
||||
if (cargo != null)
|
||||
init.Add(new RuntimeCargoInit(cargo.Passengers.ToArray()));
|
||||
|
||||
var a = w.CreateActor(ToActor, init);
|
||||
foreach (var nt in self.TraitsImplementing<INotifyTransform>())
|
||||
nt.AfterTransform(a);
|
||||
|
||||
if (selected)
|
||||
w.Selection.Add(w, a);
|
||||
if (controlgroup.HasValue)
|
||||
w.Selection.AddToControlGroup(a, controlgroup.Value);
|
||||
});
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -72,6 +72,7 @@
|
||||
<Compile Include="Activities\Air\ReturnToBase.cs" />
|
||||
<Compile Include="Activities\Air\TakeOff.cs" />
|
||||
<Compile Include="Activities\Attack.cs" />
|
||||
<Compile Include="Activities\CaptureActor.cs" />
|
||||
<Compile Include="Activities\Enter.cs" />
|
||||
<Compile Include="Activities\EnterTransport.cs" />
|
||||
<Compile Include="Activities\ExternalCaptureActor.cs" />
|
||||
@@ -90,6 +91,7 @@
|
||||
<Compile Include="Activities\RepairBuilding.cs" />
|
||||
<Compile Include="Activities\Sell.cs" />
|
||||
<Compile Include="Activities\SimpleTeleport.cs" />
|
||||
<Compile Include="Activities\Transform.cs" />
|
||||
<Compile Include="Activities\Turn.cs" />
|
||||
<Compile Include="Activities\UnloadCargo.cs" />
|
||||
<Compile Include="Activities\Wait.cs" />
|
||||
@@ -198,6 +200,9 @@
|
||||
<Compile Include="Traits\Buildings\Reservable.cs" />
|
||||
<Compile Include="Traits\Buildings\TargetableBuilding.cs" />
|
||||
<Compile Include="Traits\Burns.cs" />
|
||||
<Compile Include="Traits\Capturable.cs" />
|
||||
<Compile Include="Traits\CaptureNotification.cs" />
|
||||
<Compile Include="Traits\Captures.cs" />
|
||||
<Compile Include="Traits\Cargo.cs" />
|
||||
<Compile Include="Traits\CashTrickler.cs" />
|
||||
<Compile Include="Traits\Cloak.cs" />
|
||||
@@ -256,6 +261,8 @@
|
||||
<Compile Include="Traits\Power\RequiresPower.cs" />
|
||||
<Compile Include="Traits\Power\ScalePowerWithHealth.cs" />
|
||||
<Compile Include="Traits\ProvidesRadar.cs" />
|
||||
<Compile Include="Traits\ProximityCaptor.cs" />
|
||||
<Compile Include="Traits\ProximityCapturable.cs" />
|
||||
<Compile Include="Traits\RadarColorFromTerrain.cs" />
|
||||
<Compile Include="Traits\Reloads.cs" />
|
||||
<Compile Include="Traits\Render\Hovers.cs" />
|
||||
@@ -307,6 +314,7 @@
|
||||
<Compile Include="Traits\TargetableUnit.cs" />
|
||||
<Compile Include="Traits\ThrowsParticle.cs" />
|
||||
<Compile Include="Traits\Tooltip.cs" />
|
||||
<Compile Include="Traits\TransformOnCapture.cs" />
|
||||
<Compile Include="Traits\Turreted.cs" />
|
||||
<Compile Include="Traits\Upgrades\UpgradableTrait.cs" />
|
||||
<Compile Include="Traits\Upgrades\UpgradeManager.cs" />
|
||||
|
||||
72
OpenRA.Mods.Common/Traits/Capturable.cs
Normal file
72
OpenRA.Mods.Common/Traits/Capturable.cs
Normal file
@@ -0,0 +1,72 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2014 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. For more information,
|
||||
* see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Linq;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common.Traits
|
||||
{
|
||||
[Desc("This actor can be captured by a unit with Captures: trait.")]
|
||||
public class CapturableInfo : ITraitInfo
|
||||
{
|
||||
[Desc("Type listed under Types in Captures: trait of actors that can capture this).")]
|
||||
public readonly string Type = "building";
|
||||
public readonly bool AllowAllies = false;
|
||||
public readonly bool AllowNeutral = true;
|
||||
public readonly bool AllowEnemies = true;
|
||||
[Desc("Health percentage the target must be at (or below) before it can be captured.")]
|
||||
public readonly float CaptureThreshold = 0.5f;
|
||||
public readonly bool CancelActivity = false;
|
||||
|
||||
public object Create(ActorInitializer init) { return new Capturable(this); }
|
||||
|
||||
public bool CanBeTargetedBy(Actor captor, Player owner)
|
||||
{
|
||||
var c = captor.TraitOrDefault<Captures>();
|
||||
if (c == null)
|
||||
return false;
|
||||
|
||||
var playerRelationship = owner.Stances[captor.Owner];
|
||||
if (playerRelationship == Stance.Ally && !AllowAllies)
|
||||
return false;
|
||||
|
||||
if (playerRelationship == Stance.Enemy && !AllowEnemies)
|
||||
return false;
|
||||
|
||||
if (playerRelationship == Stance.Neutral && !AllowNeutral)
|
||||
return false;
|
||||
|
||||
if (!c.Info.CaptureTypes.Contains(Type))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public class Capturable : INotifyCapture
|
||||
{
|
||||
public readonly CapturableInfo Info;
|
||||
public bool BeingCaptured { get; private set; }
|
||||
public Capturable(CapturableInfo info) { Info = info; }
|
||||
|
||||
public void OnCapture(Actor self, Actor captor, Player oldOwner, Player newOwner)
|
||||
{
|
||||
BeingCaptured = true;
|
||||
self.World.AddFrameEndTask(w => BeingCaptured = false);
|
||||
|
||||
if (Info.CancelActivity)
|
||||
{
|
||||
var stop = new Order("Stop", self, false);
|
||||
foreach (var t in self.TraitsImplementing<IResolveOrder>())
|
||||
t.ResolveOrder(self, stop);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
40
OpenRA.Mods.Common/Traits/CaptureNotification.cs
Normal file
40
OpenRA.Mods.Common/Traits/CaptureNotification.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2014 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. For more information,
|
||||
* see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common.Traits
|
||||
{
|
||||
public class CaptureNotificationInfo : ITraitInfo
|
||||
{
|
||||
public readonly string Notification = "BuildingCaptured";
|
||||
public readonly bool NewOwnerVoice = true;
|
||||
|
||||
public object Create(ActorInitializer init) { return new CaptureNotification(this); }
|
||||
}
|
||||
|
||||
public class CaptureNotification : INotifyCapture
|
||||
{
|
||||
CaptureNotificationInfo info;
|
||||
public CaptureNotification(CaptureNotificationInfo info)
|
||||
{
|
||||
this.info = info;
|
||||
}
|
||||
|
||||
public void OnCapture(Actor self, Actor captor, Player oldOwner, Player newOwner)
|
||||
{
|
||||
if (captor.World.LocalPlayer != captor.Owner)
|
||||
return;
|
||||
|
||||
var race = info.NewOwnerVoice ? newOwner.Country.Race : oldOwner.Country.Race;
|
||||
Sound.PlayNotification(self.World.Map.Rules, captor.World.LocalPlayer, "Speech", info.Notification, race);
|
||||
}
|
||||
}
|
||||
}
|
||||
127
OpenRA.Mods.Common/Traits/Captures.cs
Normal file
127
OpenRA.Mods.Common/Traits/Captures.cs
Normal file
@@ -0,0 +1,127 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2014 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. For more information,
|
||||
* see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using OpenRA.Mods.Common.Activities;
|
||||
using OpenRA.Mods.Common.Orders;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common.Traits
|
||||
{
|
||||
[Desc("This actor can capture other actors which have the Capturable: trait.")]
|
||||
public class CapturesInfo : ITraitInfo
|
||||
{
|
||||
[Desc("Types of actors that it can capture, as long as the type also exists in the Capturable Type: trait.")]
|
||||
public readonly string[] CaptureTypes = { "building" };
|
||||
[Desc("Unit will do damage to the actor instead of capturing it. Unit is destroyed when sabotaging.")]
|
||||
public readonly bool Sabotage = true;
|
||||
[Desc("Only used if Sabotage=true. Sabotage damage expressed as a percentage of enemy health removed.")]
|
||||
public readonly float SabotageHPRemoval = 0.5f;
|
||||
|
||||
public object Create(ActorInitializer init) { return new Captures(init.Self, this); }
|
||||
}
|
||||
|
||||
public class Captures : IIssueOrder, IResolveOrder, IOrderVoice
|
||||
{
|
||||
public readonly CapturesInfo Info;
|
||||
|
||||
public Captures(Actor self, CapturesInfo info)
|
||||
{
|
||||
Info = info;
|
||||
}
|
||||
|
||||
public IEnumerable<IOrderTargeter> Orders
|
||||
{
|
||||
get
|
||||
{
|
||||
yield return new CaptureOrderTargeter(Info.Sabotage);
|
||||
}
|
||||
}
|
||||
|
||||
public Order IssueOrder(Actor self, IOrderTargeter order, Target target, bool queued)
|
||||
{
|
||||
if (order.OrderID != "CaptureActor")
|
||||
return null;
|
||||
|
||||
if (target.Type == TargetType.FrozenActor)
|
||||
return new Order(order.OrderID, self, queued) { ExtraData = target.FrozenActor.ID };
|
||||
|
||||
return new Order(order.OrderID, self, queued) { TargetActor = target.Actor };
|
||||
}
|
||||
|
||||
public string VoicePhraseForOrder(Actor self, Order order)
|
||||
{
|
||||
return order.OrderString == "CaptureActor" ? "Attack" : null;
|
||||
}
|
||||
|
||||
public void ResolveOrder(Actor self, Order order)
|
||||
{
|
||||
if (order.OrderString != "CaptureActor")
|
||||
return;
|
||||
|
||||
var target = self.ResolveFrozenActorOrder(order, Color.Red);
|
||||
if (target.Type != TargetType.Actor)
|
||||
return;
|
||||
|
||||
if (!order.Queued)
|
||||
self.CancelActivity();
|
||||
|
||||
self.SetTargetLine(target, Color.Red);
|
||||
self.QueueActivity(new CaptureActor(self, target.Actor));
|
||||
}
|
||||
|
||||
class CaptureOrderTargeter : UnitOrderTargeter
|
||||
{
|
||||
readonly bool sabotage;
|
||||
|
||||
public CaptureOrderTargeter(bool sabotage)
|
||||
: base("CaptureActor", 6, "enter", true, true)
|
||||
{
|
||||
this.sabotage = sabotage;
|
||||
}
|
||||
|
||||
public override bool CanTargetActor(Actor self, Actor target, TargetModifiers modifiers, ref string cursor)
|
||||
{
|
||||
var c = target.Info.Traits.GetOrDefault<CapturableInfo>();
|
||||
if (c == null || !c.CanBeTargetedBy(self, target.Owner))
|
||||
{
|
||||
cursor = "enter-blocked";
|
||||
return false;
|
||||
}
|
||||
|
||||
var health = target.Trait<Health>();
|
||||
var lowEnoughHealth = health.HP <= c.CaptureThreshold * health.MaxHP;
|
||||
|
||||
cursor = !sabotage || lowEnoughHealth || target.Owner.NonCombatant
|
||||
? "enter" : "capture";
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool CanTargetFrozenActor(Actor self, FrozenActor target, TargetModifiers modifiers, ref string cursor)
|
||||
{
|
||||
var c = target.Info.Traits.GetOrDefault<CapturableInfo>();
|
||||
if (c == null || !c.CanBeTargetedBy(self, target.Owner))
|
||||
{
|
||||
cursor = "enter-blocked";
|
||||
return false;
|
||||
}
|
||||
|
||||
var health = target.Info.Traits.GetOrDefault<HealthInfo>();
|
||||
var lowEnoughHealth = target.HP <= c.CaptureThreshold * health.HP;
|
||||
|
||||
cursor = !sabotage || lowEnoughHealth || target.Owner.NonCombatant
|
||||
? "enter" : "capture";
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
34
OpenRA.Mods.Common/Traits/ProximityCaptor.cs
Normal file
34
OpenRA.Mods.Common/Traits/ProximityCaptor.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2014 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. For more information,
|
||||
* see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Linq;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common.Traits
|
||||
{
|
||||
[Desc("Actor can capture ProximityCapturable actors.")]
|
||||
public class ProximityCaptorInfo : ITraitInfo
|
||||
{
|
||||
public readonly string[] Types = { };
|
||||
public object Create(ActorInitializer init) { return new ProximityCaptor(this); }
|
||||
}
|
||||
|
||||
public class ProximityCaptor
|
||||
{
|
||||
public readonly ProximityCaptorInfo Info;
|
||||
|
||||
public ProximityCaptor(ProximityCaptorInfo info) { Info = info; }
|
||||
|
||||
public bool HasAny(string[] typesList)
|
||||
{
|
||||
return typesList.Any(flag => Info.Types.Contains(flag));
|
||||
}
|
||||
}
|
||||
}
|
||||
149
OpenRA.Mods.Common/Traits/ProximityCapturable.cs
Normal file
149
OpenRA.Mods.Common/Traits/ProximityCapturable.cs
Normal file
@@ -0,0 +1,149 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2014 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. For more information,
|
||||
* see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.Effects;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common.Traits
|
||||
{
|
||||
[Desc("Actor can be captured by units in a specified proximity.")]
|
||||
public class ProximityCapturableInfo : ITraitInfo
|
||||
{
|
||||
public readonly bool Permanent = false;
|
||||
public readonly int Range = 5;
|
||||
public readonly bool MustBeClear = false;
|
||||
public readonly string[] CaptorTypes = { "Vehicle", "Tank", "Infantry" };
|
||||
|
||||
public object Create(ActorInitializer init) { return new ProximityCapturable(init.Self, this); }
|
||||
}
|
||||
|
||||
public class ProximityCapturable : ITick
|
||||
{
|
||||
public readonly Player OriginalOwner;
|
||||
public bool Captured { get { return Self.Owner != OriginalOwner; } }
|
||||
|
||||
public ProximityCapturableInfo Info;
|
||||
public Actor Self;
|
||||
|
||||
public ProximityCapturable(Actor self, ProximityCapturableInfo info)
|
||||
{
|
||||
Info = info;
|
||||
Self = self;
|
||||
OriginalOwner = self.Owner;
|
||||
}
|
||||
|
||||
public void Tick(Actor self)
|
||||
{
|
||||
if (Captured && Info.Permanent) return; // Permanent capture
|
||||
|
||||
if (!Captured)
|
||||
{
|
||||
var captor = GetInRange(self);
|
||||
|
||||
if (captor != null)
|
||||
if (!Info.MustBeClear || IsClear(self, captor.Owner, OriginalOwner))
|
||||
ChangeOwnership(self, captor);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// if the area must be clear, and there is more than 1 player nearby => return ownership to default
|
||||
if (Info.MustBeClear && !IsClear(self, self.Owner, OriginalOwner))
|
||||
{
|
||||
// Revert Ownership
|
||||
ChangeOwnership(self, OriginalOwner.PlayerActor);
|
||||
return;
|
||||
}
|
||||
|
||||
// See if the 'temporary' owner still is in range
|
||||
if (!IsStillInRange(self))
|
||||
{
|
||||
// no.. So find a new one
|
||||
var captor = GetInRange(self);
|
||||
|
||||
// got one
|
||||
if (captor != null)
|
||||
{
|
||||
ChangeOwnership(self, captor);
|
||||
return;
|
||||
}
|
||||
|
||||
// Revert Ownership otherwise
|
||||
ChangeOwnership(self, OriginalOwner.PlayerActor);
|
||||
}
|
||||
}
|
||||
|
||||
static void ChangeOwnership(Actor self, Actor captor)
|
||||
{
|
||||
self.World.AddFrameEndTask(w =>
|
||||
{
|
||||
if (self.Destroyed || captor.Destroyed) return;
|
||||
|
||||
var previousOwner = self.Owner;
|
||||
|
||||
// momentarily remove from world so the ownership queries don't get confused
|
||||
w.Remove(self);
|
||||
self.Owner = captor.Owner;
|
||||
w.Add(self);
|
||||
|
||||
if (self.Owner == self.World.LocalPlayer)
|
||||
w.Add(new FlashTarget(self));
|
||||
|
||||
foreach (var t in self.TraitsImplementing<INotifyCapture>())
|
||||
t.OnCapture(self, captor, previousOwner, self.Owner);
|
||||
});
|
||||
}
|
||||
|
||||
bool CanBeCapturedBy(Actor a)
|
||||
{
|
||||
var pc = a.TraitOrDefault<ProximityCaptor>();
|
||||
return pc != null && pc.HasAny(Info.CaptorTypes);
|
||||
}
|
||||
|
||||
IEnumerable<Actor> UnitsInRange()
|
||||
{
|
||||
return Self.World.FindActorsInCircle(Self.CenterPosition, WRange.FromCells(Info.Range))
|
||||
.Where(a => a.IsInWorld && a != Self && !a.Destroyed && !a.Owner.NonCombatant);
|
||||
}
|
||||
|
||||
bool IsClear(Actor self, Player currentOwner, Player originalOwner)
|
||||
{
|
||||
return UnitsInRange()
|
||||
.All(a => a.Owner == originalOwner || a.Owner == currentOwner ||
|
||||
WorldUtils.AreMutualAllies(a.Owner, currentOwner) || !CanBeCapturedBy(a));
|
||||
}
|
||||
|
||||
// TODO exclude other NeutralActor that arent permanent
|
||||
bool IsStillInRange(Actor self)
|
||||
{
|
||||
return UnitsInRange().Any(a => a.Owner == self.Owner && CanBeCapturedBy(a));
|
||||
}
|
||||
|
||||
IEnumerable<Actor> CaptorsInRange(Actor self)
|
||||
{
|
||||
return UnitsInRange()
|
||||
.Where(a => a.Owner != OriginalOwner && CanBeCapturedBy(a));
|
||||
}
|
||||
|
||||
// TODO exclude other NeutralActor that arent permanent
|
||||
Actor GetInRange(Actor self)
|
||||
{
|
||||
return CaptorsInRange(self).ClosestTo(self);
|
||||
}
|
||||
|
||||
int CountPlayersNear(Actor self, Player ignoreMe)
|
||||
{
|
||||
return CaptorsInRange(self).Select(a => a.Owner).Where(p => p != ignoreMe)
|
||||
.Distinct().Count();
|
||||
}
|
||||
}
|
||||
}
|
||||
41
OpenRA.Mods.Common/Traits/TransformOnCapture.cs
Normal file
41
OpenRA.Mods.Common/Traits/TransformOnCapture.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2014 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. For more information,
|
||||
* see COPYING.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using OpenRA.Mods.Common.Activities;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common.Traits
|
||||
{
|
||||
public class TransformOnCaptureInfo : ITraitInfo
|
||||
{
|
||||
[ActorReference] public readonly string IntoActor = null;
|
||||
public readonly int ForceHealthPercentage = 0;
|
||||
public readonly bool SkipMakeAnims = true;
|
||||
|
||||
public virtual object Create(ActorInitializer init) { return new TransformOnCapture(this); }
|
||||
}
|
||||
|
||||
public class TransformOnCapture : INotifyCapture
|
||||
{
|
||||
readonly TransformOnCaptureInfo info;
|
||||
|
||||
public TransformOnCapture(TransformOnCaptureInfo info) { this.info = info; }
|
||||
|
||||
public void OnCapture(Actor self, Actor captor, Player oldOwner, Player newOwner)
|
||||
{
|
||||
var facing = self.TraitOrDefault<IFacing>();
|
||||
var transform = new Transform(self, info.IntoActor) { ForceHealthPercentage = info.ForceHealthPercentage };
|
||||
if (facing != null) transform.Facing = facing.Facing;
|
||||
transform.SkipMakeAnims = info.SkipMakeAnims;
|
||||
self.CancelActivity();
|
||||
self.QueueActivity(transform);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user