Merge remote-tracking branch 'public-new/master'

This commit is contained in:
Sally Coolatta 2024-08-28 18:11:53 -04:00
commit b3dcfa248a
27 changed files with 1015 additions and 51 deletions

View file

@ -122,6 +122,7 @@ add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32
lua_blockmaplib.c
lua_hudlib.c
lua_hudlib_drawlist.c
lua_followerlib.c
lua_profile.cpp
k_kart.c
k_respawn.c

View file

@ -1917,9 +1917,9 @@ static const char *CON_LoadingStrings[LOADED_ALLDONE+1] =
"Init zone memory...", //LOADED_ZINIT
"Init game timing...", //LOADED_ISTARTUPTIMER
"Loading main assets...", //LOADED_IWAD
"Loading add-ons...", //LOADED_PWAD
"Init graphics subsystem...", //LOADED_ISTARTUPGRAPHICS
"Cache fonts...", //LOADED_HUINIT
"Loading add-ons...", //LOADED_PWAD
"Load settings...", //LOADED_CONFIG
"Cache textures...", //LOADED_INITTEXTUREDATA
"Cache sprites...", //LOADED_INITSPIRTES

View file

@ -42,9 +42,9 @@ typedef enum
LOADED_ZINIT = 1,
LOADED_ISTARTUPTIMER,
LOADED_IWAD,
LOADED_PWAD,
LOADED_ISTARTUPGRAPHICS,
LOADED_HUINIT,
LOADED_PWAD,
LOADED_CONFIG,
LOADED_INITTEXTUREDATA,
LOADED_INITSPRITES,

View file

@ -1761,17 +1761,6 @@ void D_SRB2Main(void)
CON_SetLoadingProgress(LOADED_IWAD);
CONS_Printf("W_InitMultipleFiles(): Adding external PWADs.\n");
W_InitMultipleFiles(startuppwads, true);
D_CleanFile(startuppwads);
//
// search for pwad maps
//
P_InitMapData();
CON_SetLoadingProgress(LOADED_PWAD);
M_PasswordInit();
//---------------------------------------------------- READY SCREEN
@ -1804,14 +1793,35 @@ void D_SRB2Main(void)
CON_Init();
CON_SetLoadingProgress(LOADED_HUINIT);
D_RegisterServerCommands();
D_RegisterClientCommands(); // be sure that this is called before D_CheckNetGame
R_RegisterEngineStuff();
S_RegisterSoundStuff();
I_RegisterSysCommands();
CON_SetLoadingProgress(LOADED_HUINIT);
CONS_Printf("W_InitMultipleFiles(): Adding external PWADs.\n");
// HACK: Refer to https://git.do.srb2.org/KartKrew/RingRacers/-/merge_requests/29#note_61574
partadd_earliestfile = numwadfiles;
W_InitMultipleFiles(startuppwads, true);
// Only search for pwad maps and reload graphics if we actually have a pwad added
if (startuppwads[0] != NULL)
{
//
// search for pwad maps
//
P_InitMapData();
HU_LoadGraphics();
}
D_CleanFile(startuppwads);
partadd_earliestfile = UINT16_MAX;
CON_SetLoadingProgress(LOADED_PWAD);
M_Init();

View file

@ -143,7 +143,7 @@ static inline int lib_freeslot(lua_State *L)
CONS_Printf("Skincolor SKINCOLOR_%s allocated.\n",word);
FREE_SKINCOLORS[i] = Z_Malloc(strlen(word)+1, PU_STATIC, NULL);
strcpy(FREE_SKINCOLORS[i],word);
skincolors[i].cache_spraycan = UINT16_MAX;
skincolors[SKINCOLOR_FIRSTFREESLOT+i].cache_spraycan = UINT16_MAX;
numskincolors++;
lua_pushinteger(L, SKINCOLOR_FIRSTFREESLOT + i);
r++;

View file

