示例#1
0
        bool HandleLeftClick(ProductionItem item, ProductionIcon icon, bool handleMultiple)
        {
            if (PickUpCompletedBuildingIcon(icon, item))
            {
                Sound.Play(TabClick);
                return(true);
            }

            if (item != null && item.Paused)
            {
                // Resume a paused item
                Sound.Play(TabClick);
                World.IssueOrder(Order.PauseProduction(CurrentQueue.Actor, icon.Name, false));
                return(true);
            }

            if (CurrentQueue.BuildableItems().Any(a => a.Name == icon.Name))
            {
                // Queue a new item
                Sound.Play(TabClick);
                Sound.PlayNotification(World.Map.Rules, World.LocalPlayer, "Speech", CurrentQueue.Info.QueuedAudio, World.LocalPlayer.Country.Race);
                World.IssueOrder(Order.StartProduction(CurrentQueue.Actor, icon.Name,
                                                       handleMultiple ? 5 : 1));
                return(true);
            }

            return(false);
        }
示例#2
0
        public void Send()
        {
            if (Sending)
            {
                return;
            }

            Sending = true;

            VitaNexCore.TryCatch(
                () =>
            {
                Update();

                if (Count == 0 || this[0] == null)
                {
                    return;
                }

                Processing = true;

                CurrentQueue = this[0];
                CurrentQueue.Process();

                OnSend();
            },
                VitaNexCore.ToConsole);
        }
示例#3
0
        bool HandleLeftClick(ProductionItem item, ProductionIcon icon, int handleCount)
        {
            if (PickUpCompletedBuildingIcon(icon, item))
            {
                Game.Sound.Play(SoundType.UI, TabClick);
                return(true);
            }

            if (item != null && item.Paused)
            {
                // Resume a paused item
                Game.Sound.Play(SoundType.UI, TabClick);
                World.IssueOrder(Order.PauseProduction(CurrentQueue.Actor, icon.Name, false));
                return(true);
            }

            if (CurrentQueue.BuildableItems().Any(a => a.Name == icon.Name))
            {
                // Queue a new item
                Game.Sound.Play(SoundType.UI, TabClick);
                Game.Sound.PlayNotification(World.Map.Rules, World.LocalPlayer, "Speech", CurrentQueue.Info.QueuedAudio, World.LocalPlayer.Faction.InternalName);
                World.IssueOrder(Order.StartProduction(CurrentQueue.Actor, icon.Name, handleCount));
                return(true);
            }

            return(false);
        }
示例#4
0
        bool HandleLeftClick(ProductionItem item, ProductionIcon icon, int handleCount)
        {
            if (PickUpCompletedBuildingIcon(icon, item))
            {
                Game.Sound.Play(SoundType.UI, TabClick);
                return(true);
            }

            if (item != null && item.Paused)
            {
                // Resume a paused item
                Game.Sound.Play(SoundType.UI, TabClick);
                World.IssueOrder(Order.PauseProduction(CurrentQueue.Actor, icon.Name, false));
                return(true);
            }

            var buildable = CurrentQueue.BuildableItems().FirstOrDefault(a => a.Name == icon.Name);

            if (buildable != null)
            {
                // Queue a new item
                Game.Sound.Play(SoundType.UI, TabClick);
                string notification;
                var    canQueue = CurrentQueue.CanQueue(buildable, out notification);
                Game.Sound.PlayNotification(World.Map.Rules, World.LocalPlayer, "Speech", notification, World.LocalPlayer.Faction.InternalName);

                if (canQueue)
                {
                    World.IssueOrder(Order.StartProduction(CurrentQueue.Actor, icon.Name, handleCount));
                    return(true);
                }
            }

            return(false);
        }
        bool SelectProductionBuilding()
        {
            var viewport  = worldRenderer.Viewport;
            var selection = World.Selection;

            if (CurrentQueue == null)
            {
                return(true);
            }

            var facility = CurrentQueue.MostLikelyProducer().Actor;

            if (facility == null || facility.OccupiesSpace == null)
            {
                return(true);
            }

            if (selection.Actors.Count() == 1 && selection.Contains(facility))
            {
                viewport.Center(selection.Actors);
            }
            else
            {
                selection.Combine(World, new[] { facility }, false, true);
            }

            Game.Sound.PlayNotification(World.Map.Rules, null, "Sounds", ClickSound, null);
            return(true);
        }
        bool HandleEvent(ProductionIcon icon, bool isLeftClick, bool handleMultiple)
        {
            var actor = World.Map.Rules.Actors[icon.Name];
            var first = icon.Queued.FirstOrDefault();

            if (isLeftClick)
            {
                // Pick up a completed building
                if (first != null && first.Done && actor.Traits.Contains <BuildingInfo>())
                {
                    Sound.Play(TabClick);
                    World.OrderGenerator = new PlaceBuildingOrderGenerator(CurrentQueue, icon.Name);
                }
                else if (first != null && first.Paused)
                {
                    // Resume a paused item
                    Sound.Play(TabClick);
                    World.IssueOrder(Order.PauseProduction(CurrentQueue.Actor, icon.Name, false));
                }
                else if (CurrentQueue.BuildableItems().Any(a => a.Name == icon.Name))
                {
                    // Queue a new item
                    Sound.Play(TabClick);
                    Sound.PlayNotification(World.Map.Rules, World.LocalPlayer, "Speech", CurrentQueue.Info.QueuedAudio, World.LocalPlayer.Country.Race);
                    World.IssueOrder(Order.StartProduction(CurrentQueue.Actor, icon.Name,
                                                           handleMultiple ? 5 : 1));
                }
                else
                {
                    Sound.Play(DisabledTabClick);
                }
            }
            else
            {
                // Hold/Cancel an existing item
                if (first != null)
                {
                    Sound.Play(TabClick);

                    // instant cancel of things we havent started yet and things that are finished
                    if (first.Paused || first.Done || first.TotalCost == first.RemainingCost)
                    {
                        Sound.PlayNotification(World.Map.Rules, World.LocalPlayer, "Speech", CurrentQueue.Info.CancelledAudio, World.LocalPlayer.Country.Race);
                        World.IssueOrder(Order.CancelProduction(CurrentQueue.Actor, icon.Name,
                                                                handleMultiple ? 5 : 1));
                    }
                    else
                    {
                        Sound.PlayNotification(World.Map.Rules, World.LocalPlayer, "Speech", CurrentQueue.Info.OnHoldAudio, World.LocalPlayer.Country.Race);
                        World.IssueOrder(Order.PauseProduction(CurrentQueue.Actor, icon.Name, true));
                    }
                }
                else
                {
                    Sound.Play(DisabledTabClick);
                }
            }

            return(true);
        }
示例#7
0
        public void RefreshIcons()
        {
            icons = new Dictionary <Rectangle, ProductionIcon>();
            if (CurrentQueue == null)
            {
                return;
            }

            var allBuildables = CurrentQueue.AllItems().OrderBy(a => a.Traits.Get <BuildableInfo>().BuildPaletteOrder);
            var i             = 0;
            var rb            = RenderBounds;

            foreach (var item in allBuildables)
            {
                var x    = i % Columns;
                var y    = i / Columns;
                var rect = new Rectangle(rb.X + x * 64 + 1, rb.Y + y * 48 + 1, 64, 48);
                var icon = new Animation(RenderSimple.GetImage(item));
                icon.Play(item.Traits.Get <TooltipInfo>().Icon);
                var pi = new ProductionIcon()
                {
                    Name   = item.Name,
                    Sprite = icon.Image,
                    Pos    = new float2(rect.Location),
                    Queued = CurrentQueue.AllQueued().Where(a => a.Item == item.Name).ToList(),
                };
                icons.Add(rect, pi);
                i++;
            }

            eventBounds = icons.Keys.Aggregate(Rectangle.Union);
        }
