Merge pull request #9255 from pchote/gamespeed

Add a game speed dropdown to the lobby options.
This commit is contained in:
Pavel Penev
2015-09-09 18:14:05 +03:00
26 changed files with 311 additions and 81 deletions

View File

@@ -147,7 +147,7 @@ namespace OpenRA
using (new PerfTimer("PrepareMap")) using (new PerfTimer("PrepareMap"))
map = ModData.PrepareMap(mapUID); map = ModData.PrepareMap(mapUID);
using (new PerfTimer("NewWorld")) using (new PerfTimer("NewWorld"))
OrderManager.World = new World(map, OrderManager, type) { Timestep = Timestep }; OrderManager.World = new World(map, OrderManager, type);
worldRenderer = new WorldRenderer(OrderManager.World); worldRenderer = new WorldRenderer(OrderManager.World);

40
OpenRA.Game/GameSpeed.cs Normal file
View File

@@ -0,0 +1,40 @@
#region Copyright & License Information
/*
* Copyright 2007-2015 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;
using System.Collections.Generic;
using System.Linq;
using OpenRA.Graphics;
namespace OpenRA
{
public class GameSpeed
{
[Translate]
public readonly string Name = "Default";
public readonly int Timestep = 40;
public readonly int OrderLatency = 3;
}
public class GameSpeeds : IGlobalModData
{
[FieldLoader.LoadUsing("LoadSpeeds")]
public readonly Dictionary<string, GameSpeed> Speeds;
static object LoadSpeeds(MiniYaml y)
{
var ret = new Dictionary<string, GameSpeed>();
foreach (var node in y.Nodes)
ret.Add(node.Key, FieldLoader.Load<GameSpeed>(node.Value));
return ret;
}
}
}

View File

@@ -172,6 +172,7 @@ namespace OpenRA.Network
{ {
public string ServerName; public string ServerName;
public string Map; public string Map;
public int Timestep = 40;
public int OrderLatency = 3; // net tick frames (x 120 = ms) public int OrderLatency = 3; // net tick frames (x 120 = ms)
public int RandomSeed = 0; public int RandomSeed = 0;
public bool FragileAlliances = false; // Allow diplomatic stance changes after game start. public bool FragileAlliances = false; // Allow diplomatic stance changes after game start.
@@ -187,6 +188,7 @@ namespace OpenRA.Network
public int StartingCash = 5000; public int StartingCash = 5000;
public string TechLevel = "none"; public string TechLevel = "none";
public string StartingUnitsClass = "none"; public string StartingUnitsClass = "none";
public string GameSpeedType = "default";
public bool ShortGame = true; public bool ShortGame = true;
public bool AllowVersionMismatch; public bool AllowVersionMismatch;
public string GameUid; public string GameUid;

View File

@@ -243,6 +243,7 @@
<Compile Include="Map\MapCoordsRegion.cs" /> <Compile Include="Map\MapCoordsRegion.cs" />
<Compile Include="Renderer.cs" /> <Compile Include="Renderer.cs" />
<Compile Include="Platform.cs" /> <Compile Include="Platform.cs" />
<Compile Include="GameSpeed.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="FileSystem\D2kSoundResources.cs" /> <Compile Include="FileSystem\D2kSoundResources.cs" />

View File

@@ -158,14 +158,14 @@ namespace OpenRA.Widgets
DrawRGBA(cornerBottomRight, new float2(bounds.Right - cornerBottomRight.Size.X, bounds.Bottom - cornerBottomRight.Size.Y)); DrawRGBA(cornerBottomRight, new float2(bounds.Right - cornerBottomRight.Size.X, bounds.Bottom - cornerBottomRight.Size.Y));
} }
public static string FormatTime(int ticks) public static string FormatTime(int ticks, int timestep)
{ {
return FormatTime(ticks, true); return FormatTime(ticks, true, timestep);
} }
public static string FormatTime(int ticks, bool leadingMinuteZero) public static string FormatTime(int ticks, bool leadingMinuteZero, int timestep)
{ {
var seconds = (int)Math.Ceiling(ticks / 25f); var seconds = (int)Math.Ceiling(ticks * timestep / 1000f);
return FormatTimeSeconds(seconds, leadingMinuteZero); return FormatTimeSeconds(seconds, leadingMinuteZero);
} }

View File

@@ -144,6 +144,7 @@ namespace OpenRA
OrderManager = orderManager; OrderManager = orderManager;
orderGenerator = new UnitOrderGenerator(); orderGenerator = new UnitOrderGenerator();
Map = map; Map = map;
Timestep = orderManager.LobbyInfo.GlobalSettings.Timestep;
TileSet = map.Rules.TileSets[Map.Tileset]; TileSet = map.Rules.TileSets[Map.Tileset];
SharedRandom = new MersenneTwister(orderManager.LobbyInfo.GlobalSettings.RandomSeed); SharedRandom = new MersenneTwister(orderManager.LobbyInfo.GlobalSettings.RandomSeed);

View File

@@ -19,7 +19,12 @@ namespace OpenRA.Mods.Common.Scripting
[ScriptGlobal("Utils")] [ScriptGlobal("Utils")]
public class UtilsGlobal : ScriptGlobal public class UtilsGlobal : ScriptGlobal
{ {
public UtilsGlobal(ScriptContext context) : base(context) { } readonly World world;
public UtilsGlobal(ScriptContext context)
: base(context)
{
world = context.World;
}
[Desc("Calls a function on every element in a collection.")] [Desc("Calls a function on every element in a collection.")]
public void Do(LuaValue[] collection, LuaFunction func) public void Do(LuaValue[] collection, LuaFunction func)
@@ -101,7 +106,7 @@ namespace OpenRA.Mods.Common.Scripting
[Desc("Returns the ticks formatted to HH:MM:SS.")] [Desc("Returns the ticks formatted to HH:MM:SS.")]
public string FormatTime(int ticks, bool leadingMinuteZero = true) public string FormatTime(int ticks, bool leadingMinuteZero = true)
{ {
return WidgetUtils.FormatTime(ticks, leadingMinuteZero); return WidgetUtils.FormatTime(ticks, leadingMinuteZero, world.Timestep);
} }
} }
} }

View File

@@ -675,6 +675,34 @@ namespace OpenRA.Mods.Common.Server
return true; return true;
} }
}, },
{ "gamespeed",
s =>
{
if (!client.IsAdmin)
{
server.SendOrderTo(conn, "Message", "Only the host can set that option.");
return true;
}
var gameSpeeds = Game.ModData.Manifest.Get<GameSpeeds>();
GameSpeed speed;
if (!gameSpeeds.Speeds.TryGetValue(s, out speed))
{
server.SendOrderTo(conn, "Message", "Invalid game speed selected.");
return true;
}
server.LobbyInfo.GlobalSettings.GameSpeedType = s;
server.LobbyInfo.GlobalSettings.Timestep = speed.Timestep;
server.LobbyInfo.GlobalSettings.OrderLatency = speed.OrderLatency;
server.SyncLobbyInfo();
server.SendMessage("{0} changed Game Speed to {1}.".F(client.Name, speed.Name));
return true;
}
},
{ "kick", { "kick",
s => s =>
{ {

View File

@@ -23,7 +23,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
var status = widget.GetOrNull<LabelWidget>("GAME_TIMER_STATUS"); var status = widget.GetOrNull<LabelWidget>("GAME_TIMER_STATUS");
var startTick = Ui.LastTickTime; var startTick = Ui.LastTickTime;
Func<bool> shouldShowStatus = () => (world.Paused || world.Timestep != Game.Timestep) Func<bool> shouldShowStatus = () => (world.Paused || world.Timestep != world.LobbyInfo.GlobalSettings.Timestep)
&& (Ui.LastTickTime - startTick) / 1000 % 2 == 0; && (Ui.LastTickTime - startTick) / 1000 % 2 == 0;
Func<string> statusText = () => Func<string> statusText = () =>
@@ -34,7 +34,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
if (world.Timestep == 1) if (world.Timestep == 1)
return "Max Speed"; return "Max Speed";
return "{0}% Speed".F(Game.Timestep * 100 / world.Timestep); return "{0}% Speed".F(world.LobbyInfo.GlobalSettings.Timestep * 100 / world.Timestep);
}; };
if (timer != null) if (timer != null)
@@ -44,7 +44,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
if (status == null && shouldShowStatus()) if (status == null && shouldShowStatus())
return statusText(); return statusText();
return WidgetUtils.FormatTime(world.WorldTick); return WidgetUtils.FormatTime(world.WorldTick, world.Timestep);
}; };
} }

View File

@@ -20,7 +20,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
public class ProductionTooltipLogic public class ProductionTooltipLogic
{ {
[ObjectCreator.UseCtor] [ObjectCreator.UseCtor]
public ProductionTooltipLogic(Widget widget, TooltipContainerWidget tooltipContainer, ProductionPaletteWidget palette) public ProductionTooltipLogic(Widget widget, TooltipContainerWidget tooltipContainer, ProductionPaletteWidget palette, World world)
{ {
var mapRules = palette.World.Map.Rules; var mapRules = palette.World.Map.Rules;
var pm = palette.World.LocalPlayer.PlayerActor.Trait<PowerManager>(); var pm = palette.World.LocalPlayer.PlayerActor.Trait<PowerManager>();
@@ -83,7 +83,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
var lowpower = pm.PowerState != PowerState.Normal; var lowpower = pm.PowerState != PowerState.Normal;
var time = palette.CurrentQueue == null ? 0 : palette.CurrentQueue.GetBuildTime(actor.Name) var time = palette.CurrentQueue == null ? 0 : palette.CurrentQueue.GetBuildTime(actor.Name)
* (lowpower ? palette.CurrentQueue.Info.LowPowerSlowdown : 1); * (lowpower ? palette.CurrentQueue.Info.LowPowerSlowdown : 1);
var timeString = WidgetUtils.FormatTime(time); var timeString = WidgetUtils.FormatTime(time, world.Timestep);
timeLabel.GetText = () => timeString; timeLabel.GetText = () => timeString;
timeLabel.GetColor = () => lowpower ? Color.Red : Color.White; timeLabel.GetColor = () => lowpower ? Color.Red : Color.White;

View File

@@ -8,6 +8,7 @@
*/ */
#endregion #endregion
using System;
using System.Collections.Generic; using System.Collections.Generic;
using OpenRA.Network; using OpenRA.Network;
using OpenRA.Widgets; using OpenRA.Widgets;
@@ -18,12 +19,12 @@ namespace OpenRA.Mods.Common.Widgets.Logic
{ {
enum PlaybackSpeed { Regular, Slow, Fast, Maximum } enum PlaybackSpeed { Regular, Slow, Fast, Maximum }
readonly Dictionary<PlaybackSpeed, int> timesteps = new Dictionary<PlaybackSpeed, int>() readonly Dictionary<PlaybackSpeed, float> multipliers = new Dictionary<PlaybackSpeed, float>()
{ {
{ PlaybackSpeed.Regular, Game.Timestep }, { PlaybackSpeed.Regular, 1 },
{ PlaybackSpeed.Slow, Game.Timestep * 2 }, { PlaybackSpeed.Slow, 2 },
{ PlaybackSpeed.Fast, Game.Timestep / 2 }, { PlaybackSpeed.Fast, 0.5f },
{ PlaybackSpeed.Maximum, 1 }, { PlaybackSpeed.Maximum, 0.001f },
}; };
[ObjectCreator.UseCtor] [ObjectCreator.UseCtor]
@@ -41,6 +42,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
container.Visible = true; container.Visible = true;
var speed = PlaybackSpeed.Regular; var speed = PlaybackSpeed.Regular;
var originalTimestep = world.Timestep;
var pauseButton = widget.Get<ButtonWidget>("BUTTON_PAUSE"); var pauseButton = widget.Get<ButtonWidget>("BUTTON_PAUSE");
pauseButton.IsVisible = () => world.Timestep != 0 && orderManager.NetFrameNumber < replayNetTicks; pauseButton.IsVisible = () => world.Timestep != 0 && orderManager.NetFrameNumber < replayNetTicks;
@@ -48,7 +50,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
var playButton = widget.Get<ButtonWidget>("BUTTON_PLAY"); var playButton = widget.Get<ButtonWidget>("BUTTON_PLAY");
playButton.IsVisible = () => world.Timestep == 0 || orderManager.NetFrameNumber >= replayNetTicks; playButton.IsVisible = () => world.Timestep == 0 || orderManager.NetFrameNumber >= replayNetTicks;
playButton.OnClick = () => world.Timestep = timesteps[speed]; playButton.OnClick = () => world.Timestep = (int)Math.Ceiling(originalTimestep * multipliers[speed]);
playButton.IsDisabled = () => orderManager.NetFrameNumber >= replayNetTicks; playButton.IsDisabled = () => orderManager.NetFrameNumber >= replayNetTicks;
var slowButton = widget.Get<ButtonWidget>("BUTTON_SLOW"); var slowButton = widget.Get<ButtonWidget>("BUTTON_SLOW");
@@ -58,7 +60,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
{ {
speed = PlaybackSpeed.Slow; speed = PlaybackSpeed.Slow;
if (world.Timestep != 0) if (world.Timestep != 0)
world.Timestep = timesteps[speed]; world.Timestep = (int)Math.Ceiling(originalTimestep * multipliers[speed]);
}; };
var normalSpeedButton = widget.Get<ButtonWidget>("BUTTON_REGULAR"); var normalSpeedButton = widget.Get<ButtonWidget>("BUTTON_REGULAR");
@@ -68,7 +70,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
{ {
speed = PlaybackSpeed.Regular; speed = PlaybackSpeed.Regular;
if (world.Timestep != 0) if (world.Timestep != 0)
world.Timestep = timesteps[speed]; world.Timestep = (int)Math.Ceiling(originalTimestep * multipliers[speed]);
}; };
var fastButton = widget.Get<ButtonWidget>("BUTTON_FAST"); var fastButton = widget.Get<ButtonWidget>("BUTTON_FAST");
@@ -78,7 +80,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
{ {
speed = PlaybackSpeed.Fast; speed = PlaybackSpeed.Fast;
if (world.Timestep != 0) if (world.Timestep != 0)
world.Timestep = timesteps[speed]; world.Timestep = (int)Math.Ceiling(originalTimestep * multipliers[speed]);
}; };
var maximumButton = widget.Get<ButtonWidget>("BUTTON_MAXIMUM"); var maximumButton = widget.Get<ButtonWidget>("BUTTON_MAXIMUM");
@@ -88,7 +90,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
{ {
speed = PlaybackSpeed.Maximum; speed = PlaybackSpeed.Maximum;
if (world.Timestep != 0) if (world.Timestep != 0)
world.Timestep = timesteps[speed]; world.Timestep = (int)Math.Ceiling(originalTimestep * multipliers[speed]);
}; };
} }
} }