@ -334,7 +334,7 @@ void readfreeslots(MYFILE *f)
CONS_Printf("Skincolor SKINCOLOR_%s allocated.\n",word);
FREE_SKINCOLORS[i] = Z_Malloc(strlen(word)+1, PU_STATIC, NULL);
strcpy(FREE_SKINCOLORS[i],word);
skincolors[i].cache_spraycan = UINT16_MAX;
skincolors[SKINCOLOR_FIRSTFREESLOT+i].cache_spraycan = UINT16_MAX;
numskincolors++;
break;
}

View file

@ -24,6 +24,8 @@
#include "g_state.h" // gamestate_t (for lua)
#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"
@ -5172,6 +5174,20 @@ struct int_const_s const INT_CONST[] = {
{"PRECIPFX_THUNDER",PRECIPFX_THUNDER},
{"PRECIPFX_LIGHTNING",PRECIPFX_LIGHTNING},
{"PRECIPFX_WATERPARTICLES",PRECIPFX_WATERPARTICLES},
// followermode_t
{"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

@ -333,8 +333,10 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p
Surf.PolyColor.s.alpha = softwaretranstogl[V_GetHUDTranslucency(option)];
else if (alphalevel == 12)
Surf.PolyColor.s.alpha = softwaretranstogl_hi[V_GetHUDTranslucency(option)];
else
else if (alphalevel < 10)
Surf.PolyColor.s.alpha = softwaretranstogl[10-alphalevel];
else // alphalevel > 12
return;
HWD.pfnDrawPolygon(&Surf, v, 4, flags|PF_Modulated);
}
@ -487,8 +489,10 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale,
Surf.PolyColor.s.alpha = softwaretranstogl[V_GetHUDTranslucency(option)];
else if (alphalevel == 12)
Surf.PolyColor.s.alpha = softwaretranstogl_hi[V_GetHUDTranslucency(option)];
else
else if (alphalevel < 10)
Surf.PolyColor.s.alpha = softwaretranstogl[10-alphalevel];
else // alphalevel > 12
return;
HWD.pfnDrawPolygon(&Surf, v, 4, flags|PF_Modulated);
}

View file