示例#8
0
        private void OnTick(object sender, EventArgs args)
        {
            // Remove old overflows
            if (OverflowDictionary.Count > 0)
            {
                foreach (var entry in OverflowDictionary.ToArray().Where(entry => Environment.TickCount - entry.Value > 5000))
                {
                    OverflowDictionary.Remove(entry.Key);
                }
            }

            if (ModAPI.Input.GetButton("InstantBuild"))
            {
                var ray = Camera.main.ScreenPointToRay(new Vector3(Screen.width / 2f, Screen.height / 2f, 0f));
                ray.origin += Camera.main.transform.forward * 1f;
                var raycastHits = Physics.RaycastAll(ray, 100f);
                if (raycastHits.Length > 0)
                {
                    foreach (var structure in raycastHits.Select(raycastHit => raycastHit.collider.GetComponent <Craft_Structure>()).Where(structure => structure != null))
                    {
                        AddBlueprintToQueue(structure);
                    }
                }
            }

            if (CurrentQueue.Count > 0 && Environment.TickCount - _lastAction > 1f / ActionsPerSecond * 1000)
            {
                _lastAction = Environment.TickCount;
                InstantlyFinishBlueprint(CurrentQueue[0]);
                CurrentQueue.RemoveAt(0);
            }
        }
        public TaskState Process()
        {
            ISimpleTask currentTask = CurrentQueue.Dequeue();

            CurrentTask = currentTask;

            //if (currentTask is StateTaskList tasks)
            //	tasks.Stack = new TaskStack(_game);

            _game.Log(LogLevel.VERBOSE, BlockType.TRIGGER, "TaskQueue", !_game.Logging ? "" : $"LazyTask[{currentTask.Source}]: '{currentTask.GetType().Name}' is processed!" +
                      $"'{currentTask.Source.Card.Text?.Replace("\n", " ")}'");
            if (_game.History)
            {
                _game.PowerHistory.Add(PowerHistoryBuilder.BlockStart(currentTask.IsTrigger ? BlockType.TRIGGER : BlockType.POWER, currentTask.Source.Id, "", -1, currentTask.Target?.Id ?? 0));
            }

            TaskState success = currentTask.Process();

            if (_game.History)
            {
                _game.PowerHistory.Add(PowerHistoryBuilder.BlockEnd());
            }

            // reset between task execution
            //_game.TaskStack.Reset();

            CurrentTask = null;

            return(success);
        }
示例#10
0
        public void RefreshIcons()
        {
            icons = new Dictionary <Rectangle, ProductionIcon>();
            var producer = CurrentQueue != null?CurrentQueue.MostLikelyProducer() : default(TraitPair <Production>);

            if (CurrentQueue == null || producer.Trait == null)
            {
                if (DisplayedIconCount != 0)
                {
                    OnIconCountChanged(DisplayedIconCount, 0);
                    DisplayedIconCount = 0;
                }

                return;
            }

            var oldIconCount = DisplayedIconCount;

            DisplayedIconCount = 0;

            var ks      = Game.Settings.Keys;
            var rb      = RenderBounds;
            var faction = producer.Trait.Faction;

            foreach (var item in AllBuildables.Skip(IconRowOffset * Columns).Take(MaxIconRowOffset * Columns))
            {
                var x    = DisplayedIconCount % Columns;
                var y    = DisplayedIconCount / Columns;
                var rect = new Rectangle(rb.X + x * (IconSize.X + IconMargin.X), rb.Y + y * (IconSize.Y + IconMargin.Y), IconSize.X, IconSize.Y);

                var rsi  = item.TraitInfo <RenderSpritesInfo>();
                var icon = new Animation(World, rsi.GetImage(item, World.Map.Rules.Sequences, faction));
                var bi   = item.TraitInfo <BuildableInfo>();
                icon.Play(bi.Icon);

                var pi = new ProductionIcon()
                {
                    Actor             = item,
                    Name              = item.Name,
                    Hotkey            = ks.GetProductionHotkey(DisplayedIconCount),
                    Sprite            = icon.Image,
                    Palette           = worldRenderer.Palette(bi.IconPalette),
                    IconClockPalette  = worldRenderer.Palette(ClockPalette),
                    IconDarkenPalette = worldRenderer.Palette(NotBuildablePalette),
                    Pos             = new float2(rect.Location),
                    Queued          = currentQueue.AllQueued().Where(a => a.Item == item.Name).ToList(),
                    ProductionQueue = currentQueue
                };

                icons.Add(rect, pi);
                DisplayedIconCount++;
            }

            eventBounds = icons.Any() ? icons.Keys.Aggregate(Rectangle.Union) : Rectangle.Empty;

            if (oldIconCount != DisplayedIconCount)
            {
                OnIconCountChanged(oldIconCount, DisplayedIconCount);
            }
        }
        public override void Draw()
        {
            var iconOffset = 0.5f * IconSize.ToFloat2() + IconSpriteOffset;

            if (CurrentQueue == null)
            {
                return;
            }

            var buildableItems = CurrentQueue.BuildableItems();
            var pios           = currentQueue.Actor.Owner.PlayerActor.TraitsImplementing <IProductionIconOverlay>();

            // Icons
            foreach (var icon in icons.Values)
            {
                WidgetUtils.DrawSHPCentered(icon.Sprite, icon.Pos + iconOffset, icon.Palette);

                // Draw the ProductionIconOverlay's sprite
                var pio = pios.FirstOrDefault(p => p.IsOverlayActive(icon.Actor));
                if (pio != null)
                {
                    WidgetUtils.DrawSHPCentered(pio.Sprite, icon.Pos + iconOffset + pio.Offset(IconSize), worldRenderer.Palette(pio.Palette), 1f);
                }

                if (!buildableItems.Any(a => a.Name == icon.Name))
                {
                    WidgetUtils.DrawSHPCentered(cantBuild.Image, icon.Pos + iconOffset, icon.IconDarkenPalette);
                }
            }

            // TODO: Selection overlay
        }
