diff --git a/OpenRA.Game/Graphics/HSLColor.cs b/OpenRA.Game/Graphics/HSLColor.cs
index ec5ca86e3b..c6fa0d9520 100644
--- a/OpenRA.Game/Graphics/HSLColor.cs
+++ b/OpenRA.Game/Graphics/HSLColor.cs
@@ -9,10 +9,11 @@
#endregion
using System.Drawing;
+using OpenRA.Scripting;
namespace OpenRA.Graphics
{
- public struct HSLColor
+ public struct HSLColor : IScriptBindable
{
public readonly byte H;
public readonly byte S;
diff --git a/OpenRA.Game/Scripting/ScriptTypes.cs b/OpenRA.Game/Scripting/ScriptTypes.cs
index dd5ec8fe20..14a792b7f6 100644
--- a/OpenRA.Game/Scripting/ScriptTypes.cs
+++ b/OpenRA.Game/Scripting/ScriptTypes.cs
@@ -37,6 +37,12 @@ namespace OpenRA.Scripting
{
object temp;
+ // Is t a nullable?
+ // If yes, get the underlying type
+ var nullable = Nullable.GetUnderlyingType(t);
+ if (nullable != null)
+ t = nullable;
+
// Value wraps a CLR object
if (value.TryGetClrObject(out temp))
{
diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
index f26d16d56b..4049908978 100644
--- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
+++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj
@@ -176,6 +176,8 @@
+
+
diff --git a/OpenRA.Mods.Common/Scripting/Global/HSLColorGlobal.cs b/OpenRA.Mods.Common/Scripting/Global/HSLColorGlobal.cs
new file mode 100644
index 0000000000..5328f62c2f
--- /dev/null
+++ b/OpenRA.Mods.Common/Scripting/Global/HSLColorGlobal.cs
@@ -0,0 +1,32 @@
+#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 OpenRA.Graphics;
+using OpenRA.Scripting;
+
+namespace OpenRA.Mods.Common.Scripting.Global
+{
+ [ScriptGlobal("HSLColor")]
+ public class HSLColorGlobal : ScriptGlobal
+ {
+ public HSLColorGlobal(ScriptContext context)
+ : base(context) { }
+
+ [Desc("Create a new HSL color with the specified hue/saturation/luminosity.")]
+ public HSLColor New(int hue, int saturation, int luminosity)
+ {
+ var h = (byte)hue.Clamp(0, 255);
+ var s = (byte)saturation.Clamp(0, 255);
+ var l = (byte)luminosity.Clamp(0, 255);
+
+ return new HSLColor(h, s, l);
+ }
+ }
+}
diff --git a/OpenRA.Mods.Common/Scripting/Global/MediaGlobal.cs b/OpenRA.Mods.Common/Scripting/Global/MediaGlobal.cs
index bf181b30eb..5d476640df 100644
--- a/OpenRA.Mods.Common/Scripting/Global/MediaGlobal.cs
+++ b/OpenRA.Mods.Common/Scripting/Global/MediaGlobal.cs
@@ -17,6 +17,7 @@ using OpenRA.Effects;
using OpenRA.FileFormats;
using OpenRA.FileSystem;
using OpenRA.GameRules;
+using OpenRA.Graphics;
using OpenRA.Mods.Common.Effects;
using OpenRA.Scripting;
@@ -168,24 +169,24 @@ namespace OpenRA.Mods.Common.Scripting
}
[Desc("Display a text message to the player.")]
- public void DisplayMessage(string text, string prefix = "Mission")
+ public void DisplayMessage(string text, string prefix = "Mission", HSLColor? color = null)
{
if (string.IsNullOrEmpty(text))
return;
- Color c = Color.White;
+ Color c = color.HasValue ? HSLColor.RGBFromHSL(color.Value.H / 255f, color.Value.S / 255f, color.Value.L / 255f) : Color.White;
Game.AddChatLine(c, prefix, text);
- } // TODO: expose HSLColor to Lua and add as parameter
+ }
[Desc("Display a text message at the specified location.")]
- public void FloatingText(string text, WPos position, int duration = 30)
+ public void FloatingText(string text, WPos position, int duration = 30, HSLColor? color = null)
{
if (string.IsNullOrEmpty(text) || !world.Map.Contains(world.Map.CellContaining(position)))
return;
- Color c = Color.White;
+ Color c = color.HasValue ? HSLColor.RGBFromHSL(color.Value.H / 255f, color.Value.S / 255f, color.Value.L / 255f) : Color.White;
world.AddFrameEndTask(w => w.Add(new FloatingText(position, c, text, duration)));
- } // TODO: expose HSLColor to Lua and add as parameter
+ }
public delegate VqaReader AsyncLoader(Stream s);
}
diff --git a/OpenRA.Mods.Common/Scripting/Global/UserInterfaceGlobal.cs b/OpenRA.Mods.Common/Scripting/Global/UserInterfaceGlobal.cs
new file mode 100644
index 0000000000..2c7bee9744
--- /dev/null
+++ b/OpenRA.Mods.Common/Scripting/Global/UserInterfaceGlobal.cs
@@ -0,0 +1,35 @@
+#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.Drawing;
+using OpenRA.Graphics;
+using OpenRA.Mods.Common.Widgets;
+using OpenRA.Scripting;
+using OpenRA.Widgets;
+
+namespace OpenRA.Mods.Common.Scripting.Global
+{
+ [ScriptGlobal("UserInterface")]
+ public class UserInterfaceGlobal : ScriptGlobal
+ {
+ public UserInterfaceGlobal(ScriptContext context)
+ : base(context) { }
+
+ [Desc("Displays a text message at the top center of the screen.")]
+ public void SetMissionText(string text, HSLColor? color = null)
+ {
+ var luaLabel = Ui.Root.Get("INGAME_ROOT").Get("MISSION_TEXT");
+ luaLabel.GetText = () => text;
+
+ Color c = color.HasValue ? HSLColor.RGBFromHSL(color.Value.H / 255f, color.Value.S / 255f, color.Value.L / 255f) : Color.White;
+ luaLabel.GetColor = () => c;
+ }
+ }
+}
diff --git a/mods/cnc/chrome/ingame.yaml b/mods/cnc/chrome/ingame.yaml
index 4c9d25a42b..e890e2ee6a 100644
--- a/mods/cnc/chrome/ingame.yaml
+++ b/mods/cnc/chrome/ingame.yaml
@@ -39,6 +39,14 @@ Container@INGAME_ROOT:
Container@PLAYER_ROOT:
Container@MENU_ROOT:
TooltipContainer@TOOLTIP_CONTAINER:
+ Label@MISSION_TEXT:
+ X: WINDOW_RIGHT/2 - 256
+ Y: 22
+ Width: 512
+ Height: 25
+ Font: Bold
+ Align: Center
+ Contrast: true
Container@PERF_WIDGETS:
Logic: PerfDebugLogic
diff --git a/mods/d2k/chrome/ingame.yaml b/mods/d2k/chrome/ingame.yaml
index e8e2bc69bd..dab27e3ff6 100644
--- a/mods/d2k/chrome/ingame.yaml
+++ b/mods/d2k/chrome/ingame.yaml
@@ -46,3 +46,11 @@ Container@INGAME_ROOT:
Contrast: true
Container@MENU_ROOT:
TooltipContainer@TOOLTIP_CONTAINER:
+ Label@MISSION_TEXT:
+ X: WINDOW_RIGHT/2 - 256
+ Y: 22
+ Width: 512
+ Height: 25
+ Font: Bold
+ Align: Center
+ Contrast: true
diff --git a/mods/ra/chrome/ingame.yaml b/mods/ra/chrome/ingame.yaml
index 89cc43c27f..2d5d659857 100644
--- a/mods/ra/chrome/ingame.yaml
+++ b/mods/ra/chrome/ingame.yaml
@@ -27,3 +27,11 @@ Container@INGAME_ROOT:
Container@PERF_ROOT:
Container@MENU_ROOT:
TooltipContainer@TOOLTIP_CONTAINER:
+ Label@MISSION_TEXT:
+ X: WINDOW_RIGHT/2 - 256
+ Y: 22
+ Width: 512
+ Height: 25
+ Font: Bold
+ Align: Center
+ Contrast: true
diff --git a/mods/ra/maps/survival02/map.yaml b/mods/ra/maps/survival02/map.yaml
index 17cc3b2c60..df2d7cf706 100644
--- a/mods/ra/maps/survival02/map.yaml
+++ b/mods/ra/maps/survival02/map.yaml
@@ -1017,9 +1017,6 @@ Actors:
AlliesBase: waypoint
Location: 39,37
Owner: Neutral
- Timer: MissionTimer
- Location: 5,5
- Owner: Soviets
Smudges:
@@ -1070,11 +1067,6 @@ Rules:
DropItems: E1,E1,E2,E4,E4,E1,E1,E2,E4,E4
QuantizedFacings: 8
DisplayBeacon: false
- MissionTimer:
- ParatroopersPower:
- ChargeTime: 600
- Description: Soviet reinforcements arrive in
- DisplayTimer: True
MINV:
Mine:
AvoidFriendly: yes
diff --git a/mods/ra/maps/survival02/survival02.lua b/mods/ra/maps/survival02/survival02.lua
index 7e6ec0260b..239b771ecc 100644
--- a/mods/ra/maps/survival02/survival02.lua
+++ b/mods/ra/maps/survival02/survival02.lua
@@ -62,6 +62,7 @@ GuardHarvester = function(unit, harvester)
end
end
+ticked = TimerTicks
Tick = function()
if soviets.HasNoRequiredUnits() then
if DestroyObj then
@@ -98,10 +99,18 @@ Tick = function()
end
end
- if DateTime.Minutes(5) == TimerTicks - DateTime.GameTime then
+ if DateTime.Minutes(5) == ticked then
Media.PlaySpeechNotification(allies, "WarningFiveMinutesRemaining")
InitCountDown()
end
+
+ if 0 < ticked then
+ UserInterface.SetMissionText("Soviet reinforcements arrive in " .. Utils.FormatTime(ticked), TimerColor)
+ ticked = ticked - 1
+ elseif 0 == ticked then
+ FinishTimer()
+ ticked = ticked - 1
+ end
end
SendSovietParadrops = function(table)
@@ -195,6 +204,18 @@ FinalAttack = function()
end)
end
+FinishTimer = function()
+ for i = 0, 9, 1 do
+ local c = TimerColor
+ if i % 2 == 0 then
+ c = HSLColor.New(255, 255, 255)
+ end
+
+ Trigger.AfterDelay(DateTime.Seconds(i), function() UserInterface.SetMissionText("Soviet reinforcements have arrived!", c) end)
+ end
+ Trigger.AfterDelay(DateTime.Seconds(10), function() UserInterface.SetMissionText("") end)
+end
+
wave = 1
SendParadrops = function()
SendSovietParadrops(ParaWaves[wave][2])
@@ -277,6 +298,7 @@ end
InitMission = function()
Camera.Position = AlliesBase.CenterPosition
+ TimerColor = HSLColor.New(0, 255, 128)
Trigger.AfterDelay(DateTime.Seconds(1), function() Media.PlaySpeechNotification(allies, "MissionTimerInitialised") end)
@@ -286,7 +308,6 @@ InitMission = function()
SpawnSovietVehicle(NewSovietEntryPoints, NewSovietRallyPoints)
FinalAttack()
Producing = false
- Timer.Destroy()
end)
Trigger.AfterDelay(AttackTicks, SendParadrops)