Add scripting support for TimeLimitManager

This commit is contained in:
Oliver Brakmann
2019-01-26 19:28:52 +01:00
committed by abcdefg30
parent 47d88983fb
commit 26d712728a
4 changed files with 101 additions and 5 deletions

View File

@@ -10,6 +10,8 @@
#endregion #endregion
using System; using System;
using Eluant;
using OpenRA.Mods.Common.Traits;
using OpenRA.Scripting; using OpenRA.Scripting;
namespace OpenRA.Mods.Common.Scripting namespace OpenRA.Mods.Common.Scripting
@@ -17,8 +19,13 @@ namespace OpenRA.Mods.Common.Scripting
[ScriptGlobal("DateTime")] [ScriptGlobal("DateTime")]
public class DateGlobal : ScriptGlobal public class DateGlobal : ScriptGlobal
{ {
readonly TimeLimitManager tlm;
public DateGlobal(ScriptContext context) public DateGlobal(ScriptContext context)
: base(context) { } : base(context)
{
tlm = context.World.WorldActor.TraitOrDefault<TimeLimitManager>();
}
[Desc("True on the 31st of October.")] [Desc("True on the 31st of October.")]
public bool IsHalloween public bool IsHalloween
@@ -43,5 +50,39 @@ namespace OpenRA.Mods.Common.Scripting
{ {
return Seconds(minutes * 60); return Seconds(minutes * 60);
} }
[Desc("Return or set the time limit (in ticks). When setting, the time limit will count from now. Setting the time limit to 0 will disable it.")]
public int TimeLimit
{
get
{
return tlm != null ? tlm.TimeLimit : 0;
}
set
{
if (tlm != null)
tlm.TimeLimit = value == 0 ? 0 : value + GameTime;
else
throw new LuaException("Cannot set TimeLimit, TimeLimitManager trait is missing.");
}
}
[Desc("The notification string used for custom time limit warnings. See the TimeLimitManager trait documentation for details.")]
public string TimeLimitNotification
{
get
{
return tlm != null ? tlm.Notification : null;
}
set
{
if (tlm != null)
tlm.Notification = value;
else
throw new LuaException("Cannot set TimeLimitNotification, TimeLimitManager trait is missing.");
}
}
} }
} }

View File

@@ -470,6 +470,12 @@ namespace OpenRA.Mods.Common.Scripting
GetScriptTriggers(a).RegisterCallback(Trigger.OnSold, func, Context); GetScriptTriggers(a).RegisterCallback(Trigger.OnSold, func, Context);
} }
[Desc("Call a function when the game timer expires. The callback function will be called as func().")]
public void OnTimerExpired(LuaFunction func)
{
GetScriptTriggers(Context.World.WorldActor).RegisterCallback(Trigger.OnTimerExpired, func, Context);
}
[Desc("Removes all triggers from this actor. " + [Desc("Removes all triggers from this actor. " +
"Note that the removal will only take effect at the end of a tick, " + "Note that the removal will only take effect at the end of a tick, " +
"so you must not add new triggers at the same time that you are calling this function.")] "so you must not add new triggers at the same time that you are calling this function.")]

View File

