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:
Sal 2024-08-28 22:04:31 +00:00
commit 61956f5949
5 changed files with 531 additions and 0 deletions

View file

@ -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}
};

View file

@ -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}
};

View file

@ -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)\

View file

@ -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);

View file

@ -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);