Added Buildable->BuildLimit option to limit the number of actors a player can build of the type

This commit is contained in:
Carko
2013-01-04 02:40:17 +01:00
committed by Chris Forbes
parent 0c104cfc3a
commit a51c5fd9ca
3 changed files with 46 additions and 26 deletions

View File

@@ -22,6 +22,7 @@ namespace OpenRA.Mods.RA
public readonly string Queue;
public readonly bool Hidden = false;
public readonly int BuildLimit = 0;
// todo: UI fluff; doesn't belong here
public readonly int BuildPaletteOrder = 9999;

View File

@@ -39,7 +39,7 @@ namespace OpenRA.Mods.RA
public ProductionQueueInfo Info;
PowerManager PlayerPower;
PlayerResources playerResources;
CountryInfo Race;
readonly CountryInfo Race;
// A list of things we are currently building
public List<ProductionItem> Queue = new List<ProductionItem>();
@@ -48,8 +48,8 @@ namespace OpenRA.Mods.RA
[Sync] public int CurrentRemainingCost { get { return QueueLength == 0 ? 0 : Queue[0].RemainingCost; } }
[Sync] public int CurrentRemainingTime { get { return QueueLength == 0 ? 0 : Queue[0].RemainingTime; } }
[Sync] public int CurrentSlowdown { get { return QueueLength == 0 ? 0 : Queue[0].slowdown; } }
[Sync] public bool CurrentPaused { get { return QueueLength == 0 ? false : Queue[0].Paused; } }
[Sync] public bool CurrentDone { get { return QueueLength == 0 ? false : Queue[0].Done; } }
[Sync] public bool CurrentPaused { get { return QueueLength != 0 && Queue[0].Paused; } }
[Sync] public bool CurrentDone { get { return QueueLength != 0 && Queue[0].Done; } }
// A list of things we could possibly build, even if our race doesn't normally get it
public Dictionary<ActorInfo, ProductionState> Produceable;
@@ -106,9 +106,9 @@ namespace OpenRA.Mods.RA
var bi = a.Traits.Get<BuildableInfo>();
// Can our race build this by satisfying normal prereqs?
var buildable = bi.Owner.Contains(Race.Race);
tech.Add(a, new ProductionState() { Visible = buildable && !bi.Hidden });
tech.Add(a, new ProductionState { Visible = buildable && !bi.Hidden });
if (buildable)
ttc.Add(a.Name, a.Traits.Get<BuildableInfo>().Prerequisites.ToList(), this);
ttc.Add(a.Name, bi, this);
}
return tech;
@@ -175,7 +175,7 @@ namespace OpenRA.Mods.RA
public virtual void Tick(Actor self)
{
while (Queue.Count > 0 && !BuildableItems().Any(b => b.Name == Queue[ 0 ].Item))
while (Queue.Count > 0 && BuildableItems().All(b => b.Name != Queue[ 0 ].Item))
{
playerResources.GiveCash(Queue[0].TotalCost - Queue[0].RemainingCost); // refund what's been paid so far.
FinishProduction();
@@ -198,13 +198,25 @@ namespace OpenRA.Mods.RA
var cost = unit.Traits.Contains<ValuedInfo>() ? unit.Traits.Get<ValuedInfo>().Cost : 0;
var time = GetBuildTime(order.TargetString);
if (!BuildableItems().Any(b => b.Name == order.TargetString))
if (BuildableItems().All(b => b.Name != order.TargetString))
return; /* you can't build that!! */
// Check if the player is trying to build more units that they are allowed
if (bi.BuildLimit > 0)
{
var inQueue = Queue.Count(pi => pi.Item == order.TargetString);
var owned = self.Owner.World.ActorsWithTrait<Buildable>().Count(a => a.Actor.Info.Name == order.TargetString && a.Actor.Owner == self.Owner);
if (inQueue + owned >= bi.BuildLimit)
{
Sound.PlayNotification(self.Owner, "Speech", Info.BlockedAudio, self.Owner.Country.Race);
return;
}
}
for (var n = 0; n < order.TargetLocation.X; n++) // repeat count
{
bool hasPlayedSound = false;
BeginProduction(new ProductionItem(this, order.TargetString, (int)time, cost, PlayerPower,
BeginProduction(new ProductionItem(this, order.TargetString, time, cost, PlayerPower,
() => self.World.AddFrameEndTask(
_ =>
{

View File

@@ -34,20 +34,21 @@ namespace OpenRA.Mods.RA
public void ActorChanged(Actor a)
{
if (a.Owner == player && a.HasTrait<ITechTreePrerequisite>())
var bi = a.Info.Traits.GetOrDefault<BuildableInfo>();
if (a.Owner == player && (a.HasTrait<ITechTreePrerequisite>() || (bi != null && bi.BuildLimit > 0)))
Update();
}
public void Update()
{
var buildings = GatherBuildings(player);
var buildables = GatherBuildables(player);
foreach(var w in watchers)
w.Update(buildings);
w.Update(buildables);
}
public void Add(string key, List<string> prerequisites, ITechTreeElement tte)
public void Add(string key, BuildableInfo info, ITechTreeElement tte)
{
watchers.Add(new Watcher( key, prerequisites, tte ));
watchers.Add(new Watcher( key, info, tte ));
}
public void Remove(string key)
@@ -55,18 +56,24 @@ namespace OpenRA.Mods.RA
watchers.RemoveAll(x => x.key == key);
}
static Cache<string, List<Actor>> GatherBuildings( Player player )
static Cache<string, List<Actor>> GatherBuildables( Player player )
{
var ret = new Cache<string, List<Actor>>( x => new List<Actor>() );
if (player == null)
return ret;
// Add buildables that provide prerequisites
foreach (var b in player.World.ActorsWithTrait<ITechTreePrerequisite>()
.Where(a => a.Actor.IsInWorld && !a.Actor.IsDead() && a.Actor.Owner == player))
foreach (var p in b.Trait.ProvidesPrerequisites)
ret[ p ].Add( b.Actor );
// Add buildables that have a build limit set and are not already in the list
player.World.ActorsWithTrait<Buildable>()
.Where(a => a.Actor.Info.Traits.Get<BuildableInfo>().BuildLimit > 0 && !a.Actor.IsDead() && a.Actor.Owner == player && ret.Keys.All(k => k != a.Actor.Info.Name))
.ToList()
.ForEach(b => ret[b.Actor.Info.Name].Add(b.Actor));
return ret;
}
@@ -74,30 +81,30 @@ namespace OpenRA.Mods.RA
{
public readonly string key;
// strings may be either actor type, or "alternate name" key
public readonly List<string> prerequisites;
public readonly string[] prerequisites;
public readonly ITechTreeElement watcher;
bool hasPrerequisites;
int buildLimit;
public Watcher(string key, List<string> prerequisites, ITechTreeElement watcher)
public Watcher(string key, BuildableInfo info, ITechTreeElement watcher)
{
this.key = key;
this.prerequisites = prerequisites;
this.prerequisites = info.Prerequisites;
this.watcher = watcher;
this.hasPrerequisites = false;
this.buildLimit = info.BuildLimit;
}
bool HasPrerequisites(Cache<string, List<Actor>> buildings)
bool HasPrerequisites(Cache<string, List<Actor>> buildables)
{
foreach (var p in prerequisites)
if (p.StartsWith("!") ^
!buildings.Keys.Contains(p.Replace("!","")))
return false;
return true;
return prerequisites.All(p => !(p.StartsWith("!") ^ !buildables.Keys.Contains(p.Replace("!", ""))));
}
public void Update(Cache<string, List<Actor>> buildings)
public void Update(Cache<string, List<Actor>> buildables)
{
var nowHasPrerequisites = HasPrerequisites(buildings);
var hasReachedBuildLimit = buildLimit > 0 && buildables[key].Count >= buildLimit;
var nowHasPrerequisites = HasPrerequisites(buildables) && !hasReachedBuildLimit;
if( nowHasPrerequisites && !hasPrerequisites )
watcher.PrerequisitesAvailable(key);