diff --git a/OpenRA.Mods.Common/Lint/CheckPlayers.cs b/OpenRA.Mods.Common/Lint/CheckPlayers.cs index 9702b272a6..f9591bdddd 100644 --- a/OpenRA.Mods.Common/Lint/CheckPlayers.cs +++ b/OpenRA.Mods.Common/Lint/CheckPlayers.cs @@ -61,9 +61,7 @@ namespace OpenRA.Mods.Common.Lint var actorReference = new ActorReference(kv.Value.Value, kv.Value.ToDictionary()); var ownerInit = actorReference.InitDict.GetOrDefault(); if (ownerInit == null) - { emitError("Actor {0} is not owned by any player.".F(kv.Key)); - } else { var ownerName = ownerInit.PlayerName; diff --git a/OpenRA.Mods.Common/Traits/Health.cs b/OpenRA.Mods.Common/Traits/Health.cs index 269a08299b..7da9ddcc96 100644 --- a/OpenRA.Mods.Common/Traits/Health.cs +++ b/OpenRA.Mods.Common/Traits/Health.cs @@ -91,7 +91,7 @@ namespace OpenRA.Mods.Common.Traits }; foreach (var nd in self.TraitsImplementing() - .Concat(self.Owner.PlayerActor.TraitsImplementing())) + .Concat(self.Owner.PlayerActor.TraitsImplementing())) nd.Damaged(self, ai); foreach (var nd in self.TraitsImplementing()) @@ -99,7 +99,7 @@ namespace OpenRA.Mods.Common.Traits if (Info.NotifyAppliedDamage && repairer != null && repairer.IsInWorld && !repairer.IsDead) foreach (var nd in repairer.TraitsImplementing() - .Concat(repairer.Owner.PlayerActor.TraitsImplementing())) + .Concat(repairer.Owner.PlayerActor.TraitsImplementing())) nd.AppliedDamage(repairer, self, ai); } @@ -133,7 +133,7 @@ namespace OpenRA.Mods.Common.Traits }; foreach (var nd in self.TraitsImplementing() - .Concat(self.Owner.PlayerActor.TraitsImplementing())) + .Concat(self.Owner.PlayerActor.TraitsImplementing())) nd.Damaged(self, ai); if (DamageState != oldState) @@ -142,7 +142,7 @@ namespace OpenRA.Mods.Common.Traits if (Info.NotifyAppliedDamage && attacker != null && attacker.IsInWorld && !attacker.IsDead) foreach (var nd in attacker.TraitsImplementing() - .Concat(attacker.Owner.PlayerActor.TraitsImplementing())) + .Concat(attacker.Owner.PlayerActor.TraitsImplementing())) nd.AppliedDamage(attacker, self, ai); if (hp == 0) diff --git a/OpenRA.Mods.RA/Traits/Chronoshiftable.cs b/OpenRA.Mods.RA/Traits/Chronoshiftable.cs index b545740166..43246ea059 100644 --- a/OpenRA.Mods.RA/Traits/Chronoshiftable.cs +++ b/OpenRA.Mods.RA/Traits/Chronoshiftable.cs @@ -19,21 +19,29 @@ namespace OpenRA.Mods.RA.Traits [Desc("Can be teleported via Chronoshift power.")] public class ChronoshiftableInfo : ITraitInfo { + [Desc("Should the actor die instead of being teleported?")] public readonly bool ExplodeInstead = false; public readonly string ChronoshiftSound = "chrono2.aud"; + [Desc("Should the actor return to its location after the chronoshift weared out?.")] + public readonly bool ReturnToOrigin = true; + + [Desc("The color the bar of the 'return-to-origin' logic has.")] + public readonly Color TimeBarColor = Color.White; + public object Create(ActorInitializer init) { return new Chronoshiftable(init, this); } } - public class Chronoshiftable : ITick, ISync, ISelectionBar, IDeathActorInitModifier + public class Chronoshiftable : ITick, ISync, ISelectionBar, IDeathActorInitModifier, INotifyCreated { readonly ChronoshiftableInfo info; readonly Actor self; Actor chronosphere; bool killCargo; int duration; + IPositionable iPositionable; - // Return-to-sender logic + // Return-to-origin logic [Sync] public CPos Origin; [Sync] public int ReturnTicks = 0; @@ -54,7 +62,7 @@ namespace OpenRA.Mods.RA.Traits public void Tick(Actor self) { - if (ReturnTicks <= 0) + if (!info.ReturnToOrigin || ReturnTicks <= 0) return; // Return to original location @@ -65,28 +73,33 @@ namespace OpenRA.Mods.RA.Traits } } + public void Created(Actor self) + { + iPositionable = self.TraitOrDefault(); + } + // Can't be used in synced code, except with ignoreVis. public virtual bool CanChronoshiftTo(Actor self, CPos targetLocation) { // TODO: Allow enemy units to be chronoshifted into bad terrain to kill them - return self.Info.HasTraitInfo() && self.Trait().CanEnterCell(targetLocation); + return iPositionable != null && iPositionable.CanEnterCell(targetLocation); } public virtual bool Teleport(Actor self, CPos targetLocation, int duration, bool killCargo, Actor chronosphere) { - // some things appear chronoshiftable, but instead they just die. + // Some things appear chronoshiftable, but instead they just die. if (info.ExplodeInstead) { self.World.AddFrameEndTask(w => { - // damage is inflicted by the chronosphere + // Damage is inflicted by the chronosphere if (!self.Disposed) self.InflictDamage(chronosphere, int.MaxValue, null); }); return true; } - // Set up return-to-sender info + // Set up return-to-origin info Origin = self.Location; ReturnTicks = duration; this.duration = duration; @@ -103,19 +116,23 @@ namespace OpenRA.Mods.RA.Traits // Show the remaining time as a bar public float GetValue() { - // otherwise an empty bar is rendered all the time + if (!info.ReturnToOrigin) + return 0f; + + // Otherwise an empty bar is rendered all the time if (ReturnTicks == 0 || !self.Owner.IsAlliedWith(self.World.RenderPlayer)) return 0f; return (float)ReturnTicks / duration; } - public Color GetColor() { return Color.White; } + public Color GetColor() { return info.TimeBarColor; } public void ModifyDeathActorInit(Actor self, TypeDictionary init) { - if (ReturnTicks <= 0) + if (!info.ReturnToOrigin || ReturnTicks <= 0) return; + init.Add(new ChronoshiftOriginInit(Origin)); init.Add(new ChronoshiftReturnInit(ReturnTicks)); if (chronosphere != self)