#region Copyright & License Information /* * Copyright 2007-2017 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made * available to you under the terms of the GNU General Public License * as published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. For more * information, see COPYING. */ #endregion using System; using System.Drawing; using System.Linq; using OpenRA.Graphics; using OpenRA.Mods.Common.Orders; using OpenRA.Mods.Common.Traits; using OpenRA.Orders; using OpenRA.Primitives; using OpenRA.Widgets; namespace OpenRA.Mods.Common.Widgets { /// Contains all functions that are unit-specific. public class CommandBarLogic : ChromeLogic { readonly World world; int selectionHash; Actor[] selectedActors = { }; bool attackMoveDisabled = true; bool forceMoveDisabled = true; bool forceAttackDisabled = true; bool guardDisabled = true; bool scatterDisabled = true; int deployHighlighted; int scatterHighlighted; int stopHighlighted; TraitPair[] selectedDeploys = { }; [ObjectCreator.UseCtor] public CommandBarLogic(Widget widget, World world) { this.world = world; var ks = Game.Settings.Keys; var attackMoveButton = widget.GetOrNull("ATTACK_MOVE"); if (attackMoveButton != null) { BindButtonIcon(attackMoveButton); attackMoveButton.GetKey = _ => ks.AttackMoveKey; attackMoveButton.IsDisabled = () => { UpdateStateIfNecessary(); return attackMoveDisabled; }; attackMoveButton.IsHighlighted = () => world.OrderGenerator is GenericSelectTarget && ((GenericSelectTarget)world.OrderGenerator).OrderName == "AttackMove"; attackMoveButton.OnClick = () => { if (attackMoveButton.IsHighlighted()) world.CancelInputMode(); else world.OrderGenerator = new GenericSelectTarget(selectedActors, "AttackMove", "attackmove", Game.Settings.Game.MouseButtonPreference.Action); }; } var forceMoveButton = widget.GetOrNull("FORCE_MOVE"); if (forceMoveButton != null) { BindButtonIcon(forceMoveButton); forceMoveButton.IsDisabled = () => { UpdateStateIfNecessary(); return forceMoveDisabled; }; forceMoveButton.IsHighlighted = () => !forceMoveButton.IsDisabled() && IsForceModifiersActive(Modifiers.Alt); forceMoveButton.OnClick = () => { if (forceMoveButton.IsHighlighted()) world.CancelInputMode(); else world.OrderGenerator = new ForceModifiersOrderGenerator(Modifiers.Alt, true); }; } var forceAttackButton = widget.GetOrNull("FORCE_ATTACK"); if (forceAttackButton != null) { BindButtonIcon(forceAttackButton); forceAttackButton.IsDisabled = () => { UpdateStateIfNecessary(); return forceAttackDisabled; }; forceAttackButton.IsHighlighted = () => !forceAttackButton.IsDisabled() && IsForceModifiersActive(Modifiers.Ctrl); forceAttackButton.OnClick = () => { if (forceAttackButton.IsHighlighted()) world.CancelInputMode(); else world.OrderGenerator = new ForceModifiersOrderGenerator(Modifiers.Ctrl, true); }; } var guardButton = widget.GetOrNull("GUARD"); if (guardButton != null) { BindButtonIcon(guardButton); guardButton.GetKey = _ => ks.GuardKey; guardButton.IsDisabled = () => { UpdateStateIfNecessary(); return guardDisabled; }; guardButton.IsHighlighted = () => world.OrderGenerator is GenericSelectTarget && ((GenericSelectTarget)world.OrderGenerator).OrderName == "Guard"; guardButton.OnClick = () => { if (guardButton.IsHighlighted()) world.CancelInputMode(); else world.OrderGenerator = new GuardOrderGenerator(selectedActors, "Guard", "guard", Game.Settings.Game.MouseButtonPreference.Action); }; } var scatterButton = widget.GetOrNull("SCATTER"); if (scatterButton != null) { BindButtonIcon(scatterButton); scatterButton.GetKey = _ => ks.ScatterKey; scatterButton.IsDisabled = () => { UpdateStateIfNecessary(); return scatterDisabled; }; scatterButton.IsHighlighted = () => scatterHighlighted > 0; scatterButton.OnClick = () => PerformKeyboardOrderOnSelection(a => new Order("Scatter", a, false)); scatterButton.OnKeyPress = ki => { scatterHighlighted = 2; scatterButton.OnClick(); }; } var deployButton = widget.GetOrNull("DEPLOY"); if (deployButton != null) { BindButtonIcon(deployButton); deployButton.GetKey = _ => ks.DeployKey; deployButton.IsDisabled = () => { UpdateStateIfNecessary(); return !selectedDeploys.Any(Exts.IsTraitEnabled); }; deployButton.IsHighlighted = () => deployHighlighted > 0; deployButton.OnClick = PerformDeployOrderOnSelection; deployButton.OnKeyPress = ki => { deployHighlighted = 2; deployButton.OnClick(); }; } var stopButton = widget.GetOrNull("STOP"); if (stopButton != null) { BindButtonIcon(stopButton); stopButton.GetKey = _ => ks.StopKey; stopButton.IsDisabled = () => { UpdateStateIfNecessary(); return !selectedActors.Any(); }; stopButton.IsHighlighted = () => stopHighlighted > 0; stopButton.OnClick = () => PerformKeyboardOrderOnSelection(a => new Order("Stop", a, false)); stopButton.OnKeyPress = ki => { stopHighlighted = 2; stopButton.OnClick(); }; } var queueOrdersButton = widget.GetOrNull("QUEUE_ORDERS"); if (queueOrdersButton != null) { BindButtonIcon(queueOrdersButton); queueOrdersButton.IsDisabled = () => { UpdateStateIfNecessary(); return !selectedActors.Any(); }; queueOrdersButton.IsHighlighted = () => !queueOrdersButton.IsDisabled() && IsForceModifiersActive(Modifiers.Shift); queueOrdersButton.OnClick = () => { if (queueOrdersButton.IsHighlighted()) world.CancelInputMode(); else world.OrderGenerator = new ForceModifiersOrderGenerator(Modifiers.Shift, false); }; } } public override void Tick() { if (deployHighlighted > 0) deployHighlighted--; if (scatterHighlighted > 0) scatterHighlighted--; if (stopHighlighted > 0) stopHighlighted--; base.Tick(); } void BindButtonIcon(ButtonWidget button) { var icon = button.Get("ICON"); icon.GetImageName = () => button.IsDisabled() ? icon.ImageName + "-disabled" : icon.ImageName; } bool IsForceModifiersActive(Modifiers modifiers) { var fmog = world.OrderGenerator as ForceModifiersOrderGenerator; if (fmog != null && fmog.Modifiers.HasFlag(modifiers)) return true; var uog = world.OrderGenerator as UnitOrderGenerator; if (uog != null && Game.GetModifierKeys().HasFlag(modifiers)) return true; return false; } void UpdateStateIfNecessary() { if (selectionHash == world.Selection.Hash) return; selectedActors = world.Selection.Actors .Where(a => a.Owner == world.LocalPlayer && a.IsInWorld) .ToArray(); attackMoveDisabled = !selectedActors.Any(a => a.Info.HasTraitInfo() && a.Info.HasTraitInfo()); guardDisabled = !selectedActors.Any(a => a.Info.HasTraitInfo() && a.Info.HasTraitInfo()); forceMoveDisabled = !selectedActors.Any(a => a.Info.HasTraitInfo() || a.Info.HasTraitInfo()); forceAttackDisabled = !selectedActors.Any(a => a.Info.HasTraitInfo()); scatterDisabled = !selectedActors.Any(a => a.Info.HasTraitInfo()); selectedDeploys = selectedActors .SelectMany(a => a.TraitsImplementing() .Select(d => new TraitPair(a, d))) .ToArray(); selectionHash = world.Selection.Hash; } void PerformKeyboardOrderOnSelection(Func f) { UpdateStateIfNecessary(); var orders = selectedActors .Select(f) .ToArray(); foreach (var o in orders) world.IssueOrder(o); world.PlayVoiceForOrders(orders); } void PerformDeployOrderOnSelection() { UpdateStateIfNecessary(); var orders = selectedDeploys .Where(Exts.IsTraitEnabled) .Select(d => d.Trait.IssueDeployOrder(d.Actor)) .ToArray(); foreach (var o in orders) world.IssueOrder(o); world.PlayVoiceForOrders(orders); } } }