Exemplo n.º 1
0
        /// <summary>Detail scans an area, evaluating positions.</summary>
        CPos?FindAttackLocationToSupportPower(SupportPowerInstance readyPower)
        {
            CPos?bestLocation       = null;
            var  bestAttractiveness = 0;
            var  powerDecision      = powerDecisions[readyPower.Info.OrderName];

            if (powerDecision == null)
            {
                AIUtils.BotDebug("Bot Bug: FindAttackLocationToSupportPower, couldn't find powerDecision for {0}", readyPower.Info.OrderName);
                return(null);
            }

            var availableTargets = world.ActorsHavingTrait <IOccupySpace>().Where(x => x.IsInWorld && !x.IsDead &&
                                                                                  (powerDecision.IgnoreVisibility || x.CanBeViewedByPlayer(player)) &&
                                                                                  powerDecision.Against.HasRelationship(player.RelationshipWith(x.Owner)) &&
                                                                                  powerDecision.Types.Overlaps(x.GetEnabledTargetTypes()));

            foreach (var a in availableTargets)
            {
                var pos = a.CenterPosition;
                var consideredAttractiveness = 0;
                consideredAttractiveness += powerDecision.GetAttractiveness(pos, player);

                if (consideredAttractiveness <= bestAttractiveness || consideredAttractiveness < powerDecision.MinimumAttractiveness)
                {
                    continue;
                }

                bestAttractiveness = consideredAttractiveness;
                bestLocation       = world.Map.CellContaining(pos);
            }

            return(bestLocation);
        }
        /// <summary>Scans the map in chunks, evaluating all actors in each.</summary>
        CPos?FindCoarseAttackLocationToSupportPower(SupportPowerInstance readyPower)
        {
            CPos?bestLocation  = null;
            var  powerDecision = powerDecisions[readyPower.Info.OrderName];

            if (powerDecision == null)
            {
                AIUtils.BotDebug("Bot Bug: FindAttackLocationToSupportPower, couldn't find powerDecision for {0}", readyPower.Info.OrderName);
                return(null);
            }

            var map                 = world.Map;
            var checkRadius         = powerDecision.CoarseScanRadius;
            var suitableLocations   = new List <int[]>();
            var totalAttractiveness = 0;

            for (var i = 0; i < map.MapSize.X; i += checkRadius)
            {
                for (var j = 0; j < map.MapSize.Y; j += checkRadius)
                {
                    var tl     = new MPos(i, j);
                    var br     = new MPos(i + checkRadius, j + checkRadius);
                    var region = new CellRegion(map.Grid.Type, tl, br);

                    // HACK: The AI code should not be messing with raw coordinate transformations
                    var wtl     = world.Map.CenterOfCell(tl.ToCPos(map));
                    var wbr     = world.Map.CenterOfCell(br.ToCPos(map));
                    var targets = world.ActorMap.ActorsInBox(wtl, wbr);

                    var frozenTargets = player.FrozenActorLayer != null?player.FrozenActorLayer.FrozenActorsInRegion(region) : Enumerable.Empty <FrozenActor>();

                    var consideredAttractiveness = powerDecision.GetAttractiveness(targets, player) + powerDecision.GetAttractiveness(frozenTargets, player);
                    if (consideredAttractiveness < powerDecision.MinimumAttractiveness)
                    {
                        continue;
                    }

                    suitableLocations.Add(new int[] { i, j, consideredAttractiveness });
                    totalAttractiveness += consideredAttractiveness;
                }
            }

            if (suitableLocations.Any())
            {
                // Only consider locations of above average attractiveness.
                var avgAttractiveness = totalAttractiveness / suitableLocations.Count();

                foreach (var location in Util.Shuffle(suitableLocations, world.LocalRandom))
                {
                    if (location[2] >= avgAttractiveness)
                    {
                        bestLocation = new MPos(location[0], location[1]).ToCPos(map);
                        break;
                    }
                }
            }

            return(bestLocation);
        }
Exemplo n.º 3
0
 static string GetOverlayForItem(SupportPowerInstance item, int timestep)
 {
     if (item.Disabled)
     {
         return("ON HOLD");
     }
     if (item.Ready)
     {
         return("READY");
     }
     return(WidgetUtils.FormatTime(item.RemainingTime, timestep));
 }
