/
MusicPlayer.lua
151 lines (125 loc) · 4.25 KB
/
MusicPlayer.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
-- Copyright © 2008-2016 Pioneer Developers. See AUTHORS.txt for details
-- Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
local Engine = import("Engine")
local Game = import("Game")
local Music = import("Music")
local Event = import("Event")
local music = {}
local getCategoryForSong = function (name)
if not name then return "" end
local _, _, category = string.find(name, "^music/core/([%l-]+)/")
return category
end
local playRandomSongFromCategory = function (category)
-- if there's no song in the wanted category then do nothing
if not music[category] then return end
local current_song = Music.GetSongName()
local current_category = getCategoryForSong(current_song)
if Music.IsPlaying() then
-- no category means some other script is playing something and we
-- don't want to override that
if not current_category then return end
-- don't change song if we're already playing something from this category
if current_category == category then return end
end
-- choosing a song
local song = ""
-- if the category only has one song then the choice is simple
if #music[category] == 1 then
song = music[category][1]
-- more than one so select at random
-- XXX base on system seed so you get the starting point for the system
else
-- don't choose the song currently playing (or last played)
repeat
song = music[category][Engine.rand:Integer(1,#music[category])]
until song ~= current_song
end
if Music.IsPlaying() then
Music.FadeIn(song, 0.5, false)
else
Music.Play(song, false)
end
end
-- handle separate planet/station-specific ambient music
local playAmbient = function ()
local category
-- if we're near a planet or spacestation then choose something specific
-- player can usually be in a planet's frame but still be so far away that
-- they'd say they're not near it, so only use its rotating frame (which
-- only extends to about the radius of the atmosphere). orbital stations
-- however are tiny so use their whole frame
local near = Game.player.frameBody
if near then
if near:isa("Planet") and Game.player.frameRotating then
category = "near-planet"
elseif near:isa("SpaceStation") then
category = "near-spacestation"
end
end
-- not near anything interesting so just use the normal space music
if not category then
playRandomSongFromCategory("space")
return
end
-- switch to the specific music. if the music doesn't start (ie we don't
-- have any specific music) then fall back to normal space music
playRandomSongFromCategory(category)
if not Music.IsPlaying() then
playRandomSongFromCategory("space")
end
end
Event.Register("onGameStart", function ()
music = {}
-- get all the interesting songs by category
local songs = Music.GetSongList()
for n,key in pairs(songs) do
local category = getCategoryForSong(key)
if category then
if not music[category] then music[category] = {} end
table.insert(music[category], key)
end
end
playAmbient()
end)
-- if a song finishes fall back to ambient music
Event.Register("onSongFinished", function ()
playAmbient()
end)
-- start some ambient music when first arriving in system
Event.Register("onEnterSystem", function ()
playAmbient()
end)
-- ship or player destruction (aka game over)
Event.Register("onShipDestroyed", function (ship, attacker)
if ship:IsPlayer() then
playRandomSongFromCategory("player-destroyed")
elseif attacker:isa("Ship") and attacker:IsPlayer() then
playRandomSongFromCategory("ship-destroyed")
end
end)
-- player docked
Event.Register("onShipDocked", function (ship, station)
if not ship:IsPlayer() then return end
playRandomSongFromCategory("docked")
end)
-- player undocked
Event.Register("onShipUndocked", function (ship, station)
if not ship:IsPlayer() then return end
playRandomSongFromCategory("undocked")
end)
-- ship near the player
Event.Register("onShipAlertChanged", function (ship, alert)
if not ship:IsPlayer() then return end
if alert == "SHIP_NEARBY" then
playRandomSongFromCategory("ship-nearby")
elseif alert == "SHIP_FIRING" then
playRandomSongFromCategory("ship-firing")
end
end)
-- player changed frame and might be near a planet or orbital station
Event.Register("onFrameChanged", function (body)
if not body:isa("Ship") then return end
if not body:IsPlayer() then return end
playAmbient()
end)