Reimplement demolition lock using conditions.
This commit is contained in:
@@ -52,23 +52,13 @@ namespace OpenRA.Mods.Common.Activities
|
||||
if (target.IsDead)
|
||||
return;
|
||||
|
||||
w.Add(new FlashTarget(target, count: flashes, delay: flashesDelay, interval: flashInterval));
|
||||
|
||||
foreach (var ind in notifiers)
|
||||
ind.Demolishing(self);
|
||||
|
||||
w.Add(new FlashTarget(target, count: flashes, delay: flashesDelay, interval: flashInterval));
|
||||
|
||||
w.Add(new DelayedAction(delay, () =>
|
||||
{
|
||||
if (target.IsDead)
|
||||
return;
|
||||
|
||||
var modifiers = target.TraitsImplementing<IDamageModifier>()
|
||||
.Concat(self.Owner.PlayerActor.TraitsImplementing<IDamageModifier>())
|
||||
.Select(t => t.GetDamageModifier(self, null));
|
||||
|
||||
if (Util.ApplyPercentageModifiers(100, modifiers) > 0)
|
||||
demolishables.Do(d => d.Demolish(target, self));
|
||||
}));
|
||||
foreach (var d in demolishables)
|
||||
d.Demolish(target, self, delay);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -589,6 +589,7 @@
|
||||
<Compile Include="Traits\World\WeatherOverlay.cs" />
|
||||
<Compile Include="Traits\World\ActorSpawnManager.cs" />
|
||||
<Compile Include="Traits\ActorSpawner.cs" />
|
||||
<Compile Include="UpdateRules\Rules\20180923\RemovedDemolishLocking.cs" />
|
||||
<Compile Include="UpdateRules\Rules\20180923\RenameCrateActionNotification.cs" />
|
||||
<Compile Include="UpdateRules\Rules\20180923\MergeCaptureTraits.cs" />
|
||||
<Compile Include="UpdateRules\Rules\20180923\RemovedNotifyBuildComplete.cs" />
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.Effects;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common.Traits
|
||||
@@ -164,17 +165,36 @@ namespace OpenRA.Mods.Common.Traits
|
||||
repairDelay = Info.RepairPropagationDelay;
|
||||
}
|
||||
|
||||
public void Demolish(Actor self, Actor saboteur)
|
||||
bool IDemolishable.IsValidTarget(Actor self, Actor saboteur)
|
||||
{
|
||||
if (Info.DemolishPropagationDelay > 0)
|
||||
return true;
|
||||
}
|
||||
|
||||
void IDemolishable.Demolish(Actor self, Actor saboteur, int delay)
|
||||
{
|
||||
// TODO: Handle using ITick
|
||||
self.World.Add(new DelayedAction(delay, () =>
|
||||
{
|
||||
demolishStep = 0;
|
||||
demolishSaboteur = saboteur;
|
||||
DemolishStep();
|
||||
}
|
||||
else
|
||||
foreach (var s in segments.Values)
|
||||
s.Demolish(saboteur);
|
||||
if (self.IsDead)
|
||||
return;
|
||||
|
||||
var modifiers = self.TraitsImplementing<IDamageModifier>()
|
||||
.Concat(self.Owner.PlayerActor.TraitsImplementing<IDamageModifier>())
|
||||
.Select(t => t.GetDamageModifier(self, null));
|
||||
|
||||
if (Util.ApplyPercentageModifiers(100, modifiers) > 0)
|
||||
{
|
||||
if (Info.DemolishPropagationDelay > 0)
|
||||
{
|
||||
demolishStep = 0;
|
||||
demolishSaboteur = saboteur;
|
||||
DemolishStep();
|
||||
}
|
||||
else
|
||||
foreach (var s in segments.Values)
|
||||
s.Demolish(saboteur);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
public void DemolishStep()
|
||||
@@ -202,11 +222,6 @@ namespace OpenRA.Mods.Common.Traits
|
||||
demolishStep++;
|
||||
}
|
||||
|
||||
public bool IsValidTarget(Actor self, Actor saboteur)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public DamageState BridgeDamageState
|
||||
{
|
||||
get
|
||||
|
||||
@@ -244,7 +244,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
}
|
||||
|
||||
public class Building : IOccupySpace, ITargetableCells, INotifySold, INotifyTransform, ISync, INotifyCreated,
|
||||
INotifyAddedToWorld, INotifyRemovedFromWorld, INotifyDemolition
|
||||
INotifyAddedToWorld, INotifyRemovedFromWorld
|
||||
{
|
||||
public readonly bool SkipMakeAnimation;
|
||||
public readonly BuildingInfo Info;
|
||||
@@ -333,11 +333,6 @@ namespace OpenRA.Mods.Common.Traits
|
||||
notify.BuildingComplete(self);
|
||||
}
|
||||
|
||||
void INotifyDemolition.Demolishing(Actor self)
|
||||
{
|
||||
Lock();
|
||||
}
|
||||
|
||||
void INotifySold.Selling(Actor self)
|
||||
{
|
||||
if (Info.RemoveSmudgesOnSell)
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#endregion
|
||||
|
||||
using System.Linq;
|
||||
using OpenRA.Effects;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common.Traits
|
||||
@@ -43,14 +44,26 @@ namespace OpenRA.Mods.Common.Traits
|
||||
Bridge.Do((b, d) => b.Repair(repairer, d, () => repairDirections--));
|
||||
}
|
||||
|
||||
public void Demolish(Actor self, Actor saboteur)
|
||||
{
|
||||
Bridge.Do((b, d) => b.Demolish(saboteur, d));
|
||||
}
|
||||
|
||||
public bool IsValidTarget(Actor self, Actor saboteur)
|
||||
bool IDemolishable.IsValidTarget(Actor self, Actor saboteur)
|
||||
{
|
||||
return BridgeDamageState != DamageState.Dead;
|
||||
}
|
||||
|
||||
void IDemolishable.Demolish(Actor self, Actor saboteur, int delay)
|
||||
{
|
||||
// TODO: Handle using ITick
|
||||
self.World.Add(new DelayedAction(delay, () =>
|
||||
{
|
||||
if (self.IsDead)
|
||||
return;
|
||||
|
||||
var modifiers = self.TraitsImplementing<IDamageModifier>()
|
||||
.Concat(self.Owner.PlayerActor.TraitsImplementing<IDamageModifier>())
|
||||
.Select(t => t.GetDamageModifier(self, null));
|
||||
|
||||
if (Util.ApplyPercentageModifiers(100, modifiers) > 0)
|
||||
Bridge.Do((b, d) => b.Demolish(saboteur, d));
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,43 +9,91 @@
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.Effects;
|
||||
using OpenRA.Primitives;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common.Traits
|
||||
{
|
||||
[Desc("Handle demolitions from C4 explosives.")]
|
||||
public class DemolishableInfo : IDemolishableInfo, ITraitInfo
|
||||
public class DemolishableInfo : ConditionalTraitInfo, IDemolishableInfo, ITraitInfo
|
||||
{
|
||||
public bool IsValidTarget(ActorInfo actorInfo, Actor saboteur) { return true; }
|
||||
|
||||
[Desc("If true and this actor has EjectOnDeath, no actor will be spawned.")]
|
||||
public readonly bool PreventsEjectOnDeath = false;
|
||||
[GrantedConditionReference]
|
||||
[Desc("Condition to grant during demolition countdown.")]
|
||||
public readonly string Condition = null;
|
||||
|
||||
public object Create(ActorInitializer init) { return new Demolishable(init.Self, this); }
|
||||
public override object Create(ActorInitializer init) { return new Demolishable(this); }
|
||||
}
|
||||
|
||||
public class Demolishable : IDemolishable, IPreventsEjectOnDeath
|
||||
public class Demolishable : ConditionalTrait<DemolishableInfo>, IDemolishable, ITick
|
||||
{
|
||||
readonly DemolishableInfo info;
|
||||
|
||||
public Demolishable(Actor self, DemolishableInfo info)
|
||||
class DemolishAction
|
||||
{
|
||||
this.info = info;
|
||||
public readonly Actor Saboteur;
|
||||
public readonly int Token;
|
||||
public int Delay;
|
||||
|
||||
public DemolishAction(Actor saboteur, int delay, int token)
|
||||
{
|
||||
Saboteur = saboteur;
|
||||
Delay = delay;
|
||||
Token = token;
|
||||
}
|
||||
}
|
||||
|
||||
public bool PreventsEjectOnDeath(Actor self)
|
||||
ConditionManager conditionManager;
|
||||
List<DemolishAction> actions = new List<DemolishAction>();
|
||||
|
||||
public Demolishable(DemolishableInfo info)
|
||||
: base(info) { }
|
||||
|
||||
protected override void Created(Actor self)
|
||||
{
|
||||
return info.PreventsEjectOnDeath;
|
||||
base.Created(self);
|
||||
conditionManager = self.TraitOrDefault<ConditionManager>();
|
||||
}
|
||||
|
||||
public void Demolish(Actor self, Actor saboteur)
|
||||
bool IDemolishable.IsValidTarget(Actor self, Actor saboteur)
|
||||
{
|
||||
self.Kill(saboteur);
|
||||
return !IsTraitDisabled;
|
||||
}
|
||||
|
||||
public bool IsValidTarget(Actor self, Actor saboteur)
|
||||
void IDemolishable.Demolish(Actor self, Actor saboteur, int delay)
|
||||
{
|
||||
return true;
|
||||
if (IsTraitDisabled)
|
||||
return;
|
||||
|
||||
var token = ConditionManager.InvalidConditionToken;
|
||||
if (conditionManager != null && !string.IsNullOrEmpty(Info.Condition))
|
||||
token = conditionManager.GrantCondition(self, Info.Condition);
|
||||
|
||||
actions.Add(new DemolishAction(saboteur, delay, token));
|
||||
}
|
||||
|
||||
void ITick.Tick(Actor self)
|
||||
{
|
||||
if (IsTraitDisabled)
|
||||
return;
|
||||
|
||||
foreach (var a in actions)
|
||||
{
|
||||
if (a.Delay-- <= 0)
|
||||
{
|
||||
var modifiers = self.TraitsImplementing<IDamageModifier>()
|
||||
.Concat(self.Owner.PlayerActor.TraitsImplementing<IDamageModifier>())
|
||||
.Select(t => t.GetDamageModifier(self, null));
|
||||
|
||||
if (Util.ApplyPercentageModifiers(100, modifiers) > 0)
|
||||
self.Kill(a.Saboteur);
|
||||
else if (a.Token != ConditionManager.InvalidConditionToken)
|
||||
conditionManager.RevokeCondition(self, a.Token);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -40,8 +40,6 @@ namespace OpenRA.Mods.Common.Traits
|
||||
public override object Create(ActorInitializer init) { return new EjectOnDeath(init.Self, this); }
|
||||
}
|
||||
|
||||
public interface IPreventsEjectOnDeath { bool PreventsEjectOnDeath(Actor self); }
|
||||
|
||||
public class EjectOnDeath : ConditionalTrait<EjectOnDeathInfo>, INotifyKilled
|
||||
{
|
||||
public EjectOnDeath(Actor self, EjectOnDeathInfo info)
|
||||
@@ -52,10 +50,6 @@ namespace OpenRA.Mods.Common.Traits
|
||||
if (IsTraitDisabled || self.Owner.WinState == WinState.Lost || !self.World.Map.Contains(self.Location))
|
||||
return;
|
||||
|
||||
foreach (var condition in self.TraitsImplementing<IPreventsEjectOnDeath>())
|
||||
if (condition.PreventsEjectOnDeath(self))
|
||||
return;
|
||||
|
||||
var r = self.World.SharedRandom.Next(1, 100);
|
||||
|
||||
if (r <= 100 - Info.SuccessRate)
|
||||
|
||||
@@ -71,8 +71,8 @@ namespace OpenRA.Mods.Common.Traits
|
||||
public interface IDemolishableInfo : ITraitInfoInterface { bool IsValidTarget(ActorInfo actorInfo, Actor saboteur); }
|
||||
public interface IDemolishable
|
||||
{
|
||||
void Demolish(Actor self, Actor saboteur);
|
||||
bool IsValidTarget(Actor self, Actor saboteur);
|
||||
void Demolish(Actor self, Actor saboteur, int delay);
|
||||
}
|
||||
|
||||
// Type tag for crush class bits
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
#region Copyright & License Information
|
||||
/*
|
||||
* Copyright 2007-2018 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.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace OpenRA.Mods.Common.UpdateRules.Rules
|
||||
{
|
||||
public class RemovedDemolishLocking : UpdateRule
|
||||
{
|
||||
public override string Name { get { return "Traits are no longer automatically disabled during the Demolition countdown"; } }
|
||||
public override string Description
|
||||
{
|
||||
get
|
||||
{
|
||||
return "Traits are no longer force-disabled during the Demolishing trait destruction countdown.\n" +
|
||||
"This affects the Production*, Transforms, Sellable, EjectOnDeath and ToggleConditionOnOrder traits.\n" +
|
||||
"Affected actors are listed so that conditions may be manually defined.";
|
||||
}
|
||||
}
|
||||
|
||||
static readonly string[] Traits =
|
||||
{
|
||||
"Production",
|
||||
"ProductionAirdrop",
|
||||
"ProductionFromMapEdge",
|
||||
"ProductionParadrop",
|
||||
"Transforms",
|
||||
"Sellable",
|
||||
"ToggleConditionOnOrder",
|
||||
"EjectOnDeath"
|
||||
};
|
||||
|
||||
readonly Dictionary<string, List<string>> locations = new Dictionary<string, List<string>>();
|
||||
|
||||
public override IEnumerable<string> AfterUpdate(ModData modData)
|
||||
{
|
||||
if (locations.Any())
|
||||
yield return "Review the following definitions and, if the actor is Demolishable,\n" +
|
||||
"define Demolishable.Condition and use this condition to disable them:\n" +
|
||||
UpdateUtils.FormatMessageList(locations.Select(
|
||||
kv => kv.Key + ":\n" + UpdateUtils.FormatMessageList(kv.Value)));
|
||||
|
||||
locations.Clear();
|
||||
}
|
||||
|
||||
public override IEnumerable<string> UpdateActorNode(ModData modData, MiniYamlNode actorNode)
|
||||
{
|
||||
var used = new List<string>();
|
||||
foreach (var t in Traits)
|
||||
if (actorNode.LastChildMatching(t, includeRemovals: false) != null)
|
||||
used.Add(t);
|
||||
|
||||
if (used.Any())
|
||||
{
|
||||
var location = "{0} ({1})".F(actorNode.Key, actorNode.Location.Filename);
|
||||
locations[location] = used;
|
||||
}
|
||||
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -102,6 +102,7 @@ namespace OpenRA.Mods.Common.UpdateRules
|
||||
new RemoveRepairBuildingsFromAircraft(),
|
||||
new AddRearmable(),
|
||||
new MergeAttackPlaneAndHeli(),
|
||||
new RemovedDemolishLocking(),
|
||||
})
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user