Exemplo n.º 4
0
        public SupportPowerTooltipLogic(Widget widget, TooltipContainerWidget tooltipContainer, SupportPowersWidget palette)
        {
            widget.IsVisible = () => palette.TooltipPower != null;
            var nameLabel  = widget.Get <LabelWidget>("NAME");
            var timeLabel  = widget.Get <LabelWidget>("TIME");
            var descLabel  = widget.Get <LabelWidget>("DESC");
            var nameFont   = Game.Renderer.Fonts[nameLabel.Font];
            var timeFont   = Game.Renderer.Fonts[timeLabel.Font];
            var descFont   = Game.Renderer.Fonts[descLabel.Font];
            var name       = "";
            var time       = "";
            var desc       = "";
            var baseHeight = widget.Bounds.Height;
            var timeOffset = timeLabel.Bounds.X;

            SupportPowerInstance lastPower = null;

            tooltipContainer.BeforeRender = () =>
            {
                var sp = palette.TooltipPower;
                if (sp == null)
                {
                    return;
                }

                if (sp.Info == null)
                {
                    return;                             // no instances actually exist (race with destroy)
                }
                time = "{0} / {1}".F(WidgetUtils.FormatTime(sp.RemainingTime),
                                     WidgetUtils.FormatTime(sp.Info.ChargeTime * 25));

                if (sp == lastPower)
                {
                    return;
                }

                name = sp.Info.Description;
                desc = sp.Info.LongDesc.Replace("\\n", "\n");
                var timeWidth = timeFont.Measure(time).X;
                var topWidth  = nameFont.Measure(name).X + timeWidth + timeOffset;
                var descSize  = descFont.Measure(desc);
                widget.Bounds.Width  = 2 * nameLabel.Bounds.X + Math.Max(topWidth, descSize.X);
                widget.Bounds.Height = baseHeight + descSize.Y;
                timeLabel.Bounds.X   = widget.Bounds.Width - nameLabel.Bounds.X - timeWidth;
                lastPower            = sp;
            };

            nameLabel.GetText = () => name;
            timeLabel.GetText = () => time;
            descLabel.GetText = () => desc;
        }
Exemplo n.º 5
0
        public SelectAttackPowerTarget(Actor self, string order, SupportPowerManager manager, string cursor, MouseButton button, AttackBase attack)
        {
            // Clear selection if using Left-Click Orders
            if (Game.Settings.Game.UseClassicMouseStyle)
            {
                manager.Self.World.Selection.Clear();
            }

            instance       = manager.GetPowersForActor(self).FirstOrDefault();
            this.manager   = manager;
            this.order     = order;
            this.cursor    = cursor;
            expectedButton = button;
            this.attack    = attack;
            cursorBlocked  = cursor + "-blocked";
        }
Exemplo n.º 6
0
        /// <summary>Scans the map in chunks, evaluating all actors in each.</summary>
        CPos?FindCoarseAttackLocationToSupportPower(SupportPowerInstance readyPower)
        {
            CPos?bestLocation       = null;
            var  bestAttractiveness = 0;
            var  powerDecision      = powerDecisions[readyPower.Info.OrderName];

            if (powerDecision == null)
            {
                HackyAI.BotDebug("Bot Bug: FindAttackLocationToSupportPower, couldn't find powerDecision for {0}", readyPower.Info.OrderName);
                return(null);
            }

            var map         = world.Map;
            var checkRadius = powerDecision.CoarseScanRadius;

            for (var i = 0; i < map.MapSize.X; i += checkRadius)
            {
                for (var j = 0; j < map.MapSize.Y; j += checkRadius)
                {
                    var tl     = new MPos(i, j);
                    var br     = new MPos(i + checkRadius, j + checkRadius);
                    var region = new CellRegion(map.Grid.Type, tl, br);

                    // HACK: The AI code should not be messing with raw coordinate transformations
                    var wtl     = world.Map.CenterOfCell(tl.ToCPos(map));
                    var wbr     = world.Map.CenterOfCell(br.ToCPos(map));
                    var targets = world.ActorMap.ActorsInBox(wtl, wbr);

                    var frozenTargets            = frozenLayer.FrozenActorsInRegion(region);
                    var consideredAttractiveness = powerDecision.GetAttractiveness(targets, player) + powerDecision.GetAttractiveness(frozenTargets, player);
                    if (consideredAttractiveness <= bestAttractiveness || consideredAttractiveness < powerDecision.MinimumAttractiveness)
                    {
                        continue;
                    }

                    bestAttractiveness = consideredAttractiveness;
                    bestLocation       = new MPos(i, j).ToCPos(map);
                }
            }

            return(bestLocation);
        }
