From 613b6ad44c282ea4fccd30ccd5977c4186be4140 Mon Sep 17 00:00:00 2001 From: hayaunderscore Date: Tue, 4 Jun 2024 09:41:01 +0800 Subject: [PATCH 01/15] Expose `r_splitscreen` --- src/lua_script.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/lua_script.c b/src/lua_script.c index 4f743efa3..1edbae3b7 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -178,6 +178,9 @@ int LUA_PushGlobals(lua_State *L, const char *word) } else if (fastcmp(word,"splitscreen")) { lua_pushinteger(L, splitscreen); return 1; + } else if (fastcmp(word,"r_splitscreen")) { + lua_pushinteger(L, r_splitscreen); + return 1; } else if (fastcmp(word,"gamecomplete")) { lua_pushboolean(L, (gamecomplete != 0)); return 1; From f3e1cf814e94d227ed83c3d8eba4f872fedea723 Mon Sep 17 00:00:00 2001 From: hayaunderscore Date: Tue, 4 Jun 2024 17:13:35 +0800 Subject: [PATCH 02/15] Expose `V_SetClipRect` and `V_ClearClipRect` to lua Via the `v.setClipRect` and `v.clearClipRect` functions respectively. --- src/lua_hudlib.c | 41 +++++++++++++++++++++++++++++++++++++++ src/lua_hudlib_drawlist.c | 36 ++++++++++++++++++++++++++++++++++ src/lua_hudlib_drawlist.h | 11 +++++++++++ 3 files changed, 88 insertions(+) diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index 824825fe7..dd17f67a7 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -989,6 +989,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); @@ -1207,6 +1246,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}, diff --git a/src/lua_hudlib_drawlist.c b/src/lua_hudlib_drawlist.c index 1c7ee3117..e9120c692 100644 --- a/src/lua_hudlib_drawlist.c +++ b/src/lua_hudlib_drawlist.c @@ -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; diff --git a/src/lua_hudlib_drawlist.h b/src/lua_hudlib_drawlist.h index fea4499cb..1ad55ac2a 100644 --- a/src/lua_hudlib_drawlist.h +++ b/src/lua_hudlib_drawlist.h @@ -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); From 113146d2086ed7d5e4f56b18e9e706a4e54d8d0d Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 9 Aug 2024 22:46:40 -0400 Subject: [PATCH 03/15] Disallow palette flashes with reducevfx Resolves #214 --- src/st_stuff.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/st_stuff.c b/src/st_stuff.c index 69e0b4d34..d5dc20703 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -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; From 05d47fd06ba913ae710bbd93e79474aeb3027cde Mon Sep 17 00:00:00 2001 From: wehrlia <> Date: Wed, 21 Aug 2024 16:59:04 -0300 Subject: [PATCH 04/15] hw_draw.c: Don't draw anything if alphalevel > 12 --- src/hardware/hw_draw.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index a822d1cba..1bb294cff 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -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); } From d05202257b5d2176b5fcf1b38f89162c5814d99d Mon Sep 17 00:00:00 2001 From: wehrlia <> Date: Wed, 21 Aug 2024 17:00:14 -0300 Subject: [PATCH 05/15] K_DrawTypingNotifier: Remove V_HUDTRANS From V_DrawFixedPatch function call. --- src/k_hud.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_hud.cpp b/src/k_hud.cpp index 96d6e4d44..3d66bf52f 100644 --- a/src/k_hud.cpp +++ b/src/k_hud.cpp @@ -3835,7 +3835,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); From ff035e0af5c13537744f725045294a8fc62dc895 Mon Sep 17 00:00:00 2001 From: haya_underscore Date: Thu, 22 Aug 2024 13:05:41 +0000 Subject: [PATCH 06/15] Expose follower array and follower_t to lua --- src/CMakeLists.txt | 1 + src/deh_tables.c | 5 + src/lua_baselib.c | 2 + src/lua_followerlib.c | 296 ++++++++++++++++++++++++++++++++++++++++++ src/lua_libs.h | 3 + src/lua_script.c | 1 + 6 files changed, 308 insertions(+) create mode 100644 src/lua_followerlib.c diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index af64bb0bc..f61513b31 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -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 diff --git a/src/deh_tables.c b/src/deh_tables.c index df818c094..b8109b385 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -24,6 +24,7 @@ #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 "deh_tables.h" @@ -5150,6 +5151,10 @@ 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}, {NULL,0} }; diff --git a/src/lua_baselib.c b/src/lua_baselib.c index d282b99a5..83b15c651 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -229,6 +229,8 @@ static const struct { {META_LUABANKS, "luabanks[]"}, {META_ACTIVATOR, "activator_t"}, + + {META_FOLLOWER, "follower_t"}, {NULL, NULL} }; diff --git a/src/lua_followerlib.c b/src/lua_followerlib.c new file mode 100644 index 000000000..07fe8c998 --- /dev/null +++ b/src/lua_followerlib.c @@ -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; +} diff --git a/src/lua_libs.h b/src/lua_libs.h index 09df94514..290be4101 100644 --- a/src/lua_libs.h +++ b/src/lua_libs.h @@ -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" diff --git a/src/lua_script.c b/src/lua_script.c index 4f743efa3..3a4f64f4a 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -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 }; From 02043af2f77e813b79c29836ccd0fd917bb6be56 Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 18 Aug 2024 16:16:25 +0100 Subject: [PATCH 07/15] Do not corrupt spraycan cache when freeslotting custom skincolours My mistake gomen --- src/deh_lua.c | 2 +- src/deh_soc.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/deh_lua.c b/src/deh_lua.c index 6c97cda93..224d0c010 100644 --- a/src/deh_lua.c +++ b/src/deh_lua.c @@ -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++; diff --git a/src/deh_soc.c b/src/deh_soc.c index b0e7a473a..32475d0a6 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -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; } From 069c079f163b5a2864c7c7903b64a7d24b593327 Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 18 Aug 2024 16:24:15 +0100 Subject: [PATCH 08/15] k_color: Fix support for more than 255 skincolors Resolves KartKrew/RingRacers#109 --- src/k_color.c | 10 +++++----- src/k_color.h | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/k_color.c b/src/k_color.c index 35ea3d6a8..dcf6e0fa7 100644 --- a/src/k_color.c +++ b/src/k_color.c @@ -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; diff --git a/src/k_color.h b/src/k_color.h index 2123b22e8..3d922ce5f 100644 --- a/src/k_color.h +++ b/src/k_color.h @@ -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); /*-------------------------------------------------- From 69cc74ad8ee84d7b0b24bec8d7dd8ddd9beb1be8 Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 18 Aug 2024 20:00:33 +0100 Subject: [PATCH 09/15] Minimap directioning dot will use the correct skincolor even when set up for alternate remappable indices Resolves KartKrew/RingRacers#115 --- src/k_hud.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/k_hud.cpp b/src/k_hud.cpp index 3d66bf52f..be30fef75 100644 --- a/src/k_hud.cpp +++ b/src/k_hud.cpp @@ -4881,6 +4881,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(mobj->color), GTC_CACHE); + } + K_drawKartMinimapIcon( interpx, interpy, From d97db8f2302b58cef877e413c741393c3e2dc069 Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 18 Aug 2024 19:40:58 +0100 Subject: [PATCH 10/15] Do not reapply P1's Profile in full in edit menu flow Prevents changing player skin/color cvar when backing out (resolves KartKrew/RingRacers#34) --- src/menus/options-profiles-edit-1.c | 9 ++------- src/menus/options-profiles-edit-controls.c | 4 ++-- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/menus/options-profiles-edit-1.c b/src/menus/options-profiles-edit-1.c index 93d44049a..234a0efda 100644 --- a/src/menus/options-profiles-edit-1.c +++ b/src/menus/options-profiles-edit-1.c @@ -115,15 +115,10 @@ static void M_ProfileEditApply(void) CV_SetValue(&cv_fov[belongsto], cv_dummyprofilefov.value); } - // 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); } } diff --git a/src/menus/options-profiles-edit-controls.c b/src/menus/options-profiles-edit-controls.c index 3be0e117d..2c5dcec9e 100644 --- a/src/menus/options-profiles-edit-controls.c +++ b/src/menus/options-profiles-edit-controls.c @@ -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); } } From 012bbc6a746aa5cc4ac93a60ddaf8d0024a8c651 Mon Sep 17 00:00:00 2001 From: toaster Date: Sat, 24 Aug 2024 15:43:54 +0100 Subject: [PATCH 11/15] Refactor how Profile cvar toggles are set when applying changes Reduces the number of unique places to update when adding new ones --- src/k_profiles.cpp | 17 ++++++++++++++++- src/k_profiles.h | 5 +++++ src/menus/options-profiles-edit-1.c | 10 ++-------- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/src/k_profiles.cpp b/src/k_profiles.cpp index 0b9425fcb..f054e84d3 100644 --- a/src/k_profiles.cpp +++ b/src/k_profiles.cpp @@ -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); diff --git a/src/k_profiles.h b/src/k_profiles.h index 247a08e9f..988101f98 100644 --- a/src/k_profiles.h +++ b/src/k_profiles.h @@ -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. diff --git a/src/menus/options-profiles-edit-1.c b/src/menus/options-profiles-edit-1.c index 234a0efda..8bdd552c2 100644 --- a/src/menus/options-profiles-edit-1.c +++ b/src/menus/options-profiles-edit-1.c @@ -103,16 +103,10 @@ 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 ID. From 411e3b386161decc05d33d141dda7de7b887e34b Mon Sep 17 00:00:00 2001 From: hayaunderscore Date: Mon, 26 Aug 2024 10:17:42 +0800 Subject: [PATCH 12/15] r_splitscreen -> v.splitscreen As per suggestion by Sal --- src/lua_hudlib.c | 8 ++++++++ src/lua_script.c | 3 --- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index 824825fe7..140aee2d6 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -1109,6 +1109,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 ////////////// @@ -1223,6 +1230,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}, diff --git a/src/lua_script.c b/src/lua_script.c index 1edbae3b7..4f743efa3 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -178,9 +178,6 @@ int LUA_PushGlobals(lua_State *L, const char *word) } else if (fastcmp(word,"splitscreen")) { lua_pushinteger(L, splitscreen); return 1; - } else if (fastcmp(word,"r_splitscreen")) { - lua_pushinteger(L, r_splitscreen); - return 1; } else if (fastcmp(word,"gamecomplete")) { lua_pushboolean(L, (gamecomplete != 0)); return 1; From 49c49dab3bf0b8c793eca564a6c436c005203175 Mon Sep 17 00:00:00 2001 From: hayaunderscore Date: Mon, 26 Aug 2024 10:25:09 +0800 Subject: [PATCH 13/15] Move V_ClearClipRect after call_mapped based on toaster's suggestion --- src/lua_hooklib.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 0eacf83ce..1ccedd091 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -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; } From aa1cd4d7d024d4b908fd5502ee46e5b95a4d0be7 Mon Sep 17 00:00:00 2001 From: Cheariisan Date: Wed, 28 Aug 2024 22:04:31 +0000 Subject: [PATCH 14/15] Expose most of the music handler to Lua --- src/deh_tables.c | 11 ++ src/lua_baselib.c | 433 ++++++++++++++++++++++++++++++++++++++++++++++ src/lua_script.h | 3 + src/music.cpp | 53 ++++++ src/music.h | 31 ++++ 5 files changed, 531 insertions(+) diff --git a/src/deh_tables.c b/src/deh_tables.c index c2fe2660c..c8da6cabd 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -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} }; diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 13854375b..4ee70339b 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -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} }; diff --git a/src/lua_script.h b/src/lua_script.h index 00ad2526d..33c9bfca5 100644 --- a/src/lua_script.h +++ b/src/lua_script.h @@ -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)\ diff --git a/src/music.cpp b/src/music.cpp index 9d9384b5f..e9aab9b60 100644 --- a/src/music.cpp +++ b/src/music.cpp @@ -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); diff --git a/src/music.h b/src/music.h index e8ed7dbea..4b005e282 100644 --- a/src/music.h +++ b/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); From 1f7bee7484b59a45dd2d25634f8d3a8ac47e1901 Mon Sep 17 00:00:00 2001 From: haya_underscore Date: Wed, 28 Aug 2024 22:09:08 +0000 Subject: [PATCH 15/15] Fix random desyncs with `-file` in addons with custom net cvars. --- src/console.c | 2 +- src/console.h | 2 +- src/d_main.cpp | 36 +++++++++++++++++++++++------------- 3 files changed, 25 insertions(+), 15 deletions(-) diff --git a/src/console.c b/src/console.c index b458e2dc1..45993b3be 100644 --- a/src/console.c +++ b/src/console.c @@ -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 diff --git a/src/console.h b/src/console.h index 64bdc41af..e0c1e58e3 100644 --- a/src/console.h +++ b/src/console.h @@ -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, diff --git a/src/d_main.cpp b/src/d_main.cpp index f45ccbc64..0627fbf8f 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -1755,17 +1755,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 @@ -1798,14 +1787,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();