Merge branch 'hudlib-hook-refactor' into 'next'

Refactor HUD hooks too

See merge request STJr/SRB2!1577
This commit is contained in:
Tatsuru 2021-09-13 01:38:05 +00:00
commit 952ae51669
8 changed files with 188 additions and 297 deletions

View file

@ -41,6 +41,7 @@
#include "console.h"
#include "lua_hud.h"
#include "lua_hook.h"
// Stage of animation:
// 0 = text, 1 = art screen
@ -3421,7 +3422,7 @@ void F_TitleScreenDrawer(void)
}
luahook:
LUAh_TitleHUD();
LUA_HUDHOOK(title);
}
// separate animation timer for backgrounds, since we also count

View file

@ -2104,7 +2104,7 @@ void HU_Drawer(void)
}
else
HU_DrawCoopOverlay();
LUAh_ScoresHUD();
LUA_HUDHOOK(scores);
}
if (gamestate != GS_LEVEL)

View file

@ -79,6 +79,13 @@ automatically.
X (LinedefExecute),\
X (ShouldJingleContinue),/* should jingle of the given music continue playing */\
#define HUD_HOOK_LIST(X) \
X (game),\
X (scores),/* emblems/multiplayer list */\
X (title),/* titlescreen */\
X (titlecard),\
X (intermission),\
/*
I chose to access the hook enums through a macro as well. This could provide
a hint to lookup the macro's definition instead of the enum's definition.
@ -89,18 +96,26 @@ grepped and found in the lists above.
#define MOBJ_HOOK(name) mobjhook_ ## name
#define HOOK(name) hook_ ## name
#define HUD_HOOK(name) hudhook_ ## name
#define STRING_HOOK(name) stringhook_ ## name
enum { MOBJ_HOOK_LIST (MOBJ_HOOK) MOBJ_HOOK(MAX) };
enum { HOOK_LIST (HOOK) HOOK(MAX) };
enum { STRING_HOOK_LIST (STRING_HOOK) STRING_HOOK(MAX) };
#define ENUM(X) enum { X ## _LIST (X) X(MAX) }
ENUM (MOBJ_HOOK);
ENUM (HOOK);
ENUM (HUD_HOOK);
ENUM (STRING_HOOK);
#undef ENUM
/* dead simple, LUA_HOOK(GameQuit) */
#define LUA_HOOK(type) LUA_HookVoid(HOOK(type))
#define LUA_HUDHOOK(type) LUA_HookHUD(HUD_HOOK(type))
extern boolean hook_cmd_running;
void LUA_HookVoid(int hook);
void LUA_HookHUD(int hook);
int LUA_HookMobj(mobj_t *, int hook);
int LUA_Hook2Mobj(mobj_t *, mobj_t *, int hook);

View file