Exemplo n.º 7
0
        /// <summary>Detail scans an area, evaluating positions.</summary>
        CPos?FindFineAttackLocationToSupportPower(SupportPowerInstance readyPower, CPos checkPos, int extendedRange = 1)
        {
            CPos?bestLocation       = null;
            var  bestAttractiveness = 0;
            var  powerDecision      = powerDecisions[readyPower.Info.OrderName];

            if (powerDecision == null)
            {
                BotDebug("Bot Bug: FindAttackLocationToSupportPower, couldn't find powerDecision for {0}", readyPower.Info.OrderName);
                return(null);
            }

            var checkRadius = powerDecision.CoarseScanRadius;
            var fineCheck   = powerDecision.FineScanRadius;

            for (var i = 0 - extendedRange; i <= (checkRadius + extendedRange); i += fineCheck)
            {
                var x = checkPos.X + i;

                for (var j = 0 - extendedRange; j <= (checkRadius + extendedRange); j += fineCheck)
                {
                    var y   = checkPos.Y + j;
                    var pos = World.Map.CenterOfCell(new CPos(x, y));
                    var consideredAttractiveness = 0;
                    consideredAttractiveness += powerDecision.GetAttractiveness(pos, Player);

                    if (consideredAttractiveness <= bestAttractiveness || consideredAttractiveness < powerDecision.MinimumAttractiveness)
                    {
                        continue;
                    }

                    bestAttractiveness = consideredAttractiveness;
                    bestLocation       = new CPos(x, y);
                }
            }

            return(bestLocation);
        }
Exemplo n.º 8
0
        /// <summary>Scans the map in chunks, evaluating all actors in each.</summary>
        CPos?FindCoarseAttackLocationToSupportPower(SupportPowerInstance readyPower)
        {
            CPos?bestLocation       = null;
            var  bestAttractiveness = 0;
            var  powerDecision      = powerDecisions[readyPower.Info.OrderName];

            if (powerDecision == null)
            {
                BotDebug("Bot Bug: FindAttackLocationToSupportPower, couldn't find powerDecision for {0}", readyPower.Info.OrderName);
                return(null);
            }

            var checkRadius = powerDecision.CoarseScanRadius;

            for (var i = 0; i < World.Map.MapSize.X; i += checkRadius)
            {
                for (var j = 0; j < World.Map.MapSize.Y; j += checkRadius)
                {
                    var consideredAttractiveness = 0;

                    var tl      = World.Map.CenterOfCell(new CPos(i, j));
                    var br      = World.Map.CenterOfCell(new CPos(i + checkRadius, j + checkRadius));
                    var targets = World.ActorMap.ActorsInBox(tl, br);

                    consideredAttractiveness = powerDecision.GetAttractiveness(targets, Player);
                    if (consideredAttractiveness <= bestAttractiveness || consideredAttractiveness < powerDecision.MinimumAttractiveness)
                    {
                        continue;
                    }

                    bestAttractiveness = consideredAttractiveness;
                    bestLocation       = new CPos(i, j);
                }
            }

            return(bestLocation);
        }
		static string GetOverlayForItem(SupportPowerInstance item, int timestep)
		{
			if (item.Disabled) return "ON HOLD";
			if (item.Ready) return "READY";
			return WidgetUtils.FormatTime(item.RemainingTime, timestep);
		}
