boolean LUA_CallAction(const char *csaction, mobj_t *actor) { I_Assert(csaction != NULL); I_Assert(actor != NULL); if (!gL) // Lua isn't loaded, return false; // action not called. if (superstack && fasticmp(csaction, superactions[superstack-1])) // the action is calling itself, return false; // let it call the hardcoded function instead. // grab function by uppercase name. lua_getfield(gL, LUA_REGISTRYINDEX, LREG_ACTIONS); { char *action = Z_StrDup(csaction); strupr(action); lua_getfield(gL, -1, action); Z_Free(action); } lua_remove(gL, -2); // pop LREG_ACTIONS if (lua_isnil(gL, -1)) // no match { lua_pop(gL, 1); // pop nil return false; // action not called. } if (superstack == MAXRECURSION) { CONS_Alert(CONS_WARNING, "Max Lua Action recursion reached! Cool it on the calling A_Action functions from inside A_Action functions!\n"); return true; } // Found a function. // Call it with (actor, var1, var2) I_Assert(lua_isfunction(gL, -1)); LUA_PushUserdata(gL, actor, META_MOBJ); lua_pushinteger(gL, var1); lua_pushinteger(gL, var2); superactions[superstack] = csaction; ++superstack; LUA_Call(gL, 3); --superstack; superactions[superstack] = NULL; return true; // action successfully called. }
// Load a script from a lump void LUA_LoadLump(UINT16 wad, UINT16 lump) { MYFILE f; char *name; f.wad = wad; f.size = W_LumpLengthPwad(wad, lump); f.data = Z_Malloc(f.size, PU_LUA, NULL); W_ReadLumpPwad(wad, lump, f.data); f.curpos = f.data; name = malloc(strlen(wadfiles[wad]->filename)+10); strcpy(name, wadfiles[wad]->filename); if (!fasticmp(&name[strlen(name) - 4], ".lua")) { // If it's not a .lua file, copy the lump name in too. name[strlen(wadfiles[wad]->filename)] = '|'; M_Memcpy(name+strlen(wadfiles[wad]->filename)+1, wadfiles[wad]->lumpinfo[lump].name, 8); name[strlen(wadfiles[wad]->filename)+9] = '\0'; } LUA_LoadFile(&f, name); free(name); Z_Free(f.data); }
static int lib_cvRegisterVar(lua_State *L) { const char *k; lua_Integer i; consvar_t *cvar; luaL_checktype(L, 1, LUA_TTABLE); lua_settop(L, 1); // Clear out all other possible arguments, leaving only the first one. NOHUD cvar = lua_newuserdata(L, sizeof(consvar_t)); luaL_getmetatable(L, META_CVAR); lua_setmetatable(L, -2); #define FIELDERROR(f, e) luaL_error(L, "bad value for " LUA_QL(f) " in table passed to " LUA_QL("CV_RegisterVar") " (%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: cvar table, cvar userdata, key/index, value // 1 2 3 4 i = 0; k = NULL; if (lua_isnumber(L, 3)) i = lua_tointeger(L, 3); else if (lua_isstring(L, 3)) k = lua_tostring(L, 3); if (i == 1 || (k && fasticmp(k, "name"))) { if (!lua_isstring(L, 4)) TYPEERROR("name", LUA_TSTRING) cvar->name = Z_StrDup(lua_tostring(L, 4)); } else if (i == 2 || (k && fasticmp(k, "defaultvalue"))) { if (!lua_isstring(L, 4)) TYPEERROR("defaultvalue", LUA_TSTRING) cvar->defaultvalue = Z_StrDup(lua_tostring(L, 4)); } else if (i == 3 || (k && fasticmp(k, "flags"))) { if (!lua_isnumber(L, 4)) TYPEERROR("flags", LUA_TNUMBER) cvar->flags = (INT32)lua_tointeger(L, 4); } else if (i == 4 || (k && fasticmp(k, "PossibleValue"))) { if (lua_islightuserdata(L, 4)) { CV_PossibleValue_t *pv = lua_touserdata(L, 4); if (pv == CV_OnOff || pv == CV_YesNo || pv == CV_Unsigned || pv == CV_Natural) cvar->PossibleValue = pv; else FIELDERROR("PossibleValue", "CV_PossibleValue_t expected, got unrecognised pointer") } else if (lua_istable(L, 4)) { // Accepts tables in the form of {MIN=0, MAX=9999} or {Red=0, Green=1, Blue=2} // and converts them to CV_PossibleValue_t {{0,"MIN"},{9999,"MAX"}} or {{0,"Red"},{1,"Green"},{2,"Blue"}} // // I don't really like the way this does it because a single PossibleValue table // being used for multiple cvars will be converted and stored multiple times. // So maybe instead it should be a seperate function which must be run beforehand or something. size_t count = 0; CV_PossibleValue_t *cvpv; lua_pushnil(L); while (lua_next(L, 4)) { count++; lua_pop(L, 1); } lua_getfield(L, LUA_REGISTRYINDEX, "CV_PossibleValue"); I_Assert(lua_istable(L, 5)); lua_pushvalue(L, 2); // cvar userdata cvpv = lua_newuserdata(L, sizeof(CV_PossibleValue_t) * (count+1)); lua_rawset(L, 5); lua_pop(L, 1); // pop CV_PossibleValue registry table i = 0; lua_pushnil(L); while (lua_next(L, 4)) { // stack: [...] PossibleValue table, index, value // 4 5 6 if (lua_type(L, 5) != LUA_TSTRING || lua_type(L, 6) != LUA_TNUMBER) FIELDERROR("PossibleValue", "custom PossibleValue table requires a format of string=integer, i.e. {MIN=0, MAX=9999}"); cvpv[i].strvalue = Z_StrDup(lua_tostring(L, 5)); cvpv[i].value = (INT32)lua_tonumber(L, 6); i++; lua_pop(L, 1); } cvpv[i].value = 0; cvpv[i].strvalue = NULL; cvar->PossibleValue = cvpv; } else FIELDERROR("PossibleValue", va("%s or CV_PossibleValue_t expected, got %s", lua_typename(L, LUA_TTABLE), luaL_typename(L, -1))) } else if (cvar->flags & CV_CALL && (i == 5 || (k && fasticmp(k, "func")))) {