示例#12
0
        internal QueueSongData AddToQueue(Int64 p_SongID, Int64 p_QueueID, String p_SongName, Int64 p_ArtistID, String p_ArtistName, Int64 p_AlbumID, String p_AlbumName, int p_Index = -1)
        {
            if (p_Index <= -1 || p_Index > CurrentQueue.Count)
            {
                p_Index = CurrentQueue.Count;
            }

            var s_SongData = new QueueSongData()
            {
                QueueID    = p_QueueID,
                SongID     = p_SongID,
                SongName   = p_SongName,
                ArtistID   = p_AlbumID,
                ArtistName = p_ArtistName,
                AlbumID    = p_AlbumID,
                AlbumName  = p_AlbumName,
                Votes      = 0
            };

            if (p_QueueID > CurrentQueueID)
            {
                CurrentQueueID = p_QueueID;
            }

            lock (CurrentQueue)
                CurrentQueue.Insert(p_Index, s_SongData);

            return(s_SongData);
        }
示例#13
0
        public void RtmpConn_MessageReceived(object sender, MessageReceivedEventArgs e)
        {
            try {
                if (CurrentQueue != null && CurrentQueue.HandleMessage(e))
                {
                    return;
                }

                if (CurrentLobby != null && CurrentLobby.HandleMessage(e))
                {
                    return;
                }
            } catch (Exception x) {
                ThrowException(x, "Exception while dispatching message");
            }

            var response  = e.Body as LcdsServiceProxyResponse;
            var config    = e.Body as ClientDynamicConfigurationNotification;
            var invite    = e.Body as InvitationRequest;
            var endofgame = e.Body as EndOfGameStats;

            try {
                if (response != null)
                {
                    if (response.status.Equals("ACK"))
                    {
                        Log($"Acknowledged call of method {response.methodName} [{response.messageId}]");
                    }
                    else if (response.messageId != null && RiotServices.Delegates.ContainsKey(response.messageId))
                    {
                        RiotServices.Delegates[response.messageId](response);
                        RiotServices.Delegates.Remove(response.messageId);
                    }
                    else
                    {
                        Log($"Unhandled LCDS response of method {response.methodName} [{response.messageId}], {response.payload}");
                    }
                }
                else if (config != null)
                {
                    Log("Received Configuration Notification");
                }
                else if (invite != null)
                {
                    ShowInvite(invite);
                }
                else if (endofgame != null)
                {
                    //TODO End of game
                }
                else
                {
                    Log($"Receive [{e.Subtopic}, {e.ClientId}]: '{e.Body}'");
                }
            } catch (Exception x) {
                ThrowException(x, "Exception while handling message");
            }
        }
