mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2024-11-14 17:01:07 +00:00
Merge branch 'action-super-fix' into 'next'
Make A_Action super act as expected Closes #718 See merge request STJr/SRB2!1737
This commit is contained in:
commit
5c87dd52ec
6 changed files with 119 additions and 41 deletions
|
@ -187,25 +187,31 @@ static inline int lib_freeslot(lua_State *L)
|
|||
// Arguments: mobj_t actor, int var1, int var2
|
||||
static int action_call(lua_State *L)
|
||||
{
|
||||
//actionf_t *action = lua_touserdata(L,lua_upvalueindex(1));
|
||||
actionf_t *action = *((actionf_t **)luaL_checkudata(L, 1, META_ACTION));
|
||||
mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
|
||||
|
||||
var1 = (INT32)luaL_optinteger(L, 3, 0);
|
||||
var2 = (INT32)luaL_optinteger(L, 4, 0);
|
||||
|
||||
if (!actor)
|
||||
{
|
||||
return LUA_ErrInvalid(L, "mobj_t");
|
||||
}
|
||||
|
||||
action->acp1(actor);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Hardcoded A_Action name to call for super() or NULL if super() would be invalid.
|
||||
// Set in lua_infolib.
|
||||
const char *superactions[MAXRECURSION];
|
||||
UINT8 superstack = 0;
|
||||
const char *luaactions[MAX_ACTION_RECURSION];
|
||||
UINT8 luaactionstack = 0;
|
||||
|
||||
static int lib_dummysuper(lua_State *L)
|
||||
{
|
||||
return luaL_error(L, "Can't call super() outside of hardcode-replacing A_Action functions being called by state changes!"); // convoluted, I know. @_@;;
|
||||
// TODO: Now that the restriction on only being allowed in state changes was lifted,
|
||||
// it'd be nice to have super extend to Lua A_ functions too :)
|
||||
return luaL_error(L, "Can't call super() outside of hardcode-replacing A_Action functions!");
|
||||
}
|
||||
|
||||
static void CacheAndPushConstant(lua_State *L, const char *name, lua_Integer value)
|
||||
|
@ -606,42 +612,62 @@ static inline int lib_getenum(lua_State *L)
|
|||
|
||||
if (!mathlib && fastncmp("A_",word,2)) {
|
||||
char *caps;
|
||||
// Try to get a Lua action first.
|
||||
/// \todo Push a closure that sets superactions[] and superstack.
|
||||
|
||||
// Hardcoded actions come first.
|
||||
// Trying to call them will invoke LUA_CallAction, which will handle super properly.
|
||||
// Retrieving them from this metatable allows them to be case-insensitive!
|
||||
for (i = 0; actionpointers[i].name; i++)
|
||||
{
|
||||
if (fasticmp(word, actionpointers[i].name))
|
||||
{
|
||||
// We push the actionf_t* itself as userdata!
|
||||
LUA_PushUserdata(L, &actionpointers[i].action, META_ACTION);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Now try to get Lua actions.
|
||||
/// \todo Push a closure that sets luaactions[] and luaactionstack.
|
||||
/// This would be part one of a step to get super functions working for custom A_ functions.
|
||||
/// Custom functions.
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, LREG_ACTIONS);
|
||||
|
||||
// actions are stored in all uppercase.
|
||||
caps = Z_StrDup(word);
|
||||
strupr(caps);
|
||||
lua_getfield(L, -1, caps);
|
||||
Z_Free(caps);
|
||||
|
||||
if (!lua_isnil(L, -1))
|
||||
{
|
||||
return 1; // Success! :D That was easy.
|
||||
}
|
||||
|
||||
// Welp, that failed.
|
||||
lua_pop(L, 2); // pop nil and LREG_ACTIONS
|
||||
|
||||
// Hardcoded actions as callable Lua functions!
|
||||
// Retrieving them from this metatable allows them to be case-insensitive!
|
||||
for (i = 0; actionpointers[i].name; i++)
|
||||
if (fasticmp(word, actionpointers[i].name)) {
|
||||
// We push the actionf_t* itself as userdata!
|
||||
LUA_PushUserdata(L, &actionpointers[i].action, META_ACTION);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else if (!mathlib && fastcmp("super",word))
|
||||
{
|
||||
if (!superstack)
|
||||
if (!luaactionstack)
|
||||
{
|
||||
// Not in A_ action routine
|
||||
lua_pushcfunction(L, lib_dummysuper);
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (i = 0; actionpointers[i].name; i++)
|
||||
if (fasticmp(superactions[superstack-1], actionpointers[i].name)) {
|
||||
{
|
||||
if (fasticmp(luaactions[luaactionstack-1], actionpointers[i].name))
|
||||
{
|
||||
LUA_PushUserdata(L, &actionpointers[i].action, META_ACTION);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Not a hardcoded A_ action.
|
||||
lua_pushcfunction(L, lib_dummysuper);
|
||||
return 1;
|
||||
}
|
||||
else if ((!mathlib && LUA_PushGlobals(L, word)) || ScanConstants(L, mathlib, word))
|
||||
return 1;
|
||||
|
|
|
@ -30,6 +30,7 @@ extern UINT8 used_spr[(NUMSPRITEFREESLOTS / 8) + 1]; // Bitwise flag for sprite
|
|||
memset(FREE_MOBJS,0,sizeof(char *) * NUMMOBJFREESLOTS);\
|
||||
memset(FREE_SKINCOLORS,0,sizeof(char *) * NUMCOLORFREESLOTS);\
|
||||
memset(used_spr,0,sizeof(UINT8) * ((NUMSPRITEFREESLOTS / 8) + 1));\
|
||||
memset(actionsoverridden, LUA_REFNIL, sizeof(actionsoverridden));\
|
||||
}
|
||||
|
||||
struct flickytypes_s {
|
||||
|
|
|
@ -40,9 +40,9 @@ extern boolean gamedataadded;
|
|||
extern boolean titlechanged;
|
||||
extern boolean introchanged;
|
||||
|
||||
#define MAXRECURSION 30
|
||||
extern const char *superactions[MAXRECURSION];
|
||||
extern UINT8 superstack;
|
||||
#define MAX_ACTION_RECURSION 30
|
||||
extern const char *luaactions[MAX_ACTION_RECURSION];
|
||||
extern UINT8 luaactionstack;
|
||||
|
||||
// If the dehacked patch does not match this version, we throw a warning
|
||||
#define PATCHVERSION 220
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "d_think.h"
|
||||
#include "sounds.h"
|
||||
#include "m_fixed.h"
|
||||
#include "dehacked.h" // MAX_ACTION_RECURSION
|
||||
|
||||
// deh_tables.c now has lists for the more named enums! PLEASE keep them up to date!
|
||||
// For great modding!!
|
||||
|
@ -564,7 +565,7 @@ void A_DragonWing();
|
|||
void A_DragonSegment();
|
||||
void A_ChangeHeight();
|
||||
|
||||
extern boolean actionsoverridden[NUMACTIONS];
|
||||
extern int actionsoverridden[NUMACTIONS][MAX_ACTION_RECURSION];
|
||||
|
||||
// ratio of states to sprites to mobj types is roughly 6 : 1 : 1
|
||||
#define NUMMOBJFREESLOTS 512
|
||||
|
|
|
@ -66,7 +66,7 @@ const char *const sfxinfo_wopt[] = {
|
|||
"caption",
|
||||
NULL};
|
||||
|
||||
boolean actionsoverridden[NUMACTIONS] = {false};
|
||||
int actionsoverridden[NUMACTIONS][MAX_ACTION_RECURSION];
|
||||
|
||||
//
|
||||
// Sprite Names
|
||||
|
@ -645,8 +645,8 @@ static void A_Lua(mobj_t *actor)
|
|||
if (lua_rawequal(gL, -1, -4))
|
||||
{
|
||||
found = true;
|
||||
superactions[superstack] = lua_tostring(gL, -2); // "A_ACTION"
|
||||
++superstack;
|
||||
luaactions[luaactionstack] = lua_tostring(gL, -2); // "A_ACTION"
|
||||
++luaactionstack;
|
||||
lua_pop(gL, 2); // pop the name and function
|
||||
break;
|
||||
}
|
||||
|
@ -661,8 +661,8 @@ static void A_Lua(mobj_t *actor)
|
|||
|
||||
if (found)
|
||||
{
|
||||
--superstack;
|
||||
superactions[superstack] = NULL;
|
||||
--luaactionstack;
|
||||
luaactions[luaactionstack] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -812,22 +812,54 @@ boolean LUA_SetLuaAction(void *stv, const char *action)
|
|||
return true; // action successfully set.
|
||||
}
|
||||
|
||||
static UINT8 superstack[NUMACTIONS];
|
||||
boolean LUA_CallAction(enum actionnum actionnum, mobj_t *actor)
|
||||
{
|
||||
I_Assert(actor != NULL);
|
||||
|
||||
if (!actionsoverridden[actionnum]) // The action is not overriden,
|
||||
return false; // action not called.
|
||||
if (actionsoverridden[actionnum][0] == LUA_REFNIL)
|
||||
{
|
||||
// The action was not overridden at all,
|
||||
// so just call the hardcoded version.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (superstack && fasticmp(actionpointers[actionnum].name, superactions[superstack-1])) // the action is calling itself,
|
||||
return false; // let it call the hardcoded function instead.
|
||||
if (luaactionstack && fasticmp(actionpointers[actionnum].name, luaactions[luaactionstack-1]))
|
||||
{
|
||||
// The action is calling itself,
|
||||
// so look up the next Lua reference in its stack.
|
||||
|
||||
// 0 is just the reference to the one we're calling,
|
||||
// so we increment here.
|
||||
superstack[actionnum]++;
|
||||
|
||||
if (superstack[actionnum] >= MAX_ACTION_RECURSION)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, "Max Lua super recursion reached! Cool it on calling super!\n");
|
||||
superstack[actionnum] = 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (actionsoverridden[actionnum][superstack[actionnum]] == LUA_REFNIL)
|
||||
{
|
||||
// No Lua reference beyond this point.
|
||||
// Let it call the hardcoded function instead.
|
||||
|
||||
if (superstack[actionnum])
|
||||
{
|
||||
// Decrement super stack
|
||||
superstack[actionnum]--;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Push error function
|
||||
lua_pushcfunction(gL, LUA_GetErrorMessage);
|
||||
|
||||
// grab function by uppercase name.
|
||||
lua_getfield(gL, LUA_REGISTRYINDEX, LREG_ACTIONS);
|
||||
lua_getfield(gL, -1, actionpointers[actionnum].name);
|
||||
lua_remove(gL, -2); // pop LREG_ACTIONS
|
||||
// Push function by reference.
|
||||
lua_getref(gL, actionsoverridden[actionnum][superstack[actionnum]]);
|
||||
|
||||
if (lua_isnil(gL, -1)) // no match
|
||||
{
|
||||
|
@ -835,7 +867,7 @@ boolean LUA_CallAction(enum actionnum actionnum, mobj_t *actor)
|
|||
return false; // action not called.
|
||||
}
|
||||
|
||||
if (superstack == MAXRECURSION)
|
||||
if (luaactionstack >= MAX_ACTION_RECURSION)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, "Max Lua Action recursion reached! Cool it on the calling A_Action functions from inside A_Action functions!\n");
|
||||
lua_pop(gL, 2); // pop function and error handler
|
||||
|
@ -849,14 +881,20 @@ boolean LUA_CallAction(enum actionnum actionnum, mobj_t *actor)
|
|||
lua_pushinteger(gL, var1);
|
||||
lua_pushinteger(gL, var2);
|
||||
|
||||
superactions[superstack] = actionpointers[actionnum].name;
|
||||
++superstack;
|
||||
luaactions[luaactionstack] = actionpointers[actionnum].name;
|
||||
++luaactionstack;
|
||||
|
||||
LUA_Call(gL, 3, 0, -(2 + 3));
|
||||
lua_pop(gL, -1); // Error handler
|
||||
|
||||
--superstack;
|
||||
superactions[superstack] = NULL;
|
||||
if (superstack[actionnum])
|
||||
{
|
||||
// Decrement super stack
|
||||
superstack[actionnum]--;
|
||||
}
|
||||
|
||||
--luaactionstack;
|
||||
luaactions[luaactionstack] = NULL;
|
||||
return true; // action successfully called.
|
||||
}
|
||||
|
||||
|
|
|
@ -501,7 +501,19 @@ static int setglobals(lua_State *L)
|
|||
|
||||
actionnum = LUA_GetActionNumByName(name);
|
||||
if (actionnum < NUMACTIONS)
|
||||
actionsoverridden[actionnum] = true;
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = MAX_ACTION_RECURSION-1; i > 0; i--)
|
||||
{
|
||||
// Move other references deeper.
|
||||
actionsoverridden[actionnum][i] = actionsoverridden[actionnum][i - 1];
|
||||
}
|
||||
|
||||
// Add the new reference.
|
||||
lua_pushvalue(L, 2);
|
||||
actionsoverridden[actionnum][0] = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
}
|
||||
|
||||
Z_Free(name);
|
||||
return 0;
|
||||
|
|
Loading…
Reference in a new issue