Merge branch 'cheap-queues'
This commit is contained in:
@@ -23,9 +23,9 @@ namespace OpenRa.Game
|
|||||||
readonly SpriteRenderer buildPaletteRenderer;
|
readonly SpriteRenderer buildPaletteRenderer;
|
||||||
readonly Animation cantBuild;
|
readonly Animation cantBuild;
|
||||||
readonly Animation ready;
|
readonly Animation ready;
|
||||||
|
readonly Animation clock;
|
||||||
|
|
||||||
readonly List<Pair<Rectangle, Action<bool>>> buttons = new List<Pair<Rectangle, Action<bool>>>();
|
readonly List<Pair<Rectangle, Action<bool>>> buttons = new List<Pair<Rectangle, Action<bool>>>();
|
||||||
readonly Cache<string, Animation> clockAnimations;
|
|
||||||
readonly List<Sprite> digitSprites;
|
readonly List<Sprite> digitSprites;
|
||||||
readonly Dictionary<string, Sprite[]> tabSprites;
|
readonly Dictionary<string, Sprite[]> tabSprites;
|
||||||
readonly Sprite[] shimSprites;
|
readonly Sprite[] shimSprites;
|
||||||
@@ -70,14 +70,6 @@ namespace OpenRa.Game
|
|||||||
cantBuild = new Animation("clock");
|
cantBuild = new Animation("clock");
|
||||||
cantBuild.PlayFetchIndex("idle", () => 0);
|
cantBuild.PlayFetchIndex("idle", () => 0);
|
||||||
|
|
||||||
clockAnimations = new Cache<string, Animation>(
|
|
||||||
s =>
|
|
||||||
{
|
|
||||||
var anim = new Animation("clock");
|
|
||||||
anim.PlayFetchIndex("idle", ClockAnimFrame(s));
|
|
||||||
return anim;
|
|
||||||
});
|
|
||||||
|
|
||||||
digitSprites = Util.MakeArray(10, a => a)
|
digitSprites = Util.MakeArray(10, a => a)
|
||||||
.Select(n => new Sprite(specialBin, new Rectangle(32 + 13 * n, 0, 13, 17), TextureChannel.Alpha)).ToList();
|
.Select(n => new Sprite(specialBin, new Rectangle(32 + 13 * n, 0, 13, 17), TextureChannel.Alpha)).ToList();
|
||||||
|
|
||||||
@@ -92,6 +84,7 @@ namespace OpenRa.Game
|
|||||||
|
|
||||||
ready = new Animation("pips");
|
ready = new Animation("pips");
|
||||||
ready.PlayRepeating("ready");
|
ready.PlayRepeating("ready");
|
||||||
|
clock = new Animation("clock");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Draw()
|
public void Draw()
|
||||||
@@ -144,7 +137,7 @@ namespace OpenRa.Game
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var producing = queue.Producing(groupName);
|
var producing = queue.CurrentItem(groupName);
|
||||||
var index = q.Key == currentTab ? 2 : (producing != null && producing.Done) ? 1 : 0;
|
var index = q.Key == currentTab ? 2 : (producing != null && producing.Done) ? 1 : 0;
|
||||||
|
|
||||||
|
|
||||||
@@ -173,8 +166,7 @@ namespace OpenRa.Game
|
|||||||
void CheckDeadTab( string groupName )
|
void CheckDeadTab( string groupName )
|
||||||
{
|
{
|
||||||
var queue = Game.LocalPlayer.PlayerActor.traits.Get<Traits.ProductionQueue>();
|
var queue = Game.LocalPlayer.PlayerActor.traits.Get<Traits.ProductionQueue>();
|
||||||
var item = queue.Producing( groupName );
|
foreach( var item in queue.AllItems( groupName ) )
|
||||||
if (item != null)
|
|
||||||
Game.controller.AddOrder(Order.CancelProduction(Game.LocalPlayer, item.Item));
|
Game.controller.AddOrder(Order.CancelProduction(Game.LocalPlayer, item.Item));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -226,7 +218,7 @@ namespace OpenRa.Game
|
|||||||
return () =>
|
return () =>
|
||||||
{
|
{
|
||||||
var queue = Game.LocalPlayer.PlayerActor.traits.Get<Traits.ProductionQueue>();
|
var queue = Game.LocalPlayer.PlayerActor.traits.Get<Traits.ProductionQueue>();
|
||||||
var producing = queue.Producing( group );
|
var producing = queue.CurrentItem( group );
|
||||||
if (producing == null) return 0;
|
if (producing == null) return 0;
|
||||||
return (producing.TotalTime - producing.RemainingTime) * NumClockFrames / producing.TotalTime;
|
return (producing.TotalTime - producing.RemainingTime) * NumClockFrames / producing.TotalTime;
|
||||||
};
|
};
|
||||||
@@ -251,50 +243,63 @@ namespace OpenRa.Game
|
|||||||
.OrderBy(a => Rules.UnitInfo[a].TechLevel);
|
.OrderBy(a => Rules.UnitInfo[a].TechLevel);
|
||||||
|
|
||||||
var queue = Game.LocalPlayer.PlayerActor.traits.Get<Traits.ProductionQueue>();
|
var queue = Game.LocalPlayer.PlayerActor.traits.Get<Traits.ProductionQueue>();
|
||||||
var currentItem = queue.Producing( queueName );
|
|
||||||
|
|
||||||
var overlayBits = new List<Pair<Sprite, float2>>();
|
var overlayBits = new List<Pair<Sprite, float2>>();
|
||||||
|
|
||||||
string tooltipItem = null;
|
string tooltipItem = null;
|
||||||
//int2 tooltipPos = int2.Zero;
|
|
||||||
|
|
||||||
foreach (var item in allItems)
|
foreach (var item in allItems)
|
||||||
{
|
{
|
||||||
var rect = new Rectangle(origin.X + x * 64, origin.Y + 48 * y, 64, 48);
|
var rect = new Rectangle(origin.X + x * 64, origin.Y + 48 * y, 64, 48);
|
||||||
var drawPos = Game.viewport.Location + new float2(rect.Location);
|
var drawPos = Game.viewport.Location + new float2(rect.Location);
|
||||||
var isBuildingThis = currentItem != null && currentItem.Item == item;
|
var isBuildingSomething = queue.CurrentItem(queueName) != null;
|
||||||
var isBuildingSomethingElse = currentItem != null && currentItem.Item != item;
|
|
||||||
|
|
||||||
buildPaletteRenderer.DrawSprite(sprites[item], drawPos, PaletteType.Chrome);
|
buildPaletteRenderer.DrawSprite(sprites[item], drawPos, PaletteType.Chrome);
|
||||||
|
|
||||||
|
var firstOfThis = queue.AllItems(queueName).FirstOrDefault(a => a.Item == item);
|
||||||
|
|
||||||
if (rect.Contains(lastMousePos.ToPoint()))
|
if (rect.Contains(lastMousePos.ToPoint()))
|
||||||
{
|
|
||||||
tooltipItem = item;
|
tooltipItem = item;
|
||||||
//tooltipPos = new int2(rect.Location);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!buildableItems.Contains(item) || isBuildingSomethingElse)
|
var overlayPos = drawPos + new float2((64 - ready.Image.size.X) / 2, 2);
|
||||||
overlayBits.Add(Pair.New(cantBuild.Image, drawPos));
|
|
||||||
|
|
||||||
if (isBuildingThis)
|
if (firstOfThis != null)
|
||||||
{
|
{
|
||||||
clockAnimations[queueName].Tick();
|
clock.PlayFetchIndex( "idle",
|
||||||
buildPaletteRenderer.DrawSprite(clockAnimations[queueName].Image,
|
() => (firstOfThis.TotalTime - firstOfThis.RemainingTime)
|
||||||
drawPos, PaletteType.Chrome);
|
* NumClockFrames / firstOfThis.TotalTime);
|
||||||
|
clock.Tick();
|
||||||
|
|
||||||
var overlayPos = drawPos + new float2((64 - ready.Image.size.X) / 2, 2);
|
buildPaletteRenderer.DrawSprite(clock.Image, drawPos, PaletteType.Chrome);
|
||||||
|
|
||||||
if (currentItem.Done)
|
if (firstOfThis.Done)
|
||||||
{
|
{
|
||||||
ready.Play("ready");
|
ready.Play("ready");
|
||||||
overlayBits.Add(Pair.New(ready.Image, overlayPos));
|
overlayBits.Add(Pair.New(ready.Image, overlayPos));
|
||||||
}
|
}
|
||||||
else if (currentItem.Paused)
|
else if (firstOfThis.Paused)
|
||||||
{
|
{
|
||||||
ready.Play("hold");
|
ready.Play("hold");
|
||||||
overlayBits.Add(Pair.New(ready.Image, overlayPos));
|
overlayBits.Add(Pair.New(ready.Image, overlayPos));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var repeats = queue.AllItems(queueName).Count(a => a.Item == item);
|
||||||
|
if (repeats > 1 || queue.CurrentItem(queueName) != firstOfThis)
|
||||||
|
{
|
||||||
|
var offset = -22;
|
||||||
|
var digits = repeats.ToString();
|
||||||
|
foreach (var d in digits)
|
||||||
|
{
|
||||||
|
ready.PlayFetchIndex("groups", () => d - '0');
|
||||||
|
ready.Tick();
|
||||||
|
overlayBits.Add(Pair.New(ready.Image, overlayPos + new float2(offset, 0)));
|
||||||
|
offset += 6;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
if (!buildableItems.Contains(item) || isBuildingSomething)
|
||||||
|
overlayBits.Add(Pair.New(cantBuild.Image, drawPos));
|
||||||
|
|
||||||
var closureItem = item;
|
var closureItem = item;
|
||||||
buttons.Add(Pair.New(rect,
|
buttons.Add(Pair.New(rect,
|
||||||
@@ -335,51 +340,57 @@ namespace OpenRa.Game
|
|||||||
return y*48+9;
|
return y*48+9;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void StartProduction( string item )
|
||||||
|
{
|
||||||
|
var group = Rules.UnitCategory[item];
|
||||||
|
Sound.Play((group == "Building" || group == "Defense") ? "abldgin1.aud" : "train1.aud");
|
||||||
|
Game.controller.AddOrder(Order.StartProduction(Game.LocalPlayer, item));
|
||||||
|
}
|
||||||
|
|
||||||
void HandleBuildPalette(string item, bool isLmb)
|
void HandleBuildPalette(string item, bool isLmb)
|
||||||
{
|
{
|
||||||
var player = Game.LocalPlayer;
|
var player = Game.LocalPlayer;
|
||||||
var group = Rules.UnitCategory[item];
|
var group = Rules.UnitCategory[item];
|
||||||
var queue = player.PlayerActor.traits.Get<Traits.ProductionQueue>();
|
var queue = player.PlayerActor.traits.Get<Traits.ProductionQueue>();
|
||||||
var producing = queue.Producing( group );
|
var producing = queue.AllItems(group).FirstOrDefault( a => a.Item == item );
|
||||||
|
|
||||||
Sound.Play("ramenu1.aud");
|
Sound.Play("ramenu1.aud");
|
||||||
|
|
||||||
if (isLmb)
|
if (isLmb)
|
||||||
{
|
{
|
||||||
if (producing == null)
|
if (producing != null && producing == queue.CurrentItem(group))
|
||||||
{
|
|
||||||
Game.controller.AddOrder(Order.StartProduction(player, item));
|
|
||||||
Sound.Play("abldgin1.aud");
|
|
||||||
}
|
|
||||||
else if (producing.Item == item)
|
|
||||||
{
|
{
|
||||||
if (producing.Done)
|
if (producing.Done)
|
||||||
{
|
{
|
||||||
if (group == "Building" || group == "Defense")
|
if (group == "Building" || group == "Defense")
|
||||||
Game.controller.orderGenerator = new PlaceBuilding(player.PlayerActor, item);
|
Game.controller.orderGenerator = new PlaceBuilding(player.PlayerActor, item);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
if (producing.Paused)
|
||||||
|
{
|
||||||
Game.controller.AddOrder(Order.PauseProduction(player, item, false));
|
Game.controller.AddOrder(Order.PauseProduction(player, item, false));
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
StartProduction(item);
|
||||||
Sound.Play("progres1.aud");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (producing == null) return;
|
if (producing != null)
|
||||||
if (item != producing.Item) return;
|
|
||||||
|
|
||||||
if (producing.Paused || producing.Done)
|
|
||||||
{
|
{
|
||||||
Sound.Play("cancld1.aud");
|
// instant cancel of things we havent really started yet, and things that are finished
|
||||||
Game.controller.AddOrder(Order.CancelProduction(player, item));
|
if (producing.Paused || producing.Done || producing.TotalCost == producing.RemainingCost)
|
||||||
}
|
{
|
||||||
else
|
Sound.Play("cancld1.aud");
|
||||||
{
|
Game.controller.AddOrder(Order.CancelProduction(player, item));
|
||||||
Sound.Play("onhold1.aud");
|
}
|
||||||
Game.controller.AddOrder(Order.PauseProduction(player, item, true));
|
else
|
||||||
|
{
|
||||||
|
Sound.Play("onhold1.aud");
|
||||||
|
Game.controller.AddOrder(Order.PauseProduction(player, item, true));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ namespace OpenRa.Game
|
|||||||
|
|
||||||
public void Tick()
|
public void Tick()
|
||||||
{
|
{
|
||||||
var producing = Producer.traits.Get<Traits.ProductionQueue>().Producing( Rules.UnitCategory[ Building.Name ] );
|
var producing = Producer.traits.Get<Traits.ProductionQueue>().CurrentItem( Rules.UnitCategory[ Building.Name ] );
|
||||||
if( producing == null || producing.Item != Building.Name || producing.RemainingTime != 0 )
|
if( producing == null || producing.Item != Building.Name || producing.RemainingTime != 0 )
|
||||||
Game.world.AddFrameEndTask( _ => { Game.controller.orderGenerator = null; } );
|
Game.world.AddFrameEndTask( _ => { Game.controller.orderGenerator = null; } );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using IjwFramework.Collections;
|
||||||
|
|
||||||
namespace OpenRa.Game.Traits
|
namespace OpenRa.Game.Traits
|
||||||
{
|
{
|
||||||
@@ -12,15 +13,13 @@ namespace OpenRa.Game.Traits
|
|||||||
public ProductionQueue( Actor self )
|
public ProductionQueue( Actor self )
|
||||||
{
|
{
|
||||||
this.self = self;
|
this.self = self;
|
||||||
foreach( var cat in Rules.Categories.Keys )
|
|
||||||
ProductionInit( cat );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Tick( Actor self )
|
public void Tick( Actor self )
|
||||||
{
|
{
|
||||||
foreach( var p in production )
|
foreach( var p in production )
|
||||||
if( p.Value != null )
|
if( p.Value.Count > 0 )
|
||||||
p.Value.Tick( self.Owner );
|
(p.Value)[0].Tick( self.Owner );
|
||||||
}
|
}
|
||||||
|
|
||||||
public Order IssueOrder( Actor self, int2 xy, MouseInput mi, Actor underCursor )
|
public Order IssueOrder( Actor self, int2 xy, MouseInput mi, Actor underCursor )
|
||||||
@@ -67,51 +66,62 @@ namespace OpenRa.Game.Traits
|
|||||||
}
|
}
|
||||||
case "PauseProduction":
|
case "PauseProduction":
|
||||||
{
|
{
|
||||||
var producing = Producing( Rules.UnitCategory[ order.TargetString ] );
|
var producing = CurrentItem( Rules.UnitCategory[ order.TargetString ] );
|
||||||
if( producing != null && producing.Item == order.TargetString )
|
if( producing != null && producing.Item == order.TargetString )
|
||||||
producing.Paused = ( order.TargetLocation.X != 0 );
|
producing.Paused = ( order.TargetLocation.X != 0 );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "CancelProduction":
|
case "CancelProduction":
|
||||||
{
|
{
|
||||||
var producing = Producing( Rules.UnitCategory[ order.TargetString ] );
|
CancelProduction(order.TargetString);
|
||||||
if( producing != null && producing.Item == order.TargetString )
|
|
||||||
CancelProduction( Rules.UnitCategory[ order.TargetString ] );
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Key: Production category. Categories are: Building, Infantry, Vehicle, Ship, Plane (and one per super, if they're done in here)
|
// Key: Production category.
|
||||||
readonly Dictionary<string, ProductionItem> production = new Dictionary<string, ProductionItem>();
|
readonly Cache<string, List<ProductionItem>> production
|
||||||
|
= new Cache<string, List<ProductionItem>>( _ => new List<ProductionItem>() );
|
||||||
|
|
||||||
void ProductionInit( string category )
|
public ProductionItem CurrentItem(string category)
|
||||||
{
|
{
|
||||||
production.Add( category, null );
|
return production[category].ElementAtOrDefault(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ProductionItem Producing( string category )
|
public IEnumerable<ProductionItem> AllItems(string category)
|
||||||
{
|
{
|
||||||
return production[ category ];
|
return production[category];
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CancelProduction( string category )
|
public void CancelProduction( string itemName )
|
||||||
{
|
{
|
||||||
var item = production[ category ];
|
var category = Rules.UnitCategory[itemName];
|
||||||
if( item == null ) return;
|
var queue = production[ category ];
|
||||||
self.Owner.GiveCash( item.TotalCost - item.RemainingCost ); // refund what's been paid so far.
|
if (queue.Count == 0) return;
|
||||||
FinishProduction( category );
|
|
||||||
|
var lastIndex = queue.FindLastIndex( a => a.Item == itemName );
|
||||||
|
if (lastIndex > 0)
|
||||||
|
{
|
||||||
|
queue.RemoveAt(lastIndex);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var item = queue[0];
|
||||||
|
self.Owner.GiveCash(item.TotalCost - item.RemainingCost); // refund what's been paid so far.
|
||||||
|
FinishProduction(category);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void FinishProduction( string category )
|
public void FinishProduction( string category )
|
||||||
{
|
{
|
||||||
production[ category ] = null;
|
var queue = production[category];
|
||||||
|
if (queue.Count == 0) return;
|
||||||
|
queue.RemoveAt(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void BeginProduction( string group, ProductionItem item )
|
public void BeginProduction( string group, ProductionItem item )
|
||||||
{
|
{
|
||||||
if( production[ group ] != null ) return;
|
production[group].Add(item);
|
||||||
production[ group ] = item;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void BuildUnit( string name )
|
public void BuildUnit( string name )
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ namespace OpenRa.Game
|
|||||||
{
|
{
|
||||||
var queue = order.Player.PlayerActor.traits.Get<Traits.ProductionQueue>();
|
var queue = order.Player.PlayerActor.traits.Get<Traits.ProductionQueue>();
|
||||||
var building = (BuildingInfo)Rules.UnitInfo[ order.TargetString ];
|
var building = (BuildingInfo)Rules.UnitInfo[ order.TargetString ];
|
||||||
var producing = queue.Producing(Rules.UnitCategory[order.TargetString]);
|
var producing = queue.CurrentItem(Rules.UnitCategory[order.TargetString]);
|
||||||
if( producing == null || producing.Item != order.TargetString || producing.RemainingTime != 0 )
|
if( producing == null || producing.Item != order.TargetString || producing.RemainingTime != 0 )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user