From e412230ba93065ab9ea9a2c7195bd84a82858a96 Mon Sep 17 00:00:00 2001 From: Lach Date: Wed, 29 Nov 2023 19:27:52 +1100 Subject: [PATCH] Add "continue" and "playersetup" Lua HUD hooks & draw followitems in the Player Setup menu --- src/f_finale.c | 85 +++++++++++++++++---- src/lua_hook.h | 9 +++ src/lua_hooklib.c | 68 +++++++++++++---- src/m_menu.c | 183 +++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 306 insertions(+), 39 deletions(-) diff --git a/src/f_finale.c b/src/f_finale.c index 68e9c3216..585229271 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -229,6 +229,7 @@ static UINT8 cutscene_boostspeed = 0; char stjrintro[9] = "STJRI000"; static huddrawlist_h luahuddrawlist_title; +static huddrawlist_h luahuddrawlist_continue[2]; // // This alters the text string cutscene_disptext. @@ -3529,9 +3530,14 @@ void F_TitleDemoTicker(void) static skin_t *contskins[2]; static UINT8 cont_spr2[2][6]; static UINT8 *contcolormaps[2]; +static player_t *contPlayers[2]; +static skincolornum_t contColors[2]; // it's possible to change your skincolor in the continue screen, so this is for Lua to identify the skincolor that was used to cache the colormap +static boolean contOverrides[2]; void F_StartContinue(void) { + UINT8 i; + I_Assert(!netgame && !multiplayer); if (continuesInSession && players[consoleplayer].continues <= 0) @@ -3554,9 +3560,11 @@ void F_StartContinue(void) S_ChangeMusicInternal("_conti", false); S_StopSounds(); + contPlayers[0] = &players[consoleplayer]; contskins[0] = &skins[players[consoleplayer].skin]; cont_spr2[0][0] = P_GetSkinSprite2(contskins[0], SPR2_CNT1, NULL); cont_spr2[0][2] = contskins[0]->contangle & 7; + contColors[0] = players[consoleplayer].skincolor; contcolormaps[0] = R_GetTranslationColormap(players[consoleplayer].skin, players[consoleplayer].skincolor, GTC_CACHE); cont_spr2[0][4] = contskins[0]->sprites[cont_spr2[0][0]].numframes; cont_spr2[0][5] = max(1, contskins[0]->contspeed); @@ -3570,9 +3578,11 @@ void F_StartContinue(void) else // HACK secondplaya = 1; + contPlayers[1] = &players[secondplaya]; contskins[1] = &skins[players[secondplaya].skin]; cont_spr2[1][0] = P_GetSkinSprite2(contskins[1], SPR2_CNT4, NULL); cont_spr2[1][2] = (contskins[1]->contangle >> 3) & 7; + contColors[1] = players[secondplaya].skincolor; contcolormaps[1] = R_GetTranslationColormap(players[secondplaya].skin, players[secondplaya].skincolor, GTC_CACHE); cont_spr2[1][4] = contskins[1]->sprites[cont_spr2[1][0]].numframes; if (cont_spr2[1][0] == SPR2_CNT4) @@ -3592,6 +3602,58 @@ void F_StartContinue(void) timetonext = (11*TICRATE)+11; continuetime = 0; + + // allocate and/or clear Lua continue screen draw lists + for (i = 0; i < 2; i++) + { + if (!LUA_HUD_IsDrawListValid(luahuddrawlist_continue[i])) + { + LUA_HUD_DestroyDrawList(luahuddrawlist_continue[i]); + luahuddrawlist_continue[i] = LUA_HUD_CreateDrawList(); + } + LUA_HUD_ClearDrawList(luahuddrawlist_continue[i]); + contOverrides[i] = false; + } +} + +static void F_DestroyContinueDrawLists(void) +{ + UINT8 i; + for (i = 0; i < 2; i++) + { + LUA_HUD_DestroyDrawList(luahuddrawlist_continue[i]); + luahuddrawlist_continue[i] = NULL; + contOverrides[i] = false; + } +} + +static void F_DrawContinueCharacter(INT32 dx, INT32 dy, UINT8 n) +{ + spritedef_t *sprdef; + spriteframe_t *sprframe; + patch_t *patch; + + if (renderisnewtic) + { + LUA_HUD_ClearDrawList(luahuddrawlist_continue[n]); + contOverrides[n] = LUA_HookCharacterHUD + ( + HUD_HOOK(continue), luahuddrawlist_continue[n], contPlayers[n], + dx, dy, contskins[n]->highresscale, + (INT32)(contskins[n] - skins), cont_spr2[n][0], cont_spr2[n][1], cont_spr2[n][2] + 1, contColors[n], // add 1 to rotation to convert internal angle numbers (0-7) to WAD editor angle numbers (1-8) + imcontinuing ? continuetime : timetonext, imcontinuing + ); + } + + LUA_HUD_DrawList(luahuddrawlist_continue[n]); + + if (contOverrides[n] == true) + return; + + sprdef = &contskins[n]->sprites[cont_spr2[n][0]]; + sprframe = &sprdef->spriteframes[cont_spr2[n][1]]; + patch = W_CachePatchNum(sprframe->lumppat[cont_spr2[n][2]], PU_PATCH_LOWPRIORITY); + V_DrawFixedPatch((dx), (dy), contskins[n]->highresscale, (sprframe->flip & (1<>1), ncontinues = players[consoleplayer].continues; char numbuf[9] = "CONTNUM*"; @@ -3646,7 +3706,7 @@ void F_ContinueDrawer(void) else if (ncontinues > 10) { if (!(continuetime & 1) || continuetime > 17) - V_DrawContinueIcon(x, 68, 0, players[consoleplayer].skin, players[consoleplayer].skincolor); + V_DrawContinueIcon(x, 68, 0, (INT32)(contskins[0] - skins), contColors[0]); V_DrawScaledPatch(x+12, 66, 0, stlivex); V_DrawRightAlignedString(x+38, 64, 0, va("%d",(imcontinuing ? ncontinues-1 : ncontinues))); @@ -3660,7 +3720,7 @@ void F_ContinueDrawer(void) { if (i == (ncontinues/2) && ((continuetime & 1) || continuetime > 17)) continue; - V_DrawContinueIcon(x - (i*30), 68, 0, players[consoleplayer].skin, players[consoleplayer].skincolor); + V_DrawContinueIcon(x - (i*30), 68, 0, (INT32)(contskins[0] - skins), contColors[0]); } x = BASEVIDWIDTH>>1; } @@ -3700,21 +3760,12 @@ void F_ContinueDrawer(void) else if (lift[0] > TICRATE+5) lift[0] = TICRATE+5; -#define drawchar(dx, dy, n) {\ - sprdef = &contskins[n]->sprites[cont_spr2[n][0]];\ - sprframe = &sprdef->spriteframes[cont_spr2[n][1]];\ - patch = W_CachePatchNum(sprframe->lumppat[cont_spr2[n][2]], PU_PATCH_LOWPRIORITY);\ - V_DrawFixedPatch((dx), (dy), contskins[n]->highresscale, (sprframe->flip & (1<= 0) - drawchar((BASEVIDWIDTH<<(FRACBITS-1))-offsx, ((140-lift[0])< (11*TICRATE)) V_DrawFadeScreen(31, timetonext-(11*TICRATE)); @@ -3730,6 +3781,7 @@ void F_ContinueTicker(void) { if (!(--timetonext)) { + F_DestroyContinueDrawLists(); Command_ExitGame_f(); return; } @@ -3739,6 +3791,7 @@ void F_ContinueTicker(void) { if (++continuetime == 3*TICRATE) { + F_DestroyContinueDrawLists(); G_Continue(); return; } diff --git a/src/lua_hook.h b/src/lua_hook.h index cb0e30d87..1845cc465 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -86,6 +86,8 @@ automatically. X (title),/* titlescreen */\ X (titlecard),\ X (intermission),\ + X (continue),\ + X (playersetup),\ /* I chose to access the hook enums through a macro as well. This could provide @@ -117,6 +119,13 @@ extern boolean hook_cmd_running; void LUA_HookVoid(int hook); void LUA_HookHUD(int hook, huddrawlist_h drawlist); +int LUA_HookCharacterHUD +( + int hook, huddrawlist_h drawlist, player_t *player, + fixed_t x, fixed_t y, fixed_t scale, + INT32 skinIndex, UINT8 sprite2, UINT8 frame, UINT8 rotation, skincolornum_t color, + INT32 ticker, boolean mode +); int LUA_HookMobj(mobj_t *, int hook); int LUA_Hook2Mobj(mobj_t *, mobj_t *, int hook); diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 0fc25ee6c..02b3bf45a 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -375,6 +375,17 @@ static boolean prepare_string_hook return false; } +static boolean prepare_hud_hook +( + Hook_State * hook, + int default_status, + int hook_type +){ + return init_hook_type(hook, default_status, + hook_type, 0, NULL, + hudHookIds[hook_type].numHooks); +} + static void init_hook_call ( Hook_State * hook, @@ -490,6 +501,21 @@ static int call_mobj_type_hooks(Hook_State *hook, mobjtype_t mobj_type) return call_mapped(hook, &mobjHookIds[mobj_type][hook->hook_type]); } +static void call_hud_hooks +( + Hook_State * hook, + int results, + Hook_Callback results_handler +){ + hud_running = true; // local hook + init_hook_call(hook, results, results_handler); + call_mapped(hook, &hudHookIds[hook->hook_type]); + hud_running = false; + + lua_pushnil(gL); + lua_setfield(gL, LUA_REGISTRYINDEX, "HUD_DRAW_LIST"); +} + static int call_hooks ( Hook_State * hook, @@ -648,25 +674,41 @@ int LUA_HookKey(event_t *event, int hook_type) void LUA_HookHUD(int hook_type, huddrawlist_h list) { - const hook_t * map = &hudHookIds[hook_type]; Hook_State hook; - if (map->numHooks > 0) + if (prepare_hud_hook(&hook, 0, hook_type)) { - start_hook_stack(); - begin_hook_values(&hook); - LUA_SetHudHook(hook_type, list); - - hud_running = true; // local hook - init_hook_call(&hook, 0, res_none); - call_mapped(&hook, map); - hud_running = false; - - lua_pushnil(gL); - lua_setfield(gL, LUA_REGISTRYINDEX, "HUD_DRAW_LIST"); + call_hud_hooks(&hook, 0, res_none); } } +int LUA_HookCharacterHUD +( + int hook_type, huddrawlist_h list, player_t *player, + fixed_t x, fixed_t y, fixed_t scale, + INT32 skinIndex, UINT8 sprite2, UINT8 frame, UINT8 rotation, skincolornum_t color, + INT32 ticker, boolean mode +){ + Hook_State hook; + if (prepare_hud_hook(&hook, false, hook_type)) + { + LUA_SetHudHook(hook_type, list); + LUA_PushUserdata(gL, player, META_PLAYER); + lua_pushfixed(gL, x); + lua_pushfixed(gL, y); + lua_pushfixed(gL, scale); + lua_pushstring(gL, skins[skinIndex].name); + lua_pushinteger(gL, sprite2); + lua_pushinteger(gL, frame); + lua_pushinteger(gL, rotation); + lua_pushinteger(gL, color); + lua_pushinteger(gL, ticker); + lua_pushboolean(gL, mode); + call_hud_hooks(&hook, 1, res_true); + } + return hook.status; +} + /* ========================================================================= SPECIALIZED HOOKS ========================================================================= */ diff --git a/src/m_menu.c b/src/m_menu.c index 45e74c0fc..1851bfad2 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -182,6 +182,9 @@ static fixed_t char_scroll = 0; static tic_t keydown = 0; +// Lua +static huddrawlist_h luahuddrawlist_playersetup; + // // PROTOTYPES // @@ -11988,6 +11991,19 @@ static UINT8 multi_frame; static UINT8 multi_spr2; static boolean multi_paused; static boolean multi_invcolor; +static boolean multi_override; + +static spritedef_t *multi_followitem_sprdef; +static INT32 multi_followitem_skinnum; +static UINT8 multi_followitem_numframes; +static UINT8 multi_followitem_startframe; +static UINT8 multi_followitem_frame; +static fixed_t multi_followitem_duration; +static fixed_t multi_followitem_tics; +static fixed_t multi_followitem_scale; +static fixed_t multi_followitem_yoffset; + +#define MULTI_DURATION (4*FRACUNIT) // this is set before entering the MultiPlayer setup menu, // for either player 1 or 2 @@ -12132,9 +12148,92 @@ static menucolor_t *M_GridIndexToMenuColor(UINT16 index) } } +static void M_SetPlayerSetupFollowItem() +{ + const mobjtype_t followitem = skins[setupm_fakeskin].followitem; + + switch (followitem) + { + case MT_TAILSOVERLAY: + { + const state_t *state = &states[S_TAILSOVERLAY_MINUS30DEGREES]; + const UINT8 sprite2 = P_GetSkinSprite2(&skins[setupm_fakeskin], state->frame & FF_FRAMEMASK, NULL); + + if (state->sprite != SPR_PLAY) + break; + + multi_followitem_sprdef = &skins[setupm_fakeskin].sprites[sprite2]; + multi_followitem_skinnum = setupm_fakeskin; + multi_followitem_numframes = multi_followitem_sprdef->numframes; + multi_followitem_startframe = 0; + multi_followitem_frame = multi_frame; + multi_followitem_duration = MULTI_DURATION; + multi_followitem_tics = multi_tics; + multi_followitem_scale = FRACUNIT; + multi_followitem_yoffset = 0; + + if ((state->frame & FF_SPR2MIDSTART) && (multi_followitem_numframes > 0) && M_RandomChance(FRACUNIT / 2)) + { + multi_followitem_frame += multi_followitem_numframes / 2; + } + break; + } + case MT_METALJETFUME: + { + const state_t *state = &states[S_JETFUME1]; + + if (!(state->frame & FF_ANIMATE)) + break; + + multi_followitem_sprdef = &sprites[state->sprite]; + multi_followitem_skinnum = TC_DEFAULT; + multi_followitem_numframes = state->var1 + 1; + multi_followitem_startframe = state->frame & FF_FRAMEMASK; + multi_followitem_frame = multi_followitem_startframe; + multi_followitem_duration = state->var2 * FRACUNIT; + multi_followitem_tics = multi_tics % multi_followitem_duration; + multi_followitem_scale = 2 * FRACUNIT / 3; + multi_followitem_yoffset = (skins[setupm_fakeskin].height - FixedMul(mobjinfo[followitem].height, multi_followitem_scale)) >> 1; + break; + } + default: + multi_followitem_sprdef = NULL; + break; + } +} + +static void M_DrawPlayerSetupFollowItem(INT32 x, INT32 y, fixed_t scale, INT32 flags) +{ + spriteframe_t *sprframe; + patch_t *patch; + UINT8 *colormap; + + if (multi_followitem_sprdef == NULL) + return; + + if (multi_followitem_frame >= multi_followitem_startframe + multi_followitem_numframes) + multi_followitem_frame = multi_followitem_startframe; + + colormap = R_GetTranslationColormap(multi_followitem_skinnum, setupm_fakecolor->color, GTC_CACHE); + + sprframe = &multi_followitem_sprdef->spriteframes[multi_followitem_frame]; + patch = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH); + if (sprframe->flip & 1) // Only for first sprite + flags |= V_FLIP; // This sprite is left/right flipped! + + x <<= FRACBITS; + y <<= FRACBITS; + y -= FixedMul(multi_followitem_yoffset, scale); + + scale = FixedMul(scale, multi_followitem_scale); + + V_DrawFixedPatch(x, y, scale, flags, patch, colormap); +} + static void M_DrawSetupMultiPlayerMenu(void) { INT32 x, y, cursory = 0, flags = 0; + fixed_t scale; spritedef_t *sprdef; spriteframe_t *sprframe; patch_t *patch; @@ -12184,11 +12283,24 @@ static void M_DrawSetupMultiPlayerMenu(void) y += 11; // anim the player in the box - multi_tics -= renderdeltatics; - while (!multi_paused && multi_tics <= 0) + if (!multi_paused) { - multi_frame++; - multi_tics += 4*FRACUNIT; + multi_tics -= renderdeltatics; + while (multi_tics <= 0) + { + multi_frame++; + multi_tics += MULTI_DURATION; + } + + if (multi_followitem_sprdef != NULL) + { + multi_followitem_tics -= renderdeltatics; + while (multi_followitem_tics <= 0) + { + multi_followitem_frame++; + multi_followitem_tics += multi_followitem_duration; + } + } } #define charw 74 @@ -12203,22 +12315,43 @@ static void M_DrawSetupMultiPlayerMenu(void) goto faildraw; // ok, draw player sprite for sure now - colormap = R_GetTranslationColormap(setupm_fakeskin, setupm_fakecolor->color, GTC_CACHE); - if (multi_frame >= sprdef->numframes) multi_frame = 0; + scale = FixedDiv(skins[setupm_fakeskin].highresscale, skins[setupm_fakeskin].shieldscale); + + #define chary (y+64) + + if (renderisnewtic) + { + LUA_HUD_ClearDrawList(luahuddrawlist_playersetup); + multi_override = LUA_HookCharacterHUD + ( + HUD_HOOK(playersetup), luahuddrawlist_playersetup, setupm_player, + x << FRACBITS, chary << FRACBITS, scale, + setupm_fakeskin, multi_spr2, multi_frame, 1, setupm_fakecolor->color, + (multi_tics >> FRACBITS) + 1, multi_paused + ); + } + + LUA_HUD_DrawList(luahuddrawlist_playersetup); + + if (multi_override == true) + goto colordraw; + + colormap = R_GetTranslationColormap(setupm_fakeskin, setupm_fakecolor->color, GTC_CACHE); + sprframe = &sprdef->spriteframes[multi_frame]; patch = W_CachePatchNum(sprframe->lumppat[0], PU_PATCH); if (sprframe->flip & 1) // Only for first sprite flags |= V_FLIP; // This sprite is left/right flipped! -#define chary (y+64) + M_DrawPlayerSetupFollowItem(x, chary, scale, flags & ~V_FLIP); V_DrawFixedPatch( x<color != setupm_cvcolor->value) COM_BufAddText (va("%s %d\n",setupm_cvcolor->name,setupm_fakecolor->color)); + + // de-allocate Lua player setup drawlist + LUA_HUD_DestroyDrawList(luahuddrawlist_playersetup); + luahuddrawlist_playersetup = NULL; + multi_override = false; + return true; }