diff --git a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj index e8f263effe..80738fe31c 100644 --- a/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj +++ b/OpenRA.Mods.Common/OpenRA.Mods.Common.csproj @@ -416,7 +416,6 @@ - diff --git a/OpenRA.Mods.Common/Scripting/Global/MediaGlobal.cs b/OpenRA.Mods.Common/Scripting/Global/MediaGlobal.cs index 207df3f7ef..1f0d51cda9 100644 --- a/OpenRA.Mods.Common/Scripting/Global/MediaGlobal.cs +++ b/OpenRA.Mods.Common/Scripting/Global/MediaGlobal.cs @@ -10,8 +10,11 @@ using System; using System.Drawing; +using System.Linq; using Eluant; +using OpenRA.GameRules; using OpenRA.Scripting; +using OpenRA.Traits; namespace OpenRA.Mods.Common.Scripting { @@ -49,7 +52,7 @@ namespace OpenRA.Mods.Common.Scripting try { using (f) - f.Call(); + f.Call().Dispose(); } catch (LuaException e) { @@ -63,6 +66,52 @@ namespace OpenRA.Mods.Common.Scripting Media.PlayFMVFullscreen(world, movie, onComplete); } + MusicInfo previousMusic; + [Desc("Play track defined in music.yaml or keep it empty for a random song.")] + public void PlayMusic(string track = null, LuaFunction func = null) + { + if (!Game.Settings.Sound.MapMusic) + return; + + var music = world.Map.Rules.InstalledMusic.Select(a => a.Value).ToArray(); + if (!music.Any()) + return; + + var musicInfo = !string.IsNullOrEmpty(track) ? world.Map.Rules.Music[track] + : Game.Settings.Sound.Repeat && previousMusic != null ? previousMusic + : Game.Settings.Sound.Shuffle ? music.Random(Game.CosmeticRandom) + : previousMusic == null ? music.First() + : music.SkipWhile(s => s != previousMusic).Skip(1).First(); + + if (func != null) + { + var f = func.CopyReference() as LuaFunction; + onComplete = () => + { + try + { + using (f) + f.Call().Dispose(); + } + catch (LuaException e) + { + Context.FatalError(e.Message); + } + }; + } + else + onComplete = () => { }; + + Sound.PlayMusicThen(musicInfo, onComplete); + previousMusic = Sound.CurrentMusic; + } + + [Desc("Stop the current song.")] + public void StopMusic() + { + Sound.StopMusic(); + } + [Desc("Display a text message to the player.")] public void DisplayMessage(string text, string prefix = "Mission") // TODO: expose HSLColor to Lua and add as parameter { diff --git a/OpenRA.Mods.Common/Scripting/Global/TriggerGlobal.cs b/OpenRA.Mods.Common/Scripting/Global/TriggerGlobal.cs index 304f905732..d490f9ceb1 100644 --- a/OpenRA.Mods.Common/Scripting/Global/TriggerGlobal.cs +++ b/OpenRA.Mods.Common/Scripting/Global/TriggerGlobal.cs @@ -41,7 +41,7 @@ namespace OpenRA.Mods.Common.Scripting try { using (f) - f.Call(); + f.Call().Dispose(); } catch (Exception e) { diff --git a/OpenRA.Mods.Common/Traits/World/PlayMusicOnMapLoad.cs b/OpenRA.Mods.Common/Traits/World/PlayMusicOnMapLoad.cs deleted file mode 100644 index 6fa5ded5db..0000000000 --- a/OpenRA.Mods.Common/Traits/World/PlayMusicOnMapLoad.cs +++ /dev/null @@ -1,50 +0,0 @@ -#region Copyright & License Information -/* - * Copyright 2007-2015 The OpenRA Developers (see AUTHORS) - * This file is part of OpenRA, which is free software. It is made - * available to you under the terms of the GNU General Public License - * as published by the Free Software Foundation. For more information, - * see COPYING. - */ -#endregion - -using System; -using OpenRA.Graphics; -using OpenRA.Traits; - -namespace OpenRA.Mods.Common.Traits -{ - class PlayMusicOnMapLoadInfo : ITraitInfo - { - public readonly string Music = null; - public readonly bool Loop = false; - - public object Create(ActorInitializer init) { return new PlayMusicOnMapLoad(init.World, this); } - } - - class PlayMusicOnMapLoad : IWorldLoaded - { - readonly PlayMusicOnMapLoadInfo info; - readonly World world; - - public PlayMusicOnMapLoad(World world, PlayMusicOnMapLoadInfo info) - { - this.world = world; - this.info = info; - } - - public void WorldLoaded(World world, WorldRenderer wr) - { - PlayMusic(); - } - - void PlayMusic() - { - var onComplete = info.Loop ? (Action)PlayMusic : () => { }; - - if (Game.Settings.Sound.MapMusic && - world.Map.Rules.Music.ContainsKey(info.Music)) - Sound.PlayMusicThen(world.Map.Rules.Music[info.Music], onComplete); - } - } -} \ No newline at end of file diff --git a/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs b/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs index 7723a408df..05f0abce1b 100644 --- a/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs +++ b/OpenRA.Mods.Common/UtilityCommands/UpgradeRules.cs @@ -695,6 +695,18 @@ namespace OpenRA.Mods.Common.UtilityCommands if (depth == 1 && node.Key == "MustBeDestroyed") node.Value.Nodes.Add(new MiniYamlNode("RequiredForShortGame", "true")); + // Remove PlayMusicOnMapLoad + if (engineVersion < 20150125) + { + if (depth == 0 && node.Value.Nodes.Exists(n => n.Key == "PlayMusicOnMapLoad")) + { + node.Value.Nodes.RemoveAll(n => n.Key == "PlayMusicOnMapLoad"); + Console.WriteLine("The 'PlayMusicOnMapLoad' trait has been removed."); + Console.WriteLine("Please use the Lua API function 'PlayMusic' instead."); + Console.WriteLine("See http://wiki.openra.net/Lua-API for details."); + } + } + UpgradeActorRules(engineVersion, ref node.Value.Nodes, node, depth + 1); } } diff --git a/OpenRA.Mods.RA/Widgets/Logic/MusicPlayerLogic.cs b/OpenRA.Mods.RA/Widgets/Logic/MusicPlayerLogic.cs index 930009129b..40466bffe8 100644 --- a/OpenRA.Mods.RA/Widgets/Logic/MusicPlayerLogic.cs +++ b/OpenRA.Mods.RA/Widgets/Logic/MusicPlayerLogic.cs @@ -11,6 +11,7 @@ using System; using System.Linq; using OpenRA.GameRules; +using OpenRA.Mods.Common.Widgets; using OpenRA.Traits; using OpenRA.Widgets; @@ -96,6 +97,18 @@ namespace OpenRA.Mods.RA.Widgets.Logic installButton.IsVisible = () => modRules.InstalledMusic.ToArray().Length <= installData.ShippedSoundtracks; } + var songWatcher = widget.GetOrNull("SONG_WATCHER"); + if (songWatcher != null) + { + songWatcher.OnTick = () => + { + if (Sound.CurrentMusic == null || currentSong == Sound.CurrentMusic) + return; + + currentSong = Sound.CurrentMusic; + }; + } + panel.Get("BACK_BUTTON").OnClick = () => { Game.Settings.Save(); Ui.CloseWindow(); onExit(); }; } diff --git a/mods/cnc/chrome/music.yaml b/mods/cnc/chrome/music.yaml index b7faa30885..8e8c1dbe59 100644 --- a/mods/cnc/chrome/music.yaml +++ b/mods/cnc/chrome/music.yaml @@ -5,6 +5,7 @@ Container@MUSIC_PANEL: Width: 360 Height: 435 Children: + LogicTicker@SONG_WATCHER: Label@TITLE: Width: 360 Y: 0-25 diff --git a/mods/cnc/maps/gdi01/gdi01.lua b/mods/cnc/maps/gdi01/gdi01.lua index 7dfb13fc1c..4299accccc 100644 --- a/mods/cnc/maps/gdi01/gdi01.lua +++ b/mods/cnc/maps/gdi01/gdi01.lua @@ -56,8 +56,13 @@ CheckForBase = function() return #baseBuildings >= 3 end -WorldLoaded = function() +initialSong = "aoi" +PlayMusic = function() + Media.PlayMusic(initialSong, PlayMusic) + initialSong = nil +end +WorldLoaded = function() player = Player.GetPlayer("GDI") enemy = Player.GetPlayer("Nod") @@ -73,6 +78,9 @@ WorldLoaded = function() Trigger.OnPlayerWon(player, function() Media.PlaySpeechNotification(player, "Win") + Trigger.AfterDelay(DateTime.Seconds(1), function() + Media.PlayMusic("win1") + end) end) Trigger.OnPlayerLost(player, function() @@ -85,6 +93,8 @@ WorldLoaded = function() ReinforceWithLandingCraft(MCVReinforcements, lstStart.Location + CVec.New(2, 0), lstEnd.Location + CVec.New(2, 0), mcvTarget.Location) Reinforce(InfantryReinforcements) + PlayMusic() + Trigger.OnIdle(Gunboat, function() SetGunboatPath(Gunboat) end) SendNodPatrol() diff --git a/mods/cnc/maps/gdi01/map.yaml b/mods/cnc/maps/gdi01/map.yaml index 1b106912a6..c9db5232a7 100644 --- a/mods/cnc/maps/gdi01/map.yaml +++ b/mods/cnc/maps/gdi01/map.yaml @@ -424,9 +424,6 @@ Rules: -SpawnMPUnits: -MPStartLocations: -CrateSpawner: - PlayMusicOnMapLoad: - Music: aoi - Loop: false LuaScript: Scripts: gdi01.lua ObjectivesPanel: diff --git a/mods/cnc/maps/shellmap/map.yaml b/mods/cnc/maps/shellmap/map.yaml index 0bd3072e06..2596ac7b31 100644 --- a/mods/cnc/maps/shellmap/map.yaml +++ b/mods/cnc/maps/shellmap/map.yaml @@ -992,9 +992,6 @@ Rules: -CrateSpawner: MenuPaletteEffect: Effect: Desaturated - PlayMusicOnMapLoad: - Music: map1 - Loop: true LuaScript: Scripts: shellmap.lua LST: diff --git a/mods/cnc/maps/shellmap/shellmap.lua b/mods/cnc/maps/shellmap/shellmap.lua index 2b72205e06..3a847feaa9 100644 --- a/mods/cnc/maps/shellmap/shellmap.lua +++ b/mods/cnc/maps/shellmap/shellmap.lua @@ -17,6 +17,7 @@ WorldLoaded = function() for i, unit in ipairs(units) do LoopTrack(unit, CPos.New(8, unit.Location.Y), CPos.New(87, unit.Location.Y)) end + PlayMusic() end LoopTrack = function(actor, left, right) @@ -25,6 +26,10 @@ LoopTrack = function(actor, left, right) actor.CallFunc(function() LoopTrack(actor, left, right) end) end +PlayMusic = function() + Media.PlayMusic("map1", PlayMusic) +end + LoadTransport = function(transport, passenger) transport.LoadPassenger(Actor.Create(passenger, false, { Owner = transport.Owner, Facing = transport.Facing })) end \ No newline at end of file diff --git a/mods/d2k/maps/shellmap/shellmap.lua b/mods/d2k/maps/shellmap/shellmap.lua index cea3cfcace..e096e1e0a4 100644 --- a/mods/d2k/maps/shellmap/shellmap.lua +++ b/mods/d2k/maps/shellmap/shellmap.lua @@ -16,4 +16,5 @@ WorldLoaded = function() atreides = Player.GetPlayer("Atreides") InsertHarvester() + Media.PlayMusic("score") end diff --git a/mods/ra/chrome/musicplayer.yaml b/mods/ra/chrome/musicplayer.yaml index 5189cdc0f8..474b41b11b 100644 --- a/mods/ra/chrome/musicplayer.yaml +++ b/mods/ra/chrome/musicplayer.yaml @@ -5,6 +5,7 @@ Background@MUSIC_PANEL: Width: 360 Height: 450 Children: + LogicTicker@SONG_WATCHER: ScrollPanel@MUSIC_LIST: X: 15 Y: 45 diff --git a/mods/ra/maps/desert-shellmap/desert-shellmap.lua b/mods/ra/maps/desert-shellmap/desert-shellmap.lua index 34efded0f9..32eb763cd7 100644 --- a/mods/ra/maps/desert-shellmap/desert-shellmap.lua +++ b/mods/ra/maps/desert-shellmap/desert-shellmap.lua @@ -162,4 +162,6 @@ WorldLoaded = function() SendSovietUnits(Entry5.Location, UnitTypes, 50) SendSovietUnits(Entry6.Location, UnitTypes, 50) SendSovietUnits(Entry7.Location, BeachUnitTypes, 15) + + Media.PlayMusic() end diff --git a/mods/ts/maps/blank-shellmap/map.yaml b/mods/ts/maps/blank-shellmap/map.yaml index e2771579c1..834a6a897a 100644 --- a/mods/ts/maps/blank-shellmap/map.yaml +++ b/mods/ts/maps/blank-shellmap/map.yaml @@ -40,7 +40,8 @@ Rules: -StartGameNotification: -SpawnMPUnits: -MPStartLocations: - LoadWidgetAtGameStart: + LuaScript: + Scripts: shellmap.lua Sequences: diff --git a/mods/ts/maps/blank-shellmap/shellmap.lua b/mods/ts/maps/blank-shellmap/shellmap.lua new file mode 100644 index 0000000000..d502ef195c --- /dev/null +++ b/mods/ts/maps/blank-shellmap/shellmap.lua @@ -0,0 +1,7 @@ +PlayMusic = function() + Media.PlayMusic("maps", PlayMusic) +end + +WorldLoaded = function() + PlayMusic() +end