示例#14
0
        public int GetPlayingSongIndex()
        {
            if (Library.Broadcast.PlayingSongQueueID == 0)
            {
                return(-1);
            }

            return(CurrentQueue.FindIndex(p_Item => p_Item.QueueID == Library.Broadcast.PlayingSongQueueID));
        }
示例#15
0
        public Int64 GetSongIDForQueueID(Int64 p_QueueID)
        {
            var s_SongData = CurrentQueue.FirstOrDefault(p_Item => p_Item.QueueID == p_QueueID);

            if (s_SongData == null)
            {
                return(-1);
            }

            return(s_SongData.SongID);
        }
示例#16
0
        internal void RemoveFromQueue(int p_Index)
        {
            lock (CurrentQueue)
            {
                if (p_Index < 0 || p_Index >= CurrentQueue.Count)
                {
                    return;
                }

                CurrentQueue.RemoveAt(p_Index);
            }
        }
 public void Reset()
 {
     if (this.defer.TryPeek(out var p))
     {
         this.currentQueue = CurrentQueue.Defer;
         this.deferStop    = this.defer.ProducerIndex;
     }
     else
     {
         this.currentQueue = CurrentQueue.NormalQueue;
     }
 }
示例#18
0
        public void RefreshIcons()
        {
            icons = new Dictionary <Rectangle, ProductionIcon>();
            if (CurrentQueue == null)
            {
                if (IconCount != 0)
                {
                    OnIconCountChanged(IconCount, 0);
                    IconCount = 0;
                }

                return;
            }

            var allBuildables = CurrentQueue.AllItems().OrderBy(a => a.Traits.Get <BuildableInfo>().BuildPaletteOrder);

            var oldIconCount = IconCount;

            IconCount = 0;

            var ks = Game.Settings.Keys;
            var rb = RenderBounds;

            foreach (var item in allBuildables)
            {
                var x    = IconCount % Columns;
                var y    = IconCount / Columns;
                var rect = new Rectangle(rb.X + x * (IconSize.X + IconMargin.X), rb.Y + y * (IconSize.Y + IconMargin.Y), IconSize.X, IconSize.Y);
                var icon = new Animation(World, RenderSimple.GetImage(item));
                icon.Play(item.Traits.Get <TooltipInfo>().Icon);

                var pi = new ProductionIcon()
                {
                    Actor  = item,
                    Name   = item.Name,
                    Hotkey = ks.GetProductionHotkey(IconCount),
                    Sprite = icon.Image,
                    Pos    = new float2(rect.Location),
                    Queued = CurrentQueue.AllQueued().Where(a => a.Item == item.Name).ToList(),
                };

                icons.Add(rect, pi);
                IconCount++;
            }

            eventBounds = icons.Any() ? icons.Keys.Aggregate(Rectangle.Union) : Rectangle.Empty;

            if (oldIconCount != IconCount)
            {
                OnIconCountChanged(oldIconCount, IconCount);
            }
        }
示例#19
0
        // Advances the game state forward in time
        public bool Update(Func <ActionResult> inputAction)
        {
            if (inputAction == null && !Player.HasNextStep)
            {
                return(false);
            }

            var characters = CurrentFloor.Entities.OfType <Character>().ToArray();

            Ticks++;
            if (Ticks % RegenRate == 0)
            {
                foreach (var character in characters)
                {
                    character.Regenerate();
                }
            }

            Player.PendingAction = inputAction;
            Player.Update(this);
            NextQueue.Enqueue(Player, -Player.Sequence);

            if (CurrentQueue.Count == 0)
            {
                foreach (var character in CurrentFloor.Entities.OfType <Character>())
                {
                    CurrentQueue.Enqueue(character, -character.Sequence);
                }
            }

            while (CurrentQueue.Count != 0)
            {
                var current = CurrentQueue.Dequeue();

                if (current is Player)
                {
                    return(true);
                }

                var actionResult = current.Update(this);
                Log.LogActionResult(actionResult);
                NextQueue.Enqueue(current, -current.Sequence);
            }

            var tempQueue = CurrentQueue;

            CurrentQueue = NextQueue;
            NextQueue    = tempQueue;
            NextQueue.Clear();

            return(true);
        }
示例#20
0
        private void OnSongVote(SharkEvent p_SharkEvent)
        {
            var s_Event = (SongVoteEvent)p_SharkEvent;

            var s_SongData = CurrentQueue.FirstOrDefault(p_Item => p_Item.QueueID == s_Event.QueueSongID);

            if (s_SongData == null)
            {
                return;
            }

            s_SongData.Votes = s_Event.VoteChange;
        }
示例#21
0
 /** Push element x onto stack. */
 public void Push(int x)
 {
     Discriminator = (Discriminator + 1) % 2;
     CurrentQueue.Enqueue(x);
     if (OldQueue.Count != 0)
     {
         int oldQueueCount = OldQueue.Count;
         for (int i = 0; i < oldQueueCount; i++)
         {
             CurrentQueue.Enqueue(OldQueue.Dequeue());
         }
     }
 }
示例#22
0
        public void Enqueue(ISimpleTask task)
        {
            if (_standbyEvent != null)
            {
                _eventStack.Push(_standbyEvent.Value);
                _standbyEvent = null;
                _eventCreated = true;
            }

            CurrentQueue.Enqueue(task);

            _game.Log(LogLevel.DEBUG, BlockType.TRIGGER, "TaskQueue",
                      !_game.Logging ? "" : $"{task.GetType().Name} is Enqueued in {_eventStack.Count}th stack");
        }
示例#23
0
        internal void RemoveSongFromQueue(Int64 p_QueueID)
        {
            lock (CurrentQueue)
            {
                var s_SongIndex = CurrentQueue.FindIndex(p_Item => p_Item.QueueID == p_QueueID);

                if (s_SongIndex == -1)
                {
                    return;
                }

                CurrentQueue.RemoveAt(s_SongIndex);
            }
        }
示例#24
0
        public void Enqueue(ISimpleTask task)
        {
            if (_eventFlag)                  // flag = true means Event starts and no tasks queue yet
            {
                if (CurrentQueue.Count != 0) // Check if an ongoing event exists
                {
                    _eventStack.Push(new Queue <ISimpleTask>());
                }

                _eventFlag = false;
            }

            CurrentQueue.Enqueue(task);

            //_game.Log(LogLevel.DEBUG, BlockType.TRIGGER, "TaskQueue",
            //	!_game.Logging ? "" : $"{task.GetType().Name} is Enqueued in {_eventStack.Count}th stack");
        }
示例#25
0
        internal void MoveSong(Int64 p_QueueID, int p_Index)
        {
            lock (CurrentQueue)
            {
                var s_SongIndex = CurrentQueue.FindIndex(p_Item => p_Item.QueueID == p_QueueID);

                if (s_SongIndex == -1)
                {
                    return;
                }

                var s_SongData = CurrentQueue[s_SongIndex];
                CurrentQueue.RemoveAt(s_SongIndex);

                AddToQueue(s_SongData, p_Index);
            }
        }
示例#26
0
        internal QueueSongData AddToQueue(QueueSongData p_SongData, int p_Index)
        {
            if (p_Index <= -1 || p_Index > CurrentQueue.Count)
            {
                p_Index = CurrentQueue.Count;
            }

            lock (CurrentQueue)
                CurrentQueue.Insert(p_Index, p_SongData);


            if (p_SongData.QueueID > CurrentQueueID)
            {
                CurrentQueueID = p_SongData.QueueID;
            }

            return(p_SongData);
        }
示例#27
0
 public void Logout()
 {
     if (Connected)
     {
         try {
             SaveSettings(Settings.Username, Settings);
             RtmpConn.MessageReceived -= RtmpConn_MessageReceived;
             HeartbeatTimer.Dispose();
             new Thread(async() => {
                 Connected = false;
                 CurrentQueue?.Cancel();
                 CurrentLobby?.Dispose();
                 await RiotServices.LoginService.Logout();
                 await RtmpConn.LogoutAsync();
                 RtmpConn.Close();
             }).Start();
         } catch { }
     }
     ChatManager?.Dispose();
 }
