diff --git a/CHANGELOG b/CHANGELOG index 341c716717..4d1f2e0ad0 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -52,6 +52,7 @@ NEW: Adjusted Zombie build palette position. Fixed attack dogs causing crashes by attacking non-infantry. Disabled cloak/uncloak sound for camouflaged Pillbox. + Added two Lua-powered single player missions, ported from Red Alert's single player campaign. Tiberian Dawn: C&C mod renamed to Tiberian Dawn to resolve naming ambiguities. Fixed Bio Lab wrongly belonging to a hostile faction in East vs West 3. diff --git a/OpenRA.Game/Graphics/Viewport.cs b/OpenRA.Game/Graphics/Viewport.cs index cc6ac5c0c2..4c61e2e18c 100755 --- a/OpenRA.Game/Graphics/Viewport.cs +++ b/OpenRA.Game/Graphics/Viewport.cs @@ -40,6 +40,9 @@ namespace OpenRA.Graphics // Viewport geometry (world-px) public int2 CenterLocation { get; private set; } + + public WPos CenterPosition { get { return worldRenderer.Position(CenterLocation); } } + public int2 TopLeft { get { return CenterLocation - viewportSize / 2; } } public int2 BottomRight { get { return CenterLocation + viewportSize / 2; } } int2 viewportSize; diff --git a/OpenRA.Game/World.cs b/OpenRA.Game/World.cs index 013d00bdfb..462fe8e82d 100644 --- a/OpenRA.Game/World.cs +++ b/OpenRA.Game/World.cs @@ -46,7 +46,7 @@ namespace OpenRA public bool ObserveAfterWinOrLose; public Player RenderPlayer { - get { return renderPlayer == null || (ObserveAfterWinOrLose && renderPlayer.WinState != WinState.Undefined)? null : renderPlayer; } + get { return renderPlayer == null || (ObserveAfterWinOrLose && renderPlayer.WinState != WinState.Undefined) ? null : renderPlayer; } set { renderPlayer = value; } } @@ -71,7 +71,7 @@ namespace OpenRA if (orderManager.Connection is ReplayConnection) return; - LocalPlayer = Players.FirstOrDefault(p => p.InternalName == pr); + LocalPlayer = Players.FirstOrDefault(p => p.InternalName == pr); RenderPlayer = LocalPlayer; } @@ -89,7 +89,7 @@ namespace OpenRA get { return orderGenerator_; } set { - Sync.AssertUnsynced( "The current order generator may not be changed from synced code" ); + Sync.AssertUnsynced("The current order generator may not be changed from synced code"); orderGenerator_ = value; } } @@ -145,16 +145,16 @@ namespace OpenRA wlh.WorldLoaded(this, wr); } - public Actor CreateActor( string name, TypeDictionary initDict ) + public Actor CreateActor(string name, TypeDictionary initDict) { - return CreateActor( true, name, initDict ); + return CreateActor(true, name, initDict); } - public Actor CreateActor( bool addToWorld, string name, TypeDictionary initDict ) + public Actor CreateActor(bool addToWorld, string name, TypeDictionary initDict) { - var a = new Actor( this, name, initDict ); - if( addToWorld ) - Add( a ); + var a = new Actor(this, name, initDict); + if (addToWorld) + Add(a); return a; } @@ -188,14 +188,23 @@ namespace OpenRA public bool Paused { get; internal set; } public bool PredictedPaused { get; internal set; } + public bool PauseStateLocked { get; set; } public bool IsShellmap = false; public void SetPauseState(bool paused) { + if (PauseStateLocked) + return; + IssueOrder(Order.PauseGame(paused)); PredictedPaused = paused; } + public void SetLocalPauseState(bool paused) + { + Paused = PredictedPaused = paused; + } + public void Tick() { if (!Paused && (!IsShellmap || Game.Settings.Game.ShowShellmap)) @@ -206,12 +215,12 @@ namespace OpenRA ni.Trait.TickIdle(ni.Actor); using (new PerfSample("tick_activities")) - foreach(var a in actors) + foreach (var a in actors) a.Tick(); ActorsWithTrait().DoTimed(x => x.Trait.Tick(x.Actor), "[{2}] Trait: {0} ({1:0.000} ms)", - Game.Settings.Debug.LongTickThreshold); + Game.Settings.Debug.LongTickThreshold); effects.DoTimed(e => e.Tick(this), "[{2}] Effect: {0} ({1:0.000} ms)", @@ -246,11 +255,11 @@ namespace OpenRA // hash all the actors foreach (var a in Actors) - ret += n++ * (int)(1+a.ActorID) * Sync.CalculateSyncHash(a); + ret += n++ * (int)(1 + a.ActorID) * Sync.CalculateSyncHash(a); // hash all the traits that tick foreach (var x in traitDict.ActorsWithTraitMultiple(this)) - ret += n++ * (int)(1+x.Actor.ActorID) * Sync.CalculateSyncHash(x.Trait); + ret += n++ * (int)(1 + x.Actor.ActorID) * Sync.CalculateSyncHash(x.Trait); // TODO: don't go over all effects foreach (var e in Effects) @@ -280,7 +289,7 @@ namespace OpenRA public override string ToString() { - return "{0}->{1}".F( Actor.Info.Name, Trait.GetType().Name ); + return "{0}->{1}".F(Actor.Info.Name, Trait.GetType().Name); } } } diff --git a/OpenRA.Mods.RA/AI/HackyAI.cs b/OpenRA.Mods.RA/AI/HackyAI.cs index 5c12c0935e..a5e8a46e68 100644 --- a/OpenRA.Mods.RA/AI/HackyAI.cs +++ b/OpenRA.Mods.RA/AI/HackyAI.cs @@ -738,8 +738,8 @@ namespace OpenRA.Mods.RA.AI if (desiredLocation == null) continue; - world.IssueOrder(new Order("Move", mcv, false) { TargetLocation = desiredLocation.Value }); - world.IssueOrder(new Order("DeployTransform", mcv, false)); + world.IssueOrder(new Order("Move", mcv, true) { TargetLocation = desiredLocation.Value }); + world.IssueOrder(new Order("DeployTransform", mcv, true)); } } diff --git a/OpenRA.Mods.RA/Activities/Hunt.cs b/OpenRA.Mods.RA/Activities/Hunt.cs new file mode 100644 index 0000000000..863de0cd80 --- /dev/null +++ b/OpenRA.Mods.RA/Activities/Hunt.cs @@ -0,0 +1,48 @@ +#region Copyright & License Information +/* + * Copyright 2007-2013 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.Collections.Generic; +using System.Linq; +using OpenRA.Mods.RA.Buildings; +using OpenRA.Mods.RA.Move; +using OpenRA.Traits; + +namespace OpenRA.Mods.RA.Activities +{ + public class Hunt : Activity + { + readonly IEnumerable targets; + + public Hunt(Actor self) + { + var attack = self.Trait(); + targets = self.World.Actors.Where(a => self != a && !a.IsDead() && a.IsInWorld && a.AppearsHostileTo(self) + && a.HasTrait() && attack.HasAnyValidWeapons(Target.FromActor(a))); + } + + public override Activity Tick(Actor self) + { + if (IsCanceled) + return NextActivity; + + var target = targets.ClosestTo(self); + if (target == null) + return this; + + return Util.SequenceActivities( + new AttackMove.AttackMoveActivity(self, new Move.Move(target.Location, WRange.FromCells(2))), + new Wait(25), + this); + } + } + + public class HuntableInfo : TraitInfo { } + public class Huntable { } +} \ No newline at end of file diff --git a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj index 0ae49ce679..eba63a2dde 100644 --- a/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj +++ b/OpenRA.Mods.RA/OpenRA.Mods.RA.csproj @@ -81,6 +81,7 @@ + @@ -338,6 +339,7 @@ + diff --git a/OpenRA.Mods.RA/Scripting/LuaScriptEvents.cs b/OpenRA.Mods.RA/Scripting/LuaScriptEvents.cs new file mode 100644 index 0000000000..a9a361b5be --- /dev/null +++ b/OpenRA.Mods.RA/Scripting/LuaScriptEvents.cs @@ -0,0 +1,40 @@ +#region Copyright & License Information +/* + * Copyright 2007-2013 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 OpenRA.Traits; + +namespace OpenRA.Mods.RA.Scripting +{ + public class LuaScriptEventsInfo : TraitInfo { } + + public class LuaScriptEvents : INotifyKilled, INotifyAddedToWorld, INotifyRemovedFromWorld + { + public event Action OnKilled = (self, e) => { }; + public event Action OnAddedToWorld = self => { }; + public event Action OnRemovedFromWorld = self => { }; + + public void Killed(Actor self, AttackInfo e) + { + OnKilled(self, e); + } + + public void AddedToWorld(Actor self) + { + OnAddedToWorld(self); + } + + public void RemovedFromWorld(Actor self) + { + OnRemovedFromWorld(self); + } + } +} diff --git a/OpenRA.Mods.RA/Scripting/LuaScriptInterface.cs b/OpenRA.Mods.RA/Scripting/LuaScriptInterface.cs index 43f449bb9d..db5c240a14 100644 --- a/OpenRA.Mods.RA/Scripting/LuaScriptInterface.cs +++ b/OpenRA.Mods.RA/Scripting/LuaScriptInterface.cs @@ -8,12 +8,16 @@ */ #endregion -using System; -using System.Linq; using LuaInterface; using OpenRA.Effects; using OpenRA.FileFormats; +using OpenRA.Mods.RA.Activities; +using OpenRA.Mods.RA.Air; +using OpenRA.Mods.RA.Missions; +using OpenRA.Scripting; using OpenRA.Traits; +using System; +using System.Linq; using WorldRenderer = OpenRA.Graphics.WorldRenderer; namespace OpenRA.Mods.RA.Scripting @@ -42,7 +46,7 @@ namespace OpenRA.Mods.RA.Scripting AddMapActorGlobals(); context.Lua["World"] = w; context.Lua["WorldRenderer"] = wr; - context.RegisterObject(this, "_OpenRA", false); + context.RegisterObject(this, "Internal", false); context.RegisterType(typeof(WVec), "WVec", true); context.RegisterType(typeof(WPos), "WPos", true); context.RegisterType(typeof(CPos), "CPos", true); @@ -161,5 +165,101 @@ namespace OpenRA.Mods.RA.Scripting { world.AddFrameEndTask(w => w.Add(new DelayedAction((int)delay, func))); } + + [LuaGlobal] + public void PlaySpeechNotification(Player player, string notification) + { + Sound.PlayNotification(player, "Speech", notification, player != null ? player.Country.Race : null); + } + + [LuaGlobal] + public void PlaySoundNotification(Player player, string notification) + { + Sound.PlayNotification(player, "Sounds", notification, player != null ? player.Country.Race : null); + } + + [LuaGlobal] + public void WaitFor(Actor actor, Func func) + { + actor.QueueActivity(new WaitFor(func)); + } + + [LuaGlobal] + public void CallFunc(Actor actor, Action func) + { + actor.QueueActivity(new CallFunc(func)); + } + + [LuaGlobal] + public int GetFacing(object vec, double currentFacing) + { + if (vec is CVec) + return Util.GetFacing((CVec)vec, (int)currentFacing); + if (vec is WVec) + return Util.GetFacing((WVec)vec, (int)currentFacing); + throw new ArgumentException("Unsupported vector type: {0}".F(vec.GetType())); + } + + [LuaGlobal] + public WRange GetWRangeFromCells(double cells) + { + return WRange.FromCells((int)cells); + } + + [LuaGlobal] + public void SetWinState(Player player, string winState) + { + player.WinState = Enum.Parse(winState); + } + + [LuaGlobal] + public void PlayRandomMusic() + { + MissionUtils.PlayMissionMusic(); + } + + [LuaGlobal] + public bool IsDead(Actor actor) + { + return actor.IsDead(); + } + + [LuaGlobal] + public void PlayMovieFullscreen(string movie, Action onComplete) + { + Media.PlayFMVFullscreen(world, movie, onComplete); + } + + [LuaGlobal] + public void FlyToPos(Actor actor, WPos pos) + { + actor.QueueActivity(Fly.ToPos(pos)); + } + + [LuaGlobal] + public void FlyAttackActor(Actor actor, Actor targetActor) + { + actor.QueueActivity(new FlyAttack(Target.FromActor(targetActor))); + } + + [LuaGlobal] + public void FlyAttackCell(Actor actor, CPos location) + { + actor.QueueActivity(new FlyAttack(Target.FromCell(location))); + } + + [LuaGlobal] + public void SetUnitStance(Actor actor, string stance) + { + var at = actor.TraitOrDefault(); + if (at != null) + at.stance = Enum.Parse(stance); + } + + [LuaGlobal] + public bool RequiredUnitsAreDestroyed(Player player) + { + return world.ActorsWithTrait().All(p => p.Actor.Owner != player); + } } } diff --git a/OpenRA.Mods.RA/Transforms.cs b/OpenRA.Mods.RA/Transforms.cs index 229db3eea4..2cc411ae33 100644 --- a/OpenRA.Mods.RA/Transforms.cs +++ b/OpenRA.Mods.RA/Transforms.cs @@ -68,29 +68,31 @@ namespace OpenRA.Mods.RA return null; } + public void DeployTransform() + { + var b = self.TraitOrDefault(); + + if (!CanDeploy() || (b != null && !b.Lock())) + { + foreach (var s in Info.NoTransformSounds) + Sound.PlayToPlayer(self.Owner, s); + return; + } + + if (self.HasTrait()) + self.QueueActivity(new Turn(Info.Facing)); + + var rb = self.TraitOrDefault(); + if (rb != null && self.Info.Traits.Get().HasMakeAnimation) + self.QueueActivity(new MakeAnimation(self, true, () => rb.PlayCustomAnim(self, "make"))); + + self.QueueActivity(new Transform(self, Info.IntoActor) { Offset = (CVec)Info.Offset, Facing = Info.Facing, Sounds = Info.TransformSounds }); + } + public void ResolveOrder( Actor self, Order order ) { if (order.OrderString == "DeployTransform") - { - var b = self.TraitOrDefault(); - - if (!CanDeploy() || (b != null && !b.Lock())) - { - foreach (var s in Info.NoTransformSounds) - Sound.PlayToPlayer(self.Owner, s); - return; - } - self.CancelActivity(); - - if (self.HasTrait()) - self.QueueActivity(new Turn(Info.Facing)); - - var rb = self.TraitOrDefault(); - if (rb != null && self.Info.Traits.Get().HasMakeAnimation) - self.QueueActivity(new MakeAnimation(self, true, () => rb.PlayCustomAnim(self, "make"))); - - self.QueueActivity(new Transform(self, Info.IntoActor) { Offset = (CVec)Info.Offset, Facing = Info.Facing, Sounds = Info.TransformSounds }); - } + DeployTransform(); } } } diff --git a/mods/cnc/mod.yaml b/mods/cnc/mod.yaml index 88f84b4832..f00675d58a 100644 --- a/mods/cnc/mod.yaml +++ b/mods/cnc/mod.yaml @@ -163,3 +163,12 @@ Fonts: TinyBold: Font:FreeSansBold.ttf Size:10 + +LuaScripts: + mods/ra/lua/utils.lua + mods/ra/lua/openra.lua + mods/ra/lua/map.lua + mods/ra/lua/actor.lua + mods/ra/lua/team.lua + mods/ra/lua/media.lua + mods/ra/lua/mission.lua diff --git a/mods/cnc/rules/defaults.yaml b/mods/cnc/rules/defaults.yaml index 8d2b0626be..42c27ad7fb 100644 --- a/mods/cnc/rules/defaults.yaml +++ b/mods/cnc/rules/defaults.yaml @@ -40,6 +40,8 @@ CloakDelay: 90 CloakSound: trans1.aud UncloakSound: trans1.aud + Huntable: + LuaScriptEvents: ^Tank: AppearsOnRadar: @@ -86,6 +88,8 @@ CloakDelay: 90 CloakSound: trans1.aud UncloakSound: trans1.aud + Huntable: + LuaScriptEvents: ^Helicopter: AppearsOnRadar: @@ -113,6 +117,8 @@ CombatDebugOverlay: BodyOrientation: UpdatesPlayerStatistics: + Huntable: + LuaScriptEvents: ^Infantry: AppearsOnRadar: @@ -170,6 +176,8 @@ DamageCooldown: 125 RequiresTech: InfantryHealing UpdatesPlayerStatistics: + Huntable: + LuaScriptEvents: ^CivInfantry: Inherits: ^Infantry @@ -247,6 +255,8 @@ AttackMove: AttackFrontal: UpdatesPlayerStatistics: + Huntable: + LuaScriptEvents: ^Plane: AppearsOnRadar: @@ -263,6 +273,8 @@ ActorLostNotification: CombatDebugOverlay: BodyOrientation: + Huntable: + LuaScriptEvents: ^Ship: AppearsOnRadar: @@ -286,6 +298,8 @@ Guardable: BodyOrientation: UpdatesPlayerStatistics: + Huntable: + LuaScriptEvents: ^Building: AppearsOnRadar: @@ -337,6 +351,8 @@ FrozenUnderFog: UpdatesPlayerStatistics: EngineerRepairable: + Huntable: + LuaScriptEvents: ^CivBuilding: Inherits: ^Building @@ -372,6 +388,7 @@ BodyOrientation: FrozenUnderFog: StartsRevealed: true + LuaScriptEvents: ^TechBuilding: Inherits: ^CivBuilding @@ -407,6 +424,7 @@ Palette: terrain FrozenUnderFog: StartsRevealed: true + LuaScriptEvents: ^Wall: AppearsOnRadar: @@ -437,6 +455,7 @@ Guardable: BodyOrientation: FrozenUnderFog: + LuaScriptEvents: ^Tree: Tooltip: @@ -460,6 +479,7 @@ BodyOrientation: FrozenUnderFog: StartsRevealed: true + LuaScriptEvents: ^Rock: Tooltip: @@ -477,6 +497,7 @@ BodyOrientation: FrozenUnderFog: StartsRevealed: true + LuaScriptEvents: ^Husk: Health: @@ -499,6 +520,7 @@ # AllowAllies: true # AllowNeutral: true # AllowEnemies: true + LuaScriptEvents: ^HelicopterHusk: Inherits: ^Husk @@ -524,3 +546,4 @@ DamagedSound: xplos.aud DestroyedSound: xplobig4.aud BodyOrientation: + LuaScriptEvents: diff --git a/mods/d2k/mod.yaml b/mods/d2k/mod.yaml index 02eaf01e8c..7fff8c53f6 100644 --- a/mods/d2k/mod.yaml +++ b/mods/d2k/mod.yaml @@ -144,3 +144,12 @@ Fonts: TinyBold: Font:FreeSansBold.ttf Size:10 + +LuaScripts: + mods/ra/lua/utils.lua + mods/ra/lua/openra.lua + mods/ra/lua/map.lua + mods/ra/lua/actor.lua + mods/ra/lua/team.lua + mods/ra/lua/media.lua + mods/ra/lua/mission.lua diff --git a/mods/d2k/rules/defaults.yaml b/mods/d2k/rules/defaults.yaml index 0afb310914..aed8639c40 100644 --- a/mods/d2k/rules/defaults.yaml +++ b/mods/d2k/rules/defaults.yaml @@ -35,6 +35,8 @@ RenderUnit: BodyOrientation: UpdatesPlayerStatistics: + Huntable: + LuaScriptEvents: ^Tank: AppearsOnRadar: @@ -73,6 +75,8 @@ RenderUnit: BodyOrientation: UpdatesPlayerStatistics: + Huntable: + LuaScriptEvents: ^Husk: Health: @@ -90,6 +94,7 @@ Tooltip: Name: Destroyed Tank BodyOrientation: + LuaScriptEvents: ^TowerHusk: Health: @@ -108,6 +113,7 @@ ProximityCaptor: Types:Husk BodyOrientation: + LuaScriptEvents: ^AircraftHusk: Inherits: ^Husk @@ -167,6 +173,8 @@ Guardable: BodyOrientation: UpdatesPlayerStatistics: + Huntable: + LuaScriptEvents: ^Plane: AppearsOnRadar: @@ -188,6 +196,8 @@ CombatDebugOverlay: BodyOrientation: UpdatesPlayerStatistics: + Huntable: + LuaScriptEvents: ^Helicopter: Inherits: ^Plane @@ -236,4 +246,6 @@ Range: 3 BodyOrientation: UpdatesPlayerStatistics: - WithCrumbleOverlay: \ No newline at end of file + WithCrumbleOverlay: + Huntable: + LuaScriptEvents: \ No newline at end of file diff --git a/mods/ra/lua/actor.lua b/mods/ra/lua/actor.lua new file mode 100644 index 0000000000..904b6a5be4 --- /dev/null +++ b/mods/ra/lua/actor.lua @@ -0,0 +1,147 @@ +Actor = { } + +Actor.Create = function(name, init) + if name == nil then error("No actor name specified", 2) end + if init.Owner == nil then error("No actor owner specified", 2) end + local td = OpenRA.New("TypeDictionary") + local addToWorld = true + for key, value in pairs(init) do + if key == "AddToWorld" then + addToWorld = value + else + td:Add(OpenRA.New(key .. "Init", { value })) + end + end + return World:CreateActor(addToWorld, name, td) +end + +Actor.Turn = function(actor, facing) + actor:QueueActivity(OpenRA.New("Turn", { { facing, "Int32" } })) +end + +Actor.Move = function(actor, location) + Actor.MoveNear(actor, location, 0) +end + +Actor.MoveNear = function(actor, location, nearEnough) + actor:QueueActivity(OpenRA.New("Move", { location, Map.GetWRangeFromCells(nearEnough) })) +end + +Actor.HeliFly = function(actor, position) + actor:QueueActivity(OpenRA.New("HeliFly", { position })) +end + +Actor.HeliLand = function(actor, requireSpace) + actor:QueueActivity(OpenRA.New("HeliLand", { requireSpace })) +end + +Actor.Fly = function(actor, position) + Internal.FlyToPos(actor, position) +end + +Actor.FlyAttackActor = function(actor, targetActor) + Internal.FlyAttackActor(actor, targetActor) +end + +Actor.FlyAttackCell = function(actor, location) + Internal.FlyAttackCell(actor, location) +end + +Actor.FlyOffMap = function(actor) + actor:QueueActivity(OpenRA.New("FlyOffMap")) +end + +Actor.Hunt = function(actor) + actor:QueueActivity(OpenRA.New("Hunt", { actor })) +end + +Actor.UnloadCargo = function(actor, unloadAll) + actor:QueueActivity(OpenRA.New("UnloadCargo", { unloadAll })) +end + +Actor.Harvest = function(actor) + actor:QueueActivity(OpenRA.New("FindResources")) +end + +Actor.Scatter = function(actor) + local mobile = Actor.Trait(actor, "Mobile") + mobile:Nudge(actor, actor, true) +end + +Actor.Wait = function(actor, period) + actor:QueueActivity(OpenRA.New("Wait", { { period, "Int32" } })) +end + +Actor.WaitFor = function(actor, func) + Internal.WaitFor(actor, func) +end + +Actor.CallFunc = function(actor, func) + Internal.CallFunc(actor, func) +end + +Actor.DeployTransform = function(actor) + Actor.CallFunc(actor, function() + Actor.Trait(actor, "Transforms"):DeployTransform() + end) +end + +Actor.RemoveSelf = function(actor) + actor:QueueActivity(OpenRA.New("RemoveSelf")) +end + +Actor.Stop = function(actor) + actor:CancelActivity() +end + +Actor.IsDead = function(actor) + return Internal.IsDead(actor) +end + +Actor.IsInWorld = function(actor) + return actor.IsInWorld +end + +Actor.Owner = function(actor) + return actor.Owner +end + +Actor.SetStance = function(actor, stance) + Internal.SetUnitStance(actor, stance) +end + +Actor.OnKilled = function(actor, eh) + Actor.Trait(actor, "LuaScriptEvents").OnKilled:Add(eh) +end + +Actor.OnAddedToWorld = function(actor, eh) + Actor.Trait(actor, "LuaScriptEvents").OnAddedToWorld:Add(eh) +end + +Actor.OnRemovedFromWorld = function(actor, eh) + Actor.Trait(actor, "LuaScriptEvents").OnRemovedFromWorld:Add(eh) +end + +Actor.HasTrait = function(actor, className) + return Internal.HasTrait(actor, className) +end + +Actor.TraitOrDefault = function(actor, className) + return Internal.TraitOrDefault(actor, className) +end + +Actor.Trait = function(actor, className) + return Internal.Trait(actor, className) +end + +Actor.HasTraitInfo = function(actorType, className) + return Internal.HasTraitInfo(actorType, className) +end + +Actor.TraitInfoOrDefault = function(actorType, className) + return Internal.TraitInfoOrDefault(actorType, className) +end + +Actor.TraitInfo = function(actorType, className) + return Internal.TraitInfo(actorType, className) +end \ No newline at end of file diff --git a/mods/ra/lua/map.lua b/mods/ra/lua/map.lua new file mode 100644 index 0000000000..39ed982234 --- /dev/null +++ b/mods/ra/lua/map.lua @@ -0,0 +1,9 @@ +Map = { } + +Map.GetFacing = function(vec, currentFacing) + return Internal.GetFacing(vec, currentFacing) +end + +Map.GetWRangeFromCells = function(cells) + return Internal.GetWRangeFromCells(cells) +end \ No newline at end of file diff --git a/mods/ra/lua/media.lua b/mods/ra/lua/media.lua new file mode 100644 index 0000000000..7400551f46 --- /dev/null +++ b/mods/ra/lua/media.lua @@ -0,0 +1,20 @@ +Media = { } + +Media.PlaySpeechNotification = function(notification, player) + Internal.PlaySpeechNotification(player, notification) +end + +Media.PlaySoundNotification = function(notification, player) + Internal.PlaySoundNotification(player, notification) +end + +Media.PlayRandomMusic = function() + Internal.PlayRandomMusic() +end + +Media.PlayMovieFullscreen = function(movie, onComplete) + if onComplete == nil then + onComplete = function() end + end + Internal.PlayMovieFullscreen(movie, onComplete) +end \ No newline at end of file diff --git a/mods/ra/lua/mission.lua b/mods/ra/lua/mission.lua new file mode 100644 index 0000000000..ed26c90e0a --- /dev/null +++ b/mods/ra/lua/mission.lua @@ -0,0 +1,119 @@ +Mission = { } + +Mission.PerformHelicopterInsertion = function(owner, helicopterName, passengerNames, enterPosition, unloadPosition, exitPosition) + local facing = { Map.GetFacing(WPos.op_Subtraction(unloadPosition, enterPosition), 0), "Int32" } + local altitude = { Actor.TraitInfo(helicopterName, "AircraftInfo").CruiseAltitude, "Int32" } + local heli = Actor.Create(helicopterName, { Owner = owner, CenterPosition = enterPosition, Facing = facing, Altitude = altitude }) + local cargo = Actor.Trait(heli, "Cargo") + local passengers = { } + for i, passengerName in ipairs(passengerNames) do + local passenger = Actor.Create(passengerName, { AddToWorld = false, Owner = owner }) + cargo:Load(heli, passenger) + passengers[i] = passenger + end + Actor.HeliFly(heli, unloadPosition) + Actor.Turn(heli, 0) + Actor.HeliLand(heli, true) + Actor.UnloadCargo(heli, true) + Actor.Wait(heli, 125) + Actor.HeliFly(heli, exitPosition) + Actor.RemoveSelf(heli) + return heli, passengers +end + +Mission.PerformHelicopterExtraction = function(owner, helicopterName, passengers, enterPosition, loadPosition, exitPosition) + local facing = { Map.GetFacing(WPos.op_Subtraction(loadPosition, enterPosition), 0), "Int32" } + local altitude = { Actor.TraitInfo(helicopterName, "AircraftInfo").CruiseAltitude, "Int32" } + local heli = Actor.Create(helicopterName, { Owner = owner, CenterPosition = enterPosition, Facing = facing, Altitude = altitude }) + local cargo = Actor.Trait(heli, "Cargo") + Actor.HeliFly(heli, loadPosition) + Actor.Turn(heli, 0) + Actor.HeliLand(heli, true) + Actor.WaitFor(heli, function() + for i, passenger in ipairs(passengers) do + if not cargo.Passengers:Contains(passenger) then + return false + end + end + return true + end) + Actor.Wait(heli, 125) + Actor.HeliFly(heli, exitPosition) + Actor.RemoveSelf(heli) + return heli +end + +Mission.Reinforce = function(owner, reinforcementNames, enterLocation, rallyPointLocation, interval, onCreateFunc) + local facing = { Map.GetFacing(CPos.op_Subtraction(rallyPointLocation, enterLocation), 0), "Int32" } + local ret = { } + for i = 1, #reinforcementNames do + local reinforcement = Actor.Create(reinforcementNames[i], { AddToWorld = false, Owner = owner, Location = enterLocation, Facing = facing }) + table.insert(ret, reinforcement) + OpenRA.RunAfterDelay((i - 1) * interval, function() + World:Add(reinforcement) + Actor.MoveNear(reinforcement, rallyPointLocation, 2) + if onCreateFunc ~= nil then + onCreateFunc(reinforcement) + end + end) + end + return ret +end + +Mission.Parabomb = function(owner, planeName, enterLocation, bombLocation) + local facing = { Map.GetFacing(CPos.op_Subtraction(bombLocation, enterLocation), 0), "Int32" } + local altitude = { Actor.TraitInfo(planeName, "AircraftInfo").CruiseAltitude, "Int32" } + local plane = Actor.Create(planeName, { Location = enterLocation, Owner = owner, Facing = facing, Altitude = altitude }) + Actor.Trait(plane, "AttackBomber"):SetTarget(bombLocation.CenterPosition) + Actor.Fly(plane, bombLocation.CenterPosition) + Actor.FlyOffMap(plane) + Actor.RemoveSelf(plane) +end + +Mission.Paradrop = function(owner, planeName, passengerNames, enterLocation, dropLocation) + local facing = { Map.GetFacing(CPos.op_Subtraction(dropLocation, enterLocation), 0), "Int32" } + local altitude = { Actor.TraitInfo(planeName, "AircraftInfo").CruiseAltitude, "Int32" } + local plane = Actor.Create(planeName, { Location = enterLocation, Owner = owner, Facing = facing, Altitude = altitude }) + Actor.FlyAttackCell(plane, dropLocation) + Actor.Trait(plane, "ParaDrop"):SetLZ(dropLocation) + local cargo = Actor.Trait(plane, "Cargo") + for i, passengerName in ipairs(passengerNames) do + cargo:Load(plane, Actor.Create(passengerName, { AddToWorld = false, Owner = owner })) + end +end + +Mission.MissionOver = function(winners, losers, setWinStates) + World:SetLocalPauseState(true) + World:set_PauseStateLocked(true) + if winners then + for i, player in ipairs(winners) do + Media.PlaySpeechNotification("Win", player) + if setWinStates then + OpenRA.SetWinState(player, "Won") + end + end + end + if losers then + for i, player in ipairs(losers) do + Media.PlaySpeechNotification("Lose", player) + if setWinStates then + OpenRA.SetWinState(player, "Lost") + end + end + end + Mission.MissionIsOver = true +end + +Mission.GetGroundAttackersOf = function(player) + return Utils.EnumerableWhere(World.Actors, function(actor) + return not Actor.IsDead(actor) and Actor.IsInWorld(actor) and Actor.Owner(actor) == player and Actor.HasTrait(actor, "AttackBase") and Actor.HasTrait(actor, "Mobile") + end) +end + +Mission.TickTakeOre = function(player) + OpenRA.TakeOre(player, 0.01 * OpenRA.GetOreCapacity(player) / 25) +end + +Mission.RequiredUnitsAreDestroyed = function(player) + return Internal.RequiredUnitsAreDestroyed(player) +end \ No newline at end of file diff --git a/mods/ra/lua/openra.lua b/mods/ra/lua/openra.lua new file mode 100644 index 0000000000..ae746d2db4 --- /dev/null +++ b/mods/ra/lua/openra.lua @@ -0,0 +1,69 @@ +OpenRA = { } + +OpenRA.New = function(className, args) + return Internal.New(className, args) +end + +OpenRA.RunAfterDelay = function(delay, func) + Internal.RunAfterDelay(delay, func) +end + +OpenRA.Debug = function(obj) + Internal.Debug(obj) +end + +OpenRA.SetViewportCenterPosition = function(position) + WorldRenderer.Viewport:Center(position) +end + +OpenRA.GetViewportCenterPosition = function() + return WorldRenderer.Viewport.CenterPosition +end + +OpenRA.GetDifficulty = function() + return World.LobbyInfo.GlobalSettings.Difficulty +end + +OpenRA.IsSinglePlayer = function() + return World.LobbyInfo:get_IsSinglePlayer() +end + +OpenRA.GetPlayer = function(internalName) + return Utils.EnumerableFirstOrNil(World.Players, function(p) return p.InternalName == internalName end) +end + +OpenRA.SetWinState = function(player, winState) + Internal.SetWinState(player, winState) +end + +OpenRA.TakeOre = function(player, amount) + Actor.Trait(player.PlayerActor, "PlayerResources"):TakeOre(amount) +end + +OpenRA.TakeCash = function(player, amount) + Actor.Trait(player.PlayerActor, "PlayerResources"):TakeCash(amount) +end + +OpenRA.GiveOre = function(player, amount) + Actor.Trait(player.PlayerActor, "PlayerResources"):GiveOre(amount) +end + +OpenRA.GiveCash = function(player, amount) + Actor.Trait(player.PlayerActor, "PlayerResources"):GiveCash(amount) +end + +OpenRA.CanGiveOre = function(player, amount) + return Actor.Trait(player.PlayerActor, "PlayerResources"):CanGiveOre(amount) +end + +OpenRA.GetOreCapacity = function(player) + return Actor.Trait(player.PlayerActor, "PlayerResources").OreCapacity +end + +OpenRA.GetOre = function(player) + return Actor.Trait(player.PlayerActor, "PlayerResources").Ore +end + +OpenRA.GetCash = function(player) + return Actor.Trait(player.PlayerActor, "PlayerResources").Cash +end \ No newline at end of file diff --git a/mods/ra/lua/team.lua b/mods/ra/lua/team.lua new file mode 100644 index 0000000000..f77a0733ed --- /dev/null +++ b/mods/ra/lua/team.lua @@ -0,0 +1,61 @@ +Team = { } + +Team.Create = function(actors) + local team = { } + team.Actors = actors + team.OnAllKilled = { } + team.OnAnyKilled = { } + team.OnAllRemovedFromWorld = { } + team.OnAnyRemovedFromWorld = { } + Team.AddActorEventHandlers(team) + return team +end + +Team.AddActorEventHandlers = function(team) + for i, actor in ipairs(team.Actors) do + + Actor.OnKilled(actor, function() + Team.InvokeHandlers(team.OnAnyKilled) + if Team.AllAreDead(team) then Team.InvokeHandlers(team.OnAllKilled) end + end) + + Actor.OnRemovedFromWorld(actor, function() + Team.InvokeHandlers(team.OnAnyRemovedFromWorld) + if not Team.AnyAreInWorld(team) then Team.InvokeHandlers(team.OnAllRemovedFromWorld) end + end) + end +end + +Team.InvokeHandlers = function(event) + for i, handler in ipairs(event) do + handler() + end +end + +Team.AllAreDead = function(team) + return Utils.All(team.Actors, Actor.IsDead) +end + +Team.AnyAreDead = function(team) + return Utils.Any(team.Actors, Actor.IsDead) +end + +Team.AllAreInWorld = function(team) + return Utils.All(team.Actors, Actor.IsInWorld) +end + +Team.AnyAreInWorld = function(team) + return Utils.Any(team.Actors, Actor.IsInWorld) +end + +Team.AddEventHandler = function(event, func) + table.insert(event, func) +end + +Team.Contains = function(team, actor) + return Utils.Any(team.Actors, function(a) return a == actor end) +end + +Team.Do = function(team, func) + Utils.ForEach(team.Actors, func) +end \ No newline at end of file diff --git a/mods/ra/lua/utils.lua b/mods/ra/lua/utils.lua new file mode 100644 index 0000000000..9a486d88dc --- /dev/null +++ b/mods/ra/lua/utils.lua @@ -0,0 +1,67 @@ +Utils = { } + +Utils.Enumerate = function(netEnumerable) + local enum = netEnumerable:GetEnumerator() + return function() + if enum:MoveNext() then + return enum:get_Current() + end + end +end + +Utils.EnumerableFirstOrNil = function(netEnumerable, func) + for item in Utils.Enumerate(netEnumerable) do + if func(item) then + return item + end + end + return nil +end + +Utils.EnumerableWhere = function(netEnumerable, func) + local ret = { } + for item in Utils.Enumerate(netEnumerable) do + if func(item) then + table.insert(ret, item) + end + end + return ret +end + +Utils.Where = function(array, func) + local ret = { } + for i, item in ipairs(array) do + if func(item) then + table.insert(ret, item) + end + end + return ret +end + +Utils.All = function(array, func) + for i, item in ipairs(array) do + if not func(item) then + return false + end + end + return true +end + +Utils.Any = function(array, func) + for i, item in ipairs(array) do + if func(item) then + return true + end + end + return false +end + +Utils.ForEach = function(array, func) + for i, item in ipairs(array) do + func(item) + end +end + +Utils.TableToArray = function(luaTable) + return Internal.TableToArray(luaTable) +end \ No newline at end of file diff --git a/mods/ra/maps/allies-01-classic/map.bin b/mods/ra/maps/allies-01-classic/map.bin new file mode 100644 index 0000000000..c99d9acca0 Binary files /dev/null and b/mods/ra/maps/allies-01-classic/map.bin differ diff --git a/mods/ra/maps/allies-01-classic/map.yaml b/mods/ra/maps/allies-01-classic/map.yaml new file mode 100644 index 0000000000..f56f221e72 --- /dev/null +++ b/mods/ra/maps/allies-01-classic/map.yaml @@ -0,0 +1,626 @@ +Selectable: True + +MapFormat: 6 + +Title: Allies 01: In the thick of it + +Description: In the thick of it + +Author: Westwood Studios + +Tileset: SNOW + +Options: + Crates: False + Fog: True + Shroud: True + AllyBuildRadius: False + FragileAlliances: False + StartingCash: 0 + ConfigurableStartingUnits: False + Difficulties: + +MapSize: 128,128 + +RequiresMod: ra + +Bounds: 49,45,30,36 + +UseAsShellmap: False + +Type: Campaign + +Players: + PlayerReference@USSR: + Name: USSR + Race: soviet + ColorRamp: 3,255,127 + Enemies: Greece,England + PlayerReference@Neutral: + Name: Neutral + OwnsWorld: True + NonCombatant: True + Race: allies + Enemies: USSR,Greece,England + PlayerReference@Greece: + Name: Greece + Race: allies + ColorRamp: 161,134,200 + Allies: England + Enemies: Neutral,USSR + Required: True + Playable: True + AllowBots: False + LockRace: True + LockSpawn: True + LockTeam: True + LockColor: True + PlayerReference@England: + Name: England + Race: allies + ColorRamp: 76,196,190 + Allies: Greece + Enemies: USSR + +Actors: + Actor0: t16 + Location: 66,46 + Owner: Neutral + Actor1: t17 + Location: 59,46 + Owner: Neutral + Actor2: tc04 + Location: 75,44 + Owner: Neutral + Actor3: tc05 + Location: 76,45 + Owner: Neutral + Actor4: t01 + Location: 52,50 + Owner: Neutral + Actor5: t02 + Location: 70,68 + Owner: Neutral + Actor6: t05 + Location: 73,64 + Owner: Neutral + Actor7: t14 + Location: 59,50 + Owner: Neutral + Actor8: t17 + Location: 56,61 + Owner: Neutral + Actor9: tc01 + Location: 53,64 + Owner: Neutral + Actor10: tc02 + Location: 49,66 + Owner: Neutral + Actor11: t07 + Location: 49,59 + Owner: Neutral + Actor12: tc05 + Location: 49,60 + Owner: Neutral + Actor13: tc04 + Location: 50,58 + Owner: Neutral + Actor14: tc03 + Location: 69,50 + Owner: Neutral + Actor15: t11 + Location: 77,60 + Owner: Neutral + Actor16: t01 + Location: 78,59 + Owner: Neutral + Actor17: tc01 + Location: 76,56 + Owner: Neutral + Actor18: t08 + Location: 66,50 + Owner: Neutral + Actor19: t17 + Location: 57,56 + Owner: Neutral + Actor20: t01 + Location: 73,67 + Owner: Neutral + Actor21: tc01 + Location: 54,45 + Owner: Neutral + Actor22: tsla + Location: 71,59 + Owner: USSR + Health: 1 + Facing: 0 + Actor23: powr + Location: 75,64 + Owner: USSR + Health: 1 + Facing: 0 + Actor24: powr + Location: 67,57 + Owner: USSR + Health: 1 + Facing: 0 + Actor25: powr + Location: 61,57 + Owner: USSR + Health: 1 + Facing: 0 + Lab: stek + Location: 61,60 + Owner: USSR + Health: 1 + Facing: 0 + Actor27: fact + Location: 69,62 + Owner: USSR + Health: 1 + Facing: 0 + Actor28: dome + Location: 67,65 + Owner: USSR + Health: 1 + Facing: 0 + Actor29: barr + Location: 61,64 + Owner: USSR + Health: 1 + Facing: 0 + Actor30: tsla + Location: 67,67 + Owner: USSR + Health: 1 + Facing: 0 + Actor31: tsla + Location: 60,66 + Owner: USSR + Health: 1 + Facing: 0 + Actor32: weap + Location: 65,62 + Owner: USSR + Health: 1 + Facing: 0 + Actor33: proc + Location: 73,58 + Owner: USSR + Health: 1 + Facing: 0 + FreeActor: False + Actor34: kenn + Location: 64,65 + Owner: USSR + Health: 0.9921875 + Facing: 0 + Actor35: powr + Location: 65,57 + Owner: USSR + Health: 1 + Facing: 0 + Actor36: powr + Location: 77,64 + Owner: USSR + Health: 1 + Facing: 0 + Actor37: powr + Location: 75,67 + Owner: USSR + Health: 1 + Facing: 0 + Actor38: silo + Location: 59,64 + Owner: USSR + Health: 1 + Facing: 0 + Actor39: powr + Location: 77,67 + Owner: USSR + Health: 1 + Facing: 0 + OilPump: v19 + Location: 59,57 + Owner: USSR + Health: 1 + Facing: 0 + Actor41: brl3 + Location: 60,57 + Owner: USSR + Health: 1 + Facing: 0 + Actor42: barl + Location: 60,56 + Owner: USSR + Health: 1 + Facing: 0 + Actor43: barl + Location: 61,56 + Owner: USSR + Health: 1 + Facing: 0 + Actor44: brl3 + Location: 60,58 + Owner: USSR + Health: 1 + Facing: 0 + Actor45: barl + Location: 58,56 + Owner: USSR + Health: 1 + Facing: 0 + Actor46: barl + Location: 59,59 + Owner: USSR + Health: 1 + Facing: 0 + Actor47: jeep + Location: 63,50 + Owner: Greece + Health: 1 + Facing: 128 + Harvester: harv + Location: 72,60 + Owner: USSR + Health: 1 + Facing: 224 + Actor49: jeep + Location: 62,50 + Owner: Greece + Health: 1 + Facing: 128 + Actor50: jeep + Location: 64,50 + Owner: Greece + Health: 1 + Facing: 128 + Patrol1: dog + Location: 63,59 + Owner: USSR + Health: 1 + Facing: 0 + SubCell: 2 + Patrol2: e1 + Location: 64,58 + Owner: USSR + Health: 1 + Facing: 0 + SubCell: 3 + LabGuard3: e1 + Location: 61,63 + Owner: USSR + Health: 1 + Facing: 128 + SubCell: 0 + LabGuard2: e1 + Location: 63,63 + Owner: USSR + Health: 1 + Facing: 96 + SubCell: 0 + Actor55: e2 + Location: 73,66 + Owner: USSR + Health: 1 + Facing: 0 + SubCell: 1 + Actor56: e1 + Location: 62,67 + Owner: USSR + Health: 1 + Facing: 128 + SubCell: 4 + Actor57: e1 + Location: 67,67 + Owner: USSR + Health: 1 + Facing: 160 + SubCell: 3 + Actor58: e1 + Location: 65,67 + Owner: USSR + Health: 1 + Facing: 160 + SubCell: 3 + Actor59: e1 + Location: 56,60 + Owner: USSR + Health: 1 + Facing: 96 + SubCell: 1 + Patrol4: e1 + Location: 62,55 + Owner: USSR + Health: 1 + Facing: 0 + SubCell: 4 + Patrol3: e1 + Location: 64,59 + Owner: USSR + Health: 1 + Facing: 0 + SubCell: 2 + LabGuard1: e1 + Location: 64,61 + Owner: USSR + Health: 1 + Facing: 0 + SubCell: 4 + Actor63: e1 + Location: 58,60 + Owner: USSR + Health: 1 + Facing: 64 + SubCell: 1 + Actor64: e1 + Location: 64,49 + Owner: Greece + Health: 1 + Facing: 128 + SubCell: 1 + Actor65: e1 + Location: 63,49 + Owner: Greece + Health: 1 + Facing: 128 + SubCell: 0 + Actor66: e1 + Location: 62,49 + Owner: Greece + Health: 1 + Facing: 160 + SubCell: 2 + Civilian1: c8 + Location: 74,50 + Owner: England + Health: 1 + Facing: 0 + SubCell: 0 + Civilian2: c7 + Location: 76,48 + Owner: England + Health: 1 + Facing: 0 + SubCell: 3 + Actor69: e2 + Location: 62,56 + Owner: USSR + Health: 1 + Facing: 32 + SubCell: 1 + Actor70: e2 + Location: 62,56 + Owner: USSR + Health: 1 + Facing: 0 + SubCell: 4 + Actor71: e1 + Location: 64,49 + Owner: Greece + Health: 1 + Facing: 128 + SubCell: 2 + Actor72: e1 + Location: 62,49 + Owner: Greece + Health: 1 + Facing: 128 + SubCell: 1 + ExtractionLZ: waypoint + Location: 53,49 + Owner: Neutral + waypoint1: waypoint + Location: 57,74 + Owner: Neutral + waypoint2: waypoint + Location: 53,79 + Owner: Neutral + waypoint3: waypoint + Location: 57,65 + Owner: Neutral + CruiserCameraPoint: waypoint + Location: 69,67 + Owner: Neutral + waypoint7: waypoint + Location: 69,56 + Owner: Neutral + waypoint6: waypoint + Location: 55,60 + Owner: Neutral + EinsteinSpawnPoint: waypoint + Location: 62,61 + Owner: Neutral + waypoint8: waypoint + Location: 49,55 + Owner: Neutral + waypoint9: waypoint + Location: 55,56 + Owner: Neutral + InsertionLZ: waypoint + Location: 63,47 + Owner: Neutral + InsertionEntry: waypoint + Location: 63,45 + Owner: Neutral + BaseCameraPoint: waypoint + Location: 64,63 + Owner: Neutral + CruiserPoint4: waypoint + Location: 72,75 + Owner: Neutral + SouthReinforcementsPoint: waypoint + Location: 66,80 + Owner: Neutral + ExtractionFlarePoint: waypoint + Location: 54,48 + Owner: Neutral + CruiserPoint2: waypoint + Location: 64,75 + Owner: Neutral + CruiserPoint3: waypoint + Location: 68,76 + Owner: Neutral + CruiserPoint1: waypoint + Location: 60,74 + Owner: Neutral + waypoint78: waypoint + Location: 70,60 + Owner: Neutral + waypoint98: waypoint + Location: 63,47 + Owner: Neutral + Actor48: fenc + Location: 53,60 + Owner: USSR + Actor51: fenc + Location: 53,59 + Owner: USSR + Actor52: fenc + Location: 54,59 + Owner: USSR + Actor60: fenc + Location: 53,63 + Owner: USSR + Actor61: fenc + Location: 54,63 + Owner: USSR + Actor73: fenc + Location: 55,63 + Owner: USSR + Actor74: fenc + Location: 55,64 + Owner: USSR + Actor75: fenc + Location: 55,65 + Owner: USSR + Actor76: fenc + Location: 55,66 + Owner: USSR + Actor77: fenc + Location: 55,67 + Owner: USSR + Actor78: fenc + Location: 56,67 + Owner: USSR + Actor79: fenc + Location: 57,67 + Owner: USSR + Actor80: fenc + Location: 58,67 + Owner: USSR + Actor81: fenc + Location: 58,68 + Owner: USSR + Actor82: fenc + Location: 73,70 + Owner: USSR + Actor83: fenc + Location: 74,70 + Owner: USSR + Actor84: fenc + Location: 78,70 + Owner: USSR + Actor85: fenc + Location: 77,70 + Owner: USSR + Actor86: fenc + Location: 76,70 + Owner: USSR + Actor87: fenc + Location: 78,58 + Owner: USSR + Actor99: fenc + Location: 78,59 + Owner: USSR + Actor88: fenc + Location: 77,58 + Owner: USSR + Actor89: fenc + Location: 78,57 + Owner: USSR + Actor90: fenc + Location: 78,56 + Owner: USSR + Actor91: fenc + Location: 77,56 + Owner: USSR + Actor98: fenc + Location: 76,56 + Owner: USSR + Actor92: fenc + Location: 75,56 + Owner: USSR + Actor93: fenc + Location: 74,56 + Owner: USSR + Actor94: fenc + Location: 74,55 + Owner: USSR + Actor95: fenc + Location: 68,55 + Owner: USSR + Actor96: fenc + Location: 69,55 + Owner: USSR + Actor97: fenc + Location: 68,54 + Owner: USSR + ExtractionExitPoint: waypoint + Location: 78,49 + Owner: Neutral + +Smudges: + +Rules: + Player: + -ConquestVictoryConditions: + World: + -CrateDrop: + -SpawnMPUnits: + -MPStartLocations: + LuaScriptInterface: + LuaScripts: mission.lua + TRAN.Extraction: + Inherits: TRAN + RenderUnit: + Image: tran + RevealsShroud: + Range: 0 + RejectsOrders: + -Selectable: + Cargo: + Types: Einstein + MaxWeight: 1 + TRAN.Insertion: + Inherits: TRAN.Extraction + RenderUnit: + Image: tran + Cargo: + MaxWeight: 0 + EINSTEIN: + Passenger: + CargoType: Einstein + ^CivInfantry: + RevealsShroud: + Range: 0 + +Sequences: + +VoxelSequences: + +Weapons: + 8Inch: + Range: 25 + + M60mg: + Range: 5 + ROF: 20 + Burst: 1 + Warhead: + Damage: 20 +Voices: + +Notifications: + +Translations: diff --git a/mods/ra/maps/allies-01-classic/mission.lua b/mods/ra/maps/allies-01-classic/mission.lua new file mode 100644 index 0000000000..b57014e5c3 --- /dev/null +++ b/mods/ra/maps/allies-01-classic/mission.lua @@ -0,0 +1,151 @@ +InsertionHelicopterType = "tran.insertion" +ExtractionHelicopterType = "tran.extraction" +JeepReinforcements = { "jeep", "jeep" } +JeepInterval = 50 +JeepDelay = 125 +TanyaType = "e7" +EinsteinType = "einstein" +FlareType = "flare" +Cruisers = { "ca", "ca", "ca", "ca" } +CruiserDelay = 250 +CameraDelay = 125 +CivilianWait = 150 +BaseAlertDelay = 300 + +SendInsertionHelicopter = function() + local heli, passengers = Mission.PerformHelicopterInsertion(player, InsertionHelicopterType, { TanyaType }, + InsertionEntry.CenterPosition, InsertionLZ.CenterPosition, InsertionEntry.CenterPosition) + tanya = passengers[1] + Actor.OnKilled(tanya, TanyaKilled) +end + +SendJeeps = function() + Media.PlaySpeechNotification("ReinforcementsArrived") + Mission.Reinforce(player, JeepReinforcements, InsertionEntry.Location, InsertionLZ.Location, JeepInterval) +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) +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 + end) + + OpenRA.RunAfterDelay(CruiserDelay, function() + Media.PlaySpeechNotification("AlliedReinforcementsArrived") + Actor.Create("camera", { Owner = player, Location = CruiserCameraPoint.Location }) + SendCruisers() + end) +end + +SendExtractionHelicopter = function() + local heli = Mission.PerformHelicopterExtraction(player, ExtractionHelicopterType, { einstein }, + SouthReinforcementsPoint.CenterPosition, ExtractionLZ.CenterPosition, ExtractionExitPoint.CenterPosition) + Actor.OnKilled(heli, HelicopterDestroyed) + Actor.OnRemovedFromWorld(heli, HelicopterExtractionCompleted) +end + +HelicopterExtractionCompleted = function() + MissionAccomplished() +end + +SendCruisers = function() + for i, cruiser in ipairs(Cruisers) do + local ca = Actor.Create(cruiser, { Owner = england, Location = SouthReinforcementsPoint.Location }) + Actor.Move(ca, _G["CruiserPoint" .. i].Location) + end +end + +LabDestroyed = function(self, e) + if not einstein then + MissionFailed() + end +end + +EinsteinKilled = function(self, e) + MissionFailed() +end + +HelicopterDestroyed = function(self, e) + MissionFailed() +end + +TanyaKilled = function(self, e) + MissionFailed() +end + +OilPumpDestroyed = function(self, e) + OpenRA.RunAfterDelay(JeepDelay, SendJeeps) +end + +CreateEinstein = function() + einstein = Actor.Create(EinsteinType, { Location = EinsteinSpawnPoint.Location, Owner = player }) + Actor.Scatter(einstein) + Actor.OnKilled(einstein, EinsteinKilled) +end + +MissionAccomplished = function() + Mission.MissionOver({ player }, nil, false) + --Media.PlayMovieFullscreen("snowbomb.vqa") +end + +MissionFailed = function() + Mission.MissionOver(nil, { player }, false) + 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") + end +end + +Tick = function() + Mission.TickTakeOre(ussr) +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.Create({ LabGuard1, LabGuard2, LabGuard3 }) + Team.AddEventHandler(labGuardsTeam.OnAllKilled, LabGuardsKilled) + + civiliansTeam = Team.Create({ Civilian1, Civilian2 }) + + 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 diff --git a/mods/ra/maps/allies-02-classic/map.bin b/mods/ra/maps/allies-02-classic/map.bin new file mode 100644 index 0000000000..ebace1686e Binary files /dev/null and b/mods/ra/maps/allies-02-classic/map.bin differ diff --git a/mods/ra/maps/allies-02-classic/map.yaml b/mods/ra/maps/allies-02-classic/map.yaml new file mode 100644 index 0000000000..4461dbbef2 --- /dev/null +++ b/mods/ra/maps/allies-02-classic/map.yaml @@ -0,0 +1,954 @@ +Selectable: True + +MapFormat: 6 + +Title: Allies 02: Five to one + +Description: Five to one + +Author: Westwood Studios + +Tileset: SNOW + +Options: + Crates: False + Fog: True + Shroud: True + AllyBuildRadius: False + FragileAlliances: False + StartingCash: 5700 + ConfigurableStartingUnits: False + Difficulties: + +MapSize: 128,128 + +RequiresMod: ra + +Bounds: 43,44,50,42 + +UseAsShellmap: False + +Type: Campaign + +Players: + PlayerReference@USSR: + Name: USSR + Race: soviet + ColorRamp: 3,255,127 + Allies: BadGuy + Enemies: England,Greece + PlayerReference@France: + Name: France + Race: allies + ColorRamp: 115,115,143 + Allies: England,Greece + Enemies: USSR,BadGuy + PlayerReference@Neutral: + Name: Neutral + OwnsWorld: True + NonCombatant: True + Race: allies + Enemies: England,Greece + PlayerReference@BadGuy: + Name: BadGuy + Race: soviet + ColorRamp: 3,255,127 + Allies: USSR + Enemies: England,Greece + PlayerReference@Greece: + Name: Greece + Playable: True + AllowBots: False + Required: True + LockRace: True + Race: allies + LockColor: True + ColorRamp: 161,134,200 + LockSpawn: True + LockTeam: True + Allies: France,England + Enemies: USSR,BadGuy + +Actors: + EntryPoint: t06 + Location: 75,80 + Owner: Neutral + Actor1: t03 + Location: 75,72 + Owner: Neutral + Actor2: t08 + Location: 92,60 + Owner: Neutral + Actor3: t12 + Location: 92,63 + Owner: Neutral + Actor4: t01 + Location: 89,62 + Owner: Neutral + Actor5: t16 + Location: 61,44 + Owner: Neutral + Actor6: t14 + Location: 58,49 + Owner: Neutral + Actor7: t10 + Location: 55,46 + Owner: Neutral + Actor8: t10 + Location: 43,56 + Owner: Neutral + Actor9: t01 + Location: 45,56 + Owner: Neutral + Actor10: t17 + Location: 53,66 + Owner: Neutral + Actor11: tc01 + Location: 59,60 + Owner: Neutral + Actor12: tc01 + Location: 63,74 + Owner: Neutral + Actor13: t07 + Location: 44,77 + Owner: Neutral + Actor14: t08 + Location: 50,78 + Owner: Neutral + Actor15: t11 + Location: 51,71 + Owner: Neutral + Actor16: t10 + Location: 68,77 + Owner: Neutral + Actor17: tc02 + Location: 69,72 + Owner: Neutral + Actor18: tc03 + Location: 71,52 + Owner: Neutral + Actor19: tc04 + Location: 67,76 + Owner: Neutral + Actor20: t17 + Location: 70,55 + Owner: Neutral + Actor21: tc01 + Location: 70,54 + Owner: Neutral + Actor22: t06 + Location: 67,54 + Owner: Neutral + Actor23: t01 + Location: 67,44 + Owner: Neutral + Actor24: tc02 + Location: 67,51 + Owner: Neutral + Actor25: tc04 + Location: 67,49 + Owner: Neutral + Actor26: t17 + Location: 69,50 + Owner: Neutral + Actor27: t08 + Location: 64,55 + Owner: Neutral + Actor28: t16 + Location: 72,62 + Owner: Neutral + Actor29: t15 + Location: 71,63 + Owner: Neutral + Actor30: tc04 + Location: 67,66 + Owner: Neutral + Actor31: tc05 + Location: 68,67 + Owner: Neutral + Actor32: t17 + Location: 67,62 + Owner: Neutral + Actor33: tc02 + Location: 44,68 + Owner: Neutral + Actor34: t12 + Location: 93,81 + Owner: Neutral + Actor35: t03 + Location: 93,55 + Owner: Neutral + Actor36: t02 + Location: 93,57 + Owner: Neutral + Actor37: t02 + Location: 79,47 + Owner: Neutral + Actor38: t11 + Location: 77,56 + Owner: Neutral + Actor39: t01 + Location: 92,45 + Owner: Neutral + Actor40: t05 + Location: 93,54 + Owner: Neutral + Actor41: t06 + Location: 93,82 + Owner: Neutral + Actor42: t07 + Location: 87,44 + Owner: Neutral + Actor43: t14 + Location: 46,84 + Owner: Neutral + Actor44: t08 + Location: 48,85 + Owner: Neutral + Actor45: t07 + Location: 51,84 + Owner: Neutral + Actor46: tc01 + Location: 62,84 + Owner: Neutral + Actor47: t11 + Location: 59,71 + Owner: Neutral + Actor48: t01 + Location: 45,44 + Owner: Neutral + Actor49: tc04 + Location: 45,53 + Owner: Neutral + Actor50: t11 + Location: 54,55 + Owner: Neutral + Actor51: t10 + Location: 84,71 + Owner: Neutral + Actor52: tc05 + Location: 90,83 + Owner: Neutral + Actor53: tc01 + Location: 89,84 + Owner: Neutral + Actor54: tc04 + Location: 85,81 + Owner: Neutral + Actor55: tc05 + Location: 43,71 + Owner: Neutral + Actor56: tc03 + Location: 43,70 + Owner: Neutral + Actor57: weap + Location: 60,66 + Owner: USSR + Health: 1 + Facing: 0 + Actor58: fact + Location: 62,61 + Owner: USSR + Health: 1 + Facing: 0 + Actor59: proc + Location: 53,62 + Owner: USSR + Health: 1 + Facing: 0 + FreeActor: False + Actor60: powr + Location: 57,62 + Owner: USSR + Health: 1 + Facing: 0 + Actor61: barr + Location: 56,66 + Owner: USSR + Health: 1 + Facing: 0 + Actor62: powr + Location: 59,62 + Owner: USSR + Health: 1 + Facing: 0 + Actor63: kenn + Location: 58,68 + Owner: USSR + Health: 0.9921875 + Facing: 0 + Actor64: brl3 + Location: 65,59 + Owner: USSR + Health: 1 + Facing: 0 + Actor65: barl + Location: 66,60 + Owner: USSR + Health: 1 + Facing: 0 + Actor66: barl + Location: 65,60 + Owner: USSR + Health: 1 + Facing: 0 + Actor67: brl3 + Location: 64,60 + Owner: USSR + Health: 1 + Facing: 0 + Actor68: barl + Location: 65,61 + Owner: USSR + Health: 1 + Facing: 0 + Actor69: v19 + Location: 67,60 + Owner: USSR + Health: 1 + Facing: 0 + Actor70: v19 + Location: 67,59 + Owner: USSR + Health: 1 + Facing: 0 + Actor71: barl + Location: 65,62 + Owner: USSR + Health: 1 + Facing: 0 + Actor72: silo + Location: 54,68 + Owner: USSR + Health: 1 + Facing: 0 + Actor73: brl3 + Location: 55,70 + Owner: USSR + Health: 1 + Facing: 0 + Actor74: brl3 + Location: 54,70 + Owner: USSR + Health: 1 + Facing: 0 + Actor75: barl + Location: 53,69 + Owner: USSR + Health: 1 + Facing: 0 + Actor76: barl + Location: 54,69 + Owner: USSR + Health: 1 + Facing: 0 + Actor77: barl + Location: 55,71 + Owner: USSR + Health: 1 + Facing: 0 + Actor78: brl3 + Location: 56,71 + Owner: USSR + Health: 1 + Facing: 0 + Actor79: brl3 + Location: 53,68 + Owner: USSR + Health: 1 + Facing: 0 + Actor80: v19 + Location: 56,70 + Owner: USSR + Health: 1 + Facing: 0 + Actor81: barl + Location: 55,69 + Owner: USSR + Health: 1 + Facing: 0 + Actor82: brl3 + Location: 72,51 + Owner: USSR + Health: 1 + Facing: 0 + Actor83: barl + Location: 72,50 + Owner: USSR + Health: 1 + Facing: 0 + Actor84: barl + Location: 74,48 + Owner: USSR + Health: 1 + Facing: 0 + Actor85: barl + Location: 72,49 + Owner: USSR + Health: 1 + Facing: 0 + Actor86: barl + Location: 73,48 + Owner: USSR + Health: 1 + Facing: 0 + Actor87: v19 + Location: 75,48 + Owner: USSR + Health: 0.5195313 + Facing: 0 + Actor88: v19 + Location: 62,57 + Owner: USSR + Health: 1 + Facing: 0 + Actor89: v19 + Location: 60,58 + Owner: USSR + Health: 1 + Facing: 0 + Actor90: brl3 + Location: 62,56 + Owner: USSR + Health: 1 + Facing: 0 + Actor91: brl3 + Location: 61,58 + Owner: USSR + Health: 1 + Facing: 0 + Actor92: barl + Location: 61,57 + Owner: USSR + Health: 1 + Facing: 0 + Actor93: brl3 + Location: 59,58 + Owner: USSR + Health: 1 + Facing: 0 + Actor94: barl + Location: 58,58 + Owner: USSR + Health: 1 + Facing: 0 + Harvester: harv + Location: 55,65 + Owner: USSR + Health: 0.5 + Facing: 160 + Actor96: dog + Location: 53,58 + Owner: USSR + Health: 1 + Facing: 0 + SubCell: 1 + Actor97: dog + Location: 65,68 + Owner: USSR + Health: 1 + Facing: 64 + SubCell: 3 + Actor98: dog + Location: 65,66 + Owner: USSR + Health: 1 + Facing: 32 + SubCell: 2 + Actor99: dog + Location: 59,70 + Owner: USSR + Health: 1 + Facing: 160 + SubCell: 2 + Actor100: e2 + Location: 61,56 + Owner: USSR + Health: 1 + Facing: 32 + SubCell: 3 + Actor101: e2 + Location: 59,57 + Owner: USSR + Health: 1 + Facing: 224 + SubCell: 4 + Actor102: e2 + Location: 64,67 + Owner: USSR + Health: 1 + Facing: 96 + SubCell: 0 + Actor103: e1 + Location: 77,74 + Owner: BadGuy + Health: 1 + Facing: 128 + SubCell: 2 + Actor104: e1 + Location: 80,74 + Owner: USSR + Health: 1 + Facing: 160 + SubCell: 0 + Actor105: e1 + Location: 56,68 + Owner: USSR + Health: 1 + Facing: 160 + SubCell: 3 + Actor106: e1 + Location: 50,72 + Owner: USSR + Health: 1 + Facing: 160 + SubCell: 4 + Actor107: e1 + Location: 73,60 + Owner: USSR + Health: 1 + Facing: 32 + SubCell: 2 + Actor108: e1 + Location: 74,61 + Owner: USSR + Health: 1 + Facing: 224 + SubCell: 1 + Actor109: e1 + Location: 72,60 + Owner: USSR + Health: 1 + Facing: 64 + SubCell: 0 + Actor110: e1 + Location: 49,58 + Owner: USSR + Health: 1 + Facing: 192 + SubCell: 0 + Actor111: e1 + Location: 51,58 + Owner: USSR + Health: 1 + Facing: 32 + SubCell: 1 + Actor112: e1 + Location: 60,78 + Owner: USSR + Health: 1 + Facing: 192 + SubCell: 4 + Actor113: e2 + Location: 62,79 + Owner: USSR + Health: 1 + Facing: 160 + SubCell: 4 + Actor114: e1 + Location: 57,82 + Owner: USSR + Health: 1 + Facing: 160 + SubCell: 1 + Actor115: e1 + Location: 60,64 + Owner: USSR + Health: 1 + Facing: 224 + SubCell: 3 + Actor116: e2 + Location: 68,45 + Owner: USSR + Health: 1 + Facing: 96 + SubCell: 0 + Actor117: e1 + Location: 48,72 + Owner: USSR + Health: 1 + Facing: 96 + SubCell: 0 + Actor118: e1 + Location: 57,69 + Owner: USSR + Health: 1 + Facing: 96 + SubCell: 1 + Actor119: e2 + Location: 60,70 + Owner: USSR + Health: 1 + Facing: 32 + SubCell: 0 + Actor120: e1 + Location: 89,48 + Owner: Greece + Health: 1 + Facing: 160 + SubCell: 1 + Actor121: e1 + Location: 87,48 + Owner: Greece + Health: 1 + Facing: 192 + SubCell: 4 + Actor122: e1 + Location: 87,48 + Owner: Greece + Health: 1 + Facing: 192 + SubCell: 1 + Actor123: e1 + Location: 88,48 + Owner: Greece + Health: 1 + Facing: 128 + SubCell: 4 + Actor124: e1 + Location: 88,49 + Owner: Greece + Health: 1 + Facing: 128 + SubCell: 1 + Actor125: dog + Location: 78,75 + Owner: BadGuy + Health: 1 + Facing: 160 + SubCell: 1 + Actor126: e1 + Location: 71,61 + Owner: BadGuy + Health: 1 + Facing: 160 + SubCell: 0 + Actor127: dog + Location: 70,61 + Owner: BadGuy + Health: 1 + Facing: 96 + SubCell: 4 + Actor128: e1 + Location: 50,46 + Owner: BadGuy + Health: 1 + Facing: 32 + SubCell: 1 + Actor129: e1 + Location: 49,47 + Owner: BadGuy + Health: 1 + Facing: 64 + SubCell: 0 + Actor130: e2 + Location: 49,49 + Owner: BadGuy + Health: 1 + Facing: 160 + SubCell: 1 + Actor131: e2 + Location: 47,46 + Owner: BadGuy + Health: 1 + Facing: 96 + SubCell: 3 + Actor132: e2 + Location: 48,63 + Owner: BadGuy + Health: 1 + Facing: 0 + SubCell: 1 + Actor133: e1 + Location: 49,63 + Owner: BadGuy + Health: 1 + Facing: 96 + SubCell: 2 + Actor134: e1 + Location: 74,81 + Owner: BadGuy + Health: 1 + Facing: 64 + SubCell: 3 + Actor135: e2 + Location: 75,83 + Owner: BadGuy + Health: 1 + Facing: 96 + SubCell: 0 + Actor136: e2 + Location: 69,66 + Owner: USSR + Health: 1 + Facing: 0 + SubCell: 3 + Actor137: e2 + Location: 73,51 + Owner: USSR + Health: 0.5585938 + Facing: 224 + SubCell: 4 + Actor138: medi + Location: 88,48 + Owner: Greece + Health: 1 + Facing: 160 + SubCell: 1 + TruckEntryPoint: waypoint + Location: 49,44 + Owner: Neutral + waypoint1: waypoint + Location: 49,50 + Owner: Neutral + TruckRallyPoint: waypoint + Location: 49,76 + Owner: Neutral + waypoint3: waypoint + Location: 65,82 + Owner: Neutral + waypoint4: waypoint + Location: 74,82 + Owner: Neutral + waypoint6: waypoint + Location: 65,82 + Owner: Neutral + waypoint7: waypoint + Location: 74,82 + Owner: Neutral + waypoint8: waypoint + Location: 78,74 + Owner: Neutral + waypoint9: waypoint + Location: 82,65 + Owner: Neutral + ReinforcementsRallyPoint: waypoint + Location: 88,49 + Owner: Neutral + waypoint11: waypoint + Location: 51,65 + Owner: Neutral + waypoint12: waypoint + Location: 63,64 + Owner: Neutral + waypoint13: waypoint + Location: 72,61 + Owner: Neutral + waypoint14: waypoint + Location: 69,47 + Owner: Neutral + waypoint15: waypoint + Location: 78,51 + Owner: Neutral + waypoint16: waypoint + Location: 80,45 + Owner: Neutral + waypoint25: waypoint + Location: 80,89 + Owner: Neutral + waypoint26: waypoint + Location: 43,63 + Owner: Neutral + waypoint94: waypoint + Location: 90,46 + Owner: Neutral + McvDeployPoint: waypoint + Location: 89,51 + Owner: Neutral + waypoint96: waypoint + Location: 90,68 + Owner: Neutral + waypoint98: waypoint + Location: 88,49 + Owner: Neutral + Actor139: fenc + Location: 57,75 + Owner: USSR + Actor140: fenc + Location: 57,76 + Owner: USSR + Actor141: fenc + Location: 57,77 + Owner: USSR + Actor142: fenc + Location: 58,77 + Owner: USSR + Actor143: fenc + Location: 58,78 + Owner: USSR + Actor144: fenc + Location: 57,78 + Owner: USSR + Actor145: fenc + Location: 58,75 + Owner: USSR + Actor146: fenc + Location: 58,74 + Owner: USSR + Actor147: fenc + Location: 57,74 + Owner: USSR + Actor148: fenc + Location: 66,67 + Owner: USSR + Actor149: fenc + Location: 66,68 + Owner: USSR + Actor150: fenc + Location: 66,69 + Owner: USSR + Actor151: fenc + Location: 66,70 + Owner: USSR + Actor152: fenc + Location: 65,70 + Owner: USSR + Actor153: fenc + Location: 64,70 + Owner: USSR + Actor154: fenc + Location: 63,70 + Owner: USSR + Actor155: fenc + Location: 51,68 + Owner: USSR + Actor156: fenc + Location: 52,68 + Owner: USSR + Actor157: fenc + Location: 52,67 + Owner: USSR + Actor158: fenc + Location: 52,66 + Owner: USSR + Actor159: fenc + Location: 51,66 + Owner: USSR + Actor160: fenc + Location: 51,62 + Owner: USSR + Actor161: fenc + Location: 51,63 + Owner: USSR + Actor162: fenc + Location: 67,58 + Owner: USSR + Actor163: fenc + Location: 66,58 + Owner: USSR + Actor164: fenc + Location: 66,59 + Owner: USSR + Actor165: fenc + Location: 47,51 + Owner: USSR + Actor166: fenc + Location: 47,50 + Owner: USSR + Actor167: fenc + Location: 46,50 + Owner: USSR + Actor168: fenc + Location: 51,50 + Owner: USSR + Actor169: fenc + Location: 50,50 + Owner: USSR + Actor170: fenc + Location: 50,51 + Owner: USSR + ReinforcementsEntryPoint: waypoint + Location: 90,44 + Owner: Neutral + TruckExitPoint: waypoint + Location: 80,85 + Owner: Neutral + +Smudges: + +Rules: + Player: + -ConquestVictoryConditions: + World: + -CrateDrop: + -SpawnMPUnits: + -MPStartLocations: + LuaScriptInterface: + LuaScripts: mission.lua + ^Infantry: + MustBeDestroyed: + ^Tank: + MustBeDestroyed: + ^Vehicle: + MustBeDestroyed: + APWR: + Buildable: + Owner: None + FIX: + Buildable: + Owner: None + SYRD: + Buildable: + Owner: None + WEAP: + Buildable: + Owner: None + DOME: + Buildable: + Owner: None + HPAD: + Buildable: + Owner: None + ATEK: + Buildable: + Owner: None + BRIK: + Buildable: + Owner: None + HBOX.E1: + Buildable: + Owner: None + GUN: + Buildable: + Owner: None + AGUN: + Buildable: + Owner: None + GAP: + Buildable: + Owner: None + PDOX: + Buildable: + Owner: None + MSLO: + Buildable: + Owner: None + E6: + Buildable: + Owner: None + SPY: + Buildable: + Owner: None + MECH: + Buildable: + Owner: None + E7: + Buildable: + Owner: None + +Sequences: + +VoxelSequences: + +Weapons: + M60mg: + Range: 5 + ROF: 20 + Burst: 1 + Warhead: + Damage: 20 +Voices: + +Notifications: + +Translations: diff --git a/mods/ra/maps/allies-02-classic/mission.lua b/mods/ra/maps/allies-02-classic/mission.lua new file mode 100644 index 0000000000..b6c0bf1d37 --- /dev/null +++ b/mods/ra/maps/allies-02-classic/mission.lua @@ -0,0 +1,78 @@ +Reinforcements = { "e1", "e1", "e1", "jeep" } +ReinforcementsInterval = 15 +TruckNames = { "truk", "truk", "truk" } +TruckInterval = 25 +TruckDelay = 75 +FirstJeepReinforcementsDelay = 125 +SecondJeepReinforcementsDelay = 250 + +SendMcvReinforcements = function() + Media.PlaySpeechNotification("ReinforcementsArrived") + local mcv = Actor.Create("mcv", { Owner = player, Location = ReinforcementsEntryPoint.Location }) + Actor.Move(mcv, McvDeployPoint.Location) + Actor.DeployTransform(mcv) +end + +SendJeepReinforcements = function() + Media.PlaySpeechNotification("ReinforcementsArrived") + Mission.Reinforce(player, Reinforcements, ReinforcementsEntryPoint.Location, ReinforcementsRallyPoint.Location, ReinforcementsInterval) +end + +RunInitialActivities = function() + Actor.Harvest(Harvester) +end + +MissionAccomplished = function() + Mission.MissionOver({ player }, nil, false) + Media.PlayMovieFullscreen("montpass.vqa") +end + +MissionFailed = function() + Mission.MissionOver(nil, { player }, false) + Media.PlayMovieFullscreen("frozen.vqa") +end + +Tick = function() + Mission.TickTakeOre(ussr) + + if not Mission.MissionIsOver then + if Mission.RequiredUnitsAreDestroyed(player) then + MissionFailed() + end + if not trucksSent and Mission.RequiredUnitsAreDestroyed(ussr) and Mission.RequiredUnitsAreDestroyed(badGuy) then + SendTrucks() + trucksSent = true + end + end +end + +SendTrucks = function() + Media.PlaySpeechNotification("ConvoyApproaching") + OpenRA.RunAfterDelay(TruckDelay, function() + local trucks = Mission.Reinforce(france, TruckNames, TruckEntryPoint.Location, TruckRallyPoint.Location, TruckInterval, + function(truck) + Actor.Move(truck, TruckExitPoint.Location) + Actor.RemoveSelf(truck) + end) + local trucksTeam = Team.Create(trucks) + Team.AddEventHandler(trucksTeam.OnAllRemovedFromWorld, MissionAccomplished) + Team.AddEventHandler(trucksTeam.OnAnyKilled, MissionFailed) + end) +end + +WorldLoaded = function() + player = OpenRA.GetPlayer("Greece") + france = OpenRA.GetPlayer("France") + ussr = OpenRA.GetPlayer("USSR") + badGuy = OpenRA.GetPlayer("BadGuy") + + RunInitialActivities() + + SendMcvReinforcements() + OpenRA.RunAfterDelay(FirstJeepReinforcementsDelay, SendJeepReinforcements) + OpenRA.RunAfterDelay(SecondJeepReinforcementsDelay, SendJeepReinforcements) + + OpenRA.SetViewportCenterPosition(ReinforcementsEntryPoint.CenterPosition) + + Media.PlayMovieFullscreen("ally2.vqa", function() Media.PlayMovieFullscreen("mcv.vqa", Media.PlayRandomMusic) end) +end \ No newline at end of file diff --git a/mods/ra/mod.yaml b/mods/ra/mod.yaml index d694d00fd3..e36a9a7edb 100644 --- a/mods/ra/mod.yaml +++ b/mods/ra/mod.yaml @@ -164,3 +164,12 @@ Fonts: TinyBold: Font:FreeSansBold.ttf Size:10 + +LuaScripts: + mods/ra/lua/utils.lua + mods/ra/lua/openra.lua + mods/ra/lua/map.lua + mods/ra/lua/actor.lua + mods/ra/lua/team.lua + mods/ra/lua/media.lua + mods/ra/lua/mission.lua diff --git a/mods/ra/notifications.yaml b/mods/ra/notifications.yaml index aeab522df8..ba56e3698c 100644 --- a/mods/ra/notifications.yaml +++ b/mods/ra/notifications.yaml @@ -24,7 +24,10 @@ Speech: NavalUnitLost: navylst1 AirUnitLost: aunitl1 BuildingCaptured: strucap1 - + ReinforcementsArrived: reinfor1 + SignalFlareNorth: flaren1 + AlliedReinforcementsArrived: aarrive1 + ConvoyApproaching: convyap1 Sounds: Notifications: diff --git a/mods/ra/rules/civilian.yaml b/mods/ra/rules/civilian.yaml index 68a3f7091e..5b178ffb82 100644 --- a/mods/ra/rules/civilian.yaml +++ b/mods/ra/rules/civilian.yaml @@ -242,6 +242,19 @@ V19: ExcludeTilesets: DESERT Tooltip: Name: Oil Pump + LeavesHusk: + HuskActor: V19.Husk + AutoTargetIgnore: + +V19.Husk: + Inherits: ^CivBuilding + EditorTilesetFilter: + ExcludeTilesets: DESERT + Tooltip: + Name: Husk (Oil Pump) + WithFire: + -Health: + -Selectable: BARL: Inherits: ^TechBuilding @@ -327,7 +340,6 @@ OILB: ExternalCapturable: ExternalCapturableBar: EngineerRepairable: - -MustBeDestroyed: CashTrickler: Period: 250 Amount: 100 diff --git a/mods/ra/rules/defaults.yaml b/mods/ra/rules/defaults.yaml index e498b58415..87f214d0c2 100644 --- a/mods/ra/rules/defaults.yaml +++ b/mods/ra/rules/defaults.yaml @@ -42,6 +42,8 @@ SuccessRate: 20 EjectOnGround: yes EjectInAir: no + Huntable: + LuaScriptEvents: ^Tank: AppearsOnRadar: @@ -87,6 +89,8 @@ SuccessRate: 20 EjectOnGround: yes EjectInAir: no + Huntable: + LuaScriptEvents: ^Infantry: AppearsOnRadar: @@ -142,6 +146,8 @@ HealIfBelow: 1 DamageCooldown: 125 RequiresTech: InfantryHealing + Huntable: + LuaScriptEvents: ^Ship: AppearsOnRadar: @@ -174,6 +180,8 @@ Guard: Guardable: BodyOrientation: + Huntable: + LuaScriptEvents: ^Plane: AppearsOnRadar: @@ -203,6 +211,8 @@ UpdatesPlayerStatistics: CombatDebugOverlay: BodyOrientation: + Huntable: + LuaScriptEvents: ^Helicopter: Inherits: ^Plane @@ -252,6 +262,8 @@ FrozenUnderFog: GpsDot: String:Structure + Huntable: + LuaScriptEvents: ^Wall: AppearsOnRadar: @@ -287,6 +299,7 @@ Guardable: BodyOrientation: FrozenUnderFog: + LuaScriptEvents: ^TechBuilding: Inherits: ^Building @@ -308,6 +321,7 @@ FrozenUnderFog: StartsRevealed: true -GpsDot: + -MustBeDestroyed: ^AmmoBox: Inherits: ^TechBuilding @@ -390,6 +404,7 @@ BodyOrientation: FrozenUnderFog: StartsRevealed: true + LuaScriptEvents: ^Husk: Husk: @@ -407,6 +422,7 @@ BelowUnits: BodyOrientation: Chronoshiftable: + LuaScriptEvents: ^HelicopterHusk: Inherits: ^Husk @@ -441,6 +457,7 @@ Types:Bridge AutoTargetIgnore: BodyOrientation: + LuaScriptEvents: #Temperate Terrain Expansion ^SVBridge: @@ -458,6 +475,7 @@ Types:Bridge AutoTargetIgnore: BodyOrientation: + LuaScriptEvents: ^SHBridge: Tooltip: @@ -474,6 +492,7 @@ Types:Bridge AutoTargetIgnore: BodyOrientation: + LuaScriptEvents: ^STDBridge: Tooltip: @@ -490,6 +509,7 @@ Types:Bridge AutoTargetIgnore: BodyOrientation: + LuaScriptEvents: #Desert Terrain Expansion: ^Rock: @@ -511,6 +531,7 @@ BodyOrientation: FrozenUnderFog: StartsRevealed: true + LuaScriptEvents: ^DesertCivBuilding: Inherits: ^CivBuilding diff --git a/mods/ra/sequences/decorations.yaml b/mods/ra/sequences/decorations.yaml index 873d0cdd44..25a4038ed0 100644 --- a/mods/ra/sequences/decorations.yaml +++ b/mods/ra/sequences/decorations.yaml @@ -357,9 +357,18 @@ v19: idle: Start: 0 Length: 14 - damaged-idle: - Start: 14 - Length: 15 + +v19.husk: + idle: v19 + Start: 28 + fire-start: flmspt + Start: 0 + Length: * + Offset: 7,-15 + fire-loop: flmspt + Start: 50 + Length: * + Offset: 7,-15 utilpol1: idle: diff --git a/mods/ra/voices.yaml b/mods/ra/voices.yaml index 27b02ec431..5eab711aa4 100644 --- a/mods/ra/voices.yaml +++ b/mods/ra/voices.yaml @@ -78,8 +78,8 @@ CivilianFemaleVoice: EinsteinVoice: Voices: - Select: einah1,einok1,einyes1 - Move: einah1,einok1,einyes1 + Select: einah1 + Move: einok1,einyes1 Die: dedman1,dedman2,dedman3,dedman4,dedman5,dedman6,dedman7,dedman8,dedman10 ShokVoice: diff --git a/mods/ts/mod.yaml b/mods/ts/mod.yaml index 63adc87e73..0030ff7b92 100644 --- a/mods/ts/mod.yaml +++ b/mods/ts/mod.yaml @@ -185,3 +185,12 @@ Fonts: TinyBold: Font:FreeSansBold.ttf Size:10 + +LuaScripts: + mods/ra/lua/utils.lua + mods/ra/lua/openra.lua + mods/ra/lua/map.lua + mods/ra/lua/actor.lua + mods/ra/lua/team.lua + mods/ra/lua/media.lua + mods/ra/lua/mission.lua diff --git a/mods/ts/rules/defaults.yaml b/mods/ts/rules/defaults.yaml index 3ef39c5683..9c692cc530 100644 --- a/mods/ts/rules/defaults.yaml +++ b/mods/ts/rules/defaults.yaml @@ -36,6 +36,8 @@ Guardable: Range: 3 BodyOrientation: + Huntable: + LuaScriptEvents: ^Infantry: AppearsOnRadar: @@ -80,6 +82,8 @@ Guard: Guardable: BodyOrientation: + Huntable: + LuaScriptEvents: ^CivilianInfantry: Inherits: ^Infantry @@ -145,6 +149,8 @@ Guard: Guardable: BodyOrientation: + Huntable: + LuaScriptEvents: ^Wall: AppearsOnRadar: @@ -175,6 +181,7 @@ Sellable: UpdatesPlayerStatistics: BodyOrientation: + LuaScriptEvents: ^Helicopter: AppearsOnRadar: @@ -197,4 +204,6 @@ DrawLineToTarget: ActorLostNotification: CombatDebugOverlay: - BodyOrientation: \ No newline at end of file + BodyOrientation: + Huntable: + LuaScriptEvents: \ No newline at end of file