View File

@@ -17,7 +17,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
public class SupportPowerTooltipLogic public class SupportPowerTooltipLogic
{ {
[ObjectCreator.UseCtor] [ObjectCreator.UseCtor]
public SupportPowerTooltipLogic(Widget widget, TooltipContainerWidget tooltipContainer, SupportPowersWidget palette) public SupportPowerTooltipLogic(Widget widget, TooltipContainerWidget tooltipContainer, SupportPowersWidget palette, World world)
{ {
widget.IsVisible = () => palette.TooltipIcon != null; widget.IsVisible = () => palette.TooltipIcon != null;
var nameLabel = widget.Get<LabelWidget>("NAME"); var nameLabel = widget.Get<LabelWidget>("NAME");
@@ -46,8 +46,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic
if (sp.Info == null) if (sp.Info == null)
return; // no instances actually exist (race with destroy) return; // no instances actually exist (race with destroy)
time = "{0} / {1}".F(WidgetUtils.FormatTime(sp.RemainingTime), var remaining = WidgetUtils.FormatTime(sp.RemainingTime, world.Timestep);
WidgetUtils.FormatTime(sp.Info.ChargeTime * 25)); var total = WidgetUtils.FormatTime(sp.Info.ChargeTime * 25, world.Timestep);
time = "{0} / {1}".F(remaining, total);
if (sp == lastPower) if (sp == lastPower)
return; return;

View File

@@ -490,6 +490,44 @@ namespace OpenRA.Mods.Common.Widgets.Logic
}; };
} }
var gameSpeed = optionsBin.GetOrNull<DropDownButtonWidget>("GAMESPEED_DROPDOWNBUTTON");
if (gameSpeed != null)
{
var speeds = Game.ModData.Manifest.Get<GameSpeeds>().Speeds;
gameSpeed.IsDisabled = () => Map.Status != MapStatus.Available || configurationDisabled();
gameSpeed.GetText = () =>
{
if (Map.Status != MapStatus.Available)
return "Not Available";
GameSpeed speed;
if (!speeds.TryGetValue(orderManager.LobbyInfo.GlobalSettings.GameSpeedType, out speed))
return "Unknown";
return speed.Name;
};
gameSpeed.OnMouseDown = _ =>
{
var options = speeds.Select(s => new DropDownOption
{
Title = s.Value.Name,
IsSelected = () => orderManager.LobbyInfo.GlobalSettings.GameSpeedType == s.Key,
OnClick = () => orderManager.IssueOrder(Order.Command("gamespeed {0}".F(s.Key)))
});
Func<DropDownOption, ScrollItemWidget, ScrollItemWidget> setupItem = (option, template) =>
{
var item = ScrollItemWidget.Setup(template, option.IsSelected, option.OnClick);
item.Get<LabelWidget>("LABEL").GetText = () => option.Title;
return item;
};
gameSpeed.ShowDropDown("LABEL_DROPDOWN_TEMPLATE", options.Count() * 30, options, setupItem);
};
}
var exploredMap = optionsBin.GetOrNull<CheckboxWidget>("EXPLORED_MAP_CHECKBOX"); var exploredMap = optionsBin.GetOrNull<CheckboxWidget>("EXPLORED_MAP_CHECKBOX");
if (exploredMap != null) if (exploredMap != null)
{ {

View File

@@ -92,18 +92,18 @@ namespace OpenRA.Mods.Common.Widgets
WidgetUtils.DrawSHPCentered(clock.Image, location + 0.5f * iconSize, worldRenderer.Palette(bi.IconPalette), 0.5f); WidgetUtils.DrawSHPCentered(clock.Image, location + 0.5f * iconSize, worldRenderer.Palette(bi.IconPalette), 0.5f);
var tiny = Game.Renderer.Fonts["Tiny"]; var tiny = Game.Renderer.Fonts["Tiny"];
var text = GetOverlayForItem(current); var text = GetOverlayForItem(current, world.Timestep);
tiny.DrawTextWithContrast(text, tiny.DrawTextWithContrast(text,
location + new float2(16, 16) - new float2(tiny.Measure(text).X / 2, 0), location + new float2(16, 16) - new float2(tiny.Measure(text).X / 2, 0),
Color.White, Color.Black, 1); Color.White, Color.Black, 1);
} }
} }
static string GetOverlayForItem(ProductionItem item) static string GetOverlayForItem(ProductionItem item, int timestep)
{ {
if (item.Paused) return "ON HOLD"; if (item.Paused) return "ON HOLD";
if (item.Done) return "READY"; if (item.Done) return "READY";
return WidgetUtils.FormatTime(item.RemainingTimeActual); return WidgetUtils.FormatTime(item.RemainingTimeActual, timestep);
} }
public override Widget Clone() public override Widget Clone()

