mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2025-01-31 05:30:48 +00:00
Lua save-banks!
* Array of 8 INT32's natively embedded into savedata (net and SP)! * Initialised to zero whenever a new save (or equivalent) is started, otherwise untouched by the base game. * Requires reservation to avoid clobber-conflicts. * Access via `reserveLuabanks()` - returns a read-write userdata. * Assign userdata to local variable or global rawset to use later. Mostly for future SUGOIlikes, but I'm sure someone could figure out an unrelated usage eventually.
This commit is contained in:
parent
9d2e7b66ba
commit
4e256b73b2
9 changed files with 191 additions and 8 deletions
|
@ -716,6 +716,7 @@ void D_StartTitle(void)
|
|||
botskin = 0;
|
||||
cv_debug = 0;
|
||||
emeralds = 0;
|
||||
memset(&luabanks, 0, sizeof(luabanks));
|
||||
lastmaploaded = 0;
|
||||
|
||||
// In case someone exits out at the same time they start a time attack run,
|
||||
|
|
|
@ -1908,7 +1908,10 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum)
|
|||
precache = false;
|
||||
|
||||
if (resetplayer && !FLS)
|
||||
{
|
||||
emeralds = 0;
|
||||
memset(&luabanks, 0, sizeof(luabanks));
|
||||
}
|
||||
|
||||
if (modeattacking)
|
||||
{
|
||||
|
@ -4103,6 +4106,7 @@ void Command_ExitGame_f(void)
|
|||
botskin = 0;
|
||||
cv_debug = 0;
|
||||
emeralds = 0;
|
||||
memset(&luabanks, 0, sizeof(luabanks));
|
||||
|
||||
if (dirmenu)
|
||||
closefilemenu(true);
|
||||
|
|
|
@ -418,6 +418,10 @@ extern UINT16 emeralds;
|
|||
#define EMERALD7 64
|
||||
#define ALL7EMERALDS(v) ((v & (EMERALD1|EMERALD2|EMERALD3|EMERALD4|EMERALD5|EMERALD6|EMERALD7)) == (EMERALD1|EMERALD2|EMERALD3|EMERALD4|EMERALD5|EMERALD6|EMERALD7))
|
||||
|
||||
// yes, even in non HAVE_BLUA
|
||||
#define NUM_LUABANKS 8 // please only make this number go up between versions, never down. you'll break saves otherwise. also, must fit in UINT8
|
||||
extern INT32 luabanks[NUM_LUABANKS];
|
||||
|
||||
extern INT32 nummaprings; //keep track of spawned rings/coins
|
||||
|
||||
/** Time attack information, currently a very small structure.
|
||||
|
|
25
src/g_game.c
25
src/g_game.c
|
@ -172,6 +172,7 @@ static boolean retrying = false;
|
|||
UINT8 stagefailed; // Used for GEMS BONUS? Also to see if you beat the stage.
|
||||
|
||||
UINT16 emeralds;
|
||||
INT32 luabanks[NUM_LUABANKS]; // yes, even in non HAVE_BLUA
|
||||
UINT32 token; // Number of tokens collected in a level
|
||||
UINT32 tokenlist; // List of tokens collected
|
||||
boolean gottoken; // Did you get a token? Used for end of act
|
||||
|
@ -3778,7 +3779,29 @@ void G_SaveGameOver(UINT32 slot, boolean modifylives)
|
|||
|
||||
// File end marker check
|
||||
CHECKPOS
|
||||
if (READUINT8(save_p) != 0x1d) BADSAVE;
|
||||
switch (READUINT8(save_p))
|
||||
{
|
||||
case 0xb7:
|
||||
{
|
||||
UINT8 i, banksinuse;
|
||||
CHECKPOS
|
||||
banksinuse = READUINT8(save_p);
|
||||
CHECKPOS
|
||||
if (banksinuse > NUM_LUABANKS)
|
||||
BADSAVE
|
||||
for (i = 0; i < banksinuse; i++)
|
||||
{
|
||||
(void)READINT32(save_p);
|
||||
CHECKPOS
|
||||
}
|
||||
if (READUINT8(save_p) != 0x1d)
|
||||
BADSAVE
|
||||
}
|
||||
case 0x1d:
|
||||
break;
|
||||
default:
|
||||
BADSAVE
|
||||
}
|
||||
|
||||
// done
|
||||
saved = FIL_WriteFile(backup, savebuffer, length);
|
||||
|
|
|
@ -182,6 +182,8 @@ static const struct {
|
|||
{META_CAMERA, "camera_t"},
|
||||
|
||||
{META_ACTION, "action"},
|
||||
|
||||
{META_LUABANKS, "luabanks[]"},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
@ -228,6 +230,18 @@ static int lib_isPlayerAdmin(lua_State *L)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int lib_reserveLuabanks(lua_State *L)
|
||||
{
|
||||
static boolean reserved = false;
|
||||
if (!lua_lumploading)
|
||||
return luaL_error(L, "luabanks[] cannot be reserved from within a hook or coroutine!");
|
||||
if (reserved)
|
||||
return luaL_error(L, "luabanks[] has already been reserved! Only one savedata-enabled mod at a time may use this feature.");
|
||||
reserved = true;
|
||||
LUA_PushUserdata(L, &luabanks, META_LUABANKS);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// M_RANDOM
|
||||
//////////////
|
||||
|
||||
|
@ -2736,6 +2750,7 @@ static luaL_Reg lib[] = {
|
|||
{"chatprintf", lib_chatprintf},
|
||||
{"userdataType", lib_userdataType},
|
||||
{"IsPlayerAdmin", lib_isPlayerAdmin},
|
||||
{"reserveLuabanks", lib_reserveLuabanks},
|
||||
|
||||
// m_random
|
||||
{"P_RandomFixed",lib_pRandomFixed},
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "p_mobj.h"
|
||||
#include "p_local.h"
|
||||
#include "z_zone.h"
|
||||
#include "doomstat.h" // luabanks[]
|
||||
|
||||
#include "lua_script.h"
|
||||
#include "lua_libs.h"
|
||||
|
@ -146,7 +147,7 @@ static int lib_getSpr2default(lua_State *L)
|
|||
return luaL_error(L, "spr2defaults[] invalid index");
|
||||
|
||||
if (i >= free_spr2)
|
||||
return 0;
|
||||
return luaL_error(L, "spr2defaults[] index %d out of range (%d - %d)", i, 0, free_spr2-1);
|
||||
|
||||
lua_pushinteger(L, spr2defaults[i]);
|
||||
return 1;
|
||||
|
@ -1026,6 +1027,61 @@ static int sfxinfo_num(lua_State *L)
|
|||
return 1;
|
||||
}
|
||||
|
||||
//////////////
|
||||
// LUABANKS //
|
||||
//////////////
|
||||
|
||||
static int lib_getluabanks(lua_State *L)
|
||||
{
|
||||
UINT8 i;
|
||||
|
||||
lua_remove(L, 1); // don't care about luabanks[] dummy userdata.
|
||||
|
||||
if (lua_isnumber(L, 1))
|
||||
i = lua_tonumber(L, 1);
|
||||
else
|
||||
return luaL_error(L, "luabanks[] invalid index");
|
||||
|
||||
if (i >= NUM_LUABANKS)
|
||||
luaL_error(L, "luabanks[] index %d out of range (%d - %d)", i, 0, NUM_LUABANKS);
|
||||
|
||||
lua_pushinteger(L, luabanks[i]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lib_setluabanks(lua_State *L)
|
||||
{
|
||||
UINT8 i;
|
||||
INT32 j = 0;
|
||||
|
||||
if (hud_running)
|
||||
return luaL_error(L, "Do not alter luabanks[] in HUD rendering code!");
|
||||
|
||||
lua_remove(L, 1); // don't care about luabanks[] dummy userdata.
|
||||
|
||||
if (lua_isnumber(L, 1))
|
||||
i = lua_tonumber(L, 1);
|
||||
else
|
||||
return luaL_error(L, "luabanks[] invalid index");
|
||||
|
||||
if (i >= NUM_LUABANKS)
|
||||
luaL_error(L, "luabanks[] index %d out of range (%d - %d)", i, 0, NUM_LUABANKS-1);
|
||||
|
||||
if (lua_isnumber(L, 2))
|
||||
j = lua_tonumber(L, 2);
|
||||
else
|
||||
return luaL_error(L, "luabanks[] invalid set");
|
||||
|
||||
luabanks[i] = j;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lib_luabankslen(lua_State *L)
|
||||
{
|
||||
lua_pushinteger(L, NUM_LUABANKS);
|
||||
return 1;
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
//
|
||||
// Now push all these functions into the Lua state!
|
||||
|
@ -1147,6 +1203,18 @@ int LUA_InfoLib(lua_State *L)
|
|||
lua_pushvalue(L, -1);
|
||||
lua_setglobal(L, "S_sfx");
|
||||
lua_setglobal(L, "sfxinfo");
|
||||
|
||||
luaL_newmetatable(L, META_LUABANKS);
|
||||
lua_pushcfunction(L, lib_getluabanks);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, lib_setluabanks);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
|
||||
lua_pushcfunction(L, lib_luabankslen);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_pop(L, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -67,6 +67,8 @@ extern lua_State *gL;
|
|||
|
||||
#define META_ACTION "ACTIONF_T*"
|
||||
|
||||
#define META_LUABANKS "LUABANKS[]*"
|
||||
|
||||
boolean luaL_checkboolean(lua_State *L, int narg);
|
||||
|
||||
int LUA_EnumLib(lua_State *L);
|
||||
|
|
27
src/m_menu.c
27
src/m_menu.c
|
@ -6885,6 +6885,7 @@ static void M_StartTutorial(INT32 choice)
|
|||
tutorialmode = true; // turn on tutorial mode
|
||||
|
||||
emeralds = 0;
|
||||
memset(&luabanks, 0, sizeof(luabanks));
|
||||
M_ClearMenus(true);
|
||||
gamecomplete = false;
|
||||
cursaveslot = 0;
|
||||
|
@ -7293,7 +7294,29 @@ static void M_ReadSavegameInfo(UINT32 slot)
|
|||
|
||||
// File end marker check
|
||||
CHECKPOS
|
||||
if (READUINT8(save_p) != 0x1d) BADSAVE;
|
||||
switch (READUINT8(save_p))
|
||||
{
|
||||
case 0xb7:
|
||||
{
|
||||
UINT8 i, banksinuse;
|
||||
CHECKPOS
|
||||
banksinuse = READUINT8(save_p);
|
||||
CHECKPOS
|
||||
if (banksinuse > NUM_LUABANKS)
|
||||
BADSAVE
|
||||
for (i = 0; i < banksinuse; i++)
|
||||
{
|
||||
(void)READINT32(save_p);
|
||||
CHECKPOS
|
||||
}
|
||||
if (READUINT8(save_p) != 0x1d)
|
||||
BADSAVE
|
||||
}
|
||||
case 0x1d:
|
||||
break;
|
||||
default:
|
||||
BADSAVE
|
||||
}
|
||||
|
||||
// done
|
||||
Z_Free(savebuffer);
|
||||
|
@ -8495,6 +8518,7 @@ static void M_ChooseNightsAttack(INT32 choice)
|
|||
char nameofdemo[256];
|
||||
(void)choice;
|
||||
emeralds = 0;
|
||||
memset(&luabanks, 0, sizeof(luabanks));
|
||||
M_ClearMenus(true);
|
||||
modeattacking = ATTACKING_NIGHTS;
|
||||
|
||||
|
@ -8519,6 +8543,7 @@ static void M_ChooseTimeAttack(INT32 choice)
|
|||
char nameofdemo[256];
|
||||
(void)choice;
|
||||
emeralds = 0;
|
||||
memset(&luabanks, 0, sizeof(luabanks));
|
||||
M_ClearMenus(true);
|
||||
modeattacking = ATTACKING_RECORD;
|
||||
|
||||
|
|
|
@ -4109,12 +4109,54 @@ static inline boolean P_NetUnArchiveMisc(void)
|
|||
return true;
|
||||
}
|
||||
|
||||
static inline void P_ArchiveLuabanksAndConsistency(void)
|
||||
{
|
||||
UINT8 i, banksinuse = NUM_LUABANKS;
|
||||
|
||||
while (banksinuse && !luabanks[banksinuse-1])
|
||||
banksinuse--; // get the last used bank
|
||||
|
||||
if (banksinuse)
|
||||
{
|
||||
WRITEUINT8(save_p, 0xb7); // luabanks marker
|
||||
WRITEUINT8(save_p, banksinuse);
|
||||
for (i = 0; i < banksinuse; i++)
|
||||
WRITEINT32(save_p, luabanks[i]);
|
||||
}
|
||||
|
||||
WRITEUINT8(save_p, 0x1d); // consistency marker
|
||||
}
|
||||
|
||||
static inline boolean P_UnArchiveLuabanksAndConsistency(void)
|
||||
{
|
||||
switch (READUINT8(save_p))
|
||||
{
|
||||
case 0xb7:
|
||||
{
|
||||
UINT8 i, banksinuse = READUINT8(save_p);
|
||||
if (banksinuse > NUM_LUABANKS)
|
||||
return false;
|
||||
for (i = 0; i < banksinuse; i++)
|
||||
luabanks[i] = READINT32(save_p);
|
||||
if (READUINT8(save_p) != 0x1d)
|
||||
return false;
|
||||
}
|
||||
case 0x1d:
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void P_SaveGame(void)
|
||||
{
|
||||
P_ArchiveMisc();
|
||||
P_ArchivePlayer();
|
||||
|
||||
WRITEUINT8(save_p, 0x1d); // consistency marker
|
||||
// yes, even in non HAVE_BLUA
|
||||
P_ArchiveLuabanksAndConsistency();
|
||||
}
|
||||
|
||||
void P_SaveNetGame(void)
|
||||
|
@ -4153,7 +4195,7 @@ void P_SaveNetGame(void)
|
|||
LUA_Archive();
|
||||
#endif
|
||||
|
||||
WRITEUINT8(save_p, 0x1d); // consistency marker
|
||||
P_ArchiveLuabanksAndConsistency();
|
||||
}
|
||||
|
||||
boolean P_LoadGame(INT16 mapoverride)
|
||||
|
@ -4165,8 +4207,7 @@ boolean P_LoadGame(INT16 mapoverride)
|
|||
P_UnArchiveSPGame(mapoverride);
|
||||
P_UnArchivePlayer();
|
||||
|
||||
// Savegame end marker
|
||||
if (READUINT8(save_p) != 0x1d)
|
||||
if (!P_UnArchiveLuabanksAndConsistency())
|
||||
return false;
|
||||
|
||||
// Only do this after confirming savegame is ok
|
||||
|
@ -4207,5 +4248,5 @@ boolean P_LoadNetGame(void)
|
|||
// precipitation when loading a netgame save. Instead, precip has to be spawned here.
|
||||
// This is done in P_NetUnArchiveSpecials now.
|
||||
|
||||
return READUINT8(save_p) == 0x1d;
|
||||
return P_UnArchiveLuabanksAndConsistency();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue