Allow husks to chronoshift and return to their parent actors location.

This commit is contained in:
Paul Chote
2013-07-21 13:12:42 +12:00
parent e23c1ad33e
commit 29009fe3a4
3 changed files with 60 additions and 30 deletions

View File

@@ -9,6 +9,7 @@
#endregion #endregion
using System.Drawing; using System.Drawing;
using OpenRA.FileFormats;
using OpenRA.Mods.RA.Activities; using OpenRA.Mods.RA.Activities;
using OpenRA.Traits; using OpenRA.Traits;
@@ -19,38 +20,43 @@ namespace OpenRA.Mods.RA
public readonly bool ExplodeInstead = false; public readonly bool ExplodeInstead = false;
public readonly string ChronoshiftSound = "chrono2.aud"; public readonly string ChronoshiftSound = "chrono2.aud";
public object Create(ActorInitializer init) { return new Chronoshiftable(this); } public object Create(ActorInitializer init) { return new Chronoshiftable(init, this); }
} }
public class Chronoshiftable : ITick, ISync, ISelectionBar public class Chronoshiftable : ITick, ISync, ISelectionBar
{ {
// Return-to-sender logic readonly ChronoshiftableInfo info;
[Sync] CPos chronoshiftOrigin;
[Sync] int chronoshiftReturnTicks = 0;
Actor chronosphere; Actor chronosphere;
bool killCargo; bool killCargo;
int TotalTicks; int duration;
readonly ChronoshiftableInfo info;
public Chronoshiftable(ChronoshiftableInfo info) // Return-to-sender logic
[Sync] public CPos Origin;
[Sync] public int ReturnTicks = 0;
public Chronoshiftable(ActorInitializer init, ChronoshiftableInfo info)
{ {
this.info = info; this.info = info;
if (init.Contains<ChronoshiftReturnInit>())
ReturnTicks = init.Get<ChronoshiftReturnInit, int>();
if (init.Contains<ChronoshiftOriginInit>())
Origin = init.Get<ChronoshiftOriginInit, CPos>();
} }
public void Tick(Actor self) public void Tick(Actor self)
{ {
if (chronoshiftReturnTicks <= 0) if (ReturnTicks <= 0)
return; return;
if (chronoshiftReturnTicks > 0)
chronoshiftReturnTicks--;
// Return to original location // Return to original location
if (chronoshiftReturnTicks == 0) if (--ReturnTicks == 0)
{ {
self.CancelActivity(); self.CancelActivity();
// TODO: need a new Teleport method that will move to the closest available cell // TODO: need a new Teleport method that will move to the closest available cell
self.QueueActivity(new Teleport(chronosphere, chronoshiftOrigin, killCargo, info.ChronoshiftSound)); self.QueueActivity(new Teleport(chronosphere, Origin, killCargo, info.ChronoshiftSound));
} }
} }
@@ -58,25 +64,27 @@ namespace OpenRA.Mods.RA
public virtual bool CanChronoshiftTo(Actor self, CPos targetLocation) public virtual bool CanChronoshiftTo(Actor self, CPos targetLocation)
{ {
// TODO: Allow enemy units to be chronoshifted into bad terrain to kill them // TODO: Allow enemy units to be chronoshifted into bad terrain to kill them
return (self.HasTrait<IPositionable>() && self.Trait<IPositionable>().CanEnterCell(targetLocation)); return self.HasTrait<IPositionable>() && self.Trait<IPositionable>().CanEnterCell(targetLocation);
} }
public virtual bool Teleport(Actor self, CPos targetLocation, int duration, bool killCargo, Actor chronosphere) public virtual bool Teleport(Actor self, CPos targetLocation, int duration, bool killCargo, Actor chronosphere)
{ {
if (info.ExplodeInstead) // 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 => self.World.AddFrameEndTask(w =>
{ {
// damage is inflicted by the chronosphere // damage is inflicted by the chronosphere
if (!self.Destroyed) self.InflictDamage(chronosphere, int.MaxValue, null); if (!self.Destroyed)
self.InflictDamage(chronosphere, int.MaxValue, null);
}); });
return true; return true;
} }
/// Set up return-to-sender info /// Set up return-to-sender info
chronoshiftOrigin = self.Location; Origin = self.Location;
chronoshiftReturnTicks = duration; ReturnTicks = duration;
TotalTicks = duration; this.duration = duration;
this.chronosphere = chronosphere; this.chronosphere = chronosphere;
this.killCargo = killCargo; this.killCargo = killCargo;
@@ -90,11 +98,27 @@ namespace OpenRA.Mods.RA
// Show the remaining time as a bar // Show the remaining time as a bar
public float GetValue() public float GetValue()
{ {
if (chronoshiftReturnTicks == 0) // otherwise an empty bar is rendered all the time if (ReturnTicks == 0) // otherwise an empty bar is rendered all the time
return 0f; return 0f;
return (float)chronoshiftReturnTicks / TotalTicks; return (float)ReturnTicks / duration;
} }
public Color GetColor() { return Color.White; } public Color GetColor() { return Color.White; }
} }
public class ChronoshiftReturnInit : IActorInit<int>
{
[FieldFromYamlKey] readonly int value = 0;
public ChronoshiftReturnInit() { }
public ChronoshiftReturnInit(int init) { value = init; }
public int Value(World world) { return value; }
}
public class ChronoshiftOriginInit : IActorInit<CPos>
{
[FieldFromYamlKey] readonly CPos value;
public ChronoshiftOriginInit(CPos init) { value = init; }
public CPos Value(World world) { return value; }
}
} }

View File

@@ -21,16 +21,14 @@ namespace OpenRA.Mods.RA
[ActorReference] [ActorReference]
public readonly string HuskActor = null; public readonly string HuskActor = null;
public object Create( ActorInitializer init ) { return new LeavesHusk(this); } public object Create(ActorInitializer init) { return new LeavesHusk(this); }
} }
public class LeavesHusk : INotifyKilled public class LeavesHusk : INotifyKilled
{ {
LeavesHuskInfo Info; LeavesHuskInfo info;
public LeavesHusk(LeavesHuskInfo info)
{ public LeavesHusk(LeavesHuskInfo info) { this.info = info; }
Info = info;
}
public void Killed(Actor self, AttackInfo e) public void Killed(Actor self, AttackInfo e)
{ {
@@ -58,19 +56,26 @@ namespace OpenRA.Mods.RA
var facing = self.TraitOrDefault<IFacing>(); var facing = self.TraitOrDefault<IFacing>();
if (facing != null) if (facing != null)
td.Add(new FacingInit( facing.Facing )); td.Add(new FacingInit(facing.Facing));
// TODO: This will only take the first turret if there are multiple // TODO: This will only take the first turret if there are multiple
// This isn't a problem with the current units, but may be a problem for mods // This isn't a problem with the current units, but may be a problem for mods
var turreted = self.TraitsImplementing<Turreted>().FirstOrDefault(); var turreted = self.TraitsImplementing<Turreted>().FirstOrDefault();
if (turreted != null) if (turreted != null)
td.Add( new TurretFacingInit(turreted.turretFacing) ); td.Add(new TurretFacingInit(turreted.turretFacing));
var chronoshiftable = self.TraitOrDefault<Chronoshiftable>();
if (chronoshiftable != null && chronoshiftable.ReturnTicks > 0)
{
td.Add(new ChronoshiftOriginInit(chronoshiftable.Origin));
td.Add(new ChronoshiftReturnInit(chronoshiftable.ReturnTicks));
}
var huskActor = self.TraitsImplementing<IHuskModifier>() var huskActor = self.TraitsImplementing<IHuskModifier>()
.Select(ihm => ihm.HuskActor(self)) .Select(ihm => ihm.HuskActor(self))
.FirstOrDefault(a => a != null); .FirstOrDefault(a => a != null);
w.CreateActor(huskActor ?? Info.HuskActor, td); w.CreateActor(huskActor ?? info.HuskActor, td);
}); });
} }
} }

View File

@@ -386,6 +386,7 @@
Types:Husk Types:Husk
BelowUnits: BelowUnits:
BodyOrientation: BodyOrientation:
Chronoshiftable:
^HelicopterHusk: ^HelicopterHusk:
Inherits: ^Husk Inherits: ^Husk