View File

@@ -82,18 +82,18 @@ namespace OpenRA.Mods.Common.Widgets
WidgetUtils.DrawSHPCentered(clock.Image, location + 0.5f * iconSize, worldRenderer.Palette(item.Info.IconPalette), 0.5f); WidgetUtils.DrawSHPCentered(clock.Image, location + 0.5f * iconSize, worldRenderer.Palette(item.Info.IconPalette), 0.5f);
var tiny = Game.Renderer.Fonts["Tiny"]; var tiny = Game.Renderer.Fonts["Tiny"];
var text = GetOverlayForItem(item); var text = GetOverlayForItem(item, world.Timestep);
tiny.DrawTextWithContrast(text, tiny.DrawTextWithContrast(text,
location + new float2(16, 16) - new float2(tiny.Measure(text).X / 2, 0), location + new float2(16, 16) - new float2(tiny.Measure(text).X / 2, 0),
Color.White, Color.Black, 1); Color.White, Color.Black, 1);
} }
} }
static string GetOverlayForItem(SupportPowerInstance item) static string GetOverlayForItem(SupportPowerInstance item, int timestep)
{ {
if (item.Disabled) return "ON HOLD"; if (item.Disabled) return "ON HOLD";
if (item.Ready) return "READY"; if (item.Ready) return "READY";
return WidgetUtils.FormatTime(item.RemainingTime); return WidgetUtils.FormatTime(item.RemainingTime, timestep);
} }
public override Widget Clone() public override Widget Clone()

