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
using System.Drawing;
using OpenRA.FileFormats;
using OpenRA.Mods.RA.Activities;
using OpenRA.Traits;
@@ -19,38 +20,43 @@ namespace OpenRA.Mods.RA
public readonly bool ExplodeInstead = false;
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
{
// Return-to-sender logic
[Sync] CPos chronoshiftOrigin;
[Sync] int chronoshiftReturnTicks = 0;
readonly ChronoshiftableInfo info;
Actor chronosphere;
bool killCargo;
int TotalTicks;
readonly ChronoshiftableInfo info;
int duration;
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;
if (init.Contains<ChronoshiftReturnInit>())
ReturnTicks = init.Get<ChronoshiftReturnInit, int>();
if (init.Contains<ChronoshiftOriginInit>())
Origin = init.Get<ChronoshiftOriginInit, CPos>();
}
public void Tick(Actor self)
{
if (chronoshiftReturnTicks <= 0)
if (ReturnTicks <= 0)
return;
if (chronoshiftReturnTicks > 0)
chronoshiftReturnTicks--;
// Return to original location
if (chronoshiftReturnTicks == 0)
if (--ReturnTicks == 0)
{
self.CancelActivity();
// 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)
{
// 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)
{
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 =>
{
// 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;
}
/// Set up return-to-sender info
chronoshiftOrigin = self.Location;
chronoshiftReturnTicks = duration;
TotalTicks = duration;
Origin = self.Location;
ReturnTicks = duration;
this.duration = duration;
this.chronosphere = chronosphere;
this.killCargo = killCargo;
@@ -90,11 +98,27 @@ namespace OpenRA.Mods.RA
// Show the remaining time as a bar
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 (float)chronoshiftReturnTicks / TotalTicks;
return (float)ReturnTicks / duration;
}
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]
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
{
LeavesHuskInfo Info;
public LeavesHusk(LeavesHuskInfo info)
{
Info = info;
}
LeavesHuskInfo info;
public LeavesHusk(LeavesHuskInfo info) { this.info = info; }
public void Killed(Actor self, AttackInfo e)
{
@@ -58,19 +56,26 @@ namespace OpenRA.Mods.RA
var facing = self.TraitOrDefault<IFacing>();
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
// This isn't a problem with the current units, but may be a problem for mods
var turreted = self.TraitsImplementing<Turreted>().FirstOrDefault();
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>()
.Select(ihm => ihm.HuskActor(self))
.FirstOrDefault(a => a != null);
w.CreateActor(huskActor ?? Info.HuskActor, td);
w.CreateActor(huskActor ?? info.HuskActor, td);
});
}
}

View File

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