categorize traits better

This commit is contained in:
Chris Forbes
2010-02-09 13:42:33 +13:00
parent 8cb01df8cd
commit 5a95048396
49 changed files with 49 additions and 49 deletions

View File

@@ -0,0 +1,170 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using OpenRa.Orders;
namespace OpenRa.Traits
{
class ChronoshiftPowerInfo : SupportPowerInfo
{
public readonly float Duration = 0f;
public readonly bool KillCargo = true;
public override object Create(Actor self) { return new ChronoshiftPower(self,this); }
}
class ChronoshiftPower : SupportPower, IResolveOrder
{
public ChronoshiftPower(Actor self, ChronoshiftPowerInfo info) : base(self, info) { }
protected override void OnBeginCharging() { Sound.PlayToPlayer(Owner, "chrochr1.aud"); }
protected override void OnFinishCharging() { Sound.PlayToPlayer(Owner, "chrordy1.aud"); }
protected override void OnActivate()
{
Game.controller.orderGenerator = new SelectTarget();
Sound.Play("slcttgt1.aud");
}
public void ResolveOrder(Actor self, Order order)
{
if (order.OrderString == "ChronosphereSelect" && self.Owner == self.World.LocalPlayer)
{
Game.controller.orderGenerator = new SelectDestination(order.TargetActor);
}
if (order.OrderString == "ChronosphereActivate")
{
if (self.Owner == self.World.LocalPlayer)
Game.controller.CancelInputMode();
// Cannot chronoshift into unexplored location
if (!self.Owner.Shroud.IsExplored(order.TargetLocation))
return;
// Ensure the target cell is valid for the unit
var movement = order.TargetActor.traits.GetOrDefault<IMovement>();
if (!movement.CanEnterCell(order.TargetLocation))
return;
var chronosphere = self.World.Queries
.OwnedBy[self.Owner]
.WithTrait<Chronosphere>()
.Select(x=>x.Actor).FirstOrDefault();
bool success = order.TargetActor.traits.Get<Chronoshiftable>().Activate(order.TargetActor,
order.TargetLocation,
(int)((Info as ChronoshiftPowerInfo).Duration * 25 * 60),
(Info as ChronoshiftPowerInfo).KillCargo,
chronosphere);
if (success)
{
Sound.Play("chrono2.aud");
// Trigger screen desaturate effect
foreach (var a in self.World.Queries.WithTrait<ChronoshiftPaletteEffect>())
a.Trait.DoChronoshift();
if (chronosphere != null)
chronosphere.traits.Get<RenderBuilding>().PlayCustomAnim(chronosphere, "active");
}
FinishActivate();
}
}
class SelectTarget : IOrderGenerator
{
public IEnumerable<Order> Order(World world, int2 xy, MouseInput mi)
{
if (mi.Button == MouseButton.Right)
Game.controller.CancelInputMode();
return OrderInner(world, xy, mi);
}
IEnumerable<Order> OrderInner(World world, int2 xy, MouseInput mi)
{
if (mi.Button == MouseButton.Left)
{
var underCursor = world.FindUnitsAtMouse(mi.Location)
.Where(a => a.Owner != null && a.traits.Contains<Chronoshiftable>()
&& a.traits.Contains<Selectable>()).FirstOrDefault();
if (underCursor != null)
yield return new Order("ChronosphereSelect", world.LocalPlayer.PlayerActor, underCursor);
}
yield break;
}
public void Tick( World world )
{
var hasChronosphere = world.Queries.OwnedBy[world.LocalPlayer]
.WithTrait<Chronosphere>()
.Any();
if (!hasChronosphere)
Game.controller.CancelInputMode();
// TODO: Check if the selected unit is still alive
}
public void Render( World world ) { }
public string GetCursor(World world, int2 xy, MouseInput mi)
{
mi.Button = MouseButton.Left;
return OrderInner(world, xy, mi).Any()
? "chrono-select" : "move-blocked";
}
}
class SelectDestination : IOrderGenerator
{
Actor self;
public SelectDestination(Actor self) { this.self = self; }
public IEnumerable<Order> Order(World world, int2 xy, MouseInput mi)
{
if (mi.Button == MouseButton.Right)
{
Game.controller.CancelInputMode();
yield break;
}
yield return new Order("ChronosphereActivate", world.LocalPlayer.PlayerActor, self, xy);
}
public void Tick(World world)
{
var hasChronosphere = world.Queries.OwnedBy[world.LocalPlayer]
.WithTrait<Chronosphere>()
.Any();
if (!hasChronosphere)
Game.controller.CancelInputMode();
// TODO: Check if the selected unit is still alive
}
public void Render(World world)
{
world.WorldRenderer.DrawSelectionBox(self, Color.Red, true);
}
public string GetCursor(World world, int2 xy, MouseInput mi)
{
if (!world.LocalPlayer.Shroud.IsExplored(xy))
return "move-blocked";
var movement = self.traits.GetOrDefault<IMovement>();
return (movement.CanEnterCell(xy)) ? "chrono-target" : "move-blocked";
}
}
}
// tag trait to identify the building
class ChronosphereInfo : StatelessTraitInfo<Chronosphere> { }
public class Chronosphere { }
}