@ -53,11 +53,11 @@ UINT16 K_RainbowColor(tic_t time)
}
/*--------------------------------------------------
void K_RainbowColormap(UINT8 *dest_colormap, UINT8 skincolor)
void K_RainbowColormap(UINT8 *dest_colormap, skincolornum_t skincolor)
See header file for description.
--------------------------------------------------*/
void K_RainbowColormap(UINT8 *dest_colormap, UINT8 skincolor)
void K_RainbowColormap(UINT8 *dest_colormap, skincolornum_t skincolor)
{
INT32 i;
RGBA_t color;
@ -193,7 +193,7 @@ static void K_IntermissionColormap(UINT8 *dest_colormap)
}
}
UINT16 skincolor = SKINCOLOR_INTERMISSION1;
skincolornum_t skincolor = SKINCOLOR_INTERMISSION1;
const double blue_start = 3.0;
const double blue_end = 5.0;
const double green_buffer = 0.5;
@ -214,11 +214,11 @@ static void K_IntermissionColormap(UINT8 *dest_colormap)
}
/*--------------------------------------------------
void K_GenerateKartColormap(UINT8 *dest_colormap, INT32 skinnum, UINT8 color)
void K_GenerateKartColormap(UINT8 *dest_colormap, INT32 skinnum, skincolornum_t color)
See header file for description.
--------------------------------------------------*/
void K_GenerateKartColormap(UINT8 *dest_colormap, INT32 skinnum, UINT8 color)
void K_GenerateKartColormap(UINT8 *dest_colormap, INT32 skinnum, skincolornum_t color)
{
INT32 i;
INT32 starttranscolor;

View file

@ -55,7 +55,7 @@ UINT8 K_ColorRelativeLuminance(UINT8 r, UINT8 g, UINT8 b);
UINT16 K_RainbowColor(tic_t time);
/*--------------------------------------------------
void K_RainbowColormap(UINT8 *dest_colormap, UINT8 skincolor);
void K_RainbowColormap(UINT8 *dest_colormap, skincolornum_t skincolor);
Generates a colormap to "colorize" all palette indicies
to the provided skincolor.
@ -68,7 +68,7 @@ UINT16 K_RainbowColor(tic_t time);
None
--------------------------------------------------*/
void K_RainbowColormap(UINT8 *dest_colormap, UINT8 skincolor);
void K_RainbowColormap(UINT8 *dest_colormap, skincolornum_t skincolor);
/*--------------------------------------------------
UINT8 K_HitlagColorValue(RGBA_t color);
@ -100,7 +100,7 @@ UINT8 K_HitlagColorValue(RGBA_t color);
void K_HitlagColormap(UINT8 *dest_colormap);
/*--------------------------------------------------
void K_GenerateKartColormap(UINT8 *dest_colormap, INT32 skinnum, UINT8 color);
void K_GenerateKartColormap(UINT8 *dest_colormap, INT32 skinnum, skincolornum_t color);
Generates a translation colormap for Kart, to replace R_GenerateTranslationColormap in r_draw.c
@ -113,7 +113,7 @@ void K_HitlagColormap(UINT8 *dest_colormap);
None
--------------------------------------------------*/
void K_GenerateKartColormap(UINT8 *dest_colormap, INT32 skinnum, UINT8 color);
void K_GenerateKartColormap(UINT8 *dest_colormap, INT32 skinnum, skincolornum_t color);
/*--------------------------------------------------

View file

@ -4032,7 +4032,7 @@ static void K_DrawTypingNotifier(fixed_t x, fixed_t y, player_t *p, INT32 flags)
{
if (p->cmd.flags & TICCMD_TYPING)
{
V_DrawFixedPatch(x, y, FRACUNIT, V_HUDTRANS|V_SPLITSCREEN|flags, kp_talk, NULL);
V_DrawFixedPatch(x, y, FRACUNIT, V_SPLITSCREEN|flags, kp_talk, NULL);
/* spacing closer with the last two looks a better most of the time */
K_DrawTypingDot(x + 3*FRACUNIT, y, 15, p, flags);
@ -5178,6 +5178,12 @@ static void K_drawKartMinimap(void)
if (encoremode)
ang = ANGLE_180 - ang;
if (skin && mobj->color && !mobj->colorized // relevant to redo
&& skins[skin].starttranscolor != skins[0].starttranscolor) // redoing would have an affect
{
colormap = R_GetTranslationColormap(TC_DEFAULT, static_cast<skincolornum_t>(mobj->color), GTC_CACHE);
}
K_drawKartMinimapIcon(
interpx,
interpy,

View file

@ -564,7 +564,7 @@ static void PR_ApplyProfile_Appearance(profile_t *p, UINT8 playernum)
static void PR_ApplyProfile_Settings(profile_t *p, UINT8 playernum)
{
// toggles
// toggles -- be sure to also adjust M_ProfileEditApply
CV_StealthSetValue(&cv_kickstartaccel[playernum], p->kickstartaccel);
CV_StealthSetValue(&cv_autoroulette[playernum], p->autoroulette);
CV_StealthSetValue(&cv_litesteer[playernum], p->litesteer);
@ -621,6 +621,21 @@ void PR_ApplyProfileLight(UINT8 profilenum, UINT8 playernum)
PR_ApplyProfile_Appearance(p, playernum);
}
void PR_ApplyProfileToggles(UINT8 profilenum, UINT8 playernum)
{
profile_t *p = PR_GetProfile(profilenum);
// this CAN happen!!
if (p == NULL)
{
// no need to be as loud...
profilenum = 0; // make sure to set this so that the cvar is set properly.
p = PR_GetProfile(profilenum);
}
PR_ApplyProfile_Settings(p, playernum);
}
void PR_ApplyProfilePretend(UINT8 profilenum, UINT8 playernum)
{
profile_t *p = PR_GetProfile(profilenum);

View file

@ -230,6 +230,11 @@ void PR_ApplyProfile(UINT8 profilenum, UINT8 playernum);
// Controls, kickstartaccel and "current profile" data is *not* modified.
void PR_ApplyProfileLight(UINT8 profilenum, UINT8 playernum);
// PR_ApplyProfileToggles(UINT8 profilenum, UINT8 playernum)
// Applies ONLY controls and kickstartaccel.
// Exposed for menu code exclusively.
void PR_ApplyProfileToggles(UINT8 profilenum, UINT8 playernum);
// PR_ApplyProfilePretend(UINT8 profilenum, UINT8 playernum)
// ONLY modifies "current profile" data.
// Exists because any other option inteferes with rapid testing.

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"
@ -229,6 +230,8 @@ static const struct {
{META_LUABANKS, "luabanks[]"},
{META_ACTIVATOR, "activator_t"},
{META_FOLLOWER, "follower_t"},
{NULL, NULL}
};
@ -337,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
//////////////
@ -3931,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}
};

296
src/lua_followerlib.c Normal file
View file

@ -0,0 +1,296 @@
// DR. ROBOTNIK'S RING RACERS
//-----------------------------------------------------------------------------
// Copyright (C) 2024 by Kart Krew.
// Copyright (C) 2020 by Sonic Team Junior.
// Copyright (C) 2016 by John "JTE" Muniz.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file lua_followerlib.c
/// \brief player follower structure library for Lua scripting
#include "doomdef.h"
#include "fastcmp.h"
#include "k_follower.h"
#include "r_skins.h"
#include "sounds.h"
#include "lua_script.h"
#include "lua_libs.h"
enum follower {
follower_valid = 0,
follower_name,
follower_icon,
follower_category,
follower_defaultcolor,
follower_mode,
follower_scale,
follower_bubblescale,
follower_atangle,
follower_dist,
follower_height,
follower_zoffs,
follower_horzlag,
follower_vertlag,
follower_anglelag,
follower_bobamp,
follower_bobspeed,
// states
follower_idlestate,
follower_followstate,
follower_hurtstate,
follower_winstate,
follower_losestate,
follower_hitconfirmstate,
follower_hitconfirmtime,
follower_ringstate,
follower_ringtime,
//
follower_hornsound,
};
static const char *const follower_opt[] = {
"valid",
"name",
"icon",
"category",
"defaultcolor",
"mode",
"scale",
"bubblescale",
"atangle",
"dist",
"height",
"zoffs",
"horzlag",
"vertlag",
"anglelag",
"bobamp",
"bobspeed",
// states
"idlestate",
"followstate",
"hurtstate",
"winstate",
"losestate",
"hitconfirmstate",
"hitconfirmtime",
"ringstate",
"ringtime",
//
"hornsound",
NULL
};
#define UNIMPLEMENTED luaL_error(L, LUA_QL("follower_t") " field " LUA_QS " is not implemented for Lua and cannot be accessed.", follower_opt[field])
static int follower_get(lua_State *L)
{
follower_t *follower = *((follower_t **)luaL_checkudata(L, 1, META_FOLLOWER));
enum follower field = luaL_checkoption(L, 2, NULL, follower_opt);
// followers are always valid, only added, never removed
I_Assert(follower != NULL);
switch (field)
{
case follower_valid:
lua_pushboolean(L, follower != NULL);
break;
case follower_name:
lua_pushstring(L, follower->name);
break;
case follower_icon:
lua_pushstring(L, follower->icon);
break;
case follower_category:
// This would require me to expose followercategory_t as well
// Not doing that for now, so this has no use.
return UNIMPLEMENTED;
case follower_defaultcolor:
lua_pushinteger(L, follower->defaultcolor);
break;
case follower_mode:
lua_pushinteger(L, follower->mode);
break;
case follower_scale:
lua_pushfixed(L, follower->scale);
break;
case follower_bubblescale:
lua_pushfixed(L, follower->bubblescale);
break;
case follower_atangle:
lua_pushangle(L, follower->atangle);
break;
case follower_dist:
lua_pushfixed(L, follower->dist);
break;
case follower_height:
lua_pushfixed(L, follower->height);
break;
case follower_zoffs:
lua_pushfixed(L, follower->zoffs);
break;
case follower_horzlag:
lua_pushfixed(L, follower->horzlag);
break;
case follower_vertlag:
lua_pushfixed(L, follower->vertlag);
break;
case follower_anglelag:
lua_pushfixed(L, follower->anglelag);
break;
case follower_bobamp:
lua_pushfixed(L, follower->bobamp);
break;
case follower_bobspeed:
lua_pushinteger(L, follower->bobspeed);
break;
case follower_idlestate:
lua_pushinteger(L, follower->idlestate);
break;
case follower_followstate:
lua_pushinteger(L, follower->followstate);
break;
case follower_hurtstate:
lua_pushinteger(L, follower->hurtstate);
break;
case follower_winstate:
lua_pushinteger(L, follower->winstate);
break;
case follower_losestate:
lua_pushinteger(L, follower->losestate);
break;
case follower_hitconfirmstate:
lua_pushinteger(L, follower->hitconfirmstate);
break;
case follower_hitconfirmtime:
lua_pushinteger(L, follower->hitconfirmtime);
break;
case follower_ringstate:
lua_pushinteger(L, follower->ringstate);
break;
case follower_ringtime:
lua_pushinteger(L, follower->ringtime);
break;
case follower_hornsound:
lua_pushinteger(L, follower->hornsound);
break;
}
return 1;
}
static int follower_set(lua_State *L)
{
return luaL_error(L, LUA_QL("follower_t") " struct cannot be edited by Lua.");
}
static int follower_num(lua_State *L)
{
follower_t *follower = *((follower_t **)luaL_checkudata(L, 1, META_FOLLOWER));
// followers are always valid, only added, never removed
I_Assert(follower != NULL);
lua_pushinteger(L, follower-followers);
return 1;
}
static int lib_iterateFollowers(lua_State *L)
{
INT32 i;
if (lua_gettop(L) < 2)
{
lua_pushcfunction(L, lib_iterateFollowers);
return 1;
}
lua_settop(L, 2);
lua_remove(L, 1); // state is unused.
if (!lua_isnil(L, 1))
i = (INT32)(*((follower_t **)luaL_checkudata(L, 1, META_FOLLOWER)) - followers) + 1;
else
i = 0;
// followers are always valid, only added, never removed
if (i < numfollowers)
{
LUA_PushUserdata(L, &followers[i], META_FOLLOWER);
return 1;
}
return 0;
}
static int lib_getFollower(lua_State *L)
{
const char *field;
INT32 i;
// find follower by number
if (lua_type(L, 2) == LUA_TNUMBER)
{
i = luaL_checkinteger(L, 2);
if (i < 0 || i >= MAXFOLLOWERS)
return luaL_error(L, "followers[] index %d out of range (0 - %d)", i, MAXFOLLOWERS-1);
if (i >= numfollowers)
return 0;
LUA_PushUserdata(L, &followers[i], META_FOLLOWER);
return 1;
}
field = luaL_checkstring(L, 2);
// special function iterate
if (fastcmp(field,"iterate"))
{
lua_pushcfunction(L, lib_iterateFollowers);
return 1;
}
// find follower by name
i = K_FollowerAvailable(field);
if (i != -1)
{
LUA_PushUserdata(L, &followers[i], META_FOLLOWER);
return 1;
}
return 0;
}
static int lib_numFollowers(lua_State *L)
{
lua_pushinteger(L, numfollowers);
return 1;
}
int LUA_FollowerLib(lua_State *L)
{
luaL_newmetatable(L, META_FOLLOWER);
lua_pushcfunction(L, follower_get);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, follower_set);
lua_setfield(L, -2, "__newindex");
lua_pushcfunction(L, follower_num);
lua_setfield(L, -2, "__len");
lua_pop(L,1);
lua_newuserdata(L, 0);
lua_createtable(L, 0, 2);
lua_pushcfunction(L, lib_getFollower);
lua_setfield(L, -2, "__index");
lua_pushcfunction(L, lib_numFollowers);
lua_setfield(L, -2, "__len");
lua_setmetatable(L, -2);
lua_setglobal(L, "followers");
return 0;
}