Exemplo n.º 10
0
        public override bool HandleMouseInput(MouseInput mi)
        {
            if (mi.Event == MouseInputEvent.Move)
            {
                var icon = icons.Where(i => i.Key.Contains(mi.Location))
                    .Select(i => i.Value).FirstOrDefault();
                TooltipPower = (icon != null) ? icon.Power : null;
                return false;
            }

            if (mi.Event != MouseInputEvent.Down)
                return false;

            var clicked = icons.Where(i => i.Key.Contains(mi.Location))
                .Select(i => i.Value).FirstOrDefault();

            if (clicked != null)
            {
                if (!clicked.Power.Active)
                    Sound.PlayToPlayer(spm.self.Owner, clicked.Power.Info.InsufficientPowerSound);
                spm.Target(clicked.Power.Info.OrderName);
            }

            return true;
        }
Exemplo n.º 11
0
        public SupportPowerTooltipLogic(Widget widget, TooltipContainerWidget tooltipContainer, SupportPowersWidget palette, World world, PlayerResources playerResources)
        {
            widget.IsVisible = () => palette.TooltipIcon != null;
            var nameLabel   = widget.Get <LabelWidget>("NAME");
            var hotkeyLabel = widget.Get <LabelWidget>("HOTKEY");
            var timeLabel   = widget.Get <LabelWidget>("TIME");
            var descLabel   = widget.Get <LabelWidget>("DESC");
            var costLabel   = widget.Get <LabelWidget>("COST");
            var nameFont    = Game.Renderer.Fonts[nameLabel.Font];
            var timeFont    = Game.Renderer.Fonts[timeLabel.Font];
            var descFont    = Game.Renderer.Fonts[descLabel.Font];
            var costFont    = Game.Renderer.Fonts[costLabel.Font];
            var name        = "";
            var time        = "";
            var desc        = "";
            var baseHeight  = widget.Bounds.Height;
            var timeOffset  = timeLabel.Bounds.X;
            var costOffset  = costLabel.Bounds.X;

            SupportPowerInstance lastPower = null;

            tooltipContainer.BeforeRender = () =>
            {
                var icon = palette.TooltipIcon;

                if (icon == null)
                {
                    return;
                }

                var sp = icon.Power;

                if (sp.Info == null)
                {
                    return;                             // no instances actually exist (race with destroy)
                }
                var remaining = WidgetUtils.FormatTime(sp.RemainingTime, world.Timestep);
                var total     = WidgetUtils.FormatTime(sp.Info.ChargeTime * 25, world.Timestep);
                time = "{0} / {1}".F(remaining, total);

                if (sp == lastPower)
                {
                    return;
                }

                var cost       = sp.Info.Cost;
                var costString = costLabel.Text + cost.ToString();
                costLabel.GetText  = () => costString;
                costLabel.GetColor = () => playerResources.Cash + playerResources.Resources >= cost
                                        ? Color.White : Color.Red;
                costLabel.IsVisible = () => cost != 0;

                name = sp.Info.Description;
                desc = sp.Info.LongDesc.Replace("\\n", "\n");

                var hotkey      = icon.Hotkey;
                var hotkeyText  = "({0})".F(hotkey.DisplayString());
                var hotkeyWidth = hotkey.IsValid() ? nameFont.Measure(hotkeyText).X + 2 * nameLabel.Bounds.X : 0;
                hotkeyLabel.GetText  = () => hotkeyText;
                hotkeyLabel.Bounds.X = nameFont.Measure(name).X + 2 * nameLabel.Bounds.X;
                hotkeyLabel.Visible  = hotkey.IsValid();

                var timeWidth = timeFont.Measure(time).X;
                var costWidth = costFont.Measure(costString).X;
                var topWidth  = nameFont.Measure(name).X + hotkeyWidth + timeWidth + timeOffset;

                if (cost != 0)
                {
                    topWidth += costWidth + costOffset;
                }

                var descSize = descFont.Measure(desc);
                widget.Bounds.Width  = 2 * nameLabel.Bounds.X + Math.Max(topWidth, descSize.X);
                widget.Bounds.Height = baseHeight + descSize.Y;
                timeLabel.Bounds.X   = widget.Bounds.Width - nameLabel.Bounds.X - timeWidth;

                if (cost != 0)
                {
                    timeLabel.Bounds.X -= costWidth + costOffset;
                    costLabel.Bounds.X  = widget.Bounds.Width - nameLabel.Bounds.X - costWidth;
                }

                lastPower = sp;
            };

            nameLabel.GetText = () => name;
            timeLabel.GetText = () => time;
            descLabel.GetText = () => desc;
        }
