From 867ebcec3bc55a25b3ae3616d72d0f4c0c8e325c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Mail=C3=A4nder?= Date: Sun, 31 Aug 2014 10:48:22 +0200 Subject: [PATCH] port allies-01 to new Lua API --- OpenRA.Mods.RA/OpenRA.Mods.RA.csproj | 3 + .../Scripting/Global/TriggerGlobal.cs | 32 +++ .../Properties/HarvesterProperties.cs | 34 +++ .../Properties/HelicopterProperties.cs | 30 +++ .../Scripting/Properties/MobileProperties.cs | 7 + .../Scripting/Properties/PlaneProperties.cs | 30 +++ .../Logic/Ingame/GameInfoObjectivesLogic.cs | 2 +- mods/ra/maps/allies-01-classic/allies01.lua | 247 +++++++++++------- mods/ra/maps/allies-01-classic/map.yaml | 7 +- mods/ra/notifications.yaml | 10 +- 10 files changed, 300 insertions(+), 102 deletions(-) create mode 100644 OpenRA.Mods.RA/Scripting/Properties/HarvesterProperties.cs create mode 100644 OpenRA.Mods.RA/Scripting/Properties/HelicopterProperties.cs create mode 100644 OpenRA.Mods.RA/Scripting/Properties/PlaneProperties.cs diff --git a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj index 7ac2c43d87..1401a4b0a2 100644 --- a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj +++ b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj @@ -561,6 +561,9 @@ + + + diff --git a/OpenRA.Mods.RA/Scripting/Global/TriggerGlobal.cs b/OpenRA.Mods.RA/Scripting/Global/TriggerGlobal.cs index 4e00d39da9..ecf93f3a89 100644 --- a/OpenRA.Mods.RA/Scripting/Global/TriggerGlobal.cs +++ b/OpenRA.Mods.RA/Scripting/Global/TriggerGlobal.cs @@ -102,6 +102,38 @@ namespace OpenRA.Mods.RA.Scripting GetScriptTriggers(a).OnKilledInternal += OnMemberKilled; } + [Desc("Call a function when one of the actors in a group is killed. The callback " + + "function will be called as func(Actor killed).")] + public void OnAnyKilled(LuaTable actors, LuaFunction func) + { + var group = new List(); + foreach (var kv in actors) + { + Actor actor; + if (!kv.Value.TryGetClrValue(out actor)) + throw new LuaException("OnAnyKilled requires a table of int,Actor pairs. Recieved {0},{1}".F(kv.Key.GetType().Name, kv.Value.GetType().Name)); + + group.Add(actor); + } + + var called = false; + var copy = (LuaFunction)func.CopyReference(); + Action OnMemberKilled = m => + { + if (called) + return; + + using (var killed = m.ToLuaValue(context)) + copy.Call(killed).Dispose(); + + copy.Dispose(); + called = true; + }; + + foreach (var a in group) + GetScriptTriggers(a).OnKilledInternal += OnMemberKilled; + } + [Desc("Call a function when this actor produces another actor. " + "The callback function will be called as func(Actor producer, Actor produced).")] public void OnProduction(Actor a, LuaFunction func) diff --git a/OpenRA.Mods.RA/Scripting/Properties/HarvesterProperties.cs b/OpenRA.Mods.RA/Scripting/Properties/HarvesterProperties.cs new file mode 100644 index 0000000000..3bc19c8c49 --- /dev/null +++ b/OpenRA.Mods.RA/Scripting/Properties/HarvesterProperties.cs @@ -0,0 +1,34 @@ +#region Copyright & License Information +/* + * Copyright 2007-2014 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.Scripting; +using OpenRA.Traits; + +namespace OpenRA.Mods.RA.Scripting +{ + [ScriptPropertyGroup("Harvester")] + public class HarvesterProperties : ScriptActorProperties, Requires + { + readonly Harvester harvester; + + public HarvesterProperties(ScriptContext context, Actor self) + : base(context, self) + { + harvester = self.Trait(); + } + + [ScriptActorPropertyActivity] + [Desc("Search for nearby resources and begin harvesting.")] + public void FindResources() + { + harvester.ContinueHarvesting(self); + } + } +} \ No newline at end of file diff --git a/OpenRA.Mods.RA/Scripting/Properties/HelicopterProperties.cs b/OpenRA.Mods.RA/Scripting/Properties/HelicopterProperties.cs new file mode 100644 index 0000000000..4095939090 --- /dev/null +++ b/OpenRA.Mods.RA/Scripting/Properties/HelicopterProperties.cs @@ -0,0 +1,30 @@ +#region Copyright & License Information +/* + * Copyright 2007-2014 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.Mods.RA.Air; +using OpenRA.Scripting; +using OpenRA.Traits; + +namespace OpenRA.Mods.RA.Scripting +{ + [ScriptPropertyGroup("Movement")] + public class HelicopterProperties : ScriptActorProperties, Requires + { + public HelicopterProperties(ScriptContext context, Actor self) + : base(context, self) { } + + [ScriptActorPropertyActivity] + [Desc("Fly within the cell grid.")] + public void Move(CPos cell) + { + self.QueueActivity(new HeliFly(self, Target.FromCell(self.World, cell))); + } + } +} \ No newline at end of file diff --git a/OpenRA.Mods.RA/Scripting/Properties/MobileProperties.cs b/OpenRA.Mods.RA/Scripting/Properties/MobileProperties.cs index 511aad91ff..e404255aa3 100644 --- a/OpenRA.Mods.RA/Scripting/Properties/MobileProperties.cs +++ b/OpenRA.Mods.RA/Scripting/Properties/MobileProperties.cs @@ -34,5 +34,12 @@ namespace OpenRA.Mods.RA.Scripting { self.QueueActivity(new Move.Move(cell)); } + + [ScriptActorPropertyActivity] + [Desc("Leave the current position in a random direction.")] + public void Scatter() + { + self.Trait().Nudge(self, self, true); + } } } \ No newline at end of file diff --git a/OpenRA.Mods.RA/Scripting/Properties/PlaneProperties.cs b/OpenRA.Mods.RA/Scripting/Properties/PlaneProperties.cs new file mode 100644 index 0000000000..0624c42e47 --- /dev/null +++ b/OpenRA.Mods.RA/Scripting/Properties/PlaneProperties.cs @@ -0,0 +1,30 @@ +#region Copyright & License Information +/* + * Copyright 2007-2014 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.Mods.RA.Air; +using OpenRA.Scripting; +using OpenRA.Traits; + +namespace OpenRA.Mods.RA.Scripting +{ + [ScriptPropertyGroup("Movement")] + public class PlaneProperties : ScriptActorProperties, Requires + { + public PlaneProperties(ScriptContext context, Actor self) + : base(context, self) { } + + [ScriptActorPropertyActivity] + [Desc("Fly within the cell grid.")] + public void Move(CPos cell) + { + self.QueueActivity(new Fly(self, Target.FromCell(self.World, cell))); + } + } +} \ No newline at end of file diff --git a/OpenRA.Mods.RA/Widgets/Logic/Ingame/GameInfoObjectivesLogic.cs b/OpenRA.Mods.RA/Widgets/Logic/Ingame/GameInfoObjectivesLogic.cs index b167a47f60..42451119e5 100644 --- a/OpenRA.Mods.RA/Widgets/Logic/Ingame/GameInfoObjectivesLogic.cs +++ b/OpenRA.Mods.RA/Widgets/Logic/Ingame/GameInfoObjectivesLogic.cs @@ -67,6 +67,6 @@ namespace OpenRA.Mods.RA.Widgets.Logic parent.AddChild(widget); } - } + } } } \ No newline at end of file diff --git a/mods/ra/maps/allies-01-classic/allies01.lua b/mods/ra/maps/allies-01-classic/allies01.lua index d9fbed7ae5..cc7de33d70 100644 --- a/mods/ra/maps/allies-01-classic/allies01.lua +++ b/mods/ra/maps/allies-01-classic/allies01.lua @@ -1,151 +1,202 @@ InsertionHelicopterType = "tran.insertion" +InsertionPath = { InsertionEntry.Location, InsertionLZ.Location } ExtractionHelicopterType = "tran.extraction" +ExtractionPath = { SouthReinforcementsPoint.Location, ExtractionLZ.Location } JeepReinforcements = { "jeep", "jeep" } -JeepInterval = 50 -JeepDelay = 125 -TanyaType = "e7" +TanyaReinforcements = { "e7" } EinsteinType = "einstein" FlareType = "flare" -Cruisers = { "ca", "ca", "ca", "ca" } -CruiserDelay = 250 -CameraDelay = 125 -CivilianWait = 150 -BaseAlertDelay = 300 +CruisersReinforcements = { "ca", "ca", "ca", "ca" } SendInsertionHelicopter = function() - local heli, passengers = Reinforcements.Insert(player, InsertionHelicopterType, { TanyaType }, - { InsertionEntry.Location, InsertionLZ.Location }, { InsertionEntry.Location }) - tanya = passengers[1] - Actor.OnKilled(tanya, TanyaKilled) + local passengers = Reinforcements.ReinforceWithTransport(player, InsertionHelicopterType, + TanyaReinforcements, InsertionPath, { InsertionEntry.Location })[2] + local tanya = passengers[1] + Trigger.OnKilled(tanya, RescueFailed) + tanya.Stance = "HoldFire" end SendJeeps = function() - Media.PlaySpeechNotification("ReinforcementsArrived") - Reinforcements.Reinforce(player, JeepReinforcements, InsertionEntry.Location, InsertionLZ.Location, JeepInterval) + Reinforcements.Reinforce(player, JeepReinforcements, InsertionPath, Utils.Seconds(2)) + Media.PlaySpeechNotification(player, "ReinforcementsArrived") end RunInitialActivities = function() SendInsertionHelicopter() - Actor.Hunt(Patrol1) - Actor.Hunt(Patrol2) - Actor.Hunt(Patrol3) - Actor.Hunt(Patrol4) - Actor.Harvest(Harvester) - Team.Do(civiliansTeam, function(c) - Actor.Wait(c, CivilianWait) - Actor.Hunt(c) - end) + Patrol1.Hunt() + Patrol2.Hunt() + Patrol3.Hunt() + Patrol4.Hunt() + Harvester.FindResources() + Civilian1.Wait(Utils.Seconds(6)) + Civilian2.Wait(Utils.Seconds(6)) + Civilian1.Hunt() + Civilian2.Hunt() end LabGuardsKilled = function() CreateEinstein() - - Actor.Create(FlareType, { Owner = england, Location = ExtractionFlarePoint.Location }) - Media.PlaySpeechNotification("SignalFlareNorth") - SendExtractionHelicopter() - - OpenRA.RunAfterDelay(BaseAlertDelay, function() - local ussrUnits = Mission.GetGroundAttackersOf(ussr) - for i, unit in ipairs(ussrUnits) do - Actor.Hunt(unit) - end + + Trigger.AfterDelay(Utils.Seconds(2), function() + Actor.Create(FlareType, true, { Owner = england, Location = ExtractionFlarePoint.Location }) + Media.PlaySpeechNotification(player, "SignalFlareNorth") + SendExtractionHelicopter() end) - - OpenRA.RunAfterDelay(CruiserDelay, function() - Media.PlaySpeechNotification("AlliedReinforcementsArrived") - Actor.Create("camera", { Owner = player, Location = CruiserCameraPoint.Location }) + + Trigger.AfterDelay(Utils.Seconds(10), function() + Media.PlaySpeechNotification(player, "AlliedReinforcementsArrived") + Actor.Create("camera", true, { Owner = player, Location = CruiserCameraPoint.Location }) SendCruisers() end) + + Trigger.AfterDelay(Utils.Seconds(12), function() + for i = 0, 2 do + Trigger.AfterDelay(Utils.Seconds(i), function() + Media.PlaySoundNotification(player, "AlertBuzzer") + end) + end + Utils.Do(sovietArmy, function(a) + if not a.IsDead and a.HasProperty("Hunt") then + Trigger.OnIdle(a, a.Hunt) + end + end) + end) end SendExtractionHelicopter = function() - local heli = Reinforcements.Extract(player, ExtractionHelicopterType, { einstein }, - { SouthReinforcementsPoint.Location, ExtractionLZ.Location }, { ExtractionExitPoint.Location }) - Actor.OnKilled(heli, HelicopterDestroyed) - Actor.OnRemovedFromWorld(heli, HelicopterExtractionCompleted) + heli = Reinforcements.ReinforceWithTransport(player, ExtractionHelicopterType, nil, ExtractionPath)[1] + if not einstein.IsDead then + Trigger.OnRemovedFromWorld(einstein, EvacuateHelicopter) + end + Trigger.OnKilled(heli, RescueFailed) + Trigger.OnRemovedFromWorld(heli, HelicopterGone) end -HelicopterExtractionCompleted = function() - MissionAccomplished() +EvacuateHelicopter = function() + if heli.HasPassengers then + heli.Move(ExtractionExitPoint.Location) + Trigger.OnIdle(heli, heli.Destroy) + end end SendCruisers = function() - for i, cruiser in ipairs(Cruisers) do - local ca = Actor.Create(cruiser, { Owner = england, Location = SouthReinforcementsPoint.Location }) - Actor.Move(ca, Map.GetNamedActor("CruiserPoint" .. i).Location) - end + local i = 1 + Utils.Do(CruisersReinforcements, function(cruiser) + local ca = Actor.Create(cruiser, true, { Owner = england, Location = SouthReinforcementsPoint.Location + CVec.New(2 * i, 0) }) + ca.Move(Map.NamedActor("CruiserPoint" .. i).Location) + i = i + 1 + end) end -LabDestroyed = function(self, e) +LabDestroyed = function() if not einstein then - MissionFailed() + RescueFailed() end end -EinsteinKilled = function(self, e) - MissionFailed() +RescueFailed = function() + player.MarkFailedObjective(SurviveObjective) + ussr.MarkCompletedObjective(DefendObjective) end -HelicopterDestroyed = function(self, e) - MissionFailed() +OilPumpDestroyed = function() + Trigger.AfterDelay(Utils.Seconds(5), SendJeeps) end -TanyaKilled = function(self, e) - MissionFailed() -end - -OilPumpDestroyed = function(self, e) - OpenRA.RunAfterDelay(JeepDelay, SendJeeps) +CiviliansKilled = function() + player.MarkFailedObjective(CivilProtectionObjective) + Media.PlaySpeechNotification(player, "ObjectiveNotMet") + collateralDamage = true end CreateEinstein = function() - einstein = Actor.Create(EinsteinType, { Location = EinsteinSpawnPoint.Location, Owner = player }) - Actor.Scatter(einstein) - Actor.OnKilled(einstein, EinsteinKilled) + player.MarkCompletedObjective(FindEinsteinObjective) + Media.PlaySpeechNotification(player, "ObjectiveMet") + einstein = Actor.Create(EinsteinType, true, { Location = EinsteinSpawnPoint.Location, Owner = player }) + einstein.Scatter() + Trigger.OnKilled(einstein, RescueFailed) + ExtractObjective = player.AddPrimaryObjective("Wait for the helicopter and extract Einstein.") + Trigger.AfterDelay(Utils.Seconds(1), function() Media.PlaySpeechNotification(player, "TargetFreed") end) end -MissionAccomplished = function() - Mission.MissionOver({ player }, nil, true) - --Media.PlayMovieFullscreen("snowbomb.vqa") -end - -MissionFailed = function() - Mission.MissionOver(nil, { player }, true) - Media.PlayMovieFullscreen("bmap.vqa") -end - -SetUnitStances = function() - local playerUnits = Mission.GetGroundAttackersOf(player) - local ussrUnits = Mission.GetGroundAttackersOf(ussr) - for i, unit in ipairs(playerUnits) do - Actor.SetStance(unit, "Defend") +HelicopterGone = function() + if not heli.IsDead then + Media.PlaySpeechNotification(player, "TargetRescued") + Trigger.AfterDelay(Utils.Seconds(1), function() + player.MarkCompletedObjective(ExtractObjective) + player.MarkCompletedObjective(SurviveObjective) + ussr.MarkFailedObjective(DefendObjective) + if not collateralDamage then + player.MarkCompletedObjective(CivilProtectionObjective) + end + end) end end +MissionAccomplished = function() + Media.PlaySpeechNotification(player, "Win") + --Trigger.AfterDelay(Utils.Seconds(1), function() + --Media.PlayMovieFullscreen("snowbomb.vqa") -- https://github.com/OpenRA/OpenRA/issues/4224 + --end) +end + +MissionFailed = function() + Media.PlaySpeechNotification(player, "Lose") + Trigger.AfterDelay(Utils.Seconds(1), function() Media.PlayMovieFullscreen("bmap.vqa") end) +end + +SetUnitStances = function() + Utils.Do(Map.NamedActors, function(a) + if a.Owner == player then + a.Stance = "Defend" + end + end) +end + Tick = function() - Mission.TickTakeOre(ussr) + ussr.Resources = ussr.Resources - (0.01 * ussr.ResourceCapacity / 25) end WorldLoaded = function() - player = OpenRA.GetPlayer("Greece") - england = OpenRA.GetPlayer("England") - ussr = OpenRA.GetPlayer("USSR") - - Actor.OnKilled(Lab, LabDestroyed) - Actor.OnKilled(OilPump, OilPumpDestroyed) - - labGuardsTeam = Team.New({ LabGuard1, LabGuard2, LabGuard3 }) - Team.AddEventHandler(labGuardsTeam.OnAllKilled, LabGuardsKilled) - - civiliansTeam = Team.New({ Civilian1, Civilian2 }) - + player = Player.GetPlayer("Greece") + england = Player.GetPlayer("England") + ussr = Player.GetPlayer("USSR") + + FindEinsteinObjective = player.AddPrimaryObjective("Find Einstein.") + SurviveObjective = player.AddPrimaryObjective("Tanya and Einstein must survive.") + england.AddPrimaryObjective("Destroy the soviet base after a successful rescue.") + CivilProtectionObjective = player.AddSecondaryObjective("Protect all civilians.") + DefendObjective = ussr.AddPrimaryObjective("Kill Tanya and keep Einstein hostage.") + + Trigger.OnObjectiveCompleted(player, function(p, id) + Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective completed") + end) + Trigger.OnObjectiveFailed(player, function(p, id) + Media.DisplayMessage(p.GetObjectiveDescription(id), "Objective failed") + end) + + Trigger.OnPlayerLost(player, MissionFailed) + Trigger.OnPlayerWon(player, MissionAccomplished) + + Trigger.OnKilled(Lab, LabDestroyed) + Trigger.OnKilled(OilPump, OilPumpDestroyed) + + sovietArmy = ussr.GetGroundAttackers() + + labGuardsTeam = { LabGuard1, LabGuard2, LabGuard3 } + Trigger.OnAllKilled(labGuardsTeam, LabGuardsKilled) + + collateralDamage = false + civilianTeam = { Civilian1, Civilian2 } + Trigger.OnAnyKilled(civilianTeam, CiviliansKilled) + RunInitialActivities() - + SetUnitStances() - - OpenRA.RunAfterDelay(CameraDelay, function() Actor.Create("camera", { Owner = player, Location = BaseCameraPoint.Location }) end) - - OpenRA.SetViewportCenterPosition(InsertionLZ.CenterPosition) - - Media.PlayMovieFullscreen("ally1.vqa", function() Media.PlayMovieFullscreen("landing.vqa", Media.PlayRandomMusic) end) -end \ No newline at end of file + + Trigger.AfterDelay(Utils.Seconds(5), function() Actor.Create("camera", true, { Owner = player, Location = BaseCameraPoint.Location }) end) + + Camera.Position = InsertionLZ.CenterPosition + + Media.PlayMovieFullscreen("ally1.vqa", function() Media.PlayMovieFullscreen("landing.vqa") end) +end diff --git a/mods/ra/maps/allies-01-classic/map.yaml b/mods/ra/maps/allies-01-classic/map.yaml index eb668466c8..bc9dc59bfb 100644 --- a/mods/ra/maps/allies-01-classic/map.yaml +++ b/mods/ra/maps/allies-01-classic/map.yaml @@ -580,8 +580,8 @@ Rules: -CrateSpawner: -SpawnMPUnits: -MPStartLocations: - LuaScriptInterface: - LuaScripts: allies01.lua + LuaScript: + Scripts: allies01.lua ObjectivesPanel: PanelName: MISSION_OBJECTIVES TRAN.Extraction: @@ -607,6 +607,9 @@ Rules: ^CivInfantry: RevealsShroud: Range: 0c0 + JEEP: + Cargo: + Types: Infantry, Einstein Sequences: diff --git a/mods/ra/notifications.yaml b/mods/ra/notifications.yaml index 3ec7f60190..29d5620211 100644 --- a/mods/ra/notifications.yaml +++ b/mods/ra/notifications.yaml @@ -28,6 +28,12 @@ Speech: SignalFlareNorth: flaren1 AlliedReinforcementsArrived: aarrive1 ConvoyApproaching: convyap1 + TargetFreed: targfre1 + TargetRescued: targres1 + ObjectiveMet: objmet1 + ObjectiveNotMet: objnmet1 + ObjectiveReached: objrch1 + ObjectiveNotReached: objnrch1 Sounds: Notifications: @@ -41,4 +47,6 @@ Sounds: ChatLine: scold1 ClickSound: ramenu1 ClickDisabledSound: - Beacon: beepslct \ No newline at end of file + Beacon: beepslct + AlertBuzzer: buzzy1 + AlertBleep: bleep6 \ No newline at end of file