Reimplement demolition lock using conditions.
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user