Make crushable conditional

This commit is contained in:
Mustafa Alperen Seki
2017-12-13 14:48:21 +03:00
committed by Paul Chote
parent 14f6601f2b
commit 9871abe562
2 changed files with 17 additions and 24 deletions

View File

@@ -16,7 +16,7 @@ using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
{ {
[Desc("This actor is crushable.")] [Desc("This actor is crushable.")]
class CrushableInfo : ITraitInfo class CrushableInfo : ConditionalTraitInfo
{ {
[Desc("Sound to play when being crushed.")] [Desc("Sound to play when being crushed.")]
public readonly string CrushSound = null; public readonly string CrushSound = null;
@@ -27,18 +27,17 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Will friendly units just crush me instead of pathing around.")] [Desc("Will friendly units just crush me instead of pathing around.")]
public readonly bool CrushedByFriendlies = false; public readonly bool CrushedByFriendlies = false;
public object Create(ActorInitializer init) { return new Crushable(init.Self, this); } public override object Create(ActorInitializer init) { return new Crushable(init.Self, this); }
} }
class Crushable : ICrushable, INotifyCrushed class Crushable : ConditionalTrait<CrushableInfo>, ICrushable, INotifyCrushed
{ {
readonly Actor self; readonly Actor self;
readonly CrushableInfo info;
public Crushable(Actor self, CrushableInfo info) public Crushable(Actor self, CrushableInfo info)
: base(info)
{ {
this.self = self; this.self = self;
this.info = info;
} }
void INotifyCrushed.WarnCrush(Actor self, Actor crusher, HashSet<string> crushClasses) void INotifyCrushed.WarnCrush(Actor self, Actor crusher, HashSet<string> crushClasses)
@@ -47,7 +46,7 @@ namespace OpenRA.Mods.Common.Traits
return; return;
var mobile = self.TraitOrDefault<Mobile>(); var mobile = self.TraitOrDefault<Mobile>();
if (mobile != null && self.World.SharedRandom.Next(100) <= info.WarnProbability) if (mobile != null && self.World.SharedRandom.Next(100) <= Info.WarnProbability)
mobile.Nudge(self, crusher, true); mobile.Nudge(self, crusher, true);
} }
@@ -56,7 +55,7 @@ namespace OpenRA.Mods.Common.Traits
if (!CrushableInner(crushClasses, crusher.Owner)) if (!CrushableInner(crushClasses, crusher.Owner))
return; return;
Game.Sound.Play(SoundType.World, info.CrushSound, crusher.CenterPosition); Game.Sound.Play(SoundType.World, Info.CrushSound, crusher.CenterPosition);
self.Kill(crusher); self.Kill(crusher);
} }
@@ -68,14 +67,17 @@ namespace OpenRA.Mods.Common.Traits
bool CrushableInner(HashSet<string> crushClasses, Player crushOwner) bool CrushableInner(HashSet<string> crushClasses, Player crushOwner)
{ {
if (IsTraitDisabled)
return false;
// Only make actor crushable if it is on the ground. // Only make actor crushable if it is on the ground.
if (!self.IsAtGroundLevel()) if (!self.IsAtGroundLevel())
return false; return false;
if (!info.CrushedByFriendlies && crushOwner.IsAlliedWith(self.Owner)) if (!Info.CrushedByFriendlies && crushOwner.IsAlliedWith(self.Owner))
return false; return false;
return info.CrushClasses.Overlaps(crushClasses); return Info.CrushClasses.Overlaps(crushClasses);
} }
} }
} }

View File

@@ -326,20 +326,11 @@ namespace OpenRA.Mods.Common.Traits
// If the other actor in our way cannot be crushed, we are blocked. // If the other actor in our way cannot be crushed, we are blocked.
// PERF: Avoid LINQ. // PERF: Avoid LINQ.
var crushables = otherActor.TraitsImplementing<ICrushable>(); var crushables = otherActor.TraitsImplementing<ICrushable>();
var lacksCrushability = true;
foreach (var crushable in crushables) foreach (var crushable in crushables)
{ if (crushable.CrushableBy(otherActor, self, Crushes))
lacksCrushability = false;
if (!crushable.CrushableBy(otherActor, self, Crushes))
return true;
}
// If there are no crushable traits at all, this means the other actor cannot be crushed - we are blocked.
if (lacksCrushability)
return true;
// We are not blocked by the other actor.
return false; return false;
return true;
} }
public WorldMovementInfo GetWorldMovementInfo(World world) public WorldMovementInfo GetWorldMovementInfo(World world)
@@ -737,10 +728,10 @@ namespace OpenRA.Mods.Common.Traits
return false; return false;
foreach (var crushes in crushables) foreach (var crushes in crushables)
if (!crushes.Trait.CrushableBy(crushes.Actor, self, Info.Crushes)) if (crushes.Trait.CrushableBy(crushes.Actor, self, Info.Crushes))
return false;
return true; return true;
return false;
} }
public int MovementSpeedForCell(Actor self, CPos cell) public int MovementSpeedForCell(Actor self, CPos cell)