View File

@@ -0,0 +1,70 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using OpenRa.Orders;
namespace OpenRa.Traits
{
class CrateSpawnPowerInfo : SupportPowerInfo
{
public readonly float Duration = 0f;
public override object Create(Actor self) { return new CrateSpawnPower(self, this); }
}
class CrateSpawnPower : SupportPower, IResolveOrder
{
public CrateSpawnPower(Actor self, CrateSpawnPowerInfo info) : base(self, info) { }
protected override void OnActivate()
{
Game.controller.orderGenerator = new SelectTarget();
}
public void ResolveOrder(Actor self, Order order)
{
if (order.OrderString == "SpawnCrate")
{
self.World.AddFrameEndTask(
w => w.CreateActor("crate", order.TargetLocation, self.Owner));
Game.controller.CancelInputMode();
FinishActivate();
}
}
class SelectTarget : IOrderGenerator
{
public IEnumerable<Order> Order(World world, int2 xy, MouseInput mi)
{
if (mi.Button == MouseButton.Right)
Game.controller.CancelInputMode();
return OrderInner(world, xy, mi);
}
IEnumerable<Order> OrderInner(World world, int2 xy, MouseInput mi)
{
if (mi.Button == MouseButton.Left)
{
var underCursor = world.FindUnitsAtMouse(mi.Location).FirstOrDefault();
if (underCursor == null)
yield return new Order("SpawnCrate", world.LocalPlayer.PlayerActor, xy);
}
yield break;
}
public void Tick(World world) { }
public void Render(World world) { }
public string GetCursor(World world, int2 xy, MouseInput mi)
{
mi.Button = MouseButton.Left;
return OrderInner(world, xy, mi).Any()
? "ability" : "move-blocked";
}
}
}
}

View File

@@ -0,0 +1,88 @@
using System;
using System.Collections.Generic;
using System.Linq;
using OpenRa.Orders;
namespace OpenRa.Traits
{
class NukePowerInfo : SupportPowerInfo
{
public override object Create(Actor self) { return new NukePower(self, this); }
}
class NukePower : SupportPower, IResolveOrder
{
public NukePower(Actor self, NukePowerInfo info) : base(self, info) { }
protected override void OnBeginCharging() { Sound.PlayToPlayer(Owner, "aprep1.aud"); }
protected override void OnFinishCharging() { Sound.PlayToPlayer(Owner, "aready1.aud"); }
protected override void OnActivate()
{
Game.controller.orderGenerator = new SelectTarget();
Sound.Play("slcttgt1.aud");
}
public void ResolveOrder(Actor self, Order order)
{
if (order.OrderString == "NuclearMissile")
{
var silo = self.World.Queries.OwnedBy[self.Owner]
.Where(a => a.traits.Contains<NukeSilo>())
.FirstOrDefault();
if (silo != null)
silo.traits.Get<RenderBuilding>().PlayCustomAnim(silo, "active");
Owner.World.AddFrameEndTask(w =>
{
// Play to everyone but the current player
if (Owner != Owner.World.LocalPlayer)
Sound.Play("alaunch1.aud");
// TODO: FIRE ZE MISSILES
//w.Add(new NukeLaunch(silo));
});
Game.controller.CancelInputMode();
FinishActivate();
}
}
class SelectTarget : IOrderGenerator
{
public SelectTarget() { }
public IEnumerable<Order> Order(World world, int2 xy, MouseInput mi)
{
if (mi.Button == MouseButton.Right)
Game.controller.CancelInputMode();
return OrderInner(world, xy, mi);
}
IEnumerable<Order> OrderInner(World world, int2 xy, MouseInput mi)
{
if (mi.Button == MouseButton.Left)
yield return new Order("NuclearMissile", world.LocalPlayer.PlayerActor, xy);
yield break;
}
public void Tick(World world)
{
var hasStructure = world.Queries.OwnedBy[world.LocalPlayer]
.WithTrait<NukeSilo>()
.Any();
if (!hasStructure)
Game.controller.CancelInputMode();
}
public void Render(World world) { }
public string GetCursor(World world, int2 xy, MouseInput mi) { return "nuke"; }
}
}
// tag trait for the building
class NukeSiloInfo : StatelessTraitInfo<NukeSilo> { }
class NukeSilo { }
}

