From 096d95f391f882a816be091941088d502758ae97 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 7 Apr 2013 21:52:49 +1200 Subject: [PATCH 1/4] Fix bogus pause logic. --- OpenRA.Game/Game.cs | 14 ++++---- OpenRA.Game/Network/Order.cs | 10 ++---- OpenRA.Game/Network/OrderManager.cs | 1 - OpenRA.Game/Network/UnitOrders.cs | 18 +++++++---- OpenRA.Game/Server/Server.cs | 8 ++--- OpenRA.Game/Widgets/TimerWidget.cs | 2 +- .../WorldInteractionControllerWidget.cs | 8 +---- OpenRA.Game/World.cs | 32 +++++++------------ .../Widgets/Logic/CncIngameChromeLogic.cs | 7 ++-- OpenRA.Mods.RA/Player/PlayerStatistics.cs | 4 +-- OpenRA.Mods.RA/Scripting/Media.cs | 4 +-- .../Widgets/Logic/IngameChromeLogic.cs | 14 +++++--- .../Logic/IngameObserverChromeLogic.cs | 4 +-- 13 files changed, 57 insertions(+), 69 deletions(-) diff --git a/OpenRA.Game/Game.cs b/OpenRA.Game/Game.cs index 57bc24b722..019f118d50 100755 --- a/OpenRA.Game/Game.cs +++ b/OpenRA.Game/Game.cs @@ -174,20 +174,20 @@ namespace OpenRA { var isNetTick = LocalTick % NetTickScale == 0; - if ((!isNetTick || orderManager.IsReadyForNextFrame) && !orderManager.GamePaused ) + if (!isNetTick || orderManager.IsReadyForNextFrame) { ++orderManager.LocalFrameNumber; Log.Write("debug", "--Tick: {0} ({1})", LocalTick, isNetTick ? "net" : "local"); - if (isNetTick) orderManager.Tick(); - + if (isNetTick) + orderManager.Tick(); Sync.CheckSyncUnchanged(world, () => - { - world.OrderGenerator.Tick(world); - world.Selection.Tick(world); - }); + { + world.OrderGenerator.Tick(world); + world.Selection.Tick(world); + }); world.Tick(); diff --git a/OpenRA.Game/Network/Order.cs b/OpenRA.Game/Network/Order.cs index 0f486e987b..015851a406 100755 --- a/OpenRA.Game/Network/Order.cs +++ b/OpenRA.Game/Network/Order.cs @@ -200,17 +200,11 @@ namespace OpenRA return new Order("HandshakeResponse", null, false) { IsImmediate = true, TargetString = text }; } - public static Order PauseRequest() + public static Order PauseGame(bool paused) { - return new Order("PauseRequest", null, false) { IsImmediate = true, TargetString="" }; //TODO: targetbool? - } - - public static Order PauseGame() - { - return new Order("PauseGame", null, false) { IsImmediate = true, TargetString=""}; //TODO: targetbool? + return new Order("PauseGame", null, false) { TargetString = paused ? "Pause" : "UnPause" }; } - public static Order Command(string text) { return new Order("Command", null, false) { IsImmediate = true, TargetString = text }; diff --git a/OpenRA.Game/Network/OrderManager.cs b/OpenRA.Game/Network/OrderManager.cs index c0b2cee81f..624bbd2a35 100755 --- a/OpenRA.Game/Network/OrderManager.cs +++ b/OpenRA.Game/Network/OrderManager.cs @@ -36,7 +36,6 @@ namespace OpenRA.Network public int LastTickTime = Environment.TickCount; public bool GameStarted { get { return NetFrameNumber != 0; } } - public bool GamePaused {get; set;} public IConnection Connection { get; private set; } public readonly int SyncHeaderSize = 9; diff --git a/OpenRA.Game/Network/UnitOrders.cs b/OpenRA.Game/Network/UnitOrders.cs index 5d34febd7b..24583688aa 100755 --- a/OpenRA.Game/Network/UnitOrders.cs +++ b/OpenRA.Game/Network/UnitOrders.cs @@ -95,16 +95,20 @@ namespace OpenRA.Network Game.StartGame(orderManager.LobbyInfo.GlobalSettings.Map, false); break; } - + case "PauseGame": - { + { var client = orderManager.LobbyInfo.ClientWithIndex(clientId); - - if(client != null) + if (client != null) { - orderManager.GamePaused = !orderManager.GamePaused; - var pausetext = "The game is {0} by {1}".F( orderManager.GamePaused ? "paused" : "un-paused", client.Name ); - Game.AddChatLine(Color.White, "", pausetext); + var pause = order.TargetString == "Pause"; + if (orderManager.world.Paused != pause && !world.LobbyInfo.IsSinglePlayer) + { + var pausetext = "The game is {0} by {1}".F(pause ? "paused" : "un-paused", client.Name); + Game.AddChatLine(Color.White, "", pausetext); + } + + orderManager.world.Paused = pause; } break; } diff --git a/OpenRA.Game/Server/Server.cs b/OpenRA.Game/Server/Server.cs index 6468f0c11a..7a200a0d49 100644 --- a/OpenRA.Game/Server/Server.cs +++ b/OpenRA.Game/Server/Server.cs @@ -488,11 +488,9 @@ namespace OpenRA.Server DispatchOrdersToClient(c, fromIndex, 0, so.Serialize()); break; - case "PauseRequest": - foreach (var c in conns.ToArray()) - { var x = Order.PauseGame(); - DispatchOrdersToClient(c, fromIndex, 0, x.Serialize()); - } + case "PauseGame": + foreach (var c in conns.Except(conn).ToArray()) + DispatchOrdersToClient(c, fromIndex, 0, so.Serialize()); break; } } diff --git a/OpenRA.Game/Widgets/TimerWidget.cs b/OpenRA.Game/Widgets/TimerWidget.cs index b2f5bfb2ba..e66bbc2611 100644 --- a/OpenRA.Game/Widgets/TimerWidget.cs +++ b/OpenRA.Game/Widgets/TimerWidget.cs @@ -19,7 +19,7 @@ namespace OpenRA.Widgets var font = Game.Renderer.Fonts["Title"]; var rb = RenderBounds; - var s = WidgetUtils.FormatTime(Game.LocalTick) + (Game.orderManager.GamePaused?" (paused)":""); + var s = WidgetUtils.FormatTime(Game.LocalTick) + (Game.orderManager.world.Paused?" (paused)":""); var pos = new float2(rb.Left - font.Measure(s).X / 2, rb.Top); font.DrawTextWithContrast(s, pos, Color.White, Color.Black, 1); } diff --git a/OpenRA.Game/Widgets/WorldInteractionControllerWidget.cs b/OpenRA.Game/Widgets/WorldInteractionControllerWidget.cs index 1cebd7be69..da73e51725 100644 --- a/OpenRA.Game/Widgets/WorldInteractionControllerWidget.cs +++ b/OpenRA.Game/Widgets/WorldInteractionControllerWidget.cs @@ -175,13 +175,7 @@ namespace OpenRA.Widgets return true; } else if (e.KeyName == Game.Settings.Keys.PauseKey) - { - world.IssueOrder(Order.PauseRequest()); - } - - bool handled = false; - - if (handled) return true; + world.IssueOrder(Order.PauseGame(!world.Paused)); } return false; } diff --git a/OpenRA.Game/World.cs b/OpenRA.Game/World.cs index 58ad20884b..4d7647a1c1 100644 --- a/OpenRA.Game/World.cs +++ b/OpenRA.Game/World.cs @@ -158,37 +158,29 @@ namespace OpenRA public event Action ActorAdded = _ => { }; public event Action ActorRemoved = _ => { }; - // Will do bad things in multiplayer games - public bool EnableTick = true; + public bool Paused = false; public bool IsShellmap = false; - bool ShouldTick() - { - if (!EnableTick) return false; - return !IsShellmap || Game.Settings.Game.ShowShellmap; - } - public void Tick() { - // TODO: Expose this as an order so it can be synced - if (ShouldTick()) + if (!Paused && (!IsShellmap || Game.Settings.Game.ShowShellmap)) { - using( new PerfSample("tick_idle") ) - foreach( var ni in ActorsWithTrait() ) + using (new PerfSample("tick_idle")) + foreach (var ni in ActorsWithTrait()) if (ni.Actor.IsIdle) ni.Trait.TickIdle(ni.Actor); - using( new PerfSample("tick_activities") ) - foreach( var a in actors ) + using (new PerfSample("tick_activities")) + foreach(var a in actors) a.Tick(); - ActorsWithTrait().DoTimed( x => - { - x.Trait.Tick( x.Actor ); - }, "[{2}] Trait: {0} ({1:0.000} ms)", Game.Settings.Debug.LongTickThreshold ); + ActorsWithTrait().DoTimed(x => x.Trait.Tick(x.Actor), + "[{2}] Trait: {0} ({1:0.000} ms)", + Game.Settings.Debug.LongTickThreshold); - effects.DoTimed( e => e.Tick( this ), "[{2}] Effect: {0} ({1:0.000} ms)", - Game.Settings.Debug.LongTickThreshold ); + effects.DoTimed(e => e.Tick(this), + "[{2}] Effect: {0} ({1:0.000} ms)", + Game.Settings.Debug.LongTickThreshold); } while (frameEndActions.Count != 0) diff --git a/OpenRA.Mods.Cnc/Widgets/Logic/CncIngameChromeLogic.cs b/OpenRA.Mods.Cnc/Widgets/Logic/CncIngameChromeLogic.cs index cedab28475..cb53a6dd39 100644 --- a/OpenRA.Mods.Cnc/Widgets/Logic/CncIngameChromeLogic.cs +++ b/OpenRA.Mods.Cnc/Widgets/Logic/CncIngameChromeLogic.cs @@ -85,6 +85,8 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic public void OptionsClicked() { + var cachedPause = world.Paused; + if (menu != MenuType.None) { Ui.CloseWindow(); @@ -93,14 +95,15 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic ingameRoot.IsVisible = () => false; if (world.LobbyInfo.IsSinglePlayer) - world.IssueOrder(Order.PauseGame()); + world.IssueOrder(Order.PauseGame(true)); + Game.LoadWidget(world, "INGAME_MENU", Ui.Root, new WidgetArgs() { { "onExit", () => { ingameRoot.IsVisible = () => true; if (world.LobbyInfo.IsSinglePlayer) - world.IssueOrder(Order.PauseGame()); + world.IssueOrder(Order.PauseGame(cachedPause)); } } }); diff --git a/OpenRA.Mods.RA/Player/PlayerStatistics.cs b/OpenRA.Mods.RA/Player/PlayerStatistics.cs index 97644269ef..0444936f42 100644 --- a/OpenRA.Mods.RA/Player/PlayerStatistics.cs +++ b/OpenRA.Mods.RA/Player/PlayerStatistics.cs @@ -86,7 +86,6 @@ namespace OpenRA.Mods.RA case "Chat": case "TeamChat": case "HandshakeResponse": - case "PauseRequest": case "PauseGame": case "StartGame": case "Disconnected": @@ -94,7 +93,8 @@ namespace OpenRA.Mods.RA case "SyncInfo": return; } - if (order.OrderString.StartsWith("Dev")) return; + if (order.OrderString.StartsWith("Dev")) + return; OrderCount++; } } diff --git a/OpenRA.Mods.RA/Scripting/Media.cs b/OpenRA.Mods.RA/Scripting/Media.cs index 8fbc1cca66..6bfdb5e4f6 100644 --- a/OpenRA.Mods.RA/Scripting/Media.cs +++ b/OpenRA.Mods.RA/Scripting/Media.cs @@ -32,7 +32,7 @@ namespace OpenRA.Scripting return; } - w.EnableTick = false; + w.Paused = true; // Mute world sounds var oldModifier = Sound.SoundVolumeModifier; @@ -51,7 +51,7 @@ namespace OpenRA.Scripting Ui.CloseWindow(); Sound.SoundVolumeModifier = oldModifier; - w.EnableTick = true; + w.Paused = false; onComplete(); }); } diff --git a/OpenRA.Mods.RA/Widgets/Logic/IngameChromeLogic.cs b/OpenRA.Mods.RA/Widgets/Logic/IngameChromeLogic.cs index 01e31e05d9..cad508d877 100644 --- a/OpenRA.Mods.RA/Widgets/Logic/IngameChromeLogic.cs +++ b/OpenRA.Mods.RA/Widgets/Logic/IngameChromeLogic.cs @@ -8,10 +8,11 @@ */ #endregion -using OpenRA.Traits; -using System.Linq; -using OpenRA.Widgets; using System.Drawing; +using System.Linq; +using OpenRA.Network; +using OpenRA.Traits; +using OpenRA.Widgets; namespace OpenRA.Mods.RA.Widgets.Logic { @@ -26,11 +27,14 @@ namespace OpenRA.Mods.RA.Widgets.Logic gameRoot = r.Get("INGAME_ROOT"); var optionsBG = gameRoot.Get("INGAME_OPTIONS_BG"); + // TODO: RA's broken UI wiring makes it unreasonably difficult to + // cache and restore the previous pause state, so opening/closing + // the menu in a paused singleplayer game will un-pause the game. r.Get("INGAME_OPTIONS_BUTTON").OnClick = () => { optionsBG.Visible = !optionsBG.Visible; if (world.LobbyInfo.IsSinglePlayer) - world.IssueOrder(Order.PauseGame()); + world.IssueOrder(Order.PauseGame(true)); }; var cheatsButton = gameRoot.Get("CHEATS_BUTTON"); @@ -65,7 +69,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic { optionsBG.Visible = false; if (world.LobbyInfo.IsSinglePlayer) - world.IssueOrder(Order.PauseGame()); + world.IssueOrder(Order.PauseGame(false)); }; optionsBG.Get("SURRENDER").OnClick = () => diff --git a/OpenRA.Mods.RA/Widgets/Logic/IngameObserverChromeLogic.cs b/OpenRA.Mods.RA/Widgets/Logic/IngameObserverChromeLogic.cs index 047f2411b3..b38f505ca0 100644 --- a/OpenRA.Mods.RA/Widgets/Logic/IngameObserverChromeLogic.cs +++ b/OpenRA.Mods.RA/Widgets/Logic/IngameObserverChromeLogic.cs @@ -33,7 +33,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic { optionsBG.Visible = !optionsBG.Visible; if (world.LobbyInfo.IsSinglePlayer) - world.IssueOrder(Order.PauseGame()); + world.IssueOrder(Order.PauseGame(true)); }; optionsBG.Get("DISCONNECT").OnClick = () => @@ -51,7 +51,7 @@ namespace OpenRA.Mods.RA.Widgets.Logic { optionsBG.Visible = false; if (world.LobbyInfo.IsSinglePlayer) - world.IssueOrder(Order.PauseGame()); + world.IssueOrder(Order.PauseGame(false)); }; optionsBG.Get("SURRENDER").IsVisible = () => false; From a5ec473a5995b148d3661660b81d8dfad9bb21df Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sun, 7 Apr 2013 23:40:25 +1200 Subject: [PATCH 2/4] [Sync] the world pause state. --- OpenRA.Game/OpenRA.Game.csproj | 1 + OpenRA.Game/Traits/DebugPauseState.cs | 27 +++++++++++++++++++++++++++ mods/cnc-classic/rules/system.yaml | 1 + mods/cnc/rules/system.yaml | 1 + mods/d2k/rules/system.yaml | 1 + mods/ra-classic/rules/system.yaml | 1 + mods/ra/rules/system.yaml | 1 + 7 files changed, 33 insertions(+) create mode 100644 OpenRA.Game/Traits/DebugPauseState.cs diff --git a/OpenRA.Game/OpenRA.Game.csproj b/OpenRA.Game/OpenRA.Game.csproj index 9bf40cad2a..3f30d687e7 100644 --- a/OpenRA.Game/OpenRA.Game.csproj +++ b/OpenRA.Game/OpenRA.Game.csproj @@ -222,6 +222,7 @@ + diff --git a/OpenRA.Game/Traits/DebugPauseState.cs b/OpenRA.Game/Traits/DebugPauseState.cs new file mode 100644 index 0000000000..e97dd31404 --- /dev/null +++ b/OpenRA.Game/Traits/DebugPauseState.cs @@ -0,0 +1,27 @@ +#region Copyright & License Information +/* + * Copyright 2007-2011 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. For more information, + * see COPYING. + */ +#endregion + +using System.Collections.Generic; +using OpenRA.Network; + +namespace OpenRA.Traits +{ + public class DebugPauseStateInfo : ITraitInfo + { + public object Create(ActorInitializer init) { return new DebugPauseState(init.world); } + } + + public class DebugPauseState : ISync + { + World world; + [Sync] public bool Paused { get { return world.Paused; } } + public DebugPauseState(World world) { this.world = world; } + } +} diff --git a/mods/cnc-classic/rules/system.yaml b/mods/cnc-classic/rules/system.yaml index 196bc5d8b1..35a79a5e8a 100644 --- a/mods/cnc-classic/rules/system.yaml +++ b/mods/cnc-classic/rules/system.yaml @@ -207,6 +207,7 @@ World: Shroud: PathFinder: ValidateOrder: + DebugPauseState: CRATE: Tooltip: diff --git a/mods/cnc/rules/system.yaml b/mods/cnc/rules/system.yaml index 569b1e6a0a..5136ebc526 100644 --- a/mods/cnc/rules/system.yaml +++ b/mods/cnc/rules/system.yaml @@ -312,6 +312,7 @@ World: WaterChance: 0 PathFinder: ValidateOrder: + DebugPauseState: ConquestObjectivesPanel: ObjectivesPanel: CONQUEST_OBJECTIVES diff --git a/mods/d2k/rules/system.yaml b/mods/d2k/rules/system.yaml index 7d0dd0623b..4ae5a989c6 100644 --- a/mods/d2k/rules/system.yaml +++ b/mods/d2k/rules/system.yaml @@ -392,6 +392,7 @@ World: Fog: PathFinder: ValidateOrder: + DebugPauseState: CRATE: Tooltip: diff --git a/mods/ra-classic/rules/system.yaml b/mods/ra-classic/rules/system.yaml index 74eceda6f7..6eccd968ca 100644 --- a/mods/ra-classic/rules/system.yaml +++ b/mods/ra-classic/rules/system.yaml @@ -239,6 +239,7 @@ World: Shroud: PathFinder: ValidateOrder: + DebugPauseState: MINP: Mine: diff --git a/mods/ra/rules/system.yaml b/mods/ra/rules/system.yaml index 04dba4b76d..970f1dd8e1 100644 --- a/mods/ra/rules/system.yaml +++ b/mods/ra/rules/system.yaml @@ -625,6 +625,7 @@ World: Fog: PathFinder: ValidateOrder: + DebugPauseState: MINP: Mine: From 76b206670a53fb98e9eb5d5aa02785616f065a01 Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sat, 6 Apr 2013 18:58:44 +1300 Subject: [PATCH 3/4] Make cheats logic robust against missing widgets. Also removes force-desync stdout spam. --- OpenRA.Mods.RA/Widgets/Logic/CheatsLogic.cs | 167 +++++++++++--------- 1 file changed, 96 insertions(+), 71 deletions(-) diff --git a/OpenRA.Mods.RA/Widgets/Logic/CheatsLogic.cs b/OpenRA.Mods.RA/Widgets/Logic/CheatsLogic.cs index b5d4c3b299..68f1d6bea1 100644 --- a/OpenRA.Mods.RA/Widgets/Logic/CheatsLogic.cs +++ b/OpenRA.Mods.RA/Widgets/Logic/CheatsLogic.cs @@ -28,101 +28,126 @@ namespace OpenRA.Mods.RA.Widgets.Logic { var devTrait = world.LocalPlayer.PlayerActor.Trait(); - var shroudCheckbox = widget.Get("DISABLE_SHROUD"); - shroudCheckbox.IsChecked = () => devTrait.DisableShroud; - shroudCheckbox.OnClick = () => Order(world, "DevShroudDisable"); + var shroudCheckbox = widget.GetOrNull("DISABLE_SHROUD"); + if (shroudCheckbox != null) + { + shroudCheckbox.IsChecked = () => devTrait.DisableShroud; + shroudCheckbox.OnClick = () => Order(world, "DevShroudDisable"); + } - var pathCheckbox = widget.Get("SHOW_UNIT_PATHS"); - pathCheckbox.IsChecked = () => devTrait.PathDebug; - pathCheckbox.OnClick = () => Order(world, "DevPathDebug"); + var pathCheckbox = widget.GetOrNull("SHOW_UNIT_PATHS"); + if (pathCheckbox != null) + { + pathCheckbox.IsChecked = () => devTrait.PathDebug; + pathCheckbox.OnClick = () => Order(world, "DevPathDebug"); + } - widget.Get("GIVE_CASH").OnClick = () => + var cashButton = widget.GetOrNull("GIVE_CASH"); + if (cashButton != null) + cashButton.OnClick = () => world.IssueOrder(new Order("DevGiveCash", world.LocalPlayer.PlayerActor, false)); - var fastBuildCheckbox = widget.Get("INSTANT_BUILD"); - fastBuildCheckbox.IsChecked = () => devTrait.FastBuild; - fastBuildCheckbox.OnClick = () => Order(world, "DevFastBuild"); + var fastBuildCheckbox = widget.GetOrNull("INSTANT_BUILD"); + if (fastBuildCheckbox != null) + { + fastBuildCheckbox.IsChecked = () => devTrait.FastBuild; + fastBuildCheckbox.OnClick = () => Order(world, "DevFastBuild"); + } - var fastChargeCheckbox = widget.Get("INSTANT_CHARGE"); - fastChargeCheckbox.IsChecked = () => devTrait.FastCharge; - fastChargeCheckbox.OnClick = () => Order(world, "DevFastCharge"); + var fastChargeCheckbox = widget.GetOrNull("INSTANT_CHARGE"); + if (fastChargeCheckbox != null) + { + fastChargeCheckbox.IsChecked = () => devTrait.FastCharge; + fastChargeCheckbox.OnClick = () => Order(world, "DevFastCharge"); + } - var showMuzzlesCheckbox = widget.Get("SHOW_MUZZLES"); - showMuzzlesCheckbox.IsChecked = () => devTrait.ShowMuzzles; - showMuzzlesCheckbox.OnClick = () => devTrait.ShowMuzzles ^= true; + var showMuzzlesCheckbox = widget.GetOrNull("SHOW_MUZZLES"); + if (showMuzzlesCheckbox != null) + { + showMuzzlesCheckbox.IsChecked = () => devTrait.ShowMuzzles; + showMuzzlesCheckbox.OnClick = () => devTrait.ShowMuzzles ^= true; + } - var allTechCheckbox = widget.Get("ENABLE_TECH"); - allTechCheckbox.IsChecked = () => devTrait.AllTech; - allTechCheckbox.OnClick = () => Order(world, "DevEnableTech"); + var allTechCheckbox = widget.GetOrNull("ENABLE_TECH"); + if (allTechCheckbox != null) + { + allTechCheckbox.IsChecked = () => devTrait.AllTech; + allTechCheckbox.OnClick = () => Order(world, "DevEnableTech"); + } - var powerCheckbox = widget.Get("UNLIMITED_POWER"); - powerCheckbox.IsChecked = () => devTrait.UnlimitedPower; - powerCheckbox.OnClick = () => Order(world, "DevUnlimitedPower"); + var powerCheckbox = widget.GetOrNull("UNLIMITED_POWER"); + if (powerCheckbox != null) + { + powerCheckbox.IsChecked = () => devTrait.UnlimitedPower; + powerCheckbox.OnClick = () => Order(world, "DevUnlimitedPower"); + } - var buildAnywhereCheckbox = widget.Get("BUILD_ANYWHERE"); - buildAnywhereCheckbox.IsChecked = () => devTrait.BuildAnywhere; - buildAnywhereCheckbox.OnClick = () => Order(world, "DevBuildAnywhere"); + var buildAnywhereCheckbox = widget.GetOrNull("BUILD_ANYWHERE"); + if (buildAnywhereCheckbox != null) + { + buildAnywhereCheckbox.IsChecked = () => devTrait.BuildAnywhere; + buildAnywhereCheckbox.OnClick = () => Order(world, "DevBuildAnywhere"); + } - widget.Get("GIVE_EXPLORATION").OnClick = () => + var explorationButton = widget.GetOrNull("GIVE_EXPLORATION"); + if (explorationButton != null) + explorationButton.OnClick = () => world.IssueOrder(new Order("DevGiveExploration", world.LocalPlayer.PlayerActor, false)); - widget.Get("RESET_EXPLORATION").OnClick = () => + var noexplorationButton = widget.GetOrNull("RESET_EXPLORATION"); + if (noexplorationButton != null) + noexplorationButton.OnClick = () => world.IssueOrder(new Order("DevResetExploration", world.LocalPlayer.PlayerActor, false)); var dbgOverlay = world.WorldActor.TraitOrDefault(); - var showAstarCostCheckbox = widget.Get("SHOW_ASTAR"); - showAstarCostCheckbox.IsChecked = () => dbgOverlay != null ? dbgOverlay.Visible : false; - showAstarCostCheckbox.OnClick = () => { if (dbgOverlay != null) dbgOverlay.Visible ^= true; }; - - - var desync = widget.Get("DESYNC"); - var desyncEnabled = widget.Get("DESYNC_ARMED"); - desyncEnabled.IsChecked = () => !desync.Disabled; - desyncEnabled.OnClick = () => desync.Disabled ^= true; - - desync.Disabled = true; - desync.OnClick = () => + var showAstarCostCheckbox = widget.GetOrNull("SHOW_ASTAR"); + if (showAstarCostCheckbox != null) { - var trait = world.ActorsWithTrait().Random(CosmeticRandom).Trait; - var t = trait.GetType(); - string s; - const BindingFlags bf = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance; + showAstarCostCheckbox.IsChecked = () => dbgOverlay != null ? dbgOverlay.Visible : false; + showAstarCostCheckbox.OnClick = () => { if (dbgOverlay != null) dbgOverlay.Visible ^= true; }; + } + var desync = widget.GetOrNull("DESYNC"); + var desyncEnabled = widget.GetOrNull("DESYNC_ARMED"); + if (desync != null && desyncEnabled != null) + { + desyncEnabled.IsChecked = () => !desync.Disabled; + desyncEnabled.OnClick = () => desync.Disabled ^= true; - var fields = t.GetFields(bf).Where(x => x.HasAttribute()).ToArray(); - if (fields.Length > 0) - { + desync.Disabled = true; + desync.OnClick = () => TriggerDesync(world); + } - var f = fields[CosmeticRandom.Next(fields.Length)]; - var before = f.GetValue(trait); + var close = widget.GetOrNull("CLOSE"); + if (close != null) + close.OnClick = () => { Ui.CloseWindow(); onExit(); }; + } - if (f.FieldType == typeof(Boolean)) - f.SetValue(trait, !(Boolean) f.GetValue(trait)); - else if (f.FieldType == typeof(Int32)) - f.SetValue(trait, CosmeticRandom.Next(Int32.MaxValue)); - else - { - s = "Sorry, Field-Type not implemented. Try again!"; - Game.AddChatLine(Color.White, "Debug", s); - Console.WriteLine(s); - } + void TriggerDesync(World world) + { + var trait = world.ActorsWithTrait().Random(CosmeticRandom).Trait; + var t = trait.GetType(); + const BindingFlags bf = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance; + var fields = t.GetFields(bf).Where(x => x.HasAttribute()).ToArray(); + if (fields.Length > 0) + { + var f = fields[CosmeticRandom.Next(fields.Length)]; + var before = f.GetValue(trait); - var after = f.GetValue(trait); - - s = "Type: {0}\nField: ({1}) {2}\nBefore: {3}\nAfter: {4}".F(t.Name, f.FieldType.Name, f.Name, before, after); - Game.AddChatLine(Color.White, "Debug", s); - Console.WriteLine(s); - } + if (f.FieldType == typeof(Boolean)) + f.SetValue(trait, !(Boolean) f.GetValue(trait)); + else if (f.FieldType == typeof(Int32)) + f.SetValue(trait, CosmeticRandom.Next(Int32.MaxValue)); else - { - s = "Bad random choice. This trait has no fields. Try again!"; - Game.AddChatLine(Color.White, "Debug", s); - Console.WriteLine(s); - } - }; + Game.AddChatLine(Color.White, "Debug", "Sorry, Field-Type not implemented. Try again!"); - widget.Get("CLOSE").OnClick = () => { Ui.CloseWindow(); onExit(); }; + var after = f.GetValue(trait); + Game.AddChatLine(Color.White, "Debug", "Type: {0}\nField: ({1}) {2}\nBefore: {3}\nAfter: {4}" + .F(t.Name, f.FieldType.Name, f.Name, before, after)); + } + else + Game.AddChatLine(Color.White, "Debug", "Bad random choice. This trait has no fields. Try again!"); } public void Order(World world, string order) From 3968609a1e1bb5007ade407691541e6dd39de65e Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Sat, 6 Apr 2013 20:34:37 +1300 Subject: [PATCH 4/4] Move C&C cheats into a panel on options menu. --- .../Widgets/Logic/CncIngameChromeLogic.cs | 11 -- .../Widgets/Logic/CncIngameMenuLogic.cs | 41 +++++- mods/cnc/chrome/cheats.yaml | 124 ++++++++---------- mods/cnc/chrome/ingame.yaml | 6 - mods/cnc/chrome/ingamemenu.yaml | 19 +++ mods/cnc/chrome/lobby.yaml | 2 +- mods/cnc/chrome/objectives.yaml | 6 +- 7 files changed, 116 insertions(+), 93 deletions(-) diff --git a/OpenRA.Mods.Cnc/Widgets/Logic/CncIngameChromeLogic.cs b/OpenRA.Mods.Cnc/Widgets/Logic/CncIngameChromeLogic.cs index cb53a6dd39..8d9d3f26b4 100644 --- a/OpenRA.Mods.Cnc/Widgets/Logic/CncIngameChromeLogic.cs +++ b/OpenRA.Mods.Cnc/Widgets/Logic/CncIngameChromeLogic.cs @@ -147,17 +147,6 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic playerWidgets.Get("OPTIONS_BUTTON").OnClick = OptionsClicked; - var cheatsButton = playerWidgets.Get("CHEATS_BUTTON"); - cheatsButton.OnClick = () => - { - if (menu != MenuType.None) - Ui.CloseWindow(); - - menu = MenuType.Cheats; - Game.OpenWindow("CHEATS_PANEL", new WidgetArgs() {{"onExit", () => menu = MenuType.None }}); - }; - cheatsButton.IsVisible = () => world.LocalPlayer != null && world.LobbyInfo.GlobalSettings.AllowCheats; - var winLossWatcher = playerWidgets.Get("WIN_LOSS_WATCHER"); winLossWatcher.OnTick = () => { diff --git a/OpenRA.Mods.Cnc/Widgets/Logic/CncIngameMenuLogic.cs b/OpenRA.Mods.Cnc/Widgets/Logic/CncIngameMenuLogic.cs index 7d2776a00d..14ad6a064b 100644 --- a/OpenRA.Mods.Cnc/Widgets/Logic/CncIngameMenuLogic.cs +++ b/OpenRA.Mods.Cnc/Widgets/Logic/CncIngameMenuLogic.cs @@ -20,6 +20,8 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic { Widget menu; + enum PanelType { Objectives, Debug } + [ObjectCreator.UseCtor] public CncIngameMenuLogic(Widget widget, World world, Action onExit, WorldRenderer worldRenderer) { @@ -41,9 +43,9 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic Game.RunAfterDelay(1200, () => mpe.Fade(CncMenuPaletteEffect.EffectType.Black)); Game.RunAfterDelay(1200 + 40 * mpe.Info.FadeLength, () => { - Game.Disconnect(); - Ui.ResetAll(); - Game.LoadShellMap(); + Game.Disconnect(); + Ui.ResetAll(); + Game.LoadShellMap(); }); }; @@ -88,10 +90,39 @@ namespace OpenRA.Mods.Cnc.Widgets.Logic onExit(); }; - // Mission objectives panel + // Menu panels - ordered from lowest to highest priority + var panelParent = Game.OpenWindow(world, "INGAME_MENU_PANEL"); + PanelType Panel = PanelType.Objectives; + var visibleButtons = 0; + + // Debug / Cheats panel + var debugButton = panelParent.Get("DEBUG_BUTTON"); + debugButton.OnClick = () => Panel = PanelType.Debug; + debugButton.IsDisabled = () => Panel == PanelType.Debug; + + if (world.LocalPlayer != null && world.LobbyInfo.GlobalSettings.AllowCheats) + { + Panel = PanelType.Debug; + visibleButtons++; + var debugPanel = Game.LoadWidget(world, "CHEATS_PANEL", panelParent, new WidgetArgs(){{"onExit", doNothing}}); + debugPanel.IsVisible = () => Panel == PanelType.Debug; + debugButton.IsVisible = () => visibleButtons > 1; + } + + // Mission objectives var iop = world.WorldActor.TraitsImplementing().FirstOrDefault(); + var objectivesButton = panelParent.Get("OBJECTIVES_BUTTON"); + objectivesButton.OnClick = () => Panel = PanelType.Objectives; + objectivesButton.IsDisabled = () => Panel == PanelType.Objectives; + if (iop != null && iop.ObjectivesPanel != null) - Game.OpenWindow(world, iop.ObjectivesPanel); + { + Panel = PanelType.Objectives; + visibleButtons++; + var objectivesPanel = Game.LoadWidget(world, iop.ObjectivesPanel, panelParent, new WidgetArgs()); + objectivesPanel.IsVisible = () => Panel == PanelType.Objectives; + objectivesButton.IsVisible = () => visibleButtons > 1; + } } } } diff --git a/mods/cnc/chrome/cheats.yaml b/mods/cnc/chrome/cheats.yaml index 7b4f564c61..7f68f3c389 100644 --- a/mods/cnc/chrome/cheats.yaml +++ b/mods/cnc/chrome/cheats.yaml @@ -1,109 +1,101 @@ Container@CHEATS_PANEL: Logic:CheatsLogic - X:(WINDOW_RIGHT - WIDTH)/2 - Y:(WINDOW_BOTTOM - 110)/2 - Width:590 - Height:145 + Width:PARENT_RIGHT + Height:PARENT_BOTTOM Children: Label@TITLE: - Width:590 + Width:PARENT_RIGHT Y:0-25 Font:BigBold Contrast:true Align:Center - Text:Cheats + Text:Debug Options Background@bg: - Width:590 - Height:140 + Width:PARENT_RIGHT + Height:PARENT_BOTTOM Background:panel-black Children: + Label@CHEATS_TITLE: + Y:25 + Font:Bold + Text:Cheats + Align:Center + Width:PARENT_RIGHT Checkbox@INSTANT_BUILD: - X:15 - Y:15 + X:45 + Y:45 Width:200 Height:20 Text:Instant Build Speed Checkbox@ENABLE_TECH: - X:15 - Y:45 + X:45 + Y:75 Width:200 Height:20 Text:Build Everything Checkbox@BUILD_ANYWHERE: - X:15 - Y:75 + X:45 + Y:105 Width:200 Height:20 Text:Build Anywhere Checkbox@UNLIMITED_POWER: - X:200 - Y:15 + X:290 + Y:45 Width:200 Height:20 Text:Unlimited Power Checkbox@INSTANT_CHARGE: - X:200 - Y:45 + X:290 + Y:75 Width:200 Height:20 Text:Instant Charge Time - Checkbox@SHOW_MUZZLES: - X:200 - Y:75 - Height:20 - Width:200 - Text:Show Muzzle Positions Checkbox@DISABLE_SHROUD: - X:400 - Y:15 + X:290 + Y:105 Height:20 Width:200 - Text:Disable Shroud + Text:Disable Shroud & Fog + Button@GIVE_CASH: + X:20 + Y:155 + Width:140 + Height:35 + Text:Give $20,000 + Button@GIVE_EXPLORATION: + X:186 + Y:155 + Width:140 + Height:35 + Text:Clear Shroud + Button@RESET_EXPLORATION: + X:352 + Y:155 + Width:140 + Height:35 + Text:Reset Shroud + Label@VISUALIZATIONS_TITLE: + Y:215 + Font:Bold + Text:Visualizations + Align:Center + Width:PARENT_RIGHT Checkbox@SHOW_UNIT_PATHS: - X:400 - Y:45 + X:45 + Y:235 Width:200 Height:20 Text:Show Unit Paths Checkbox@SHOW_ASTAR: - X:400 - Y:75 + X:45 + Y:265 Height:20 Width:200 Text:Show A* Cost - Checkbox@DESYNC_ARMED: - X:400 - Y:105 - Width:20 + Checkbox@SHOW_MUZZLES: + X:290 + Y:235 Height:20 - Button@DESYNC: - X:430 - Y:100 - Width:120 - Height:25 - Text: Force Desync - Button@CLOSE: - Key:escape - X:0 - Y:139 - Width:140 - Height:35 - Text:Close - Button@GIVE_CASH: - X:150 - Y:139 - Width:140 - Height:35 - Text:Give Cash - Button@GIVE_EXPLORATION: - X:300 - Y:139 - Width:140 - Height:35 - Text:Give Exploration - Button@RESET_EXPLORATION: - X:450 - Y:139 - Width:140 - Height:35 - Text:Reset Exploration \ No newline at end of file + Width:200 + Text:Show Muzzle Positions \ No newline at end of file diff --git a/mods/cnc/chrome/ingame.yaml b/mods/cnc/chrome/ingame.yaml index 21d839f3b0..cb20c9db33 100644 --- a/mods/cnc/chrome/ingame.yaml +++ b/mods/cnc/chrome/ingame.yaml @@ -74,12 +74,6 @@ Container@OBSERVER_WIDGETS: Container@PLAYER_WIDGETS: Children: LogicTicker@WIN_LOSS_WATCHER: - Button@CHEATS_BUTTON: - X:WINDOW_RIGHT-400 - Y:5 - Width:140 - Height:35 - Text:Cheats WorldCommand: Width:WINDOW_RIGHT Height:WINDOW_BOTTOM diff --git a/mods/cnc/chrome/ingamemenu.yaml b/mods/cnc/chrome/ingamemenu.yaml index 99fb390134..1d5447483d 100644 --- a/mods/cnc/chrome/ingamemenu.yaml +++ b/mods/cnc/chrome/ingamemenu.yaml @@ -1,3 +1,22 @@ +Container@INGAME_MENU_PANEL: + X:(WINDOW_RIGHT - WIDTH)/2 + Y:(WINDOW_BOTTOM - HEIGHT)/2 + Width:512 + Height:320 + Children: + Button@OBJECTIVES_BUTTON: + Y:PARENT_BOTTOM - 1 + Width:140 + Height:35 + Text:Objectives + Visible: false + Button@DEBUG_BUTTON: + X:150 + Y:PARENT_BOTTOM - 1 + Width:140 + Height:35 + Text:Debug + Visible: false Container@INGAME_MENU: Width:WINDOW_RIGHT Height:WINDOW_BOTTOM diff --git a/mods/cnc/chrome/lobby.yaml b/mods/cnc/chrome/lobby.yaml index a040f5f7b7..f37737d71c 100644 --- a/mods/cnc/chrome/lobby.yaml +++ b/mods/cnc/chrome/lobby.yaml @@ -347,7 +347,7 @@ Container@SERVER_LOBBY: Y:257 Width:130 Height:20 - Text: Allow Cheats + Text: Debug Menu Checkbox@CRATES_CHECKBOX: X:160 Y:257 diff --git a/mods/cnc/chrome/objectives.yaml b/mods/cnc/chrome/objectives.yaml index 184771f640..334adda0ce 100644 --- a/mods/cnc/chrome/objectives.yaml +++ b/mods/cnc/chrome/objectives.yaml @@ -1,9 +1,7 @@ Container@CONQUEST_OBJECTIVES: Logic:CncConquestObjectivesLogic - X:(WINDOW_RIGHT - WIDTH)/2 - Y:(WINDOW_BOTTOM - HEIGHT)/2 - Width:512 - Height:320 + Width:PARENT_RIGHT + Height:PARENT_BOTTOM Children: Label@TITLE: Width:PARENT_RIGHT