Exemplo n.º 12
0
		/// <summary>Detail scans an area, evaluating positions.</summary>
		CPos? FindFineAttackLocationToSupportPower(SupportPowerInstance readyPower, CPos checkPos, int extendedRange = 1)
		{
			CPos? bestLocation = null;
			var bestAttractiveness = 0;
			var powerDecision = powerDecisions[readyPower.Info.OrderName];
			if (powerDecision == null)
			{
				BotDebug("Bot Bug: FindAttackLocationToSupportPower, couldn't find powerDecision for {0}", readyPower.Info.OrderName);
				return null;
			}

			var checkRadius = powerDecision.CoarseScanRadius;
			var fineCheck = powerDecision.FineScanRadius;
			for (var i = 0 - extendedRange; i <= (checkRadius + extendedRange); i += fineCheck)
			{
				var x = checkPos.X + i;

				for (var j = 0 - extendedRange; j <= (checkRadius + extendedRange); j += fineCheck)
				{
					var y = checkPos.Y + j;
					var pos = World.Map.CenterOfCell(new CPos(x, y));
					var consideredAttractiveness = 0;
					consideredAttractiveness += powerDecision.GetAttractiveness(pos, Player);

					if (consideredAttractiveness <= bestAttractiveness || consideredAttractiveness < powerDecision.MinimumAttractiveness)
						continue;

					bestAttractiveness = consideredAttractiveness;
					bestLocation = new CPos(x, y);
				}
			}

			return bestLocation;
		}
Exemplo n.º 13
0
		/// <summary>Scans the map in chunks, evaluating all actors in each.</summary>
		CPos? FindCoarseAttackLocationToSupportPower(SupportPowerInstance readyPower)
		{
			CPos? bestLocation = null;
			var bestAttractiveness = 0;
			var powerDecision = powerDecisions[readyPower.Info.OrderName];
			if (powerDecision == null)
			{
				BotDebug("Bot Bug: FindAttackLocationToSupportPower, couldn't find powerDecision for {0}", readyPower.Info.OrderName);
				return null;
			}

			var checkRadius = powerDecision.CoarseScanRadius;
			for (var i = 0; i < World.Map.MapSize.X; i += checkRadius)
			{
				for (var j = 0; j < World.Map.MapSize.Y; j += checkRadius)
				{
					var consideredAttractiveness = 0;

					var tl = World.Map.CenterOfCell(new CPos(i, j));
					var br = World.Map.CenterOfCell(new CPos(i + checkRadius, j + checkRadius));
					var targets = World.ActorMap.ActorsInBox(tl, br);

					consideredAttractiveness = powerDecision.GetAttractiveness(targets, Player);
					if (consideredAttractiveness <= bestAttractiveness || consideredAttractiveness < powerDecision.MinimumAttractiveness)
						continue;

					bestAttractiveness = consideredAttractiveness;
					bestLocation = new CPos(i, j);
				}
			}

			return bestLocation;
		}
Exemplo n.º 14
0
 public void Deactivate(Actor self, SupportPowerInstance instance)
 {
     active = false;
     techTree.ActorChanged(self);
 }
