mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
Merge branch 'expose-music' into 'master'
Expose most of the music handler to Lua See merge request KartKrew/RingRacers!41
This commit is contained in:
commit
61956f5949
5 changed files with 531 additions and 0 deletions
|
|
@ -25,6 +25,7 @@
|
|||
#include "r_data.h" // patchalphastyle_t
|
||||
#include "k_boss.h" // spottype_t (for lua)
|
||||
#include "k_follower.h" // followermode_t (for lua)
|
||||
#include "music.h" // tune flags (for lua)
|
||||
|
||||
#include "deh_tables.h"
|
||||
|
||||
|
|
@ -5161,6 +5162,16 @@ struct int_const_s const INT_CONST[] = {
|
|||
{"FOLLOWERMODE_FLOAT",FOLLOWERMODE_FLOAT},
|
||||
{"FOLLOWERMODE_GROUND",FOLLOWERMODE_GROUND},
|
||||
|
||||
// tune flags
|
||||
{"TN_INCLUSIVEFADE",TN_INCLUSIVEFADE},
|
||||
{"TN_USEMAPVOLUME",TN_USEMAPVOLUME},
|
||||
{"TN_SYNCMUSIC",TN_SYNCMUSIC},
|
||||
{"TN_MUSICCRED",TN_MUSICCRED},
|
||||
{"TN_VAPES",TN_VAPES},
|
||||
{"TN_NIGHTCOREABLE",TN_NIGHTCOREABLE},
|
||||
{"TN_CHANGEPITCH",TN_CHANGEPITCH},
|
||||
{"TN_LOOPING",TN_LOOPING},
|
||||
|
||||
{NULL,0}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@
|
|||
#include "hu_stuff.h" // for the cecho
|
||||
#include "k_powerup.h"
|
||||
#include "k_hitlag.h"
|
||||
#include "music.h" // music functions necessary for lua integration
|
||||
|
||||
#include "lua_script.h"
|
||||
#include "lua_libs.h"
|
||||
|
|
@ -339,6 +340,418 @@ static int lib_reserveLuabanks(lua_State *L)
|
|||
return 1;
|
||||
}
|
||||
|
||||
// MUSIC
|
||||
////////////
|
||||
|
||||
static int lib_mMusicAddTune(lua_State *L)
|
||||
{
|
||||
UINT32 priority, tuneflags;
|
||||
|
||||
if (!lua_lumploading)
|
||||
return luaL_error(L, "Tunes cannot be added from within a hook or coroutine!");
|
||||
|
||||
//NOHUD
|
||||
const char *tune_id = luaL_checkstring(L, 1);
|
||||
priority = (UINT32)luaL_optinteger(L, 2, 0);
|
||||
tuneflags = (UINT32)luaL_optinteger(L, 3, 0);
|
||||
|
||||
if (!Music_TuneExists(tune_id))
|
||||
{
|
||||
Music_AddTune(tune_id, priority, tuneflags);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lib_mMusicPlay(lua_State *L)
|
||||
{
|
||||
const char *tune_id = luaL_checkstring(L, 1);
|
||||
player_t *player = NULL;
|
||||
|
||||
//NOHUD
|
||||
if (!lua_isnone(L, 2) && lua_isuserdata(L, 2))
|
||||
{
|
||||
player = *((player_t **)luaL_checkudata(L, 2, META_PLAYER));
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
}
|
||||
|
||||
if (!Music_TuneExists(tune_id))
|
||||
{
|
||||
return LUA_ErrNoTune(L, tune_id);
|
||||
}
|
||||
|
||||
Music_Play(tune_id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lib_mMusicStopAll(lua_State *L)
|
||||
{
|
||||
player_t *player = NULL;
|
||||
|
||||
//NOHUD
|
||||
if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
|
||||
{
|
||||
player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
}
|
||||
|
||||
Music_StopAll();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lib_mMusicPauseAll(lua_State *L)
|
||||
{
|
||||
player_t *player = NULL;
|
||||
|
||||
//NOHUD
|
||||
if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
|
||||
{
|
||||
player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
}
|
||||
|
||||
Music_PauseAll();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lib_mMusicUnPauseAll(lua_State *L)
|
||||
{
|
||||
player_t *player = NULL;
|
||||
|
||||
//NOHUD
|
||||
if (!lua_isnone(L, 1) && lua_isuserdata(L, 1))
|
||||
{
|
||||
player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
}
|
||||
|
||||
Music_UnPauseAll();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lib_mMusicRemap(lua_State *L)
|
||||
{
|
||||
const char *tune_id = luaL_checkstring(L, 1);
|
||||
const char *music_name = luaL_checkstring(L, 2);
|
||||
player_t *player = NULL;
|
||||
|
||||
//NOHUD
|
||||
if (!lua_isnone(L, 3) && lua_isuserdata(L, 3))
|
||||
{
|
||||
player = *((player_t **)luaL_checkudata(L, 3, META_PLAYER));
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
}
|
||||
|
||||
if (!Music_TuneExists(tune_id))
|
||||
{
|
||||
return LUA_ErrNoTune(L, tune_id);
|
||||
}
|
||||
|
||||
Music_Remap(tune_id, music_name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lib_mMusicDim(lua_State *L)
|
||||
{
|
||||
tic_t fade = (tic_t)luaL_checkinteger(L, 1);
|
||||
tic_t duration = INFTICS;
|
||||
|
||||
// If a dim is ongoing, do not interrupt it
|
||||
if (g_musicfade.start < leveltime && g_musicfade.end < leveltime)
|
||||
{
|
||||
g_musicfade.start = leveltime;
|
||||
}
|
||||
|
||||
if (!lua_isnoneornil(L, 2))
|
||||
{
|
||||
duration = (tic_t)luaL_checkinteger(L, 2);
|
||||
}
|
||||
|
||||
g_musicfade.end = (duration != INFTICS) ? leveltime + duration + 2*fade : INFTICS;
|
||||
g_musicfade.fade = fade;
|
||||
g_musicfade.ticked = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lib_mMusicSetFadeOut(lua_State *L)
|
||||
{
|
||||
UINT32 fadeoutms;
|
||||
|
||||
const char *tune_id = luaL_checkstring(L, 1);
|
||||
fadeoutms = (UINT32)luaL_optinteger(L, 2, 0);
|
||||
player_t *player = NULL;
|
||||
|
||||
//NOHUD
|
||||
if (!lua_isnone(L, 3) && lua_isuserdata(L, 3))
|
||||
{
|
||||
player = *((player_t **)luaL_checkudata(L, 3, META_PLAYER));
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
}
|
||||
|
||||
if (!Music_TuneExists(tune_id))
|
||||
{
|
||||
return LUA_ErrNoTune(L, tune_id);
|
||||
}
|
||||
|
||||
Music_SetFadeOut(tune_id, fadeoutms);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lib_mMusicSetFadeIn(lua_State *L)
|
||||
{
|
||||
UINT32 fadeinms;
|
||||
|
||||
const char *tune_id = luaL_checkstring(L, 1);
|
||||
fadeinms = (UINT32)luaL_optinteger(L, 2, 0);
|
||||
boolean resumefade = lua_optboolean(L, 3);
|
||||
|
||||
player_t *player = NULL;
|
||||
|
||||
//NOHUD
|
||||
if (!lua_isnone(L, 4) && lua_isuserdata(L, 4))
|
||||
{
|
||||
player = *((player_t **)luaL_checkudata(L, 4, META_PLAYER));
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
}
|
||||
|
||||
if (!Music_TuneExists(tune_id))
|
||||
{
|
||||
return LUA_ErrNoTune(L, tune_id);
|
||||
}
|
||||
|
||||
Music_SetFadeIn(tune_id, fadeinms, resumefade);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lib_mMusicDelayEnd(lua_State *L)
|
||||
{
|
||||
tic_t duration;
|
||||
|
||||
const char *tune_id = luaL_checkstring(L, 1);
|
||||
duration = (tic_t)luaL_optinteger(L, 2, 0);
|
||||
player_t *player = NULL;
|
||||
|
||||
//NOHUD
|
||||
if (!lua_isnone(L, 3) && lua_isuserdata(L, 3))
|
||||
{
|
||||
player = *((player_t **)luaL_checkudata(L, 3, META_PLAYER));
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
}
|
||||
|
||||
if (!Music_TuneExists(tune_id))
|
||||
{
|
||||
return LUA_ErrNoTune(L, tune_id);
|
||||
}
|
||||
|
||||
Music_DelayEnd(tune_id, duration);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lib_mMusicSeek(lua_State *L)
|
||||
{
|
||||
UINT32 seekms;
|
||||
|
||||
const char *tune_id = luaL_checkstring(L, 1);
|
||||
seekms = (UINT32)luaL_optinteger(L, 2, 0);
|
||||
player_t *player = NULL;
|
||||
|
||||
//NOHUD
|
||||
if (!lua_isnone(L, 3) && lua_isuserdata(L, 3))
|
||||
{
|
||||
player = *((player_t **)luaL_checkudata(L, 3, META_PLAYER));
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
}
|
||||
|
||||
if (!Music_TuneExists(tune_id))
|
||||
{
|
||||
return LUA_ErrNoTune(L, tune_id);
|
||||
}
|
||||
|
||||
Music_Seek(tune_id, seekms);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lib_mMusicStop(lua_State *L)
|
||||
{
|
||||
const char *tune_id = luaL_checkstring(L, 1);
|
||||
player_t *player = NULL;
|
||||
|
||||
//NOHUD
|
||||
if (!lua_isnone(L, 2) && lua_isuserdata(L, 2))
|
||||
{
|
||||
player = *((player_t **)luaL_checkudata(L, 2, META_PLAYER));
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
}
|
||||
|
||||
if (!Music_TuneExists(tune_id))
|
||||
{
|
||||
return LUA_ErrNoTune(L, tune_id);
|
||||
}
|
||||
|
||||
Music_Stop(tune_id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lib_mMusicPause(lua_State *L)
|
||||
{
|
||||
const char *tune_id = luaL_checkstring(L, 1);
|
||||
player_t *player = NULL;
|
||||
|
||||
//NOHUD
|
||||
if (!lua_isnone(L, 2) && lua_isuserdata(L, 2))
|
||||
{
|
||||
player = *((player_t **)luaL_checkudata(L, 2, META_PLAYER));
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
}
|
||||
|
||||
if (!Music_TuneExists(tune_id))
|
||||
{
|
||||
return LUA_ErrNoTune(L, tune_id);
|
||||
}
|
||||
|
||||
Music_Pause(tune_id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lib_mMusicUnPause(lua_State *L)
|
||||
{
|
||||
const char *tune_id = luaL_checkstring(L, 1);
|
||||
player_t *player = NULL;
|
||||
|
||||
//NOHUD
|
||||
if (!lua_isnone(L, 2) && lua_isuserdata(L, 2))
|
||||
{
|
||||
player = *((player_t **)luaL_checkudata(L, 2, META_PLAYER));
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
}
|
||||
|
||||
if (!Music_TuneExists(tune_id))
|
||||
{
|
||||
return LUA_ErrNoTune(L, tune_id);
|
||||
}
|
||||
|
||||
Music_UnPause(tune_id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lib_mMusicSuspend(lua_State *L)
|
||||
{
|
||||
const char *tune_id = luaL_checkstring(L, 1);
|
||||
player_t *player = NULL;
|
||||
|
||||
//NOHUD
|
||||
if (!lua_isnone(L, 2) && lua_isuserdata(L, 2))
|
||||
{
|
||||
player = *((player_t **)luaL_checkudata(L, 2, META_PLAYER));
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
}
|
||||
|
||||
if (!Music_TuneExists(tune_id))
|
||||
{
|
||||
return LUA_ErrNoTune(L, tune_id);
|
||||
}
|
||||
|
||||
Music_Suspend(tune_id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lib_mMusicUnSuspend(lua_State *L)
|
||||
{
|
||||
const char *tune_id = luaL_checkstring(L, 1);
|
||||
player_t *player = NULL;
|
||||
|
||||
//NOHUD
|
||||
if (!lua_isnone(L, 2) && lua_isuserdata(L, 2))
|
||||
{
|
||||
player = *((player_t **)luaL_checkudata(L, 2, META_PLAYER));
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
}
|
||||
|
||||
if (!Music_TuneExists(tune_id))
|
||||
{
|
||||
return LUA_ErrNoTune(L, tune_id);
|
||||
}
|
||||
|
||||
Music_UnSuspend(tune_id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lib_mMusicLoop(lua_State *L)
|
||||
{
|
||||
const char *tune_id = luaL_checkstring(L, 1);
|
||||
boolean loop = lua_optboolean(L, 2);
|
||||
player_t *player = NULL;
|
||||
|
||||
//NOHUD
|
||||
if (!lua_isnone(L, 3) && lua_isuserdata(L, 3))
|
||||
{
|
||||
player = *((player_t **)luaL_checkudata(L, 3, META_PLAYER));
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
}
|
||||
|
||||
if (!Music_TuneExists(tune_id))
|
||||
{
|
||||
return LUA_ErrNoTune(L, tune_id);
|
||||
}
|
||||
|
||||
Music_Loop(tune_id, loop);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lib_mMusicBatchExempt(lua_State *L)
|
||||
{
|
||||
const char *tune_id = luaL_checkstring(L, 1);
|
||||
player_t *player = NULL;
|
||||
|
||||
//NOHUD
|
||||
if (!lua_isnone(L, 2) && lua_isuserdata(L, 2))
|
||||
{
|
||||
player = *((player_t **)luaL_checkudata(L, 2, META_PLAYER));
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
}
|
||||
|
||||
if (!Music_TuneExists(tune_id))
|
||||
{
|
||||
return LUA_ErrNoTune(L, tune_id);
|
||||
}
|
||||
|
||||
Music_BatchExempt(tune_id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// M_MENU
|
||||
//////////////
|
||||
|
||||
|
|
@ -3933,6 +4346,26 @@ static luaL_Reg lib[] = {
|
|||
// hu_stuff technically?
|
||||
{"HU_DoTitlecardCEcho", lib_startTitlecardCecho},
|
||||
|
||||
// music
|
||||
{"Music_AddTune", lib_mMusicAddTune},
|
||||
{"Music_Play", lib_mMusicPlay},
|
||||
{"Music_Remap", lib_mMusicRemap},
|
||||
{"Music_SetFadeOut", lib_mMusicSetFadeOut},
|
||||
{"Music_SetFadeIn", lib_mMusicSetFadeIn},
|
||||
{"Music_DelayEnd", lib_mMusicDelayEnd},
|
||||
{"Music_Dim", lib_mMusicDim},
|
||||
{"Music_Seek", lib_mMusicSeek},
|
||||
{"Music_Stop", lib_mMusicStop},
|
||||
{"Music_Pause", lib_mMusicPause},
|
||||
{"Music_UnPause", lib_mMusicUnPause},
|
||||
{"Music_Suspend", lib_mMusicSuspend},
|
||||
{"Music_UnSuspend", lib_mMusicUnSuspend},
|
||||
{"Music_StopAll", lib_mMusicStopAll},
|
||||
{"Music_PauseAll", lib_mMusicPauseAll},
|
||||
{"Music_UnPauseAll", lib_mMusicUnPauseAll},
|
||||
{"Music_Loop", lib_mMusicLoop},
|
||||
{"Music_BatchExempt", lib_mMusicBatchExempt},
|
||||
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -114,6 +114,9 @@ void COM_Lua_f(void);
|
|||
|
||||
#define LUA_ErrSetDirectly(L, type, field) luaL_error(L, type " field " LUA_QL(field) " cannot be set directly.")
|
||||
|
||||
// Music: "No tune" error.
|
||||
#define LUA_ErrNoTune(L, tune) luaL_error(L, "tune \"%s\" does not exist", tune)
|
||||
|
||||
// Deprecation warnings
|
||||
// Shows once upon use. Then doesn't show again.
|
||||
#define LUA_Deprecated(L,this_func,use_instead)\
|
||||
|
|
|
|||
|
|
@ -219,6 +219,8 @@ void Music_Init(void)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Music_Tick(void)
|
||||
{
|
||||
g_tunes.tick();
|
||||
|
|
@ -229,6 +231,22 @@ void Music_Flip(void)
|
|||
g_tunes.flip();
|
||||
}
|
||||
|
||||
void Music_AddTune(const char* id, int priority, int tuneflags)
|
||||
{
|
||||
Tune& tune = g_tunes.insert(id);
|
||||
|
||||
tune.song = "";
|
||||
tune.priority = priority;
|
||||
|
||||
tune.loop = (tuneflags & TN_LOOPING);
|
||||
tune.fade_out_inclusive = (tuneflags & TN_INCLUSIVEFADE);
|
||||
tune.use_level_volume = (tuneflags & TN_USEMAPVOLUME);
|
||||
tune.sync = (tuneflags & TN_SYNCMUSIC);
|
||||
tune.credit = (tuneflags & TN_MUSICCRED);
|
||||
tune.vapes = (tuneflags & TN_VAPES);
|
||||
tune.nightcoreable = (tuneflags & TN_NIGHTCOREABLE);
|
||||
}
|
||||
|
||||
void Music_Play(const char* id)
|
||||
{
|
||||
Tune* tune = g_tunes.find(id);
|
||||
|
|
@ -257,6 +275,30 @@ void Music_SetFadeOut(const char* id, int fade_out)
|
|||
}
|
||||
}
|
||||
|
||||
void Music_SetFadeIn(const char* id, int fade_in, boolean resume)
|
||||
{
|
||||
Tune* tune = g_tunes.find(id);
|
||||
|
||||
if (tune)
|
||||
{
|
||||
if (resume)
|
||||
{
|
||||
tune->resume_fade_in = fade_in;
|
||||
}
|
||||
else
|
||||
{
|
||||
tune->fade_in = fade_in;
|
||||
}
|
||||
|
||||
if (tune->elapsed() <= detail::msec_to_tics(fade_in))
|
||||
{
|
||||
// If this action would cause a fade in, start
|
||||
// fading immediately.
|
||||
g_tunes.tick();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Music_DelayEnd(const char* id, tic_t duration)
|
||||
{
|
||||
Tune* tune = g_tunes.find(id);
|
||||
|
|
@ -368,6 +410,17 @@ void Music_Remap(const char* id, const char* song)
|
|||
}
|
||||
}
|
||||
|
||||
boolean Music_TuneExists(const char* id)
|
||||
{
|
||||
const Tune* tune = g_tunes.find(id);
|
||||
|
||||
if (tune)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean Music_Playing(const char* id)
|
||||
{
|
||||
const Tune* tune = g_tunes.find(id);
|
||||
|
|
|
|||
31
src/music.h
31
src/music.h
|
|
@ -35,6 +35,29 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
//
|
||||
// Tuneflags, for Music_AddTune
|
||||
//
|
||||
|
||||
// inclusive fade out
|
||||
#define TN_INCLUSIVEFADE 0x01
|
||||
|
||||
// should the tune use the level volume?
|
||||
#define TN_USEMAPVOLUME 0x02
|
||||
|
||||
// sync tune to game logic
|
||||
#define TN_SYNCMUSIC 0x04
|
||||
|
||||
// show tune credit (only on first play)
|
||||
#define TN_MUSICCRED 0x08
|
||||
|
||||
// allow the game to slow down the music in encore mode
|
||||
#define TN_VAPES 0x10
|
||||
#define TN_NIGHTCOREABLE 0x20
|
||||
#define TN_CHANGEPITCH (TN_VAPES | TN_NIGHTCOREABLE)
|
||||
|
||||
// looping?
|
||||
#define TN_LOOPING 0x40
|
||||
|
||||
//
|
||||
// Get the currently playing tune.
|
||||
|
|
@ -54,6 +77,8 @@ const char *Music_CurrentId(void);
|
|||
// Actions that take effect immediately.
|
||||
//
|
||||
|
||||
// Add a new tune to the tunes list.
|
||||
void Music_AddTune(const char* id, int priority, int tuneflags);
|
||||
|
||||
// Begin playing a tune, duration is infinite. If the tune was
|
||||
// already playing, this resets its current position (seeks
|
||||
|
|
@ -64,6 +89,10 @@ void Music_Play(const char *id);
|
|||
// with Stereo Mode.
|
||||
void Music_SetFadeOut(const char* id, int fade_out);
|
||||
|
||||
// Set fade in duration. Done for parity with the BLUA music
|
||||
// functions.
|
||||
void Music_SetFadeIn(const char* id, int fade_in, boolean resume);
|
||||
|
||||
// Postpone the end of this tune until N tics from now. The
|
||||
// tune should already be playing before calling this.
|
||||
void Music_DelayEnd(const char *id, tic_t duration);
|
||||
|
|
@ -121,6 +150,8 @@ void Music_ResetLevelVolume(void);
|
|||
// Query properties.
|
||||
//
|
||||
|
||||
// Returns true if the tune exists.
|
||||
boolean Music_TuneExists(const char* id);
|
||||
|
||||
// Returns true if the tune is configured to loop.
|
||||
boolean Music_CanLoop(const char *id);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue