Beispiel #1
0
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.
}
Beispiel #2
0
// 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);
}
Beispiel #3
0
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")))) {