示例#28
0
        public override void Draw()
        {
            var iconOffset = 0.5f * IconSize.ToVector2() + IconSpriteOffset;

            overlayFont  = WarGame.Renderer.Fonts["TinyBold"];
            timeOffset   = iconOffset - overlayFont.Measure(WidgetUtils.FormatTime(0, World.Timestep)) / 2;
            queuedOffset = new Vector2(4, 2);
            holdOffset   = iconOffset - overlayFont.Measure(HoldText) / 2;
            readyOffset  = iconOffset - overlayFont.Measure(ReadyText) / 2;

            if (CurrentQueue == null)
            {
                return;
            }

            var buildableItems = CurrentQueue.BuildableItems();

            var pios = currentQueue.Actor.Owner.PlayerActor.TraitsImplementing <IProductionIconOverlay>();


            //Icons
            foreach (var icon in icons.Values)
            {
                WidgetUtils.DrawSHPCentered(icon.Sprite, icon.Pos + iconOffset, icon.Palette);

                //Build progress
                if (icon.Queued.Count > 0)
                {
                    var first = icon.Queued[0];

                    clock.PlayFetchIndex(ClockSequence, () => (first.TotalTime - first.RemainingTime) * (clock.CurrentSequence.Length - 1) / first.TotalTime);
                    clock.Tick();

                    WidgetUtils.DrawSHPCentered(clock.Image, icon.Pos + iconOffset, icon.IconClockPalette);
                }
                else if (!buildableItems.Any(a => a.Name == icon.Name))
                {
                    WidgetUtils.DrawSHPCentered(cantBuild.Image, icon.Pos + iconOffset, icon.IconDarkenPalette);
                }
            }
        }
        bool HandleLeftClick(ProductionItem item, ProductionIcon icon, int handleCount, Modifiers modifiers)
        {
            if (PickUpCompletedBuildingIcon(icon, item))
            {
                Game.Sound.PlayNotification(World.Map.Rules, World.LocalPlayer, "Sounds", ClickSound, null);
                return(true);
            }

            if (item != null && item.Paused)
            {
                // Resume a paused item
                Game.Sound.PlayNotification(World.Map.Rules, World.LocalPlayer, "Sounds", ClickSound, null);
                Game.Sound.PlayNotification(World.Map.Rules, World.LocalPlayer, "Speech", CurrentQueue.Info.QueuedAudio, World.LocalPlayer.Faction.InternalName);
                World.IssueOrder(Order.PauseProduction(CurrentQueue.Actor, icon.Name, false));
                return(true);
            }

            var buildable = CurrentQueue.BuildableItems().FirstOrDefault(a => a.Name == icon.Name);

            if (buildable != null)
            {
                // Queue a new item
                Game.Sound.PlayNotification(World.Map.Rules, World.LocalPlayer, "Sounds", ClickSound, null);
                string notification;
                var    canQueue = CurrentQueue.CanQueue(buildable, out notification);

                if (!CurrentQueue.AllQueued().Any())
                {
                    Game.Sound.PlayNotification(World.Map.Rules, World.LocalPlayer, "Speech", notification, World.LocalPlayer.Faction.InternalName);
                }

                if (canQueue)
                {
                    var queued = !modifiers.HasModifier(Modifiers.Ctrl);
                    World.IssueOrder(Order.StartProduction(CurrentQueue.Actor, icon.Name, handleCount, queued));
                    return(true);
                }
            }

            return(false);
        }
        public bool Next(out TNode node)
        {
            if (this.currentQueue == CurrentQueue.Defer)
            {
                if (this.deferStop >= this.defer.ConsumerIndex)
                {
                    this.currentQueue = CurrentQueue.NormalQueue;
                }
                else
                {
                    if (!this.defer.TryPoll(out node))
                    {
                        this.currentQueue = CurrentQueue.NormalQueue;
                    }
                    else
                    {
                        return(true);
                    }
                }
            }

            return(this.primary.TryPoll(out node));
        }