Reimplement demolition lock using conditions.

This commit is contained in:
Paul Chote
2018-10-27 17:09:30 +00:00
committed by abcdefg30
parent 0901a7d9de
commit 18b84750aa
25 changed files with 239 additions and 71 deletions

View File

@@ -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);
}
}
}
}
}