/// <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); }
static string GetOverlayForItem(SupportPowerInstance item, int timestep) { if (item.Disabled) { return("ON HOLD"); } if (item.Ready) { return("READY"); } return(WidgetUtils.FormatTime(item.RemainingTime, timestep)); }
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; }
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"; }
/// <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); }
/// <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); }
/// <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); }
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; }
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; }
/// <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; }
/// <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; }
public void Deactivate(Actor self, SupportPowerInstance instance) { active = false; techTree.ActorChanged(self); }
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; }
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; }
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; }