View File

@@ -0,0 +1,132 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace OpenRa.Traits
{
public abstract class SupportPowerInfo : ITraitInfo
{
public readonly bool RequiresPower = true;
public readonly bool OneShot = false;
public readonly float ChargeTime = 0;
public readonly string Image = null;
public readonly string Description = "";
public readonly string LongDesc = "";
public readonly string[] Prerequisites = { };
public readonly int TechLevel = -1;
public readonly bool GivenAuto = true;
public abstract object Create(Actor self);
}
public class SupportPower : ITick
{
public readonly SupportPowerInfo Info;
public int RemainingTime { get; private set; }
public int TotalTime { get { return (int)(Info.ChargeTime * 60 * 25); } }
public bool IsUsed;
public bool IsAvailable;
public bool IsReady { get { return RemainingTime == 0; } }
public readonly Player Owner;
bool notifiedCharging;
bool notifiedReady;
public SupportPower(Actor self, SupportPowerInfo info)
{
Info = info;
RemainingTime = TotalTime;
Owner = self.Owner;
}
public void Tick(Actor self)
{
if (Info.OneShot && IsUsed)
return;
var buildings = Rules.TechTree.GatherBuildings(self.Owner);
var effectivePrereq = Info.Prerequisites
.Select(a => a.ToLowerInvariant())
.Where(a => Rules.Info[a].Traits.Get<BuildableInfo>().Owner.Contains(self.Owner.Race));
if (Info.GivenAuto)
{
IsAvailable = Info.TechLevel > -1
&& effectivePrereq.Any()
&& effectivePrereq.All(a => buildings[a].Count > 0);
}
if (IsAvailable && (!Info.RequiresPower || IsPowered()))
{
if (RemainingTime > 0) --RemainingTime;
if (!notifiedCharging)
{
OnBeginCharging();
notifiedCharging = true;
}
}
if (RemainingTime == 0
&& !notifiedReady)
{
OnFinishCharging();
notifiedReady = true;
}
}
bool IsPowered()
{
var buildings = Rules.TechTree.GatherBuildings(Owner);
var effectivePrereq = Info.Prerequisites
.Select(a => a.ToLowerInvariant())
.Where(a => Rules.Info[a].Traits.Get<BuildableInfo>().Owner.Contains(Owner.Race));
if (Info.Prerequisites.Count() == 0)
return Owner.GetPowerState() == PowerState.Normal;
return effectivePrereq.Any() &&
effectivePrereq.All(a => buildings[a].Any(b => !b.traits.Get<Building>().Disabled));
}
public void FinishActivate()
{
if (Info.OneShot)
{
IsUsed = true;
IsAvailable = false;
}
RemainingTime = TotalTime;
notifiedReady = false;
notifiedCharging = false;
}
public void Give(float charge)
{
IsAvailable = true;
IsUsed = false;
RemainingTime = (int)(charge * TotalTime);
}
protected virtual void OnBeginCharging() { }
protected virtual void OnFinishCharging() { }
protected virtual void OnActivate() { }
public void Activate()
{
if (!IsAvailable || !IsReady)
{
Sound.Play("briefing.aud");
return;
}
if (Info.RequiresPower && !IsPowered())
{
Sound.Play("nopowr1.aud");
return;
}
OnActivate();
}
}
}