View File

@@ -162,7 +162,7 @@ namespace OpenRA.Mods.Common.Widgets
{ {
if (TooltipContainer != null) if (TooltipContainer != null)
tooltipContainer.Value.SetTooltip(TooltipTemplate, tooltipContainer.Value.SetTooltip(TooltipTemplate,
new WidgetArgs() { { "palette", this } }); new WidgetArgs() { { "world", World }, { "palette", this } });
} }
public override void MouseExited() public override void MouseExited()
@@ -353,7 +353,7 @@ namespace OpenRA.Mods.Common.Widgets
var iconOffset = 0.5f * IconSize.ToFloat2() + IconSpriteOffset; var iconOffset = 0.5f * IconSize.ToFloat2() + IconSpriteOffset;
overlayFont = Game.Renderer.Fonts["TinyBold"]; overlayFont = Game.Renderer.Fonts["TinyBold"];
timeOffset = iconOffset - overlayFont.Measure(WidgetUtils.FormatTime(0)) / 2; timeOffset = iconOffset - overlayFont.Measure(WidgetUtils.FormatTime(0, World.Timestep)) / 2;
queuedOffset = new float2(4, 2); queuedOffset = new float2(4, 2);
holdOffset = iconOffset - overlayFont.Measure(HoldText) / 2; holdOffset = iconOffset - overlayFont.Measure(HoldText) / 2;
readyOffset = iconOffset - overlayFont.Measure(ReadyText) / 2; readyOffset = iconOffset - overlayFont.Measure(ReadyText) / 2;
@@ -400,7 +400,7 @@ namespace OpenRA.Mods.Common.Widgets
var waiting = first != CurrentQueue.CurrentItem() && !first.Done; var waiting = first != CurrentQueue.CurrentItem() && !first.Done;
if (first.Done) if (first.Done)
{ {
if (ReadyTextStyle == ReadyTextStyleOptions.Solid || orderManager.LocalFrameNumber / 9 % 2 == 0) if (ReadyTextStyle == ReadyTextStyleOptions.Solid || orderManager.LocalFrameNumber * worldRenderer.World.Timestep / 360 % 2 == 0)
overlayFont.DrawTextWithContrast(ReadyText, icon.Pos + readyOffset, Color.White, Color.Black, 1); overlayFont.DrawTextWithContrast(ReadyText, icon.Pos + readyOffset, Color.White, Color.Black, 1);
else if (ReadyTextStyle == ReadyTextStyleOptions.AlternatingColor) else if (ReadyTextStyle == ReadyTextStyleOptions.AlternatingColor)
overlayFont.DrawTextWithContrast(ReadyText, icon.Pos + readyOffset, ReadyTextAltColor, Color.Black, 1); overlayFont.DrawTextWithContrast(ReadyText, icon.Pos + readyOffset, ReadyTextAltColor, Color.Black, 1);
@@ -410,7 +410,7 @@ namespace OpenRA.Mods.Common.Widgets
icon.Pos + holdOffset, icon.Pos + holdOffset,
Color.White, Color.Black, 1); Color.White, Color.Black, 1);
else if (!waiting) else if (!waiting)
overlayFont.DrawTextWithContrast(WidgetUtils.FormatTime(first.RemainingTimeActual), overlayFont.DrawTextWithContrast(WidgetUtils.FormatTime(first.RemainingTimeActual, World.Timestep),
icon.Pos + timeOffset, icon.Pos + timeOffset,
Color.White, Color.Black, 1); Color.White, Color.Black, 1);