View file

@ -688,11 +688,11 @@ void LUA_HookHUD(huddrawlist_h list, int hook_type)
hud_running = true; // local hook
// Catch runaway clipping rectangles.
V_ClearClipRect();
init_hook_call(&hook, 0, res_none);
call_mapped(&hook, &hudHookIds[hook_type]);
// Catch runaway clipping rectangles.
V_ClearClipRect();
hud_running = false;
}

View file

@ -893,6 +893,45 @@ static int libd_drawKartString(lua_State *L)
return 0;
}
static int libd_setClipRect(lua_State *L)
{
fixed_t x = luaL_checkinteger(L, 1);
fixed_t y = luaL_checkinteger(L, 2);
fixed_t w = luaL_checkinteger(L, 3);
fixed_t h = luaL_checkinteger(L, 4);
INT32 flags = luaL_optinteger(L, 5, 0);
huddrawlist_h list;
flags &= ~V_PARAMMASK; // Don't let crashes happen.
HUDONLY
lua_getfield(L, LUA_REGISTRYINDEX, "HUD_DRAW_LIST");
list = (huddrawlist_h) lua_touserdata(L, -1);
lua_pop(L, 1);
if (LUA_HUD_IsDrawListValid(list))
LUA_HUD_AddSetClipRect(list, x, y, w, h, flags);
else
V_SetClipRect(x, y, w, h, flags);
return 0;
}
static int libd_clearClipRect(lua_State *L)
{
huddrawlist_h list;
HUDONLY
lua_getfield(L, LUA_REGISTRYINDEX, "HUD_DRAW_LIST");
list = (huddrawlist_h) lua_touserdata(L, -1);
lua_pop(L, 1);
if (LUA_HUD_IsDrawListValid(list))
LUA_HUD_AddClearClipRect(list);
else
V_ClearClipRect();
return 0;
}
static int libd_titleCardStringWidth(lua_State *L)
{
const char *str = luaL_checkstring(L, 1);
@ -1013,6 +1052,13 @@ static int libd_renderer(lua_State *L)
return 1;
}
static int libd_splitscreen(lua_State *L)
{
HUDONLY
lua_pushinteger(L, r_splitscreen); // push splitscreen
return 1;
}
// M_RANDOM
//////////////
@ -1111,6 +1157,8 @@ static luaL_Reg lib_draw[] = {
{"drawString", libd_drawString},
{"drawTitleCardString", libd_drawTitleCardString},
{"drawKartString", libd_drawKartString},
{"setClipRect", libd_setClipRect},
{"clearClipRect", libd_clearClipRect},
// misc
{"stringWidth", libd_stringWidth},
{"titleCardStringWidth", libd_titleCardStringWidth},
@ -1127,6 +1175,7 @@ static luaL_Reg lib_draw[] = {
{"dupx", libd_dupx},
{"dupy", libd_dupy},
{"renderer", libd_renderer},
{"splitscreen", libd_splitscreen},
{"localTransFlag", libd_getlocaltransflag},
{"drawOnMinimap", libd_drawOnMinimap},
{"getDeltaTime", libd_getDeltaTime},

View file

@ -30,6 +30,8 @@ enum drawitem_e {
DI_FadeScreen,
DI_DrawTitleCardString,
DI_DrawKartString,
DI_SetClipRect,
DI_ClearClipRect,
DI_MAX,
};
@ -394,6 +396,34 @@ void LUA_HUD_AddDrawKartString(
item->flags = flags;
}
void LUA_HUD_AddSetClipRect(
huddrawlist_h list,
fixed_t x,
fixed_t y,
fixed_t w,
fixed_t h,
INT32 flags
)
{
size_t i = AllocateDrawItem(list);
drawitem_t *item = &list->items[i];
item->type = DI_SetClipRect;
item->x = x;
item->y = y;
item->w = w;
item->h = h;
item->flags = flags;
}
void LUA_HUD_AddClearClipRect(
huddrawlist_h list
)
{
size_t i = AllocateDrawItem(list);
drawitem_t *item = &list->items[i];
item->type = DI_ClearClipRect;
}
void LUA_HUD_DrawList(huddrawlist_h list)
{
size_t i;
@ -474,6 +504,12 @@ void LUA_HUD_DrawList(huddrawlist_h list)
case DI_DrawKartString:
V_DrawTimerString(item->x, item->y, item->flags, itemstr);
break;
case DI_SetClipRect:
V_SetClipRect(item->x, item->y, item->w, item->h, item->flags);
break;
case DI_ClearClipRect:
V_ClearClipRect();
break;
default:
I_Error("can't draw draw list item: invalid draw list item type");
continue;

View file

@ -122,6 +122,17 @@ void LUA_HUD_AddDrawKartString(
const char *str,
INT32 flags
);
void LUA_HUD_AddSetClipRect(
huddrawlist_h list,
fixed_t x,
fixed_t y,
fixed_t w,
fixed_t h,
INT32 flags
);
void LUA_HUD_AddClearClipRect(
huddrawlist_h list
);
// Draws the given draw list
void LUA_HUD_DrawList(huddrawlist_h list);

View file

@ -102,6 +102,8 @@ extern lua_State *gL;
#define META_ACTIVATOR "ACTIVATOR_T*"
#define META_FOLLOWER "FOLLOWER_T*"
boolean luaL_checkboolean(lua_State *L, int narg);
int LUA_EnumLib(lua_State *L);
@ -120,6 +122,7 @@ int LUA_TagLib(lua_State *L);
int LUA_PolyObjLib(lua_State *L);
int LUA_BlockmapLib(lua_State *L);
int LUA_HudLib(lua_State *L);
int LUA_FollowerLib(lua_State *L);
#ifdef __cplusplus
} // extern "C"

View file

@ -60,6 +60,7 @@ static lua_CFunction liblist[] = {
LUA_PolyObjLib, // polyobj_t
LUA_BlockmapLib, // blockmap stuff
LUA_HudLib, // HUD stuff
LUA_FollowerLib, // follower_t, followers[]
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

@ -103,27 +103,16 @@ static void M_ProfileEditApply(void)
optionsmenu.profile->fov = cv_dummyprofilefov.value;
// If this profile is in-use by anyone, apply the changes immediately upon exiting.
// Don't apply the profile itself as that would lead to issues mid-game.
// Don't apply the full profile itself as that would lead to issues mid-game.
if (belongsto > -1 && belongsto < MAXSPLITSCREENPLAYERS)
{
extern consvar_t cv_fov[MAXSPLITSCREENPLAYERS];
CV_SetValue(&cv_kickstartaccel[belongsto], cv_dummyprofilekickstart.value);
CV_SetValue(&cv_autoroulette[belongsto], cv_dummyprofileautoroulette.value);
CV_SetValue(&cv_litesteer[belongsto], cv_dummyprofilelitesteer.value);
CV_SetValue(&cv_autoring[belongsto], cv_dummyprofileautoring.value);
CV_SetValue(&cv_rumble[belongsto], cv_dummyprofilerumble.value);
CV_SetValue(&cv_fov[belongsto], cv_dummyprofilefov.value);
PR_ApplyProfileToggles(optionsmenu.profilen, belongsto);
}
// Reapply player 1's real profile.
// (And then we do this for P1 anyway. I didn't write
// this code so I'm not sure why it's doing this, but it
// can override cv_skin if forcecharacter is in effect!
// I suspect this is intended to set cv_currprofile.
// FIXME?)
// Reapply player 1's real profile ID.
if (cv_currprofile.value > -1)
{
PR_ApplyProfile(cv_lastprofile[0].value, 0);
PR_ApplyProfilePretend(cv_lastprofile[0].value, 0);
}
}

View file

@ -278,10 +278,10 @@ void M_ProfileControlsConfirm(INT32 choice)
M_ProfileControlSaveResponse(MA_YES);
// Reapply player 1's real profile.
// Reapply player 1's real profile ID.
if (cv_currprofile.value > -1)
{
PR_ApplyProfile(cv_lastprofile[0].value, 0);
PR_ApplyProfilePretend(cv_lastprofile[0].value, 0);
}
}

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

View file

@ -125,7 +125,7 @@ void ST_doPaletteStuff(void)
{
INT32 palette;
if (stplyr && stplyr->flashcount)
if (stplyr && stplyr->flashcount && cv_reducevfx.value == 0)
palette = stplyr->flashpal;
else
palette = 0;