diff --git a/OpenRA.Game/Game.cs b/OpenRA.Game/Game.cs
index e134e464ab..b206baaef6 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/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/Server/Server.cs b/OpenRA.Game/Server/Server.cs
index ebdef63822..3c5dc08baf 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/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/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..8d9d3f26b4 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));
}
}
});
@@ -144,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/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/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)
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;
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/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
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: