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,7 +165,24 @@ namespace OpenRA.Mods.Common.Traits
|
||||
repairDelay = Info.RepairPropagationDelay;
|
||||
}
|
||||
|
||||
public void Demolish(Actor self, Actor saboteur)
|
||||
bool IDemolishable.IsValidTarget(Actor self, Actor saboteur)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if (Info.DemolishPropagationDelay > 0)
|
||||
{
|
||||
@@ -176,6 +194,8 @@ namespace OpenRA.Mods.Common.Traits
|
||||
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;
|
||||
class DemolishAction
|
||||
{
|
||||
public readonly Actor Saboteur;
|
||||
public readonly int Token;
|
||||
public int Delay;
|
||||
|
||||
public Demolishable(Actor self, DemolishableInfo info)
|
||||
public DemolishAction(Actor saboteur, int delay, int token)
|
||||
{
|
||||
this.info = info;
|
||||
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(),
|
||||
})
|
||||
};
|
||||
|
||||
|
||||
@@ -13,16 +13,22 @@ World:
|
||||
|
||||
NUKE:
|
||||
-Sellable:
|
||||
Demolishable:
|
||||
-Condition:
|
||||
Buildable:
|
||||
BuildLimit: 1
|
||||
|
||||
PYLE:
|
||||
-Sellable:
|
||||
Demolishable:
|
||||
-Condition:
|
||||
Buildable:
|
||||
BuildLimit: 1
|
||||
|
||||
FACT:
|
||||
-Sellable:
|
||||
Demolishable:
|
||||
-Condition:
|
||||
|
||||
PROC:
|
||||
Buildable:
|
||||
|
||||
@@ -144,6 +144,8 @@ HPAD.IN:
|
||||
BuildSounds: placbldg.aud, build5.aud
|
||||
UndeploySounds: cashturn.aud
|
||||
-Sellable:
|
||||
Demolishable:
|
||||
-Condition:
|
||||
-Power:
|
||||
|
||||
ORCA.IN:
|
||||
|
||||
@@ -744,7 +744,10 @@
|
||||
SpawnActorsOnSell:
|
||||
ActorTypes: e6,e1,e1,e1
|
||||
EngineerRepairable:
|
||||
Demolishable:
|
||||
Condition: being-demolished
|
||||
Sellable:
|
||||
RequiresCondition: !being-demolished
|
||||
SellSounds: cashturn.aud
|
||||
CaptureManager:
|
||||
Capturable:
|
||||
|
||||
@@ -20,10 +20,11 @@ FACT:
|
||||
Production:
|
||||
Produces: Building.GDI, Building.Nod, Defence.GDI, Defence.Nod
|
||||
Transforms:
|
||||
RequiresCondition: factundeploy
|
||||
PauseOnCondition: being-demolished
|
||||
IntoActor: mcv
|
||||
Offset: 1,1
|
||||
Facing: 108
|
||||
RequiresCondition: factundeploy
|
||||
GrantConditionOnPrerequisite@GLOBALFACTUNDEPLOY:
|
||||
Condition: factundeploy
|
||||
Prerequisites: global-factundeploy
|
||||
|
||||
@@ -144,6 +144,8 @@ sietch:
|
||||
-Sellable:
|
||||
-Capturable:
|
||||
-RepairableBuilding:
|
||||
Demolishable:
|
||||
-Condition:
|
||||
ProvidesPrerequisite@buildingname:
|
||||
-WithMakeAnimation:
|
||||
-WithCrumbleOverlay:
|
||||
|
||||
@@ -409,11 +409,13 @@
|
||||
ActorLostNotification:
|
||||
Notification: BuildingLost
|
||||
ShakeOnDeath:
|
||||
Demolishable:
|
||||
Condition: being-demolished
|
||||
Sellable:
|
||||
RequiresCondition: !being-demolished
|
||||
SellSounds: BUILD1.WAV
|
||||
Guardable:
|
||||
Range: 3c0
|
||||
Demolishable:
|
||||
DamagedByTerrain:
|
||||
Damage: 500
|
||||
DamageInterval: 100
|
||||
|
||||
@@ -75,6 +75,8 @@ ATEK:
|
||||
CaptureManager:
|
||||
-BeingCapturedCondition:
|
||||
-Sellable:
|
||||
Demolishable:
|
||||
-Condition:
|
||||
|
||||
PDOX:
|
||||
Inherits@IDISABLE: ^DisableOnLowPower
|
||||
@@ -85,6 +87,8 @@ PDOX:
|
||||
CaptureManager:
|
||||
-BeingCapturedCondition:
|
||||
-Sellable:
|
||||
Demolishable:
|
||||
-Condition:
|
||||
|
||||
IRON:
|
||||
Buildable:
|
||||
|
||||
@@ -170,6 +170,8 @@ TENT:
|
||||
Production:
|
||||
Produces: Infantry, Soldier, Dog, Defense
|
||||
-Sellable:
|
||||
Demolishable:
|
||||
-Condition:
|
||||
BaseProvider:
|
||||
Range: 12c0
|
||||
Power:
|
||||
|
||||
@@ -39,13 +39,19 @@ AFLD:
|
||||
DropItems: E1,E1,E1,E2,E2
|
||||
-RallyPoint:
|
||||
-Sellable:
|
||||
Demolishable:
|
||||
-Condition:
|
||||
|
||||
DOME:
|
||||
CaptureManager:
|
||||
-BeingCapturedCondition:
|
||||
-Sellable:
|
||||
Demolishable:
|
||||
-Condition:
|
||||
|
||||
POWR:
|
||||
CaptureManager:
|
||||
-BeingCapturedCondition:
|
||||
-Sellable:
|
||||
Demolishable:
|
||||
-Condition:
|
||||
|
||||
@@ -33,6 +33,8 @@ FTUR:
|
||||
CaptureManager:
|
||||
-BeingCapturedCondition:
|
||||
-Sellable:
|
||||
Demolishable:
|
||||
-Condition:
|
||||
|
||||
PBOX:
|
||||
-AutoTarget:
|
||||
|
||||
@@ -663,8 +663,10 @@
|
||||
RequiredForShortGame: true
|
||||
GpsDot:
|
||||
String: Structure
|
||||
Demolishable:
|
||||
Condition: being-demolished
|
||||
Sellable:
|
||||
RequiresCondition: !being-captured
|
||||
RequiresCondition: !being-captured && !being-demolished
|
||||
SellSounds: cashturn.aud
|
||||
WithBuildingRepairDecoration:
|
||||
Image: allyrepair
|
||||
|
||||
@@ -1127,13 +1127,13 @@ FACT:
|
||||
ActorTypes: e1,e1,e1,tecn,tecn,e6
|
||||
BaseBuilding:
|
||||
Transforms:
|
||||
PauseOnCondition: chrono-vortex || being-captured
|
||||
RequiresCondition: factundeploy
|
||||
PauseOnCondition: chrono-vortex || being-captured || being-demolished
|
||||
IntoActor: mcv
|
||||
Offset: 1,1
|
||||
Facing: 96
|
||||
RequiresCondition: factundeploy
|
||||
Sellable:
|
||||
RequiresCondition: !chrono-vortex && !being-captured
|
||||
RequiresCondition: !chrono-vortex && !being-captured && !being-demolished
|
||||
GrantConditionOnPrerequisite@GLOBALFACTUNDEPLOY:
|
||||
Condition: factundeploy
|
||||
Prerequisites: global-factundeploy
|
||||
|
||||
@@ -369,7 +369,10 @@
|
||||
MustBeDestroyed:
|
||||
RequiredForShortGame: true
|
||||
CaptureNotification:
|
||||
Demolishable:
|
||||
Condition: being-demolished
|
||||
Sellable:
|
||||
RequiresCondition: !being-demolished
|
||||
SellSounds: cashturn.aud
|
||||
WithMakeAnimation:
|
||||
ThrowsShrapnel@SMALL:
|
||||
@@ -478,9 +481,11 @@
|
||||
TargetTypes: Ground, Wall, C4
|
||||
WithWallSpriteBody:
|
||||
Type: wall
|
||||
Sellable:
|
||||
SellSounds: cashturn.aud
|
||||
Demolishable:
|
||||
Condition: being-demolished
|
||||
Sellable:
|
||||
RequiresCondition: !being-demolished
|
||||
SellSounds: cashturn.aud
|
||||
ScriptTriggers:
|
||||
ConditionManager:
|
||||
Health:
|
||||
|
||||
@@ -93,6 +93,8 @@ NAFNCE:
|
||||
Types: laserfence
|
||||
-Crushable:
|
||||
-Sellable:
|
||||
Demolishable:
|
||||
-Condition:
|
||||
-Targetable:
|
||||
-Building:
|
||||
EnergyWall:
|
||||
|
||||
@@ -28,11 +28,12 @@ GACNST:
|
||||
Value: 2500
|
||||
BaseBuilding:
|
||||
Transforms:
|
||||
RequiresCondition: factundeploy
|
||||
PauseOnCondition: being-demolished
|
||||
IntoActor: mcv
|
||||
Offset: 1,1
|
||||
Facing: 96
|
||||
DeployCursor: undeploy
|
||||
RequiresCondition: factundeploy
|
||||
GrantConditionOnPrerequisite@GLOBALFACTUNDEPLOY:
|
||||
Condition: factundeploy
|
||||
Prerequisites: global-factundeploy
|
||||
|
||||
Reference in New Issue
Block a user