@ -31,12 +31,15 @@
ABSTRACTION
========================================================================= */
static const char * const mobjHookNames[] = { MOBJ_HOOK_LIST (TOSTR) NULL };
static const char * const hookNames[] = { HOOK_LIST (TOSTR) NULL };
#define LIST(id, M) \
static const char * const id [] = { M (TOSTR) NULL }
static const char * const stringHookNames[] = {
STRING_HOOK_LIST (TOSTR) NULL
};
LIST (mobjHookNames, MOBJ_HOOK_LIST);
LIST (hookNames, HOOK_LIST);
LIST (hudHookNames, HUD_HOOK_LIST);
LIST (stringHookNames, STRING_HOOK_LIST);
#undef LIST
typedef struct {
int numHooks;
@ -49,6 +52,7 @@ typedef struct {
} stringhook_t;
static hook_t hookIds[HOOK(MAX)];
static hook_t hudHookIds[HUD_HOOK(MAX)];
static hook_t mobjHookIds[NUMMOBJTYPES][MOBJ_HOOK(MAX)];
// Lua tables are used to lookup string hook ids.
@ -56,6 +60,7 @@ static stringhook_t stringHooks[STRING_HOOK(MAX)];
// This will be indexed by hook id, the value of which fetches the registry.
static int * hookRefs;
static int nextid;
// After a hook errors once, don't print the error again.
static UINT8 * hooksErrored;
@ -104,13 +109,13 @@ static void get_table(lua_State *L)
lua_remove(L, -2);
}
static void add_hook_to_table(lua_State *L, int id, int n)
static void add_hook_to_table(lua_State *L, int n)
{
lua_pushnumber(L, id);
lua_pushnumber(L, nextid);
lua_rawseti(L, -2, n);
}
static void add_string_hook(lua_State *L, int type, int id)
static void add_string_hook(lua_State *L, int type)
{
stringhook_t * hook = &stringHooks[type];
@ -146,33 +151,54 @@ static void add_string_hook(lua_State *L, int type, int id)
{
lua_pushstring(L, string);
get_table(L);
add_hook_to_table(L, id, 1 + lua_objlen(L, -1));
add_hook_to_table(L, 1 + lua_objlen(L, -1));
}
else
add_hook_to_table(L, id, ++hook->numGeneric);
add_hook_to_table(L, ++hook->numGeneric);
}
static void add_hook(hook_t *map, int id)
static void add_hook(hook_t *map)
{
Z_Realloc(map->ids, (map->numHooks + 1) * sizeof *map->ids,
PU_STATIC, &map->ids);
map->ids[map->numHooks++] = id;
map->ids[map->numHooks++] = nextid;
}
static void add_mobj_hook(lua_State *L, int hook_type, int id)
static void add_mobj_hook(lua_State *L, int hook_type)
{
mobjtype_t mobj_type = luaL_optnumber(L, 3, MT_NULL);
luaL_argcheck(L, mobj_type < NUMMOBJTYPES, 3, "invalid mobjtype_t");
add_hook(&mobjHookIds[mobj_type][hook_type], id);
add_hook(&mobjHookIds[mobj_type][hook_type]);
}
static void add_hud_hook(lua_State *L, int idx)
{
add_hook(&hudHookIds[luaL_checkoption(L,
idx, "game", hudHookNames)]);
}
static void add_hook_ref(lua_State *L, int idx)
{
if (!(nextid & 7))
{
Z_Realloc(hooksErrored,
BIT_ARRAY_SIZE (nextid + 1) * sizeof *hooksErrored,
PU_STATIC, &hooksErrored);
hooksErrored[nextid >> 3] = 0;
}
Z_Realloc(hookRefs, (nextid + 1) * sizeof *hookRefs, PU_STATIC, &hookRefs);
// set the hook function in the registry.
lua_pushvalue(L, idx);
hookRefs[nextid++] = luaL_ref(L, LUA_REGISTRYINDEX);
}
// Takes hook, function, and additional arguments (mobj type to act on, etc.)
static int lib_addHook(lua_State *L)
{
static int nextid;
const char * name;
int type;
@ -185,34 +211,26 @@ static int lib_addHook(lua_State *L)
/* this is a very special case */
if (( type = hook_in_list(name, stringHookNames) ) < STRING_HOOK(MAX))
{
add_string_hook(L, type, nextid);
add_string_hook(L, type);
}
else if (( type = hook_in_list(name, mobjHookNames) ) < MOBJ_HOOK(MAX))
{
add_mobj_hook(L, type, nextid);
add_mobj_hook(L, type);
}
else if (( type = hook_in_list(name, hookNames) ) < HOOK(MAX))
{
add_hook(&hookIds[type], nextid);
add_hook(&hookIds[type]);
}
else if (strcmp(name, "HUD") == 0)
{
add_hud_hook(L, 3);
}
else
{
return luaL_argerror(L, 1, lua_pushfstring(L, "invalid hook " LUA_QS, name));
}
if (!(nextid & 7))
{
Z_Realloc(hooksErrored,
BIT_ARRAY_SIZE (nextid + 1) * sizeof *hooksErrored,
PU_STATIC, &hooksErrored);
hooksErrored[nextid >> 3] = 0;
}
Z_Realloc(hookRefs, (nextid + 1) * sizeof *hookRefs, PU_STATIC, &hookRefs);
// set the hook function in the registry.
lua_pushvalue(L, 2);/* the function */
hookRefs[nextid++] = luaL_ref(L, LUA_REGISTRYINDEX);
add_hook_ref(L, 2);/* the function */
return 0;
}
@ -227,6 +245,23 @@ int LUA_HookLib(lua_State *L)
return 0;
}
/* TODO: remove in next backwards incompatible release */
#if MODID == 18
int lib_hudadd(lua_State *L);/* yeah compiler */
int lib_hudadd(lua_State *L)
{
if (!lua_lumploading)
return luaL_error(L, "This function cannot be called from within a hook or coroutine!");
luaL_checktype(L, 1, LUA_TFUNCTION);
add_hud_hook(L, 2);
add_hook_ref(L, 1);
return 0;
}
#endif
typedef struct Hook_State Hook_State;
typedef void (*Hook_Callback)(Hook_State *);
@ -259,11 +294,16 @@ static void push_string(void)
lua_pushvalue(gL, SINDEX);
}
static boolean start_hook_stack(void)
static boolean begin_hook_values(Hook_State *hook)
{
hook->top = lua_gettop(gL);
return true;
}
static void start_hook_stack(void)
{
lua_settop(gL, 0);
push_error_handler();
return true;
}
static boolean init_hook_type
@ -279,10 +319,11 @@ static boolean init_hook_type
if (nonzero)
{
start_hook_stack();
hook->hook_type = hook_type;
hook->mobj_type = mobj_type;
hook->string = string;
return start_hook_stack();
return begin_hook_values(hook);
}
else
return false;
@ -323,7 +364,7 @@ static boolean prepare_string_hook
stringHooks[hook_type].ref))
{
lua_pushstring(gL, string);
return true;
return begin_hook_values(hook);
}
else
return false;
@ -332,12 +373,12 @@ static boolean prepare_string_hook
static void init_hook_call
(
Hook_State * hook,
int values,
int results,
Hook_Callback results_handler
){
hook->top = lua_gettop(gL);
hook->values = values;
const int top = lua_gettop(gL);
hook->values = (top - hook->top);
hook->top = top;
hook->results = results;
hook->results_handler = results_handler;
}
@ -447,13 +488,12 @@ static int call_mobj_type_hooks(Hook_State *hook, mobjtype_t mobj_type)
static int call_hooks
(
Hook_State * hook,
int values,
int results,
Hook_Callback results_handler
){
int calls = 0;
init_hook_call(hook, values, results, results_handler);
init_hook_call(hook, results, results_handler);
if (hook->string)
{
@ -514,7 +554,7 @@ int LUA_HookMobj(mobj_t *mobj, int hook_type)
if (prepare_mobj_hook(&hook, false, hook_type, mobj->type))
{
LUA_PushUserdata(gL, mobj, META_MOBJ);
call_hooks(&hook, 1, 1, res_true);
call_hooks(&hook, 1, res_true);
}
return hook.status;
}
@ -526,7 +566,7 @@ int LUA_Hook2Mobj(mobj_t *t1, mobj_t *t2, int hook_type)
{
LUA_PushUserdata(gL, t1, META_MOBJ);
LUA_PushUserdata(gL, t2, META_MOBJ);
call_hooks(&hook, 2, 1, res_force);
call_hooks(&hook, 1, res_force);
}
return hook.status;
}
@ -535,7 +575,7 @@ void LUA_HookVoid(int type)
{
Hook_State hook;
if (prepare_hook(&hook, 0, type))
call_hooks(&hook, 0, 0, res_none);
call_hooks(&hook, 0, res_none);
}
void LUA_HookInt(INT32 number, int hook_type)
@ -544,7 +584,7 @@ void LUA_HookInt(INT32 number, int hook_type)
if (prepare_hook(&hook, 0, hook_type))
{
lua_pushinteger(gL, number);
call_hooks(&hook, 1, 0, res_none);
call_hooks(&hook, 0, res_none);
}
}
@ -554,7 +594,7 @@ void LUA_HookBool(boolean value, int hook_type)
if (prepare_hook(&hook, 0, hook_type))
{
lua_pushboolean(gL, value);
call_hooks(&hook, 1, 0, res_none);
call_hooks(&hook, 0, res_none);
}
}
@ -564,7 +604,7 @@ int LUA_HookPlayer(player_t *player, int hook_type)
if (prepare_hook(&hook, false, hook_type))
{
LUA_PushUserdata(gL, player, META_PLAYER);
call_hooks(&hook, 1, 1, res_true);
call_hooks(&hook, 1, res_true);
}
return hook.status;
}
@ -580,7 +620,7 @@ int LUA_HookTiccmd(player_t *player, ticcmd_t *cmd, int hook_type)
if (hook_type == HOOK(PlayerCmd))
hook_cmd_running = true;
call_hooks(&hook, 2, 1, res_true);
call_hooks(&hook, 1, res_true);
if (hook_type == HOOK(PlayerCmd))
hook_cmd_running = false;
@ -594,11 +634,29 @@ int LUA_HookKey(event_t *event, int hook_type)
if (prepare_hook(&hook, false, hook_type))
{
LUA_PushUserdata(gL, event, META_KEYEVENT);
call_hooks(&hook, 1, 1, res_true);
call_hooks(&hook, 1, res_true);
}
return hook.status;
}
void LUA_HookHUD(int hook_type)
{
const hook_t * map = &hudHookIds[hook_type];
Hook_State hook;
if (map->numHooks > 0)
{
start_hook_stack();
begin_hook_values(&hook);
LUA_SetHudHook(hook_type);
hud_running = true; // local hook
init_hook_call(&hook, 0, res_none);
call_mapped(&hook, map);
hud_running = false;
}
}
/* =========================================================================
SPECIALIZED HOOKS
========================================================================= */
@ -618,7 +676,7 @@ void LUA_HookThinkFrame(void)
if (prepare_hook(&hook, 0, type))
{
init_hook_call(&hook, 0, 0, res_none);
init_hook_call(&hook, 0, res_none);
for (k = 0; k < map->numHooks; ++k)
{
@ -653,7 +711,7 @@ int LUA_HookMobjLineCollide(mobj_t *mobj, line_t *line)
{
LUA_PushUserdata(gL, mobj, META_MOBJ);
LUA_PushUserdata(gL, line, META_LINE);
call_hooks(&hook, 2, 1, res_force);
call_hooks(&hook, 1, res_force);
}
return hook.status;
}
@ -665,7 +723,7 @@ int LUA_HookTouchSpecial(mobj_t *special, mobj_t *toucher)
{
LUA_PushUserdata(gL, special, META_MOBJ);
LUA_PushUserdata(gL, toucher, META_MOBJ);
call_hooks(&hook, 2, 1, res_true);
call_hooks(&hook, 1, res_true);
}
return hook.status;
}
@ -678,7 +736,6 @@ static int damage_hook
INT32 damage,
UINT8 damagetype,
int hook_type,
int values,
Hook_Callback results_handler
){
Hook_State hook;
@ -687,10 +744,10 @@ static int damage_hook
LUA_PushUserdata(gL, target, META_MOBJ);
LUA_PushUserdata(gL, inflictor, META_MOBJ);
LUA_PushUserdata(gL, source, META_MOBJ);
if (values == 5)
if (hook_type != MOBJ_HOOK(MobjDeath))
lua_pushinteger(gL, damage);
lua_pushinteger(gL, damagetype);
call_hooks(&hook, values, 1, results_handler);
call_hooks(&hook, 1, results_handler);
}
return hook.status;
}
@ -698,19 +755,19 @@ static int damage_hook
int LUA_HookShouldDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype)
{
return damage_hook(target, inflictor, source, damage, damagetype,
MOBJ_HOOK(ShouldDamage), 5, res_force);
MOBJ_HOOK(ShouldDamage), res_force);
}
int LUA_HookMobjDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype)
{
return damage_hook(target, inflictor, source, damage, damagetype,
MOBJ_HOOK(MobjDamage), 5, res_true);
MOBJ_HOOK(MobjDamage), res_true);
}
int LUA_HookMobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damagetype)
{
return damage_hook(target, inflictor, source, 0, damagetype,
MOBJ_HOOK(MobjDeath), 4, res_true);
MOBJ_HOOK(MobjDeath), res_true);
}
int LUA_HookMobjMoveBlocked(mobj_t *t1, mobj_t *t2, line_t *line)
@ -721,7 +778,7 @@ int LUA_HookMobjMoveBlocked(mobj_t *t1, mobj_t *t2, line_t *line)
LUA_PushUserdata(gL, t1, META_MOBJ);
LUA_PushUserdata(gL, t2, META_MOBJ);
LUA_PushUserdata(gL, line, META_LINE);
call_hooks(&hook, 3, 1, res_true);
call_hooks(&hook, 1, res_true);
}
return hook.status;
}
@ -796,7 +853,7 @@ int LUA_HookBotAI(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd)
hook.userdata = &botai;
call_hooks(&hook, 2, 8, res_botai);
call_hooks(&hook, 8, res_botai);
}
return hook.status;
@ -811,7 +868,7 @@ void LUA_HookLinedefExecute(line_t *line, mobj_t *mo, sector_t *sector)
LUA_PushUserdata(gL, line, META_LINE);
LUA_PushUserdata(gL, mo, META_MOBJ);
LUA_PushUserdata(gL, sector, META_SECTOR);
ps_lua_mobjhooks += call_hooks(&hook, 3, 0, res_none);
ps_lua_mobjhooks += call_hooks(&hook, 0, res_none);
}
}
@ -835,7 +892,7 @@ int LUA_HookPlayerMsg(int source, int target, int flags, char *msg)
LUA_PushUserdata(gL, &players[target-1], META_PLAYER); // target
}
lua_pushstring(gL, msg); // msg
call_hooks(&hook, 4, 1, res_true);
call_hooks(&hook, 1, res_true);
}
return hook.status;
}
@ -849,7 +906,7 @@ int LUA_HookHurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source, UINT8 d
LUA_PushUserdata(gL, inflictor, META_MOBJ);
LUA_PushUserdata(gL, source, META_MOBJ);
lua_pushinteger(gL, damagetype);
call_hooks(&hook, 4, 1, res_true);
call_hooks(&hook, 1, res_true);
}
return hook.status;
}
@ -868,12 +925,14 @@ void LUA_HookNetArchive(lua_CFunction archFunc)
push_error_handler();
lua_insert(gL, EINDEX);
begin_hook_values(&hook);
// tables becomes an upvalue of archFunc
lua_pushvalue(gL, -1);
lua_pushcclosure(gL, archFunc, 1);
// stack: tables, archFunc
init_hook_call(&hook, 1, 0, res_none);
init_hook_call(&hook, 0, res_none);
call_mapped(&hook, map);
lua_pop(gL, 1); // pop archFunc
@ -889,7 +948,7 @@ int LUA_HookMapThingSpawn(mobj_t *mobj, mapthing_t *mthing)
{
LUA_PushUserdata(gL, mobj, META_MOBJ);
LUA_PushUserdata(gL, mthing, META_MAPTHING);
call_hooks(&hook, 2, 1, res_true);
call_hooks(&hook, 1, res_true);
}
return hook.status;
}
@ -901,7 +960,7 @@ int LUA_HookFollowMobj(player_t *player, mobj_t *mobj)
{
LUA_PushUserdata(gL, player, META_PLAYER);
LUA_PushUserdata(gL, mobj, META_MOBJ);
call_hooks(&hook, 2, 1, res_true);
call_hooks(&hook, 1, res_true);
}
return hook.status;
}
@ -913,7 +972,7 @@ int LUA_HookPlayerCanDamage(player_t *player, mobj_t *mobj)
{
LUA_PushUserdata(gL, player, META_PLAYER);
LUA_PushUserdata(gL, mobj, META_MOBJ);
call_hooks(&hook, 2, 1, res_force);
call_hooks(&hook, 1, res_force);
}
return hook.status;
}
@ -925,7 +984,7 @@ void LUA_HookPlayerQuit(player_t *plr, kickreason_t reason)
{
LUA_PushUserdata(gL, plr, META_PLAYER); // Player that quit
lua_pushinteger(gL, reason); // Reason for quitting
call_hooks(&hook, 2, 0, res_none);
call_hooks(&hook, 0, res_none);
}
}
@ -939,7 +998,7 @@ int LUA_HookTeamSwitch(player_t *player, int newteam, boolean fromspectators, bo
lua_pushboolean(gL, fromspectators);
lua_pushboolean(gL, tryingautobalance);
lua_pushboolean(gL, tryingscramble);
call_hooks(&hook, 5, 1, res_false);
call_hooks(&hook, 1, res_false);
}
return hook.status;
}
@ -954,7 +1013,7 @@ int LUA_HookViewpointSwitch(player_t *player, player_t *newdisplayplayer, boolea
lua_pushboolean(gL, forced);
hud_running = true; // local hook
call_hooks(&hook, 3, 1, res_force);
call_hooks(&hook, 1, res_force);
hud_running = false;
}
return hook.status;
@ -969,7 +1028,7 @@ int LUA_HookSeenPlayer(player_t *player, player_t *seenfriend)
LUA_PushUserdata(gL, seenfriend, META_PLAYER);
hud_running = true; // local hook
call_hooks(&hook, 2, 1, res_false);
call_hooks(&hook, 1, res_false);
hud_running = false;
}
return hook.status;
@ -985,7 +1044,7 @@ int LUA_HookShouldJingleContinue(player_t *player, const char *musname)
push_string();
hud_running = true; // local hook
call_hooks(&hook, 2, 1, res_true);
call_hooks(&hook, 1, res_true);
hud_running = false;
}
return hook.status;
@ -1051,7 +1110,8 @@ int LUA_HookMusicChange(const char *oldname, struct MusicChange *param)
if (prepare_hook(&hook, false, type))
{
init_hook_call(&hook, 7, 6, res_musicchange);
init_hook_call(&hook, 6, res_musicchange);
hook.values = 7;/* values pushed later */
hook.userdata = param;
lua_pushstring(gL, oldname);/* the only constant value */
@ -1097,7 +1157,7 @@ fixed_t LUA_HookPlayerHeight(player_t *player)
if (prepare_hook(&hook, -1, HOOK(PlayerHeight)))
{
LUA_PushUserdata(gL, player, META_PLAYER);
call_hooks(&hook, 1, 1, res_playerheight);
call_hooks(&hook, 1, res_playerheight);
}
return hook.status;
}
@ -1108,7 +1168,7 @@ int LUA_HookPlayerCanEnterSpinGaps(player_t *player)
if (prepare_hook(&hook, 0, HOOK(PlayerCanEnterSpinGaps)))
{
LUA_PushUserdata(gL, player, META_PLAYER);
call_hooks(&hook, 1, 1, res_force);
call_hooks(&hook, 1, res_force);
}
return hook.status;
}

