diff --git a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj index e2987960d4..84ed13657c 100644 --- a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj +++ b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj @@ -515,7 +515,7 @@ - + @@ -586,4 +586,4 @@ copy "FuzzyLogicLibrary.dll" "$(SolutionDir)" cd "$(SolutionDir)" - \ No newline at end of file + diff --git a/OpenRA.Mods.RA/Scripting/Global/DateGlobal.cs b/OpenRA.Mods.RA/Scripting/Global/DateTimeGlobal.cs similarity index 66% rename from OpenRA.Mods.RA/Scripting/Global/DateGlobal.cs rename to OpenRA.Mods.RA/Scripting/Global/DateTimeGlobal.cs index e93919bcf6..c87e7239d2 100644 --- a/OpenRA.Mods.RA/Scripting/Global/DateGlobal.cs +++ b/OpenRA.Mods.RA/Scripting/Global/DateTimeGlobal.cs @@ -17,7 +17,8 @@ namespace OpenRA.Mods.RA.Scripting [ScriptGlobal("Date")] public class DateGlobal : ScriptGlobal { - public DateGlobal(ScriptContext context) : base(context) { } + public DateGlobal(ScriptContext context) + : base(context) { } [Desc("True on the 31st of October.")] public bool IsHalloween @@ -25,4 +26,17 @@ namespace OpenRA.Mods.RA.Scripting get { return DateTime.Today.Month == 10 && DateTime.Today.Day == 31; } } } + + [ScriptGlobal("Time")] + public class TimeGlobal : ScriptGlobal + { + public TimeGlobal(ScriptContext context) + : base(context) { } + + [Desc("Get the current game time (in ticks)")] + public int GameTime + { + get { return context.World.WorldTick; } + } + } } diff --git a/OpenRA.Mods.RA/Scripting/Properties/CombatProperties.cs b/OpenRA.Mods.RA/Scripting/Properties/CombatProperties.cs index 382599b41d..6f864728e8 100644 --- a/OpenRA.Mods.RA/Scripting/Properties/CombatProperties.cs +++ b/OpenRA.Mods.RA/Scripting/Properties/CombatProperties.cs @@ -8,6 +8,9 @@ */ #endregion +using Eluant; +using System; +using System.Linq; using OpenRA.Mods.RA.Activities; using OpenRA.Scripting; using OpenRA.Traits; @@ -17,8 +20,13 @@ namespace OpenRA.Mods.RA.Scripting [ScriptPropertyGroup("Combat")] public class CombatProperties : ScriptActorProperties, Requires, Requires { + readonly IMove move; + public CombatProperties(ScriptContext context, Actor self) - : base(context, self) { } + : base(context, self) + { + move = self.Trait(); + } [ScriptActorPropertyActivity] [Desc("Seek out and attack nearby targets.")] @@ -33,11 +41,35 @@ namespace OpenRA.Mods.RA.Scripting "close enough to complete the activity.")] public void AttackMove(CPos cell, int closeEnough = 0) { - var move = self.TraitOrDefault(); - if (move == null) - return; - self.QueueActivity(new AttackMove.AttackMoveActivity(self, move.MoveTo(cell, closeEnough))); } + + [ScriptActorPropertyActivity] + [Desc("Patrol along a set of given waypoints. The action is repeated by default, " + + "and the actor will wait for `wait` ticks at each waypoint.")] + public void Patrol(CPos[] waypoints, bool loop = true, int wait = 0) + { + foreach (var wpt in waypoints) + { + self.QueueActivity(new AttackMove.AttackMoveActivity(self, move.MoveTo(wpt, 2))); + self.QueueActivity(new Wait(wait)); + } + + if (loop) + self.QueueActivity(new CallFunc(() => Patrol(waypoints, loop, wait))); + } + + [ScriptActorPropertyActivity] + [Desc("Patrol along a set of given waypoints until a condition becomes true. " + + "The actor will wait for `wait` ticks at each waypoint.")] + public void PatrolUntil(CPos[] waypoints, LuaFunction func, int wait = 0) + { + Patrol(waypoints, false, wait); + + var repeat = func.Call(self.ToLuaValue(context)).First().ToBoolean(); + if (repeat) + using (var f = func.CopyReference() as LuaFunction) + self.QueueActivity(new CallFunc(() => PatrolUntil(waypoints, f, wait))); + } } } diff --git a/OpenRA.Mods.RA/Scripting/Properties/HealthProperties.cs b/OpenRA.Mods.RA/Scripting/Properties/HealthProperties.cs index c11867ff9e..0143f33983 100644 --- a/OpenRA.Mods.RA/Scripting/Properties/HealthProperties.cs +++ b/OpenRA.Mods.RA/Scripting/Properties/HealthProperties.cs @@ -8,6 +8,7 @@ */ #endregion +using OpenRA.Mods.RA.Buildings; using OpenRA.Scripting; using OpenRA.Traits; @@ -33,4 +34,34 @@ namespace OpenRA.Mods.RA.Scripting [Desc("Maximum health of the actor.")] public int MaxHealth { get { return health.MaxHP; } } } + + [ScriptPropertyGroup("General")] + public class RepairableBuildingProperties : ScriptActorProperties, Requires + { + readonly RepairableBuilding rb; + + public RepairableBuildingProperties(ScriptContext context, Actor self) + : base(context, self) + { + rb = self.Trait(); + } + + [Desc("Start repairs on this building. `repairer` can be an allied player.")] + public void StartBuildingRepairs(Player repairer = null) + { + repairer = repairer ?? self.Owner; + + if (!rb.Repairers.Contains(repairer)) + rb.RepairBuilding(self, repairer); + } + + [Desc("Stop repairs on this building. `repairer` can be an allied player.")] + public void StopBuildingRepairs(Player repairer = null) + { + repairer = repairer ?? self.Owner; + + if (rb.RepairActive && rb.Repairers.Contains(repairer)) + rb.RepairBuilding(self, repairer); + } + } } \ No newline at end of file diff --git a/OpenRA.Mods.RA/Scripting/Properties/PlaneProperties.cs b/OpenRA.Mods.RA/Scripting/Properties/PlaneProperties.cs index 0624c42e47..d56e8211eb 100644 --- a/OpenRA.Mods.RA/Scripting/Properties/PlaneProperties.cs +++ b/OpenRA.Mods.RA/Scripting/Properties/PlaneProperties.cs @@ -27,4 +27,17 @@ namespace OpenRA.Mods.RA.Scripting self.QueueActivity(new Fly(self, Target.FromCell(self.World, cell))); } } + + [ScriptPropertyGroup("Combat")] + public class PlaneCombatProperties : ScriptActorProperties, Requires + { + public PlaneCombatProperties(ScriptContext context, Actor self) + : base(context, self) { } + + [Desc("Fly an attack against the target actor.")] + public void Attack(Actor target) + { + self.QueueActivity(new FlyAttack(Target.FromActor(target))); + } + } } \ No newline at end of file