@@ -24,7 +24,7 @@ namespace OpenRA.Mods.Common.Scripting
OnIdle, OnDamaged, OnKilled, OnProduction, OnOtherProduction, OnPlayerWon, OnPlayerLost, OnIdle, OnDamaged, OnKilled, OnProduction, OnOtherProduction, OnPlayerWon, OnPlayerLost,
OnObjectiveAdded, OnObjectiveCompleted, OnObjectiveFailed, OnCapture, OnInfiltrated, OnObjectiveAdded, OnObjectiveCompleted, OnObjectiveFailed, OnCapture, OnInfiltrated,
OnAddedToWorld, OnRemovedFromWorld, OnDiscovered, OnPlayerDiscovered, OnAddedToWorld, OnRemovedFromWorld, OnDiscovered, OnPlayerDiscovered,
OnPassengerEntered, OnPassengerExited, OnSold OnPassengerEntered, OnPassengerExited, OnSold, OnTimerExpired
} }
[Desc("Allows map scripts to attach triggers to this actor via the Triggers global.")] [Desc("Allows map scripts to attach triggers to this actor via the Triggers global.")]
@@ -35,7 +35,7 @@ namespace OpenRA.Mods.Common.Scripting
public sealed class ScriptTriggers : INotifyIdle, INotifyDamage, INotifyKilled, INotifyProduction, INotifyOtherProduction, public sealed class ScriptTriggers : INotifyIdle, INotifyDamage, INotifyKilled, INotifyProduction, INotifyOtherProduction,
INotifyObjectivesUpdated, INotifyCapture, INotifyInfiltrated, INotifyAddedToWorld, INotifyRemovedFromWorld, INotifyDiscovered, INotifyActorDisposing, INotifyObjectivesUpdated, INotifyCapture, INotifyInfiltrated, INotifyAddedToWorld, INotifyRemovedFromWorld, INotifyDiscovered, INotifyActorDisposing,
INotifyPassengerEntered, INotifyPassengerExited, INotifySold, INotifyWinStateChanged INotifyPassengerEntered, INotifyPassengerExited, INotifySold, INotifyWinStateChanged, INotifyTimeLimit
{ {
readonly World world; readonly World world;
readonly Actor self; readonly Actor self;
@@ -493,6 +493,25 @@ namespace OpenRA.Mods.Common.Scripting
} }
} }
void INotifyTimeLimit.NotifyTimerExpired(Actor self)
{
if (world.Disposing)
return;
foreach (var f in Triggerables(Trigger.OnTimerExpired))
{
try
{
f.Function.Call().Dispose();
}
catch (Exception ex)
{
f.Context.FatalError(ex.Message);
return;
}
}
}
public void Clear(Trigger trigger) public void Clear(Trigger trigger)
{ {
world.AddFrameEndTask(w => world.AddFrameEndTask(w =>

View File

@@ -12,8 +12,10 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using OpenRA.Mods.Common.Widgets;
using OpenRA.Primitives; using OpenRA.Primitives;
using OpenRA.Traits; using OpenRA.Traits;
using OpenRA.Widgets;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
{ {
@@ -55,6 +57,18 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Notification text for time limit warnings. The string '{0}' will be replaced by the remaining time in minutes, '{1}' is used for the plural form.")] [Desc("Notification text for time limit warnings. The string '{0}' will be replaced by the remaining time in minutes, '{1}' is used for the plural form.")]
public readonly string Notification = "{0} minute{1} remaining."; public readonly string Notification = "{0} minute{1} remaining.";
[Desc("ID of the LabelWidget used to display a text ingame that will be updated every second.")]
public readonly string CountdownLabel = null;
[Desc("Text to be shown using the CountdownLabel. The string '{0}' will be replaced by the time in hh:mm:ss format.")]
public readonly string CountdownText = null;
[Desc("Will prevent showing/playing the built-in time limit warnings when set to true.")]
public readonly bool SkipTimeRemainingNotifications = false;
[Desc("Will prevent showing/playing the built-in timer expired notification when set to true.")]
public readonly bool SkipTimerExpiredNotification = false;
IEnumerable<LobbyOption> ILobbyOptions.LobbyOptions(Ruleset rules) IEnumerable<LobbyOption> ILobbyOptions.LobbyOptions(Ruleset rules)
{ {
var timelimits = TimeLimitOptions.ToDictionary(c => c.ToString(), c => var timelimits = TimeLimitOptions.ToDictionary(c => c.ToString(), c =>
@@ -76,6 +90,8 @@ namespace OpenRA.Mods.Common.Traits
{ {
readonly TimeLimitManagerInfo info; readonly TimeLimitManagerInfo info;
MapOptions mapOptions; MapOptions mapOptions;
LabelWidget countdownLabel;
CachedTransform<int, string> countdown;
int ticksRemaining; int ticksRemaining;
public int TimeLimit; public int TimeLimit;
@@ -97,6 +113,16 @@ namespace OpenRA.Mods.Common.Traits
void IWorldLoaded.WorldLoaded(World w, OpenRA.Graphics.WorldRenderer wr) void IWorldLoaded.WorldLoaded(World w, OpenRA.Graphics.WorldRenderer wr)
{ {
mapOptions = w.WorldActor.Trait<MapOptions>(); mapOptions = w.WorldActor.Trait<MapOptions>();
if (string.IsNullOrWhiteSpace(info.CountdownLabel) || string.IsNullOrWhiteSpace(info.CountdownText))
return;
countdownLabel = Ui.Root.GetOrNull<LabelWidget>(info.CountdownLabel);
if (countdownLabel != null)
{
countdown = new CachedTransform<int, string>(t =>
info.CountdownText.F(WidgetUtils.FormatTime(t, true, w.IsReplay ? mapOptions.GameSpeed.Timestep : w.Timestep)));
countdownLabel.GetText = () => countdown.Update(ticksRemaining);
}
} }
void ITick.Tick(Actor self) void ITick.Tick(Actor self)
@@ -119,7 +145,7 @@ namespace OpenRA.Mods.Common.Traits
return; return;
} }
if (ticksRemaining < 0) if (ticksRemaining < 0 || info.SkipTimeRemainingNotifications)
return; return;
foreach (var m in info.TimeLimitWarnings.Keys) foreach (var m in info.TimeLimitWarnings.Keys)
@@ -136,7 +162,11 @@ namespace OpenRA.Mods.Common.Traits
void INotifyTimeLimit.NotifyTimerExpired(Actor self) void INotifyTimeLimit.NotifyTimerExpired(Actor self)
{ {
Game.AddSystemLine("Battlefield Control", "Time limit has expired."); if (countdownLabel != null)
countdownLabel.GetText = () => null;
if (!info.SkipTimerExpiredNotification)
Game.AddSystemLine("Battlefield Control", "Time limit has expired.");
} }
} }
} }