From 57e684d1d918fd5a457adc44187a9678c5018e1e Mon Sep 17 00:00:00 2001 From: Zimmermann Gyula Date: Mon, 13 Jul 2015 14:50:01 +0200 Subject: [PATCH] Implements victory and defeat music. --- OpenRA.Game/Traits/TraitsInterfaces.cs | 2 + OpenRA.Game/Traits/World/MusicPlaylist.cs | 55 ++++++++++++++++++++++- OpenRA.Game/World.cs | 4 ++ mods/cnc/maps/gdi01/gdi01.lua | 3 -- mods/cnc/rules/world.yaml | 2 + mods/d2k/maps/shellmap/map.yaml | 2 +- mods/d2k/rules/world.yaml | 2 + mods/ra/rules/world.yaml | 2 + mods/ts/rules/world.yaml | 2 + 9 files changed, 69 insertions(+), 5 deletions(-) diff --git a/OpenRA.Game/Traits/TraitsInterfaces.cs b/OpenRA.Game/Traits/TraitsInterfaces.cs index f6845d7187..d5856d24c9 100644 --- a/OpenRA.Game/Traits/TraitsInterfaces.cs +++ b/OpenRA.Game/Traits/TraitsInterfaces.cs @@ -352,6 +352,8 @@ namespace OpenRA.Traits void OnObjectiveFailed(Player player, int objectiveID); } + public interface IGameOver { void GameOver(World world); } + public interface IWarhead { int Delay { get; } diff --git a/OpenRA.Game/Traits/World/MusicPlaylist.cs b/OpenRA.Game/Traits/World/MusicPlaylist.cs index 143bae11a0..cf275ba64a 100644 --- a/OpenRA.Game/Traits/World/MusicPlaylist.cs +++ b/OpenRA.Game/Traits/World/MusicPlaylist.cs @@ -17,14 +17,31 @@ namespace OpenRA.Traits [Desc("Trait for music handling. Attach this to the world actor.")] public class MusicPlaylistInfo : ITraitInfo { + [Desc("Music to play when the map starts.", "Plays the first song on the playlist when undefined.")] public readonly string StartingMusic = null; + + [Desc("Should the starting music loop?")] public readonly bool LoopStartingMusic = false; + [Desc("Music to play when the game has been won.")] + public readonly string VictoryMusic = null; + + [Desc("Should the victory music loop?")] + public readonly bool LoopVictoryMusic = false; + + [Desc("Music to play when the game has been lost.")] + public readonly string DefeatMusic = null; + + [Desc("Should the defeat music loop?")] + public readonly bool LoopDefeatMusic = false; + public object Create(ActorInitializer init) { return new MusicPlaylist(init.World, this); } } - public class MusicPlaylist : INotifyActorDisposing + public class MusicPlaylist : INotifyActorDisposing, IGameOver { + readonly MusicPlaylistInfo info; + readonly MusicInfo[] random; readonly MusicInfo[] playlist; @@ -35,6 +52,8 @@ namespace OpenRA.Traits public MusicPlaylist(World world, MusicPlaylistInfo info) { + this.info = info; + IsMusicAvailable = world.Map.Rules.InstalledMusic.Any(); playlist = world.Map.Rules.InstalledMusic.Select(a => a.Value).ToArray(); @@ -71,6 +90,40 @@ namespace OpenRA.Traits return playlist; } + public void GameOver(World world) + { + if (!IsMusicAvailable) + return; + + var playedSong = currentSong; + + if (world.LocalPlayer.WinState == WinState.Won) + { + if (!string.IsNullOrEmpty(info.VictoryMusic) + && world.Map.Rules.Music.ContainsKey(info.VictoryMusic) + && world.Map.Rules.Music[info.VictoryMusic].Exists) + { + currentSong = world.Map.Rules.Music[info.VictoryMusic]; + repeat = info.LoopVictoryMusic; + } + } + else + { + // Most RTS treats observers losing the game, + // no need for a special handling involving them here. + if (!string.IsNullOrEmpty(info.DefeatMusic) + && world.Map.Rules.Music.ContainsKey(info.DefeatMusic) + && world.Map.Rules.Music[info.DefeatMusic].Exists) + { + currentSong = world.Map.Rules.Music[info.DefeatMusic]; + repeat = info.LoopDefeatMusic; + } + } + + if (playedSong != currentSong) + Play(); + } + void Play() { if (currentSong == null || !IsMusicAvailable) diff --git a/OpenRA.Game/World.cs b/OpenRA.Game/World.cs index 2413c73913..eeb224692a 100644 --- a/OpenRA.Game/World.cs +++ b/OpenRA.Game/World.cs @@ -58,6 +58,10 @@ namespace OpenRA if (!gameOver) { gameOver = true; + + foreach (var t in WorldActor.TraitsImplementing()) + t.GameOver(this); + GameOver(); } } diff --git a/mods/cnc/maps/gdi01/gdi01.lua b/mods/cnc/maps/gdi01/gdi01.lua index 24c4265c0c..490e72f695 100644 --- a/mods/cnc/maps/gdi01/gdi01.lua +++ b/mods/cnc/maps/gdi01/gdi01.lua @@ -72,9 +72,6 @@ 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() diff --git a/mods/cnc/rules/world.yaml b/mods/cnc/rules/world.yaml index 5a4c6f174a..2c961f6314 100644 --- a/mods/cnc/rules/world.yaml +++ b/mods/cnc/rules/world.yaml @@ -4,6 +4,8 @@ ScreenMap: ActorMap: MusicPlaylist: + VictoryMusic: win1 + DefeatMusic: heart TerrainGeometryOverlay: ShroudRenderer: ShroudVariants: typea, typeb, typec, typed diff --git a/mods/d2k/maps/shellmap/map.yaml b/mods/d2k/maps/shellmap/map.yaml index fd42ee8e29..2bb6499885 100644 --- a/mods/d2k/maps/shellmap/map.yaml +++ b/mods/d2k/maps/shellmap/map.yaml @@ -126,7 +126,7 @@ Rules: LuaScript: Scripts: shellmap.lua MusicPlaylist: - StartingMusic: score + StartingMusic: waitgame GlobalLightingPaletteEffect: rockettower: Power: diff --git a/mods/d2k/rules/world.yaml b/mods/d2k/rules/world.yaml index b90ee115b6..443a8b2e56 100644 --- a/mods/d2k/rules/world.yaml +++ b/mods/d2k/rules/world.yaml @@ -4,6 +4,8 @@ ScreenMap: ActorMap: MusicPlaylist: + VictoryMusic: score + DefeatMusic: options TerrainGeometryOverlay: ShroudRenderer: ShroudVariants: typea, typeb, typec, typed diff --git a/mods/ra/rules/world.yaml b/mods/ra/rules/world.yaml index 2a1d469c82..d359a4326f 100644 --- a/mods/ra/rules/world.yaml +++ b/mods/ra/rules/world.yaml @@ -4,6 +4,8 @@ ActorMap: ScreenMap: MusicPlaylist: + VictoryMusic: score + DefeatMusic: map TerrainGeometryOverlay: LoadWidgetAtGameStart: ShroudRenderer: diff --git a/mods/ts/rules/world.yaml b/mods/ts/rules/world.yaml index c5a588430a..60747a2f31 100644 --- a/mods/ts/rules/world.yaml +++ b/mods/ts/rules/world.yaml @@ -4,6 +4,8 @@ ScreenMap: ActorMap: MusicPlaylist: + VictoryMusic: score + DefeatMusic: maps LoadWidgetAtGameStart: ShroudRenderer: Index: 255, 16, 32, 48, 64, 80, 96, 112, 128, 144, 160, 176, 192, 208, 224, 240, 20, 40, 56, 65, 97, 130, 148, 194, 24, 33, 66, 132, 28, 41, 67, 134, 1, 2, 4, 8, 3, 6, 12, 9, 7, 14, 13, 11, 5, 10, 15, 255