View File

@@ -65,7 +65,7 @@ namespace OpenRA.Mods.Common.Widgets
var isVictory = pendingWinner == world.LocalPlayer || !WorldUtils.AreMutualAllies(pendingWinner, world.LocalPlayer); var isVictory = pendingWinner == world.LocalPlayer || !WorldUtils.AreMutualAllies(pendingWinner, world.LocalPlayer);
var tc = "Strategic {0} in {1}".F( var tc = "Strategic {0} in {1}".F(
isVictory ? "victory" : "defeat", isVictory ? "victory" : "defeat",
WidgetUtils.FormatTime(winnerSvc.TicksLeft)); WidgetUtils.FormatTime(winnerSvc.TicksLeft, world.Timestep));
var font = Game.Renderer.Fonts["Bold"]; var font = Game.Renderer.Fonts["Bold"];

View File

@@ -23,12 +23,14 @@ namespace OpenRA.Mods.Common.Widgets
public readonly string Format = "{0}: {1}"; public readonly string Format = "{0}: {1}";
public readonly TimerOrder Order = TimerOrder.Descending; public readonly TimerOrder Order = TimerOrder.Descending;
readonly World world;
readonly IEnumerable<SupportPowerInstance> powers; readonly IEnumerable<SupportPowerInstance> powers;
Pair<string, Color>[] texts; Pair<string, Color>[] texts;
[ObjectCreator.UseCtor] [ObjectCreator.UseCtor]
public SupportPowerTimerWidget(World world) public SupportPowerTimerWidget(World world)
{ {
this.world = world;
powers = world.ActorsWithTrait<SupportPowerManager>() powers = world.ActorsWithTrait<SupportPowerManager>()
.Where(p => !p.Actor.IsDead && !p.Actor.Owner.NonCombatant) .Where(p => !p.Actor.IsDead && !p.Actor.Owner.NonCombatant)
.SelectMany(s => s.Trait.Powers.Values) .SelectMany(s => s.Trait.Powers.Values)
@@ -39,7 +41,7 @@ namespace OpenRA.Mods.Common.Widgets
{ {
texts = powers.Select(p => texts = powers.Select(p =>
{ {
var time = WidgetUtils.FormatTime(p.RemainingTime, false); var time = WidgetUtils.FormatTime(p.RemainingTime, false, world.Timestep);
var text = Format.F(p.Info.Description, time); var text = Format.F(p.Info.Description, time);
var color = !p.Ready || Game.LocalTick % 50 < 25 ? p.Instances[0].Self.Owner.Color.RGB : Color.White; var color = !p.Ready || Game.LocalTick % 50 < 25 ? p.Instances[0].Self.Owner.Color.RGB : Color.White;
return Pair.New(text, color); return Pair.New(text, color);

View File

@@ -142,7 +142,7 @@ namespace OpenRA.Mods.Common.Widgets
holdOffset = iconOffset - overlayFont.Measure(HoldText) / 2; holdOffset = iconOffset - overlayFont.Measure(HoldText) / 2;
readyOffset = iconOffset - overlayFont.Measure(ReadyText) / 2; readyOffset = iconOffset - overlayFont.Measure(ReadyText) / 2;
timeOffset = iconOffset - overlayFont.Measure(WidgetUtils.FormatTime(0)) / 2; timeOffset = iconOffset - overlayFont.Measure(WidgetUtils.FormatTime(0, worldRenderer.World.Timestep)) / 2;
// Icons // Icons
foreach (var p in icons.Values) foreach (var p in icons.Values)
@@ -171,7 +171,7 @@ namespace OpenRA.Mods.Common.Widgets
p.Pos + holdOffset, p.Pos + holdOffset,
Color.White, Color.Black, 1); Color.White, Color.Black, 1);
else else
overlayFont.DrawTextWithContrast(WidgetUtils.FormatTime(p.Power.RemainingTime), overlayFont.DrawTextWithContrast(WidgetUtils.FormatTime(p.Power.RemainingTime, worldRenderer.World.Timestep),
p.Pos + timeOffset, p.Pos + timeOffset,
Color.White, Color.Black, 1); Color.White, Color.Black, 1);
} }
@@ -189,7 +189,7 @@ namespace OpenRA.Mods.Common.Widgets
return; return;
tooltipContainer.Value.SetTooltip(TooltipTemplate, tooltipContainer.Value.SetTooltip(TooltipTemplate,
new WidgetArgs() { { "palette", this } }); new WidgetArgs() { { "world", worldRenderer.World }, { "palette", this } });
} }
public override void MouseExited() public override void MouseExited()

View File

@@ -175,19 +175,6 @@ Background@LOBBY_OPTIONS_BIN:
Width: 140 Width: 140
Height: 25 Height: 25
Font: Regular Font: Regular
Label@DIFFICULTY_DESC:
X: PARENT_RIGHT - WIDTH - 135
Y: 107
Width: 120
Height: 25
Text: Mission Difficulty:
Align: Right
DropDownButton@DIFFICULTY_DROPDOWNBUTTON:
X: PARENT_RIGHT - WIDTH + 10
Y: 107
Width: 140
Height: 25
Font: Regular
DropDownButton@TECHLEVEL_DROPDOWNBUTTON: DropDownButton@TECHLEVEL_DROPDOWNBUTTON:
X: 85 X: 85
Y: 112 Y: 112
@@ -201,7 +188,32 @@ Background@LOBBY_OPTIONS_BIN:
Height: 25 Height: 25
Text: Tech Level: Text: Tech Level:
Align: Right Align: Right
Label@GAMESPEED_DESC:
X: PARENT_RIGHT - WIDTH - 135
Y: 112
Width: 120
Height: 25
Text: Game Speed:
Align: Right
DropDownButton@GAMESPEED_DROPDOWNBUTTON:
X: PARENT_RIGHT - WIDTH + 10
Y: 112
Width: 140
Height: 25
Font: Regular
Label@DIFFICULTY_DESC:
X: PARENT_RIGHT - WIDTH - 135
Y: 152
Width: 120
Height: 25
Text: Mission Difficulty:
Align: Right
DropDownButton@DIFFICULTY_DROPDOWNBUTTON:
X: PARENT_RIGHT - WIDTH + 10
Y: 152
Width: 140
Height: 25
Font: Regular
Background@FORCE_START_DIALOG: Background@FORCE_START_DIALOG:
X: 15 X: 15
Y: 30 Y: 30

View File

@@ -214,3 +214,21 @@ SpriteSequenceFormat: TilesetSpecificSpriteSequence
SNOW: .sno SNOW: .sno
DESERT: .des DESERT: .des
JUNGLE: .jun JUNGLE: .jun
GameSpeeds:
slower:
Name: Slower
Timestep: 50
OrderLatency: 3
default:
Name: Default
Timestep: 40
OrderLatency: 3
faster:
Name: Faster
Timestep: 30
OrderLatency: 4
fastest:
Name: Fastest
Timestep: 20
OrderLatency: 6

View File

@@ -151,6 +151,19 @@ Background@LOBBY_OPTIONS_BIN:
Width: 140 Width: 140
Height: 20 Height: 20
Text: Debug Menu Text: Debug Menu
Label@DIFFICULTY_DESC:
X: PARENT_RIGHT - WIDTH - 145
Y: 70
Width: 120
Height: 25
Text: Mission Difficulty:
Align: Right
DropDownButton@DIFFICULTY_DROPDOWNBUTTON:
X: PARENT_RIGHT - WIDTH
Y: 70
Width: 140
Height: 25
Font: Regular
Label@STARTINGCASH_DESC: Label@STARTINGCASH_DESC:
Y: 110 Y: 110
Width: 80 Width: 80
@@ -177,19 +190,6 @@ Background@LOBBY_OPTIONS_BIN:
Width: 140 Width: 140
Height: 25 Height: 25
Font: Regular Font: Regular
Label@DIFFICULTY_DESC:
X: PARENT_RIGHT - WIDTH - 145
Y: 150
Width: 120
Height: 25
Text: Mission Difficulty:
Align: Right
DropDownButton@DIFFICULTY_DROPDOWNBUTTON:
X: PARENT_RIGHT - WIDTH
Y: 150
Width: 140
Height: 25
Font: Regular
DropDownButton@TECHLEVEL_DROPDOWNBUTTON: DropDownButton@TECHLEVEL_DROPDOWNBUTTON:
X: 85 X: 85
Y: 150 Y: 150
@@ -203,6 +203,19 @@ Background@LOBBY_OPTIONS_BIN:
Height: 25 Height: 25
Text: Tech Level: Text: Tech Level:
Align: Right Align: Right
Label@GAMESPEED_DESC:
X: PARENT_RIGHT - WIDTH - 145
Y: 150
Width: 120
Height: 25
Text: Game Speed:
Align: Right
DropDownButton@GAMESPEED_DROPDOWNBUTTON:
X: PARENT_RIGHT - WIDTH
Y: 150
Width: 140
Height: 25
Font: Regular
Background@FORCE_START_DIALOG: Background@FORCE_START_DIALOG:
X: 20 X: 20

View File

@@ -193,3 +193,21 @@ SupportsMapsFrom: d2k
SpriteFormats: R8, ShpTD, TmpRA SpriteFormats: R8, ShpTD, TmpRA
SpriteSequenceFormat: DefaultSpriteSequence SpriteSequenceFormat: DefaultSpriteSequence
GameSpeeds:
slower:
Name: Slower
Timestep: 50
OrderLatency: 3
default:
Name: Default
Timestep: 40
OrderLatency: 3
faster:
Name: Faster
Timestep: 30
OrderLatency: 4
fastest:
Name: Fastest
Timestep: 20
OrderLatency: 6

View File

@@ -145,6 +145,19 @@ Background@LOBBY_OPTIONS_BIN:
Width: 140 Width: 140
Height: 20 Height: 20
Text: Debug Menu Text: Debug Menu
Label@DIFFICULTY_DESC:
X: PARENT_RIGHT - WIDTH - 145
Y: 70
Width: 120
Height: 25
Text: Mission Difficulty:
Align: Right
DropDownButton@DIFFICULTY_DROPDOWNBUTTON:
X: PARENT_RIGHT - WIDTH
Y: 70
Width: 140
Height: 25
Font: Regular
Label@STARTINGCASH_DESC: Label@STARTINGCASH_DESC:
Y: 110 Y: 110
Width: 80 Width: 80
@@ -171,19 +184,6 @@ Background@LOBBY_OPTIONS_BIN:
Width: 140 Width: 140
Height: 25 Height: 25
Font: Regular Font: Regular
Label@DIFFICULTY_DESC:
X: PARENT_RIGHT - WIDTH - 145
Y: 150
Width: 120
Height: 25
Text: Mission Difficulty:
Align: Right
DropDownButton@DIFFICULTY_DROPDOWNBUTTON:
X: PARENT_RIGHT - WIDTH
Y: 150
Width: 140
Height: 25
Font: Regular
DropDownButton@TECHLEVEL_DROPDOWNBUTTON: DropDownButton@TECHLEVEL_DROPDOWNBUTTON:
X: 85 X: 85
Y: 150 Y: 150
@@ -197,6 +197,19 @@ Background@LOBBY_OPTIONS_BIN:
Height: 25 Height: 25
Text: Tech Level: Text: Tech Level:
Align: Right Align: Right
Label@GAMESPEED_DESC:
X: PARENT_RIGHT - WIDTH - 145
Y: 150
Width: 120
Height: 25
Text: Game Speed:
Align: Right
DropDownButton@GAMESPEED_DROPDOWNBUTTON:
X: PARENT_RIGHT - WIDTH
Y: 150
Width: 140
Height: 25
Font: Regular
Background@FORCE_START_DIALOG: Background@FORCE_START_DIALOG:
X: 20 X: 20

View File

@@ -213,3 +213,21 @@ SpriteSequenceFormat: TilesetSpecificSpriteSequence
SNOW: .sno SNOW: .sno
INTERIOR: .int INTERIOR: .int
DESERT: .des DESERT: .des
GameSpeeds:
slower:
Name: Slower
Timestep: 50
OrderLatency: 3
default:
Name: Default
Timestep: 40
OrderLatency: 3
faster:
Name: Faster
Timestep: 30
OrderLatency: 4
fastest:
Name: Fastest
Timestep: 20
OrderLatency: 6

View File

@@ -258,3 +258,21 @@ SpriteSequenceFormat: TilesetSpecificSpriteSequence
TilesetCodes: TilesetCodes:
TEMPERATE: t TEMPERATE: t
SNOW: a SNOW: a
GameSpeeds:
slower:
Name: Slower
Timestep: 50
OrderLatency: 3
default:
Name: Default
Timestep: 40
OrderLatency: 3
faster:
Name: Faster
Timestep: 30
OrderLatency: 4
fastest:
Name: Fastest
Timestep: 20
OrderLatency: 6