Exemplo n.º 15
0
        public SupportPowerTooltipLogic(Widget widget, TooltipContainerWidget tooltipContainer, Player player, SupportPowersWidget palette, World world,
                                        PlayerResources playerResources)
        {
            widget.IsVisible = () => palette.TooltipIcon != null && palette.TooltipIcon.Power.Info != null;
            var nameLabel   = widget.Get <LabelWidget>("NAME");
            var hotkeyLabel = widget.Get <LabelWidget>("HOTKEY");
            var timeLabel   = widget.Get <LabelWidget>("TIME");
            var descLabel   = widget.Get <LabelWidget>("DESC");
            var costLabel   = widget.Get <LabelWidget>("COST");
            var nameFont    = Game.Renderer.Fonts[nameLabel.Font];
            var hotkeyFont  = Game.Renderer.Fonts[hotkeyLabel.Font];
            var timeFont    = Game.Renderer.Fonts[timeLabel.Font];
            var descFont    = Game.Renderer.Fonts[descLabel.Font];
            var costFont    = Game.Renderer.Fonts[costLabel.Font];
            var baseHeight  = widget.Bounds.Height;
            var timeOffset  = timeLabel.Bounds.X;
            var costOffset  = costLabel.Bounds.X;

            SupportPowerInstance lastPower = null;
            Hotkey lastHotkey           = Hotkey.Invalid;
            var    lastRemainingSeconds = 0;

            tooltipContainer.BeforeRender = () =>
            {
                var icon = palette.TooltipIcon;
                if (icon == null)
                {
                    return;
                }

                var sp = icon.Power;

                // HACK: This abuses knowledge of the internals of WidgetUtils.FormatTime
                // to efficiently work when the label is going to change, requiring a panel relayout
                var remainingSeconds = (int)Math.Ceiling(sp.RemainingTime * world.Timestep / 1000f);

                var hotkey = icon.Hotkey != null?icon.Hotkey.GetValue() : Hotkey.Invalid;

                if (sp == lastPower && hotkey == lastHotkey && lastRemainingSeconds == remainingSeconds)
                {
                    return;
                }

                var cost       = sp.Info.Cost;
                var costString = costLabel.Text + cost.ToString();
                costLabel.GetText  = () => costString;
                costLabel.GetColor = () => playerResources.Cash + playerResources.Resources >= cost
                                        ? Color.White : Color.Red;
                costLabel.IsVisible = () => cost != 0;

                nameLabel.Text = sp.Info.Description;
                var nameSize = nameFont.Measure(nameLabel.Text);

                descLabel.Text = sp.Info.LongDesc.Replace("\\n", "\n");
                var descSize = descFont.Measure(descLabel.Text);

                var remaining = WidgetUtils.FormatTime(sp.RemainingTime, world.Timestep);
                var total     = WidgetUtils.FormatTime(sp.Info.ChargeTime * 25, world.Timestep);
                timeLabel.Text = "{0} / {1}".F(remaining, total);
                var timeSize = timeFont.Measure(timeLabel.Text);

                var hotkeyWidth = 0;
                hotkeyLabel.Visible = hotkey.IsValid();
                if (hotkeyLabel.Visible)
                {
                    var hotkeyText = "({0})".F(hotkey.DisplayString());

                    hotkeyWidth          = hotkeyFont.Measure(hotkeyText).X + 2 * nameLabel.Bounds.X;
                    hotkeyLabel.Text     = hotkeyText;
                    hotkeyLabel.Bounds.X = nameSize.X + 2 * nameLabel.Bounds.X;
                }

                var timeWidth = timeSize.X;
                var costWidth = costFont.Measure(costString).X;
                var topWidth  = nameSize.X + hotkeyWidth + timeWidth + timeOffset;

                if (cost != 0)
                {
                    topWidth += costWidth + costOffset;
                }

                widget.Bounds.Width  = 2 * nameLabel.Bounds.X + Math.Max(topWidth, descSize.X);
                widget.Bounds.Height = baseHeight + descSize.Y;
                timeLabel.Bounds.X   = widget.Bounds.Width - nameLabel.Bounds.X - timeWidth;

                if (cost != 0)
                {
                    timeLabel.Bounds.X -= costWidth + costOffset;
                    costLabel.Bounds.X  = widget.Bounds.Width - nameLabel.Bounds.X - costWidth;
                }

                lastPower            = sp;
                lastHotkey           = hotkey;
                lastRemainingSeconds = remainingSeconds;
            };

            timeLabel.GetColor = () => palette.TooltipIcon != null && !palette.TooltipIcon.Power.Active
                                ? Color.Red : Color.White;
        }
