diff --git a/src/dehacked.c b/src/dehacked.c index 871fe72a0..5301bef68 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -1146,7 +1146,6 @@ static void readgametype(MYFILE *f, char *gtname) char *word; char *word2, *word2lwr = NULL; char *tmp; - char *gtconst; INT32 i, j; INT16 newgtidx = 0; @@ -1326,51 +1325,7 @@ static void readgametype(MYFILE *f, char *gtname) Gametype_Names[newgtidx] = Z_StrDup((const char *)gtname); // Write the constant name. - gtconst = Z_Malloc(strlen((const char *)gtname) + 3, PU_STATIC, NULL); - // Copy GT_ and the gametype name. - strcpy(gtconst, "GT_"); - strcat(gtconst, (const char *)gtname); - // Make uppercase. - strupr(gtconst); - // Remove characters. -#define REMOVECHAR(chr) \ - word = strchr(gtconst, chr); \ - while (word) \ - { \ - *word = '_'; \ - word = strchr(word, chr); \ - } - - // Space - REMOVECHAR(' ') - // Used for operations - REMOVECHAR('+') - REMOVECHAR('-') - REMOVECHAR('*') - REMOVECHAR('/') - REMOVECHAR('%') - REMOVECHAR('^') - // Part of Lua's syntax - REMOVECHAR('#') - REMOVECHAR('=') - REMOVECHAR('~') - REMOVECHAR('<') - REMOVECHAR('>') - REMOVECHAR('(') - REMOVECHAR(')') - REMOVECHAR('{') - REMOVECHAR('}') - REMOVECHAR('[') - REMOVECHAR(']') - REMOVECHAR(':') - REMOVECHAR(';') - REMOVECHAR(',') - REMOVECHAR('.') - -#undef REMOVECHAR - - // Finally, set the constant string. - Gametype_ConstantNames[newgtidx] = gtconst; + G_AddGametypeConstant(newgtidx, (const char *)gtname); // Update gametype_cons_t accordingly. G_UpdateGametypeSelections(); @@ -10439,6 +10394,20 @@ static inline int lib_freeslot(lua_State *L) } r++; } + else if (fastcmp(type, "TOL")) + { + if (lastcustomtol > 31) + CONS_Alert(CONS_WARNING, "Ran out of free typeoflevel slots!\n"); + else + { + UINT32 newtol = (1<') + REMOVECHAR('(') + REMOVECHAR(')') + REMOVECHAR('{') + REMOVECHAR('}') + REMOVECHAR('[') + REMOVECHAR(']') + REMOVECHAR(':') + REMOVECHAR(';') + REMOVECHAR(',') + REMOVECHAR('.') + +#undef REMOVECHAR + + // Finally, set the constant string. + Gametype_ConstantNames[gtype] = gtconst; +} + // // G_UpdateGametypeSelections // diff --git a/src/g_game.h b/src/g_game.h index bd0dc0180..de644756f 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -207,6 +207,7 @@ extern INT16 gametyperankings[NUMGAMETYPES]; void G_SetGametype(INT16 gametype); INT16 G_AddGametype(UINT32 rules); +void G_AddGametypeConstant(INT16 gtype, const char *newgtconst); void G_UpdateGametypeSelections(void); void G_AddTOL(UINT32 newtol, const char *tolname); void G_AddGametypeTOL(INT16 gtype, UINT32 newtol); diff --git a/src/lua_baselib.c b/src/lua_baselib.c index b68d16c2a..450da6576 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -12,6 +12,7 @@ #include "doomdef.h" #ifdef HAVE_BLUA +#include "fastcmp.h" #include "p_local.h" #include "p_setup.h" // So we can have P_SetupLevelSky #ifdef ESLOPE @@ -23,6 +24,7 @@ #include "m_random.h" #include "s_sound.h" #include "g_game.h" +#include "y_inter.h" #include "hu_stuff.h" // HU_AddChatText #include "console.h" #include "d_netcmd.h" // IsPlayerAdmin @@ -2632,6 +2634,133 @@ static int lib_sStartMusicCaption(lua_State *L) // G_GAME //////////// +// Copypasted from lib_cvRegisterVar :] +static int lib_gAddGametype(lua_State *L) +{ + const char *k; + lua_Integer i; + + const char *gtname = NULL; + const char *gtdescription = NULL; + INT16 newgtidx = 0; + UINT32 newgtrules = 0; + UINT32 newgttol = 0; + INT32 newgtpointlimit = 0; + INT32 newgttimelimit = 0; + UINT8 newgtleftcolor = 0; + UINT8 newgtrightcolor = 0; + INT16 newgtrankingstype = -1; + int newgtinttype = 0; + + luaL_checktype(L, 1, LUA_TTABLE); + lua_settop(L, 1); // Clear out all other possible arguments, leaving only the first one. + + if (!lua_lumploading) + return luaL_error(L, "This function cannot be called from within a hook or coroutine!"); + +#define FIELDERROR(f, e) luaL_error(L, "bad value for " LUA_QL(f) " in table passed to " LUA_QL("G_AddGametype") " (%s)", e); +#define TYPEERROR(f, t) FIELDERROR(f, va("%s expected, got %s", lua_typename(L, t), luaL_typename(L, -1))) + + lua_pushnil(L); + while (lua_next(L, 1)) { + // stack: gametype table, key/index, value + // 1 2 3 + i = 0; + k = NULL; + if (lua_isnumber(L, 2)) + i = lua_tointeger(L, 2); + else if (lua_isstring(L, 2)) + k = lua_tostring(L, 2); + + // Sorry, no gametype rules as key names. + if (i == 1 || (k && fasticmp(k, "name"))) { + if (!lua_isstring(L, 3)) + TYPEERROR("name", LUA_TSTRING) + gtname = Z_StrDup(lua_tostring(L, 3)); + } else if (i == 2 || (k && fasticmp(k, "rules"))) { + if (!lua_isnumber(L, 3)) + TYPEERROR("rules", LUA_TNUMBER) + newgtrules = (UINT32)lua_tointeger(L, 3); + } else if (i == 3 || (k && fasticmp(k, "typeoflevel"))) { + if (!lua_isnumber(L, 3)) + TYPEERROR("typeoflevel", LUA_TNUMBER) + newgttol = (UINT32)lua_tointeger(L, 3); + } else if (i == 4 || (k && fasticmp(k, "rankingtype"))) { + if (!lua_isnumber(L, 3)) + TYPEERROR("rankingtype", LUA_TNUMBER) + newgtrankingstype = (INT16)lua_tointeger(L, 3); + } else if (i == 5 || (k && fasticmp(k, "intermissiontype"))) { + if (!lua_isnumber(L, 3)) + TYPEERROR("intermissiontype", LUA_TNUMBER) + newgtinttype = (int)lua_tointeger(L, 3); + } else if (i == 6 || (k && fasticmp(k, "defaultpointlimit"))) { + if (!lua_isnumber(L, 3)) + TYPEERROR("defaultpointlimit", LUA_TNUMBER) + newgtpointlimit = (INT32)lua_tointeger(L, 3); + } else if (i == 7 || (k && fasticmp(k, "defaulttimelimit"))) { + if (!lua_isnumber(L, 3)) + TYPEERROR("defaulttimelimit", LUA_TNUMBER) + newgttimelimit = (INT32)lua_tointeger(L, 3); + } else if (i == 8 || (k && fasticmp(k, "description"))) { + if (!lua_isstring(L, 3)) + TYPEERROR("description", LUA_TSTRING) + gtdescription = Z_StrDup(lua_tostring(L, 3)); + } else if (i == 9 || (k && fasticmp(k, "headerleftcolor"))) { + if (!lua_isnumber(L, 3)) + TYPEERROR("headerleftcolor", LUA_TNUMBER) + newgtleftcolor = (UINT8)lua_tointeger(L, 3); + } else if (i == 10 || (k && fasticmp(k, "headerrightcolor"))) { + if (!lua_isnumber(L, 3)) + TYPEERROR("headerrightcolor", LUA_TNUMBER) + newgtrightcolor = (UINT8)lua_tointeger(L, 3); + // Key name specified + } else if ((!i) && (k && fasticmp(k, "headercolor"))) { + if (!lua_isnumber(L, 3)) + TYPEERROR("headercolor", LUA_TNUMBER) + newgtleftcolor = newgtrightcolor = (UINT8)lua_tointeger(L, 3); + } + lua_pop(L, 1); + } + +#undef FIELDERROR +#undef TYPEERROR + + // pop gametype table + lua_pop(L, 1); + + // Set defaults + if (gtname == NULL) + gtname = Z_StrDup("Unnamed gametype"); + if (gtdescription == NULL) + gtdescription = Z_StrDup("???"); + + // Add the new gametype + newgtidx = G_AddGametype(newgtrules); + G_AddGametypeTOL(newgtidx, newgttol); + G_SetGametypeDescription(newgtidx, (char *)gtdescription, newgtleftcolor, newgtrightcolor); + + // Not covered by G_AddGametype alone. + if (newgtrankingstype == -1) + newgtrankingstype = newgtidx; + gametyperankings[newgtidx] = newgtrankingstype; + intermissiontypes[newgtidx] = newgtinttype; + pointlimits[newgtidx] = newgtpointlimit; + timelimits[newgtidx] = newgttimelimit; + + // Write the new gametype name. + Gametype_Names[newgtidx] = gtname; + + // Write the constant name. + G_AddGametypeConstant(newgtidx, gtname); + + // Update gametype_cons_t accordingly. + G_UpdateGametypeSelections(); + + // done + CONS_Printf("Added gametype %s\n", Gametype_Names[newgtidx]); + return 0; +} + static int lib_gBuildMapName(lua_State *L) { INT32 map = luaL_optinteger(L, 1, gamemap); @@ -2997,6 +3126,7 @@ static luaL_Reg lib[] = { {"S_StartMusicCaption", lib_sStartMusicCaption}, // g_game + {"G_AddGametype", lib_gAddGametype}, {"G_BuildMapName",lib_gBuildMapName}, {"G_DoReborn",lib_gDoReborn}, {"G_SetCustomExitVars",lib_gSetCustomExitVars},