View file

@ -47,8 +47,4 @@ extern boolean hud_running;
boolean LUA_HudEnabled(enum hud option);
void LUAh_GameHUD(player_t *stplyr);
void LUAh_ScoresHUD(void);
void LUAh_TitleHUD(void);
void LUAh_TitleCardHUD(player_t *stplayr);
void LUAh_IntermissionHUD(boolean failedstage);
void LUA_SetHudHook(int hook);

View file

@ -23,18 +23,18 @@
#include "v_video.h"
#include "w_wad.h"
#include "z_zone.h"
#include "y_inter.h"
#include "lua_script.h"
#include "lua_libs.h"
#include "lua_hud.h"
#include "lua_hook.h"
#define HUDONLY if (!hud_running) return luaL_error(L, "HUD rendering code should not be called outside of rendering hooks!");
boolean hud_running = false;
static UINT8 hud_enabled[(hud_MAX/8)+1];
static UINT8 hudAvailable; // hud hooks field
// must match enum hud in lua_hud.h
static const char *const hud_disable_options[] = {
"stagetitle",
@ -95,21 +95,6 @@ static const char *const patch_opt[] = {
"topoffset",
NULL};
enum hudhook {
hudhook_game = 0,
hudhook_scores,
hudhook_intermission,
hudhook_title,
hudhook_titlecard
};
static const char *const hudhook_opt[] = {
"game",
"scores",
"intermission",
"title",
"titlecard",
NULL};
// alignment types for v.drawString
enum align {
align_left = 0,
@ -1279,6 +1264,8 @@ static luaL_Reg lib_draw[] = {
{NULL, NULL}
};
static int lib_draw_ref;
//
// lib_hud
//
@ -1313,28 +1300,7 @@ static int lib_hudenabled(lua_State *L)
// add a HUD element for rendering
static int lib_hudadd(lua_State *L)
{
enum hudhook field;
luaL_checktype(L, 1, LUA_TFUNCTION);
field = luaL_checkoption(L, 2, "game", hudhook_opt);
if (!lua_lumploading)
return luaL_error(L, "This function cannot be called from within a hook or coroutine!");
lua_getfield(L, LUA_REGISTRYINDEX, "HUD");
I_Assert(lua_istable(L, -1));
lua_rawgeti(L, -1, field+2); // HUD[2+]
I_Assert(lua_istable(L, -1));
lua_remove(L, -2);
lua_pushvalue(L, 1);
lua_rawseti(L, -2, (int)(lua_objlen(L, -2) + 1));
hudAvailable |= 1<<field;
return 0;
}
extern int lib_hudadd(lua_State *L);
static luaL_Reg lib_hud[] = {
{"enable", lib_hudenable},
@ -1352,26 +1318,9 @@ int LUA_HudLib(lua_State *L)
{
memset(hud_enabled, 0xff, (hud_MAX/8)+1);
lua_newtable(L); // HUD registry table
lua_newtable(L);
luaL_register(L, NULL, lib_draw);
lua_rawseti(L, -2, 1); // HUD[1] = lib_draw
lua_newtable(L);
lua_rawseti(L, -2, 2); // HUD[2] = game rendering functions array
lua_newtable(L);
lua_rawseti(L, -2, 3); // HUD[3] = scores rendering functions array
lua_newtable(L);
lua_rawseti(L, -2, 4); // HUD[4] = intermission rendering functions array
lua_newtable(L);
lua_rawseti(L, -2, 5); // HUD[5] = title rendering functions array
lua_newtable(L);
lua_rawseti(L, -2, 6); // HUD[6] = title card rendering functions array
lua_setfield(L, LUA_REGISTRYINDEX, "HUD");
lua_newtable(L);
luaL_register(L, NULL, lib_draw);
lib_draw_ref = luaL_ref(L, LUA_REGISTRYINDEX);
luaL_newmetatable(L, META_HUDINFO);
lua_pushcfunction(L, hudinfo_get);
@ -1432,160 +1381,29 @@ boolean LUA_HudEnabled(enum hud option)
return false;
}
// Hook for HUD rendering
void LUAh_GameHUD(player_t *stplayr)
void LUA_SetHudHook(int hook)
{
if (!gL || !(hudAvailable & (1<<hudhook_game)))
return;
lua_getref(gL, lib_draw_ref);
hud_running = true;
lua_settop(gL, 0);
switch (hook)
{
case HUD_HOOK(game): {
camera_t *cam = (splitscreen && stplyr ==
&players[secondarydisplayplayer])
? &camera2 : &camera;
lua_pushcfunction(gL, LUA_GetErrorMessage);
LUA_PushUserdata(gL, stplyr, META_PLAYER);
LUA_PushUserdata(gL, cam, META_CAMERA);
} break;
lua_getfield(gL, LUA_REGISTRYINDEX, "HUD");
I_Assert(lua_istable(gL, -1));
lua_rawgeti(gL, -1, 2+hudhook_game); // HUD[2] = rendering funcs
I_Assert(lua_istable(gL, -1));
case HUD_HOOK(titlecard):
LUA_PushUserdata(gL, stplyr, META_PLAYER);
lua_pushinteger(gL, lt_ticker);
lua_pushinteger(gL, (lt_endtime + TICRATE));
break;
lua_rawgeti(gL, -2, 1); // HUD[1] = lib_draw
I_Assert(lua_istable(gL, -1));
lua_remove(gL, -3); // pop HUD
LUA_PushUserdata(gL, stplayr, META_PLAYER);
if (splitscreen && stplayr == &players[secondarydisplayplayer])
LUA_PushUserdata(gL, &camera2, META_CAMERA);
else
LUA_PushUserdata(gL, &camera, META_CAMERA);
lua_pushnil(gL);
while (lua_next(gL, -5) != 0) {
lua_pushvalue(gL, -5); // graphics library (HUD[1])
lua_pushvalue(gL, -5); // stplayr
lua_pushvalue(gL, -5); // camera
LUA_Call(gL, 3, 0, 1);
case HUD_HOOK(intermission):
lua_pushboolean(gL, intertype == int_spec &&
stagefailed);
}
lua_settop(gL, 0);
hud_running = false;
}
void LUAh_ScoresHUD(void)
{
if (!gL || !(hudAvailable & (1<<hudhook_scores)))
return;
hud_running = true;
lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage);
lua_getfield(gL, LUA_REGISTRYINDEX, "HUD");
I_Assert(lua_istable(gL, -1));
lua_rawgeti(gL, -1, 2+hudhook_scores); // HUD[3] = rendering funcs
I_Assert(lua_istable(gL, -1));
lua_rawgeti(gL, -2, 1); // HUD[1] = lib_draw
I_Assert(lua_istable(gL, -1));
lua_remove(gL, -3); // pop HUD
lua_pushnil(gL);
while (lua_next(gL, -3) != 0) {
lua_pushvalue(gL, -3); // graphics library (HUD[1])
LUA_Call(gL, 1, 0, 1);
}
lua_settop(gL, 0);
hud_running = false;
}
void LUAh_TitleHUD(void)
{
if (!gL || !(hudAvailable & (1<<hudhook_title)))
return;
hud_running = true;
lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage);
lua_getfield(gL, LUA_REGISTRYINDEX, "HUD");
I_Assert(lua_istable(gL, -1));
lua_rawgeti(gL, -1, 2+hudhook_title); // HUD[5] = rendering funcs
I_Assert(lua_istable(gL, -1));
lua_rawgeti(gL, -2, 1); // HUD[1] = lib_draw
I_Assert(lua_istable(gL, -1));
lua_remove(gL, -3); // pop HUD
lua_pushnil(gL);
while (lua_next(gL, -3) != 0) {
lua_pushvalue(gL, -3); // graphics library (HUD[1])
LUA_Call(gL, 1, 0, 1);
}
lua_settop(gL, 0);
hud_running = false;
}
void LUAh_TitleCardHUD(player_t *stplayr)
{
if (!gL || !(hudAvailable & (1<<hudhook_titlecard)))
return;
hud_running = true;
lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage);
lua_getfield(gL, LUA_REGISTRYINDEX, "HUD");
I_Assert(lua_istable(gL, -1));
lua_rawgeti(gL, -1, 2+hudhook_titlecard); // HUD[6] = rendering funcs
I_Assert(lua_istable(gL, -1));
lua_rawgeti(gL, -2, 1); // HUD[1] = lib_draw
I_Assert(lua_istable(gL, -1));
lua_remove(gL, -3); // pop HUD
LUA_PushUserdata(gL, stplayr, META_PLAYER);
lua_pushinteger(gL, lt_ticker);
lua_pushinteger(gL, (lt_endtime + TICRATE));
lua_pushnil(gL);
while (lua_next(gL, -6) != 0) {
lua_pushvalue(gL, -6); // graphics library (HUD[1])
lua_pushvalue(gL, -6); // stplayr
lua_pushvalue(gL, -6); // lt_ticker
lua_pushvalue(gL, -6); // lt_endtime
LUA_Call(gL, 4, 0, 1);
}
lua_settop(gL, 0);
hud_running = false;
}
void LUAh_IntermissionHUD(boolean failedstage)
{
if (!gL || !(hudAvailable & (1<<hudhook_intermission)))
return;
hud_running = true;
lua_settop(gL, 0);
lua_pushcfunction(gL, LUA_GetErrorMessage);
lua_getfield(gL, LUA_REGISTRYINDEX, "HUD");
I_Assert(lua_istable(gL, -1));
lua_rawgeti(gL, -1, 2+hudhook_intermission); // HUD[4] = rendering funcs
I_Assert(lua_istable(gL, -1));
lua_rawgeti(gL, -2, 1); // HUD[1] = lib_draw
I_Assert(lua_istable(gL, -1));
lua_remove(gL, -3); // pop HUD
lua_pushboolean(gL, failedstage); // stagefailed
lua_pushnil(gL);
while (lua_next(gL, -4) != 0) {
lua_pushvalue(gL, -4); // graphics library (HUD[1])
lua_pushvalue(gL, -4); // stagefailed
LUA_Call(gL, 2, 0, 1);
}
lua_settop(gL, 0);
hud_running = false;
}

View file

@ -43,6 +43,7 @@
#endif
#include "lua_hud.h"
#include "lua_hook.h"
UINT16 objectsdrawn = 0;
@ -1391,7 +1392,7 @@ void ST_drawTitleCard(void)
lt_lasttic = lt_ticker;
luahook:
LUAh_TitleCardHUD(stplyr);
LUA_HUDHOOK(titlecard);
}
//
@ -2732,7 +2733,7 @@ static void ST_overlayDrawer(void)
ST_drawPowerupHUD(); // same as it ever was...
if (!(netgame || multiplayer) || !hu_showscores)
LUAh_GameHUD(stplyr);
LUA_HUDHOOK(game);
// draw level title Tails
if (stagetitle && (!WipeInAction) && (!WipeStageTitle))

View file

@ -430,7 +430,7 @@ void Y_IntermissionDrawer(void)
else if (bgtile)
V_DrawPatchFill(bgtile);
LUAh_IntermissionHUD(intertype == int_spec && stagefailed);
LUA_HUDHOOK(intermission);
if (!LUA_HudEnabled(hud_intermissiontally))
goto skiptallydrawer;