-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathapi-song.lua
389 lines (339 loc) · 11.9 KB
/
api-song.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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
---@diagnostic disable: param-type-mismatch
-- Credits to _6b by the original code
-- https://mods.sm64coopdx.com/members/_6b.207/
-- This is an super edited version of the code by JasminDreasond. The code was rewritten to behave like an API.
--Don't know what course ID to put for a map? No worries. Just turn this to true, and the pause menu will show the course number in the corner.
--Feel free to turn this off if (you don't want to show the music name in the pause menu
local pauseMenuShouldShowSongData = false
local pauseMenuMusicRGBA = { 200, 200, 200, 255 }
--Below here is just a bunch of internal stuff.
local curMap = -1
local curAreaSeqId = -1
local curCourseNum = -1
local curActNum = -1
local curAreaIndex = -1
local audioMainPaused = false
local forceStopGameSongs = false
local stopSongOnSelectStars = false
local activeMainId = nil
local audioMain = nil
-- Used for the main audio
local audioSpecial = nil -- Used for things like cap music
local sampleSelectStarSound = nil -- Used for the select star audio
local sampleLoseSound = nil -- Used for the mario die time
local audioCurSeq = nil
local marioIndex = 0
_G.tsjSongs = {}
--- @class TinySongBgms
--- @field public audio string
--- @field public name string
--- @field public loopEnd number
--- @field public loopStart number
--- @field public volume number
--- @type TinySongBgms
local bgms = {}
local streams = {}
local streamsStar = {}
local streamsLose = {}
-- Default Songs
local defaultSongs = {}
defaultSongs[SEQ_LEVEL_INSIDE_CASTLE] = true
defaultSongs[SEQ_LEVEL_GRASS] = true
defaultSongs[SEQ_EVENT_BOSS] = true
defaultSongs[SEQ_EVENT_POWERUP] = true
defaultSongs[SEQ_EVENT_METAL_CAP] = true
defaultSongs[SEQ_EVENT_RACE] = true
defaultSongs[SEQ_LEVEL_SLIDE] = true
defaultSongs[SEQ_LEVEL_SNOW] = true
defaultSongs[SEQ_LEVEL_KOOPA_ROAD] = true
defaultSongs[SEQ_LEVEL_BOSS_KOOPA_FINAL] = true
defaultSongs[SEQ_LEVEL_HOT] = true
defaultSongs[SEQ_LEVEL_SPOOKY] = true
defaultSongs[SEQ_LEVEL_WATER] = true
defaultSongs[SEQ_LEVEL_BOSS_KOOPA] = true
defaultSongs[SEQ_LEVEL_UNDERGROUND] = true
defaultSongs[SEQ_LEVEL_BOSS_KOOPA_FINAL] = true
-- Enable default song
--- @param id string | number | integer
function tsjSongs.enableDefaultSong(id)
defaultSongs[id] = true
end
-- Disable default song
--- @param id string | number | integer
function tsjSongs.disableDefaultSong(id)
defaultSongs[id] = false
end
-- Registers the select star sound
--- @param id string
function tsjSongs.addSelectStarSound(id, stream)
streamsStar[id] = stream
end
function tsjSongs.setSelectStarSound(id)
sampleSelectStarSound = streamsStar[id]
end
-- Registers the mario die sound
--- @param id string
function tsjSongs.addLoseSound(id, stream)
streamsLose[id] = stream
end
function tsjSongs.setLoseSound(id)
sampleLoseSound = streamsLose[id]
end
-- Set if it forces to stop all the original songs of the game.
--- @param value boolean
function tsjSongs.setForceStopGameSongs(value)
forceStopGameSongs = value
end
-- Set if it forces to stop all the original songs of the select star screen.
--- @param value boolean
function tsjSongs.setStopSongOnStarSelector(value)
stopSongOnSelectStars = value
end
-- Registers a new song
--- @param id string | number | integer
--- @param data ObjectList
function tsjSongs.addSong(id, stream, data)
bgms[id] = data
---@diagnostic disable-next-line: undefined-field
streams[id] = stream
end
-- Registers a new sub song
--- @param id string | number | integer
--- @param areaIndex string | number | integer
--- @param actNum string | number | integer
--- @param courseNum string | number | integer
--- @param data ObjectList
function tsjSongs.addSubSong(id, areaIndex, actNum, courseNum, stream, data)
local superId = tostring(id) ..
"-" .. tostring(areaIndex) .. "-" .. tostring(actNum) .. "-" .. tostring(courseNum)
bgms[superId] = data
---@diagnostic disable-next-line: undefined-field
streams[superId] = stream
end
-- Load the song
---@param index number
function tsjSongs.loadSong(index)
if (audioMain == nil) then
audioMain = streams[index]
if (audioMain ~= nil) then
audio_stream_set_looping(audioMain, true)
audio_stream_play(audioMain, true, bgms[index].volume)
activeMainId = index
else
djui_popup_create('Missing audio!: ' .. bgms[index].name, 10)
print("Attempted to load filed audio file, but couldn't find it on the system: " .. bgms[index].name)
activeMainId = nil
end
end
end
-- Stop the song
function tsjSongs.stopSong()
if (audioMain ~= nil) then
audio_stream_stop(audioMain)
audioMain = nil
activeMainId = nil
end
end
-- Load the special song
---@param index number
function tsjSongs.loadSpecialSong(index)
if (audioSpecial == nil) then
audioSpecial = streams[index]
if (audioSpecial ~= nil) then
audio_stream_set_looping(audioSpecial, true)
audio_stream_play(audioSpecial, true, bgms[index].volume)
else
djui_popup_create('Missing audio!: ' .. bgms[index].name, 10)
print("Attempted to load filed audio file, but couldn't find it on the system: " .. bgms[index].name)
end
end
end
-- Stop the special song
function tsjSongs.stopSpecialSong()
if (audioSpecial ~= nil) then
audio_stream_stop(audioSpecial)
audioSpecial = nil
if (audioMain ~= nil and audioMainPaused == true) then
audioMainPaused = false
audio_stream_play(audioMain, false, bgms[activeMainId].volume)
else
set_background_music(0, audioCurSeq, 10)
end
end
end
local function handleMusic()
------------------------------------------------------
-- Force stop game songs --
------------------------------------------------------
for k, v in pairs(defaultSongs) do
if v == false or forceStopGameSongs then
stop_background_music(k)
end
end
------------------------------------------------------
-- Selec start music --
------------------------------------------------------
if sampleSelectStarSound ~= nil and get_current_background_music() == SEQ_MENU_STAR_SELECT then
stop_background_music(SEQ_MENU_STAR_SELECT)
if (stopSongOnSelectStars) then
tsjSongs.stopSpecialSong()
tsjSongs.stopSong()
end
audio_sample_play(sampleSelectStarSound, gMarioStates[0].marioObj.header.gfx.cameraToObject, 2)
end
------------------------------------------------------
-- Handle stopping/starting of music --
------------------------------------------------------
--Handle main course music
local newIndex = nil
local needChangeSong = false
local needPrepareChangeSong = false
-- Check curMap
if (gMarioStates[marioIndex].area.macroObjects ~= nil and curMap ~= gNetworkPlayers[marioIndex].currLevelNum) then
curMap = gNetworkPlayers[marioIndex].currLevelNum
newIndex = curMap
needChangeSong = true
end
-- Check areaSqId
if (curAreaSeqId ~= gNetworkPlayers[marioIndex].currLevelAreaSeqId) then
curAreaSeqId = gNetworkPlayers[marioIndex].currLevelAreaSeqId
needPrepareChangeSong = true
end
-- Check curseNumber
if (curCourseNum ~= gNetworkPlayers[marioIndex].currCourseNum) then
curCourseNum = gNetworkPlayers[marioIndex].currCourseNum
needPrepareChangeSong = true
end
-- Check actNum
if (curActNum ~= gNetworkPlayers[marioIndex].currActNum) then
curActNum = gNetworkPlayers[marioIndex].currActNum
needPrepareChangeSong = true
end
-- Check areaIndex
if (curAreaIndex ~= gNetworkPlayers[marioIndex].currAreaIndex) then
curAreaIndex = gNetworkPlayers[marioIndex].currAreaIndex
needPrepareChangeSong = true
end
-- Exist sub song?
if (needPrepareChangeSong) then
local superId = tostring(curMap) ..
"-" ..
tostring(curAreaIndex) ..
"-" .. tostring(curActNum) .. "-" .. tostring(curCourseNum)
if (superId ~= activeMainId) then
if (bgms[superId] ~= nil and bgms[superId].name ~= nil) then
newIndex = superId
needChangeSong = true
elseif (curMap ~= activeMainId) then
newIndex = curMap
needChangeSong = true
end
end
end
-- Request new song
if (needChangeSong) then
audioCurSeq = get_current_background_music()
tsjSongs.stopSong()
if (bgms[newIndex] ~= nil and bgms[newIndex].name ~= nil) then
set_background_music(0, 0, 0)
tsjSongs.loadSong(newIndex)
else
print("No audio for this map, so not stopping default: " .. curMap)
end
end
--Handle cap music
if (gMarioStates[marioIndex].capTimer > 0 and bgms[-2] ~= nil) then
--Handle pausing main streamed music, if applicable.
if (audioMain ~= nil and audioMainPaused == false) then
audioMainPaused = true
audio_stream_pause(audioMain)
end
--Start up cap music if it's defined.
if (audioSpecial == nil) then
set_background_music(0, 0, 0)
stop_cap_music()
tsjSongs.loadSpecialSong(-2)
end
else
tsjSongs.stopSpecialSong()
end
------------------------------------------------------
-- Handle music looping --
------------------------------------------------------
if (audioMain ~= nil and audioMain.loaded) then
local curPosition = audio_stream_get_position(audioMain)
if (curPosition >= bgms[activeMainId].loopEnd) then
local minus = bgms[activeMainId].loopStart - bgms[activeMainId].loopEnd
audio_stream_set_position(audioMain, curPosition - math.abs(minus))
end
end
if (audioSpecial ~= nil) then
local curPosition = audio_stream_get_position(audioSpecial)
if (curPosition >= bgms[-2].loopEnd) then
local minus = bgms[-2].loopStart - bgms[-2].loopEnd
audio_stream_set_position(audioSpecial, curPosition - math.abs(minus))
end
end
end
local function hud_render()
if (pauseMenuShouldShowSongData == true and is_game_paused()) then
djui_hud_set_resolution(RESOLUTION_DJUI);
djui_hud_set_font(FONT_NORMAL);
local screenHeight = djui_hud_get_screen_height()
local height = 64
local y = screenHeight - height
local x = 30
local scale = 1
djui_hud_set_color(pauseMenuMusicRGBA[1], pauseMenuMusicRGBA[2], pauseMenuMusicRGBA[3], pauseMenuMusicRGBA[4]);
djui_hud_print_text("Tiny Script - Song API", x, y, scale);
djui_hud_print_text("Level ID: " .. curMap, x, y - 30, scale);
djui_hud_print_text("Level Area Seq ID: " .. curAreaSeqId, x, y - 60, scale);
djui_hud_print_text("Course Number: " .. curCourseNum, x, y - 90, scale);
djui_hud_print_text("Current Act Number: " .. curActNum, x, y - 120, scale);
djui_hud_print_text("Current Area Index: " .. curAreaIndex, x, y - 150, scale);
if (audioMain ~= nil) then
djui_hud_print_text("Song: " .. bgms[activeMainId].name, x, y - 180, scale);
djui_hud_print_text("Song loaded: " .. tostring(audioMain.loaded), x, y - 210, scale);
end
if (audioSpecial ~= nil) then
djui_hud_print_text("Special Song: " .. bgms[-2].name, x, y - 240, scale);
djui_hud_print_text("Special Song loaded: " .. tostring(audioSpecial.loaded), x, y - 270, scale);
end
end
end
hook_event(HOOK_ON_HUD_RENDER, hud_render)
hook_event(HOOK_UPDATE, handleMusic)
local deathTable = {
[ACT_DEATH_ON_STOMACH] = true,
[ACT_DEATH_ON_BACK] = true,
[ACT_EATEN_BY_BUBBA] = true,
[ACT_SUFFOCATION] = true,
[ACT_STANDING_DEATH] = true,
[ACT_QUICKSAND_DEATH] = true,
[ACT_DROWNING] = true,
}
local function on_set_mario_action(m)
if sampleLoseSound ~= nil and deathTable[m.action] then
audio_sample_play(sampleLoseSound, { x = 0, y = 0, z = 0 }, 2)
end
end
hook_event(HOOK_ON_SET_MARIO_ACTION, on_set_mario_action)
-----------------------------------------------------------------------------
-- Music Mod End --
-----------------------------------------------------------------------------
------------------------------------------------------
-- Debug commands --
------------------------------------------------------
local function song_debug_command(msg)
if msg == "on" then
djui_chat_message_create("Song Debug: enabled")
pauseMenuShouldShowSongData = true
return true
elseif msg == "off" then
djui_chat_message_create("Song Debug: disabled")
pauseMenuShouldShowSongData = false
return true
end
return false
end
hook_chat_command("lvlinfodebug", "[on|off] ", song_debug_command)