Exemplo n.º 16
0
        public SupportPowerTooltipLogic(Widget widget, TooltipContainerWidget tooltipContainer, Func <SupportPowersWidget.SupportPowerIcon> getTooltipIcon, World world)
        {
            widget.IsVisible = () => getTooltipIcon() != null && getTooltipIcon().Power.Info != null;
            var nameLabel   = widget.Get <LabelWidget>("NAME");
            var hotkeyLabel = widget.Get <LabelWidget>("HOTKEY");
            var timeLabel   = widget.Get <LabelWidget>("TIME");
            var descLabel   = widget.Get <LabelWidget>("DESC");
            var nameFont    = Game.Renderer.Fonts[nameLabel.Font];
            var hotkeyFont  = Game.Renderer.Fonts[hotkeyLabel.Font];
            var timeFont    = Game.Renderer.Fonts[timeLabel.Font];
            var descFont    = Game.Renderer.Fonts[descLabel.Font];
            var baseHeight  = widget.Bounds.Height;
            var timeOffset  = timeLabel.Bounds.X;

            SupportPowerInstance lastPower = null;
            Hotkey lastHotkey           = Hotkey.Invalid;
            var    lastRemainingSeconds = 0;

            tooltipContainer.BeforeRender = () =>
            {
                var icon = getTooltipIcon();
                if (icon == null || icon.Power == null || icon.Power.Instances.Count == 0)
                {
                    return;
                }

                var sp = icon.Power;

                // HACK: This abuses knowledge of the internals of WidgetUtils.FormatTime
                // to efficiently work when the label is going to change, requiring a panel relayout
                var remainingSeconds = (int)Math.Ceiling(sp.RemainingTicks * world.Timestep / 1000f);

                var hotkey = icon.Hotkey?.GetValue() ?? Hotkey.Invalid;
                if (sp == lastPower && hotkey == lastHotkey && lastRemainingSeconds == remainingSeconds)
                {
                    return;
                }

                nameLabel.Text = sp.Info.Description;
                var nameSize = nameFont.Measure(nameLabel.Text);

                descLabel.Text = sp.Info.LongDesc.Replace("\\n", "\n");
                var descSize = descFont.Measure(descLabel.Text);

                var customLabel = sp.TooltipTimeTextOverride();
                if (customLabel == null)
                {
                    var remaining = WidgetUtils.FormatTime(sp.RemainingTicks, world.Timestep);
                    var total     = WidgetUtils.FormatTime(sp.Info.ChargeInterval, world.Timestep);
                    timeLabel.Text = $"{remaining} / {total}";
                }
                else
                {
                    timeLabel.Text = customLabel;
                }

                var timeSize    = timeFont.Measure(timeLabel.Text);
                var hotkeyWidth = 0;
                hotkeyLabel.Visible = hotkey.IsValid();
                if (hotkeyLabel.Visible)
                {
                    var hotkeyText = $"({hotkey.DisplayString()})";

                    hotkeyWidth          = hotkeyFont.Measure(hotkeyText).X + 2 * nameLabel.Bounds.X;
                    hotkeyLabel.Text     = hotkeyText;
                    hotkeyLabel.Bounds.X = nameSize.X + 2 * nameLabel.Bounds.X;
                }

                var timeWidth = timeSize.X;
                var topWidth  = nameSize.X + hotkeyWidth + timeWidth + timeOffset;
                widget.Bounds.Width  = 2 * nameLabel.Bounds.X + Math.Max(topWidth, descSize.X);
                widget.Bounds.Height = baseHeight + descSize.Y;
                timeLabel.Bounds.X   = widget.Bounds.Width - nameLabel.Bounds.X - timeWidth;

                lastPower            = sp;
                lastHotkey           = hotkey;
                lastRemainingSeconds = remainingSeconds;
            };

            timeLabel.GetColor = () => getTooltipIcon() != null && !getTooltipIcon().Power.Active
                                ? Color.Red : Color.White;
        }
Exemplo n.º 17
0
        public override bool HandleMouseInput(MouseInput mi)
        {
            if (mi.Event == MouseInputEvent.Move)
            {
                var icon = icons.Where(i => i.Key.Contains(mi.Location))
                    .Select(i => i.Value).FirstOrDefault();
                TooltipPower = (icon != null) ? icon.Power : null;
                return false;
            }

            if (mi.Event != MouseInputEvent.Down)
                return false;

            var clicked = icons.Where(i => i.Key.Contains(mi.Location))
                .Select(i => i.Value).FirstOrDefault();

            if (clicked != null)
                spm.Target(clicked.Power.Info.OrderName);

            return true;
        }