Merge branch 'lua-more-stuff' into 'master'

Lua more stuff

More new Lua features and fixes:
* Most Lua functions that deal with stuff that exists only in levels now should spout Lua errors instead of crashing the game if you try to use them outside of levels. Likewise, accessing any of the tables that contain level-only stuff (players, sectors, lines, etc etc) spouts Lua errors too outside of levels.
* `userdataType(variable)` now exists: this function simply returns the type of the userdata variable given as a string (e.g. `userdataType(players[0])` returns "player_t", `userdataType(sectors[0])` returns "sector_t"). This also includes "minor" userdata types for array members of other userdata types, such as .powers of player_t variables or .lines of sector_t variables (which would give the strings "player_t.powers" and "sector_t.lines" respectively).
* The Lua hook "MobjMoveBlocked" now exists: functions for this hook are called whenever a mobj attempts to move horizontally but is blocked by a wall or solid mobj (or whatever else can cause P_TryMove to return false, assuming it doesn't remove the mobj). In theory this hook could be very useful for behaviour such as sliding or bouncing off walls without the need of flags like MF_SLIDEME or MF_BOUNCE etc. Format for use is just like most generic mobj hooks: `addHook("MobjMoveBlocked", functionname, MT_OBJECTTYPE)`, where `functionname` is a function that takes a single mobj_t argument.

See MonsterIestyn/lua-more-stuff on the FTP for a test exe (srb2win-lua-more-stuff.exe) and some test scripts for the above changes.

See merge request !67
This commit is contained in:
Monster Iestyn 2017-03-13 14:29:35 -04:00
commit 386fec037f
10 changed files with 372 additions and 4 deletions

View file

@ -25,7 +25,10 @@
#include "lua_libs.h"
#include "lua_hud.h" // hud_running errors
#define NOHUD if (hud_running) return luaL_error(L, "HUD rendering code should not call this function!");
#define NOHUD if (hud_running)\
return luaL_error(L, "HUD rendering code should not call this function!");
#define INLEVEL if (gamestate != GS_LEVEL)\
return luaL_error(L, "This function can only be used in a level!");
boolean luaL_checkboolean(lua_State *L, int narg) {
luaL_checktype(L, narg, LUA_TBOOLEAN);
@ -84,6 +87,86 @@ static int lib_print(lua_State *L)
return 0;
}
static const struct {
const char *meta;
const char *utype;
} meta2utype[] = {
{META_STATE, "state_t"},
{META_MOBJINFO, "mobjinfo_t"},
{META_SFXINFO, "sfxinfo_t"},
{META_MOBJ, "mobj_t"},
{META_MAPTHING, "mapthing_t"},
{META_PLAYER, "player_t"},
{META_TICCMD, "ticcmd_t"},
{META_SKIN, "skin_t"},
{META_POWERS, "player_t.powers"},
{META_SOUNDSID, "skin_t.soundsid"},
{META_VERTEX, "vertex_t"},
{META_LINE, "line_t"},
{META_SIDE, "side_t"},
{META_SUBSECTOR, "subsector_t"},
{META_SECTOR, "sector_t"},
{META_FFLOOR, "ffloor_t"},
#ifdef HAVE_LUA_SEGS
{META_SEG, "seg_t"},
{META_NODE, "node_t"},
#endif
{META_MAPHEADER, "mapheader_t"},
{META_CVAR, "consvar_t"},
{META_SECTORLINES, "sector_t.lines"},
{META_SIDENUM, "line_t.sidenum"},
#ifdef HAVE_LUA_SEGS
{META_NODEBBOX, "node_t.bbox"},
{META_NODECHILDREN, "node_t.children"},
#endif
{META_BBOX, "bbox"},
{META_HUDINFO, "hudinfo_t"},
{META_PATCH, "patch_t"},
{META_COLORMAP, "colormap"},
{META_CAMERA, "camera_t"},
{NULL, NULL}
};
// goes through the above list and returns the utype string for the userdata type
// returns "unknown" instead if we couldn't find the right userdata type
static const char *GetUserdataUType(lua_State *L)
{
UINT8 i;
lua_getmetatable(L, -1);
for (i = 0; meta2utype[i].meta; i++)
{
luaL_getmetatable(L, meta2utype[i].meta);
if (lua_rawequal(L, -1, -2))
{
lua_pop(L, 2);
return meta2utype[i].utype;
}
lua_pop(L, 1);
}
lua_pop(L, 1);
return "unknown";
}
// Return a string representing the type of userdata the given var is
// e.g. players[0] -> "player_t"
// or players[0].powers -> "player_t.powers"
static int lib_userdataType(lua_State *L)
{
lua_settop(L, 1); // pop everything except arg 1 (in case somebody decided to add more)
luaL_checktype(L, 1, LUA_TUSERDATA);
lua_pushstring(L, GetUserdataUType(L));
return 1;
}
// M_RANDOM
//////////////
@ -246,6 +329,7 @@ static int lib_pCheckMeleeRange(lua_State *L)
{
mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
NOHUD
INLEVEL
if (!actor)
return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_CheckMeleeRange(actor));
@ -256,6 +340,7 @@ static int lib_pJetbCheckMeleeRange(lua_State *L)
{
mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
NOHUD
INLEVEL
if (!actor)
return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_JetbCheckMeleeRange(actor));
@ -266,6 +351,7 @@ static int lib_pFaceStabCheckMeleeRange(lua_State *L)
{
mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
NOHUD
INLEVEL
if (!actor)
return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_FaceStabCheckMeleeRange(actor));
@ -276,6 +362,7 @@ static int lib_pSkimCheckMeleeRange(lua_State *L)
{
mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
NOHUD
INLEVEL
if (!actor)
return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_SkimCheckMeleeRange(actor));
@ -286,6 +373,7 @@ static int lib_pCheckMissileRange(lua_State *L)
{
mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
NOHUD
INLEVEL
if (!actor)
return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_CheckMissileRange(actor));
@ -296,6 +384,7 @@ static int lib_pNewChaseDir(lua_State *L)
{
mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
NOHUD
INLEVEL
if (!actor)
return LUA_ErrInvalid(L, "mobj_t");
P_NewChaseDir(actor);
@ -309,6 +398,7 @@ static int lib_pLookForPlayers(lua_State *L)
boolean allaround = lua_optboolean(L, 3);
boolean tracer = lua_optboolean(L, 4);
NOHUD
INLEVEL
if (!actor)
return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_LookForPlayers(actor, allaround, tracer, dist));
@ -325,6 +415,7 @@ static int lib_pSpawnMobj(lua_State *L)
fixed_t z = luaL_checkfixed(L, 3);
mobjtype_t type = luaL_checkinteger(L, 4);
NOHUD
INLEVEL
if (type >= NUMMOBJTYPES)
return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1);
LUA_PushUserdata(L, P_SpawnMobj(x, y, z, type), META_MOBJ);
@ -335,6 +426,7 @@ static int lib_pRemoveMobj(lua_State *L)
{
mobj_t *th = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
NOHUD
INLEVEL
if (!th)
return LUA_ErrInvalid(L, "mobj_t");
if (th->player)
@ -350,6 +442,7 @@ static int lib_pIsValidSprite2(lua_State *L)
mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
UINT8 spr2 = (UINT8)luaL_checkinteger(L, 2);
//HUDSAFE
INLEVEL
if (!mobj)
return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, (mobj->skin && (((skin_t *)mobj->skin)->sprites[spr2].numframes > 0)));
@ -362,6 +455,7 @@ static int lib_pSpawnMissile(lua_State *L)
mobj_t *dest = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
mobjtype_t type = luaL_checkinteger(L, 3);
NOHUD
INLEVEL
if (!source || !dest)
return LUA_ErrInvalid(L, "mobj_t");
if (type >= NUMMOBJTYPES)
@ -379,6 +473,7 @@ static int lib_pSpawnXYZMissile(lua_State *L)
fixed_t y = luaL_checkfixed(L, 5);
fixed_t z = luaL_checkfixed(L, 6);
NOHUD
INLEVEL
if (!source || !dest)
return LUA_ErrInvalid(L, "mobj_t");
if (type >= NUMMOBJTYPES)
@ -398,6 +493,7 @@ static int lib_pSpawnPointMissile(lua_State *L)
fixed_t y = luaL_checkfixed(L, 7);
fixed_t z = luaL_checkfixed(L, 8);
NOHUD
INLEVEL
if (!source)
return LUA_ErrInvalid(L, "mobj_t");
if (type >= NUMMOBJTYPES)
@ -415,6 +511,7 @@ static int lib_pSpawnAlteredDirectionMissile(lua_State *L)
fixed_t z = luaL_checkfixed(L, 5);
INT32 shiftingAngle = (INT32)luaL_checkinteger(L, 5);
NOHUD
INLEVEL
if (!source)
return LUA_ErrInvalid(L, "mobj_t");
if (type >= NUMMOBJTYPES)
@ -428,6 +525,7 @@ static int lib_pColorTeamMissile(lua_State *L)
mobj_t *missile = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
player_t *source = *((player_t **)luaL_checkudata(L, 2, META_PLAYER));
NOHUD
INLEVEL
if (!missile)
return LUA_ErrInvalid(L, "mobj_t");
if (!source)
@ -444,6 +542,7 @@ static int lib_pSPMAngle(lua_State *L)
UINT8 allowaim = (UINT8)luaL_optinteger(L, 4, 0);
UINT32 flags2 = (UINT32)luaL_optinteger(L, 5, 0);
NOHUD
INLEVEL
if (!source)
return LUA_ErrInvalid(L, "mobj_t");
if (type >= NUMMOBJTYPES)
@ -458,6 +557,7 @@ static int lib_pSpawnPlayerMissile(lua_State *L)
mobjtype_t type = luaL_checkinteger(L, 2);
UINT32 flags2 = (UINT32)luaL_optinteger(L, 3, 0);
NOHUD
INLEVEL
if (!source)
return LUA_ErrInvalid(L, "mobj_t");
if (type >= NUMMOBJTYPES)
@ -470,6 +570,7 @@ static int lib_pMobjFlip(lua_State *L)
{
mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
//HUDSAFE
INLEVEL
if (!mobj)
return LUA_ErrInvalid(L, "mobj_t");
lua_pushinteger(L, P_MobjFlip(mobj));
@ -480,6 +581,7 @@ static int lib_pGetMobjGravity(lua_State *L)
{
mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
//HUDSAFE
INLEVEL
if (!mobj)
return LUA_ErrInvalid(L, "mobj_t");
lua_pushfixed(L, P_GetMobjGravity(mobj));
@ -502,6 +604,7 @@ static int lib_pFlashPal(lua_State *L)
UINT16 type = (UINT16)luaL_checkinteger(L, 2);
UINT16 duration = (UINT16)luaL_checkinteger(L, 3);
NOHUD
INLEVEL
if (!pl)
return LUA_ErrInvalid(L, "player_t");
P_FlashPal(pl, type, duration);
@ -512,6 +615,7 @@ static int lib_pGetClosestAxis(lua_State *L)
{
mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
//HUDSAFE
INLEVEL
if (!source)
return LUA_ErrInvalid(L, "mobj_t");
LUA_PushUserdata(L, P_GetClosestAxis(source), META_MOBJ);
@ -530,6 +634,7 @@ static int lib_pSpawnParaloop(lua_State *L)
statenum_t nstate = luaL_optinteger(L, 8, S_NULL);
boolean spawncenter = lua_optboolean(L, 9);
NOHUD
INLEVEL
if (type >= NUMMOBJTYPES)
return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1);
if (nstate >= NUMSTATES)
@ -543,6 +648,7 @@ static int lib_pBossTargetPlayer(lua_State *L)
mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
boolean closest = lua_optboolean(L, 2);
NOHUD
INLEVEL
if (!actor)
return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_BossTargetPlayer(actor, closest));
@ -553,6 +659,7 @@ static int lib_pSupermanLook4Players(lua_State *L)
{
mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
NOHUD
INLEVEL
if (!actor)
return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_SupermanLook4Players(actor));
@ -564,6 +671,7 @@ static int lib_pSetScale(lua_State *L)
mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
fixed_t newscale = luaL_checkfixed(L, 2);
NOHUD
INLEVEL
if (!mobj)
return LUA_ErrInvalid(L, "mobj_t");
if (newscale < FRACUNIT/100)
@ -577,6 +685,7 @@ static int lib_pInsideANonSolidFFloor(lua_State *L)
mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
ffloor_t *rover = *((ffloor_t **)luaL_checkudata(L, 2, META_FFLOOR));
//HUDSAFE
INLEVEL
if (!mobj)
return LUA_ErrInvalid(L, "mobj_t");
if (!rover)
@ -589,6 +698,7 @@ static int lib_pCheckDeathPitCollide(lua_State *L)
{
mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
//HUDSAFE
INLEVEL
if (!mo)
return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_CheckDeathPitCollide(mo));
@ -600,6 +710,7 @@ static int lib_pCheckSolidLava(lua_State *L)
mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
ffloor_t *rover = *((ffloor_t **)luaL_checkudata(L, 2, META_FFLOOR));
//HUDSAFE
INLEVEL
if (!mo)
return LUA_ErrInvalid(L, "mobj_t");
if (!rover)
@ -613,6 +724,7 @@ static int lib_pCanRunOnWater(lua_State *L)
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
ffloor_t *rover = *((ffloor_t **)luaL_checkudata(L, 2, META_FFLOOR));
//HUDSAFE
INLEVEL
if (!player)
return LUA_ErrInvalid(L, "player_t");
if (!rover)
@ -628,6 +740,7 @@ static int lib_pGetPlayerHeight(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
//HUDSAFE
INLEVEL
if (!player)
return LUA_ErrInvalid(L, "player_t");
lua_pushfixed(L, P_GetPlayerHeight(player));
@ -638,6 +751,7 @@ static int lib_pGetPlayerSpinHeight(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
//HUDSAFE
INLEVEL
if (!player)
return LUA_ErrInvalid(L, "player_t");
lua_pushfixed(L, P_GetPlayerSpinHeight(player));
@ -648,6 +762,7 @@ static int lib_pGetPlayerControlDirection(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
//HUDSAFE
INLEVEL
if (!player)
return LUA_ErrInvalid(L, "player_t");
lua_pushinteger(L, P_GetPlayerControlDirection(player));
@ -659,6 +774,7 @@ static int lib_pAddPlayerScore(lua_State *L)
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
UINT32 amount = (UINT32)luaL_checkinteger(L, 2);
NOHUD
INLEVEL
if (!player)
return LUA_ErrInvalid(L, "player_t");
P_AddPlayerScore(player, amount);
@ -670,6 +786,7 @@ static int lib_pStealPlayerScore(lua_State *L)
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
UINT32 amount = (UINT32)luaL_checkinteger(L, 2);
NOHUD
INLEVEL
if (!player)
return LUA_ErrInvalid(L, "player_t");
P_StealPlayerScore(player, amount);
@ -680,6 +797,7 @@ static int lib_pPlayerInPain(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
//HUDSAFE
INLEVEL
if (!player)
return LUA_ErrInvalid(L, "player_t");
lua_pushboolean(L, P_PlayerInPain(player));
@ -691,6 +809,7 @@ static int lib_pDoPlayerPain(lua_State *L)
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
mobj_t *source = NULL, *inflictor = NULL;
NOHUD
INLEVEL
if (!player)
return LUA_ErrInvalid(L, "player_t");
if (!lua_isnone(L, 2) && lua_isuserdata(L, 2))
@ -705,6 +824,7 @@ static int lib_pResetPlayer(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
NOHUD
INLEVEL
if (!player)
return LUA_ErrInvalid(L, "player_t");
P_ResetPlayer(player);
@ -715,6 +835,7 @@ static int lib_pIsObjectInGoop(lua_State *L)
{
mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
//HUDSAFE
INLEVEL
if (!mo)
return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_IsObjectInGoop(mo));
@ -725,6 +846,7 @@ static int lib_pIsObjectOnGround(lua_State *L)
{
mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
//HUDSAFE
INLEVEL
if (!mo)
return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_IsObjectOnGround(mo));
@ -735,6 +857,7 @@ static int lib_pInSpaceSector(lua_State *L)
{
mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
//HUDSAFE
INLEVEL
if (!mo)
return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_InSpaceSector(mo));
@ -745,6 +868,7 @@ static int lib_pInQuicksand(lua_State *L)
{
mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
//HUDSAFE
INLEVEL
if (!mo)
return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_InQuicksand(mo));
@ -757,6 +881,7 @@ static int lib_pSetObjectMomZ(lua_State *L)
fixed_t value = luaL_checkfixed(L, 2);
boolean relative = lua_optboolean(L, 3);
NOHUD
INLEVEL
if (!mo)
return LUA_ErrInvalid(L, "mobj_t");
P_SetObjectMomZ(mo, value, relative);
@ -767,6 +892,7 @@ static int lib_pRestoreMusic(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
NOHUD
INLEVEL
if (!player)
return LUA_ErrInvalid(L, "player_t");
P_RestoreMusic(player);
@ -777,6 +903,7 @@ static int lib_pSpawnShieldOrb(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
NOHUD
INLEVEL
if (!player)
return LUA_ErrInvalid(L, "player_t");
P_SpawnShieldOrb(player);
@ -787,6 +914,7 @@ static int lib_pSpawnGhostMobj(lua_State *L)
{
mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
NOHUD
INLEVEL
if (!mobj)
return LUA_ErrInvalid(L, "mobj_t");
LUA_PushUserdata(L, P_SpawnGhostMobj(mobj), META_MOBJ);
@ -798,6 +926,7 @@ static int lib_pGivePlayerRings(lua_State *L)
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
INT32 num_rings = (INT32)luaL_checkinteger(L, 2);
NOHUD
INLEVEL
if (!player)
return LUA_ErrInvalid(L, "player_t");
P_GivePlayerRings(player, num_rings);
@ -809,6 +938,7 @@ static int lib_pGivePlayerLives(lua_State *L)
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
INT32 numlives = (INT32)luaL_checkinteger(L, 2);
NOHUD
INLEVEL
if (!player)
return LUA_ErrInvalid(L, "player_t");
P_GivePlayerLives(player, numlives);
@ -819,6 +949,7 @@ static int lib_pResetScore(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
NOHUD
INLEVEL
if (!player)
return LUA_ErrInvalid(L, "player_t");
P_ResetScore(player);
@ -829,6 +960,7 @@ static int lib_pDoJumpShield(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
NOHUD
INLEVEL
if (!player)
return LUA_ErrInvalid(L, "player_t");
P_DoJumpShield(player);
@ -839,6 +971,7 @@ static int lib_pDoBubbleBounce(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
NOHUD
INLEVEL
if (!player)
return LUA_ErrInvalid(L, "player_t");
P_DoBubbleBounce(player);
@ -849,6 +982,7 @@ static int lib_pBlackOw(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
NOHUD
INLEVEL
if (!player)
return LUA_ErrInvalid(L, "player_t");
P_BlackOw(player);
@ -860,6 +994,7 @@ static int lib_pElementalFire(lua_State *L)
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
boolean cropcircle = lua_optboolean(L, 2);
NOHUD
INLEVEL
if (!player)
return LUA_ErrInvalid(L, "player_t");
P_ElementalFire(player, cropcircle);
@ -870,6 +1005,7 @@ static int lib_pDoPlayerExit(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
NOHUD
INLEVEL
if (!player)
return LUA_ErrInvalid(L, "player_t");
P_DoPlayerExit(player);
@ -882,6 +1018,7 @@ static int lib_pInstaThrust(lua_State *L)
angle_t angle = luaL_checkangle(L, 2);
fixed_t move = luaL_checkfixed(L, 3);
NOHUD
INLEVEL
if (!mo)
return LUA_ErrInvalid(L, "mobj_t");
P_InstaThrust(mo, angle, move);
@ -919,6 +1056,7 @@ static int lib_pLookForEnemies(lua_State *L)
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
boolean nonenemies = lua_opttrueboolean(L, 2);
NOHUD
INLEVEL
if (!player)
return LUA_ErrInvalid(L, "player_t");
lua_pushboolean(L, P_LookForEnemies(player, nonenemies));
@ -931,6 +1069,7 @@ static int lib_pNukeEnemies(lua_State *L)
mobj_t *source = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
fixed_t radius = luaL_checkfixed(L, 3);
NOHUD
INLEVEL
if (!inflictor || !source)
return LUA_ErrInvalid(L, "mobj_t");
P_NukeEnemies(inflictor, source, radius);
@ -942,6 +1081,7 @@ static int lib_pHomingAttack(lua_State *L)
mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
mobj_t *enemy = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
NOHUD
INLEVEL
if (!source || !enemy)
return LUA_ErrInvalid(L, "mobj_t");
P_HomingAttack(source, enemy);
@ -952,6 +1092,7 @@ static int lib_pSuperReady(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
//HUDSAFE
INLEVEL
if (!player)
return LUA_ErrInvalid(L, "player_t");
lua_pushboolean(L, P_SuperReady(player));
@ -963,6 +1104,7 @@ static int lib_pDoJump(lua_State *L)
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
boolean soundandstate = (boolean)lua_opttrueboolean(L, 2);
NOHUD
INLEVEL
if (!player)
return LUA_ErrInvalid(L, "player_t");
P_DoJump(player, soundandstate);
@ -973,6 +1115,7 @@ static int lib_pSpawnThokMobj(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
NOHUD
INLEVEL
if (!player)
return LUA_ErrInvalid(L, "player_t");
P_SpawnThokMobj(player);
@ -984,6 +1127,7 @@ static int lib_pSpawnSpinMobj(lua_State *L)
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
mobjtype_t type = luaL_checkinteger(L, 2);
NOHUD
INLEVEL
if (!player)
return LUA_ErrInvalid(L, "player_t");
if (type >= NUMMOBJTYPES)
@ -998,6 +1142,7 @@ static int lib_pTelekinesis(lua_State *L)
fixed_t thrust = luaL_checkfixed(L, 2);
fixed_t range = luaL_checkfixed(L, 3);
NOHUD
INLEVEL
if (!player)
return LUA_ErrInvalid(L, "player_t");
P_Telekinesis(player, thrust, range);
@ -1014,6 +1159,7 @@ static int lib_pCheckPosition(lua_State *L)
fixed_t x = luaL_checkfixed(L, 2);
fixed_t y = luaL_checkfixed(L, 3);
NOHUD
INLEVEL
if (!thing)
return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_CheckPosition(thing, x, y));
@ -1030,6 +1176,7 @@ static int lib_pTryMove(lua_State *L)
fixed_t y = luaL_checkfixed(L, 3);
boolean allowdropoff = lua_optboolean(L, 4);
NOHUD
INLEVEL
if (!thing)
return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_TryMove(thing, x, y, allowdropoff));
@ -1044,6 +1191,7 @@ static int lib_pMove(lua_State *L)
mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
fixed_t speed = luaL_checkfixed(L, 2);
NOHUD
INLEVEL
if (!actor)
return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_Move(actor, speed));
@ -1060,6 +1208,7 @@ static int lib_pTeleportMove(lua_State *L)
fixed_t y = luaL_checkfixed(L, 3);
fixed_t z = luaL_checkfixed(L, 4);
NOHUD
INLEVEL
if (!thing)
return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_TeleportMove(thing, x, y, z));
@ -1072,6 +1221,7 @@ static int lib_pSlideMove(lua_State *L)
{
mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
NOHUD
INLEVEL
if (!mo)
return LUA_ErrInvalid(L, "mobj_t");
P_SlideMove(mo);
@ -1082,6 +1232,7 @@ static int lib_pBounceMove(lua_State *L)
{
mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
NOHUD
INLEVEL
if (!mo)
return LUA_ErrInvalid(L, "mobj_t");
P_BounceMove(mo);
@ -1093,6 +1244,7 @@ static int lib_pCheckSight(lua_State *L)
mobj_t *t1 = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
mobj_t *t2 = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
//HUDSAFE?
INLEVEL
if (!t1 || !t2)
return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_CheckSight(t1, t2));
@ -1107,6 +1259,7 @@ static int lib_pCheckHoopPosition(lua_State *L)
fixed_t z = luaL_checkfixed(L, 4);
fixed_t radius = luaL_checkfixed(L, 5);
NOHUD
INLEVEL
if (!hoopthing)
return LUA_ErrInvalid(L, "mobj_t");
P_CheckHoopPosition(hoopthing, x, y, z, radius);
@ -1119,6 +1272,7 @@ static int lib_pRadiusAttack(lua_State *L)
mobj_t *source = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
fixed_t damagedist = luaL_checkfixed(L, 3);
NOHUD
INLEVEL
if (!spot || !source)
return LUA_ErrInvalid(L, "mobj_t");
P_RadiusAttack(spot, source, damagedist);
@ -1132,6 +1286,7 @@ static int lib_pFloorzAtPos(lua_State *L)
fixed_t z = luaL_checkfixed(L, 3);
fixed_t height = luaL_checkfixed(L, 4);
//HUDSAFE
INLEVEL
lua_pushfixed(L, P_FloorzAtPos(x, y, z, height));
return 1;
}
@ -1141,6 +1296,7 @@ static int lib_pDoSpring(lua_State *L)
mobj_t *spring = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
mobj_t *object = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
NOHUD
INLEVEL
if (!spring || !object)
return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, P_DoSpring(spring, object));
@ -1154,6 +1310,7 @@ static int lib_pRemoveShield(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
NOHUD
INLEVEL
if (!player)
return LUA_ErrInvalid(L, "player_t");
P_RemoveShield(player);
@ -1166,6 +1323,7 @@ static int lib_pDamageMobj(lua_State *L)
INT32 damage;
UINT8 damagetype;
NOHUD
INLEVEL
if (!target)
return LUA_ErrInvalid(L, "mobj_t");
if (!lua_isnone(L, 2) && lua_isuserdata(L, 2))
@ -1183,6 +1341,7 @@ static int lib_pKillMobj(lua_State *L)
mobj_t *target = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)), *inflictor = NULL, *source = NULL;
UINT8 damagetype;
NOHUD
INLEVEL
if (!target)
return LUA_ErrInvalid(L, "mobj_t");
if (!lua_isnone(L, 2) && lua_isuserdata(L, 2))
@ -1199,6 +1358,7 @@ static int lib_pPlayerRingBurst(lua_State *L)
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
INT32 num_rings = (INT32)luaL_optinteger(L, 2, -1);
NOHUD
INLEVEL
if (!player)
return LUA_ErrInvalid(L, "player_t");
if (num_rings == -1)
@ -1211,6 +1371,7 @@ static int lib_pPlayerWeaponPanelBurst(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
NOHUD
INLEVEL
if (!player)
return LUA_ErrInvalid(L, "player_t");
P_PlayerWeaponPanelBurst(player);
@ -1221,6 +1382,7 @@ static int lib_pPlayerWeaponAmmoBurst(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
NOHUD
INLEVEL
if (!player)
return LUA_ErrInvalid(L, "player_t");
P_PlayerWeaponAmmoBurst(player);
@ -1231,6 +1393,7 @@ static int lib_pPlayerWeaponPanelOrAmmoBurst(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
NOHUD
INLEVEL
if (!player)
return LUA_ErrInvalid(L, "player_t");
P_PlayerWeaponPanelOrAmmoBurst(player);
@ -1242,6 +1405,7 @@ static int lib_pPlayerEmeraldBurst(lua_State *L)
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
boolean toss = lua_optboolean(L, 2);
NOHUD
INLEVEL
if (!player)
return LUA_ErrInvalid(L, "player_t");
P_PlayerEmeraldBurst(player, toss);
@ -1253,6 +1417,7 @@ static int lib_pPlayerFlagBurst(lua_State *L)
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
boolean toss = lua_optboolean(L, 2);
NOHUD
INLEVEL
if (!player)
return LUA_ErrInvalid(L, "player_t");
P_PlayerFlagBurst(player, toss);
@ -1264,6 +1429,7 @@ static int lib_pPlayRinglossSound(lua_State *L)
mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
player_t *player = NULL;
NOHUD
INLEVEL
if (!source)
return LUA_ErrInvalid(L, "mobj_t");
if (!lua_isnone(L, 2) && lua_isuserdata(L, 2))
@ -1282,6 +1448,7 @@ static int lib_pPlayDeathSound(lua_State *L)
mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
player_t *player = NULL;
NOHUD
INLEVEL
if (!source)
return LUA_ErrInvalid(L, "mobj_t");
if (!lua_isnone(L, 2) && lua_isuserdata(L, 2))
@ -1300,6 +1467,7 @@ static int lib_pPlayVictorySound(lua_State *L)
mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
player_t *player = NULL;
NOHUD
INLEVEL
if (!source)
return LUA_ErrInvalid(L, "mobj_t");
if (!lua_isnone(L, 2) && lua_isuserdata(L, 2))
@ -1317,6 +1485,7 @@ static int lib_pPlayLivesJingle(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
NOHUD
INLEVEL
if (!player)
return LUA_ErrInvalid(L, "player_t");
P_PlayLivesJingle(player);
@ -1328,6 +1497,7 @@ static int lib_pCanPickupItem(lua_State *L)
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
boolean weapon = lua_optboolean(L, 2);
//HUDSAFE
INLEVEL
if (!player)
return LUA_ErrInvalid(L, "player_t");
lua_pushboolean(L, P_CanPickupItem(player, weapon));
@ -1338,6 +1508,7 @@ static int lib_pDoNightsScore(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
NOHUD
INLEVEL
if (!player)
return LUA_ErrInvalid(L, "player_t");
P_DoNightsScore(player);
@ -1348,6 +1519,7 @@ static int lib_pDoMatchSuper(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
NOHUD
INLEVEL
if (!player)
return LUA_ErrInvalid(L, "player_t");
P_DoMatchSuper(player);
@ -1363,6 +1535,7 @@ static int lib_pThrust(lua_State *L)
angle_t angle = luaL_checkangle(L, 2);
fixed_t move = luaL_checkfixed(L, 3);
NOHUD
INLEVEL
if (!mo)
return LUA_ErrInvalid(L, "mobj_t");
P_Thrust(mo, angle, move);
@ -1374,6 +1547,7 @@ static int lib_pSetMobjStateNF(lua_State *L)
mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
statenum_t state = luaL_checkinteger(L, 2);
NOHUD
INLEVEL
if (!mobj)
return LUA_ErrInvalid(L, "mobj_t");
if (state >= NUMSTATES)
@ -1389,6 +1563,7 @@ static int lib_pDoSuperTransformation(lua_State *L)
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
boolean giverings = lua_optboolean(L, 2);
NOHUD
INLEVEL
if (!player)
return LUA_ErrInvalid(L, "player_t");
P_DoSuperTransformation(player, giverings);
@ -1399,6 +1574,7 @@ static int lib_pExplodeMissile(lua_State *L)
{
mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
NOHUD
INLEVEL
if (!mo)
return LUA_ErrInvalid(L, "mobj_t");
P_ExplodeMissile(mo);
@ -1411,6 +1587,7 @@ static int lib_pPlayerTouchingSectorSpecial(lua_State *L)
INT32 section = (INT32)luaL_checkinteger(L, 2);
INT32 number = (INT32)luaL_checkinteger(L, 3);
//HUDSAFE
INLEVEL
if (!player)
return LUA_ErrInvalid(L, "player_t");
LUA_PushUserdata(L, P_PlayerTouchingSectorSpecial(player, section, number), META_SECTOR);
@ -1423,6 +1600,7 @@ static int lib_pFindSpecialLineFromTag(lua_State *L)
INT16 line = (INT16)luaL_checkinteger(L, 2);
INT32 start = (INT32)luaL_optinteger(L, 3, -1);
NOHUD
INLEVEL
lua_pushinteger(L, P_FindSpecialLineFromTag(special, line, start));
return 1;
}
@ -1432,6 +1610,7 @@ static int lib_pSwitchWeather(lua_State *L)
INT32 weathernum = (INT32)luaL_checkinteger(L, 1);
player_t *user = NULL;
NOHUD
INLEVEL
if (!lua_isnone(L, 2) && lua_isuserdata(L, 2)) // if a player, setup weather for only the player, otherwise setup weather for all players
user = *((player_t **)luaL_checkudata(L, 2, META_PLAYER));
if (!user) // global
@ -1447,6 +1626,7 @@ static int lib_pLinedefExecute(lua_State *L)
mobj_t *actor = NULL;
sector_t *caller = NULL;
NOHUD
INLEVEL
if (!lua_isnone(L, 2) && lua_isuserdata(L, 2))
actor = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
if (!lua_isnone(L, 3) && lua_isuserdata(L, 3))
@ -1459,6 +1639,7 @@ static int lib_pSpawnLightningFlash(lua_State *L)
{
sector_t *sector = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR));
NOHUD
INLEVEL
if (!sector)
return LUA_ErrInvalid(L, "sector_t");
P_SpawnLightningFlash(sector);
@ -1471,6 +1652,7 @@ static int lib_pFadeLight(lua_State *L)
INT32 destvalue = (INT32)luaL_checkinteger(L, 2);
INT32 speed = (INT32)luaL_checkinteger(L, 3);
NOHUD
INLEVEL
P_FadeLight(tag, destvalue, speed);
return 0;
}
@ -1479,6 +1661,7 @@ static int lib_pThingOnSpecial3DFloor(lua_State *L)
{
mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
NOHUD
INLEVEL
if (!mo)
return LUA_ErrInvalid(L, "mobj_t");
LUA_PushUserdata(L, P_ThingOnSpecial3DFloor(mo), META_SECTOR);
@ -1489,6 +1672,7 @@ static int lib_pIsFlagAtBase(lua_State *L)
{
mobjtype_t flag = luaL_checkinteger(L, 1);
NOHUD
INLEVEL
if (flag >= NUMMOBJTYPES)
return luaL_error(L, "mobj type %d out of range (0 - %d)", flag, NUMMOBJTYPES-1);
lua_pushboolean(L, P_IsFlagAtBase(flag));
@ -1500,6 +1684,7 @@ static int lib_pSetupLevelSky(lua_State *L)
INT32 skynum = (INT32)luaL_checkinteger(L, 1);
player_t *user = NULL;
NOHUD
INLEVEL
if (!lua_isnone(L, 2) && lua_isuserdata(L, 2)) // if a player, setup sky for only the player, otherwise setup sky for all players
user = *((player_t **)luaL_checkudata(L, 2, META_PLAYER));
if (!user) // global
@ -1518,6 +1703,7 @@ static int lib_pSetSkyboxMobj(lua_State *L)
int w = 0;
NOHUD
INLEVEL
if (!lua_isnil(L,1)) // nil leaves mo as NULL to remove the skybox rendering.
{
mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); // otherwise it is a skybox mobj.
@ -1564,6 +1750,7 @@ static int lib_pStartQuake(lua_State *L)
static mappoint_t q_epicenter = {0,0,0};
NOHUD
INLEVEL
// While technically we don't support epicenter and radius,
// we get their values anyway if they exist.
@ -1625,6 +1812,7 @@ static int lib_evCrumbleChain(lua_State *L)
sector_t *sec = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR));
ffloor_t *rover = *((ffloor_t **)luaL_checkudata(L, 2, META_FFLOOR));
NOHUD
INLEVEL
if (!sec)
return LUA_ErrInvalid(L, "sector_t");
if (!rover)
@ -1681,6 +1869,7 @@ static int lib_rPointInSubsector(lua_State *L)
fixed_t x = luaL_checkfixed(L, 1);
fixed_t y = luaL_checkfixed(L, 2);
//HUDSAFE
INLEVEL
LUA_PushUserdata(L, R_PointInSubsector(x, y), META_SUBSECTOR);
return 1;
}
@ -1715,6 +1904,7 @@ static int lib_rSetPlayerSkin(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
NOHUD
INLEVEL
if (!player)
return LUA_ErrInvalid(L, "player_t");
if (lua_isnoneornil(L, 2))
@ -1899,6 +2089,7 @@ static int lib_sOriginPlaying(lua_State *L)
{
void *origin = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
NOHUD
INLEVEL
if (!origin)
return LUA_ErrInvalid(L, "mobj_t");
lua_pushboolean(L, S_OriginPlaying(origin));
@ -1920,6 +2111,7 @@ static int lib_sSoundPlaying(lua_State *L)
void *origin = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
sfxenum_t id = luaL_checkinteger(L, 2);
NOHUD
INLEVEL
if (!origin)
return LUA_ErrInvalid(L, "mobj_t");
if (id >= NUMSFX)
@ -1935,6 +2127,7 @@ static int lib_gBuildMapName(lua_State *L)
{
INT32 map = luaL_optinteger(L, 1, gamemap);
//HUDSAFE
INLEVEL
lua_pushstring(L, G_BuildMapName(map));
return 1;
}
@ -1943,6 +2136,7 @@ static int lib_gDoReborn(lua_State *L)
{
INT32 playernum = luaL_checkinteger(L, 1);
NOHUD
INLEVEL
if (playernum >= MAXPLAYERS)
return luaL_error(L, "playernum %d out of range (0 - %d)", playernum, MAXPLAYERS-1);
G_DoReborn(playernum);
@ -1953,6 +2147,7 @@ static int lib_gExitLevel(lua_State *L)
{
int n = lua_gettop(L); // Num arguments
NOHUD
INLEVEL
// LUA EXTENSION: Custom exit like support
// Supported:
@ -1979,6 +2174,7 @@ static int lib_gIsSpecialStage(lua_State *L)
{
INT32 mapnum = luaL_optinteger(L, 1, gamemap);
//HUDSAFE
INLEVEL
lua_pushboolean(L, G_IsSpecialStage(mapnum));
return 1;
}
@ -1986,6 +2182,7 @@ static int lib_gIsSpecialStage(lua_State *L)
static int lib_gGametypeUsesLives(lua_State *L)
{
//HUDSAFE
INLEVEL
lua_pushboolean(L, G_GametypeUsesLives());
return 1;
}
@ -1993,6 +2190,7 @@ static int lib_gGametypeUsesLives(lua_State *L)
static int lib_gGametypeHasTeams(lua_State *L)
{
//HUDSAFE
INLEVEL
lua_pushboolean(L, G_GametypeHasTeams());
return 1;
}
@ -2000,6 +2198,7 @@ static int lib_gGametypeHasTeams(lua_State *L)
static int lib_gGametypeHasSpectators(lua_State *L)
{
//HUDSAFE
INLEVEL
lua_pushboolean(L, G_GametypeHasSpectators());
return 1;
}
@ -2007,6 +2206,7 @@ static int lib_gGametypeHasSpectators(lua_State *L)
static int lib_gRingSlingerGametype(lua_State *L)
{
//HUDSAFE
INLEVEL
lua_pushboolean(L, G_RingSlingerGametype());
return 1;
}
@ -2014,6 +2214,7 @@ static int lib_gRingSlingerGametype(lua_State *L)
static int lib_gPlatformGametype(lua_State *L)
{
//HUDSAFE
INLEVEL
lua_pushboolean(L, G_PlatformGametype());
return 1;
}
@ -2021,6 +2222,7 @@ static int lib_gPlatformGametype(lua_State *L)
static int lib_gTagGametype(lua_State *L)
{
//HUDSAFE
INLEVEL
lua_pushboolean(L, G_TagGametype());
return 1;
}
@ -2068,6 +2270,7 @@ static int lib_gTicsToMilliseconds(lua_State *L)
static luaL_Reg lib[] = {
{"print", lib_print},
{"userdataType", lib_userdataType},
// m_random
{"P_RandomFixed",lib_pRandomFixed},

View file

@ -186,6 +186,9 @@ static int lib_searchBlockmap(lua_State *L)
UINT8 funcret = 0;
blockmap_func searchFunc;
if (gamestate != GS_LEVEL)
return luaL_error(L, "This function can only be used in a level!");
lua_remove(L, 1); // remove searchtype, stack is now function, mobj, [x1, x2, y1, y2]
luaL_checktype(L, 1, LUA_TFUNCTION);

View file

@ -22,7 +22,10 @@
#include "lua_libs.h"
#include "lua_hud.h" // hud_running errors
#define NOHUD if (hud_running) return luaL_error(L, "HUD rendering code should not call this function!");
#define NOHUD if (hud_running)\
return luaL_error(L, "HUD rendering code should not call this function!");
#define INLEVEL if (gamestate != GS_LEVEL)\
return luaL_error(L, "This function can only be used in a level!");
static const char *cvname = NULL;
@ -412,6 +415,7 @@ static int lib_consPrintf(lua_State *L)
if (n < 2)
return luaL_error(L, "CONS_Printf requires at least two arguments: player and text.");
//HUDSAFE
INLEVEL
plr = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
if (!plr)
return LUA_ErrInvalid(L, "player_t");

View file

@ -45,6 +45,7 @@ enum hook {
hook_PlayerSpawn,
hook_ShieldSpawn,
hook_ShieldSpecial,
hook_MobjMoveBlocked,
hook_MAX // last hook
};
@ -81,5 +82,6 @@ boolean LUAh_HurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source, UINT8
#define LUAh_PlayerSpawn(player) LUAh_PlayerHook(player, hook_PlayerSpawn) // Hook for G_SpawnPlayer
#define LUAh_ShieldSpawn(player) LUAh_PlayerHook(player, hook_ShieldSpawn) // Hook for P_SpawnShieldOrb
#define LUAh_ShieldSpecial(player) LUAh_PlayerHook(player, hook_ShieldSpecial) // Hook for shield abilities
#define LUAh_MobjMoveBlocked(mo) LUAh_MobjHook(mo, hook_MobjMoveBlocked) // Hook for P_XYMovement (when movement is blocked)
#endif

View file

@ -56,6 +56,7 @@ const char *const hookNames[hook_MAX+1] = {
"PlayerSpawn",
"ShieldSpawn",
"ShieldSpecial",
"MobjMoveBlocked",
NULL
};
@ -126,6 +127,7 @@ static int lib_addHook(lua_State *L)
case hook_BossDeath:
case hook_MobjRemoved:
case hook_HurtMsg:
case hook_MobjMoveBlocked:
hook.s.mt = MT_NULL;
if (lua_isnumber(L, 2))
hook.s.mt = lua_tonumber(L, 2);
@ -184,6 +186,7 @@ static int lib_addHook(lua_State *L)
case hook_MobjDeath:
case hook_BossDeath:
case hook_MobjRemoved:
case hook_MobjMoveBlocked:
lastp = &mobjhooks[hook.s.mt];
break;
case hook_JumpSpecial:

View file

@ -264,12 +264,19 @@ static const char *const bbox_opt[] = {
static const char *const array_opt[] ={"iterate",NULL};
static const char *const valid_opt[] ={"valid",NULL};
///////////////////////////////////
// sector list iterate functions //
///////////////////////////////////
// iterates through a sector's thinglist!
static int lib_iterateSectorThinglist(lua_State *L)
{
mobj_t *state = NULL;
mobj_t *thing = NULL;
if (gamestate != GS_LEVEL)
return luaL_error(L, "This function can only be used in a level!");
if (lua_gettop(L) < 2)
return luaL_error(L, "Don't call sector.thinglist() directly, use it as 'for rover in sector.thinglist do <block> end'.");
@ -303,6 +310,9 @@ static int lib_iterateSectorFFloors(lua_State *L)
ffloor_t *state = NULL;
ffloor_t *ffloor = NULL;
if (gamestate != GS_LEVEL)
return luaL_error(L, "This function can only be used in a level!");
if (lua_gettop(L) < 2)
return luaL_error(L, "Don't call sector.ffloors() directly, use it as 'for rover in sector.ffloors do <block> end'.");
@ -338,6 +348,10 @@ static int sector_iterate(lua_State *L)
return 3;
}
////////////////////
// sector.lines[] //
////////////////////
// sector.lines, i -> sector.lines[i]
// sector.lines.valid, for validity checking
static int sectorlines_get(lua_State *L)
@ -399,6 +413,10 @@ static int sectorlines_num(lua_State *L)
return 1;
}
//////////////
// sector_t //
//////////////
static int sector_get(lua_State *L)
{
sector_t *sector = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR));
@ -540,6 +558,10 @@ static int sector_num(lua_State *L)
return 1;
}
/////////////////
// subsector_t //
/////////////////
static int subsector_get(lua_State *L)
{
subsector_t *subsector = *((subsector_t **)luaL_checkudata(L, 1, META_SUBSECTOR));
@ -579,6 +601,10 @@ static int subsector_num(lua_State *L)
return 1;
}
////////////
// line_t //
////////////
static int line_get(lua_State *L)
{
line_t *line = *((line_t **)luaL_checkudata(L, 1, META_LINE));
@ -676,6 +702,10 @@ static int line_num(lua_State *L)
return 1;
}
////////////////////
// line.sidenum[] //
////////////////////
static int sidenum_get(lua_State *L)
{
UINT16 *sidenum = *((UINT16 **)luaL_checkudata(L, 1, META_SIDENUM));
@ -704,6 +734,10 @@ static int sidenum_get(lua_State *L)
return 1;
}
////////////
// side_t //
////////////
static int side_get(lua_State *L)
{
side_t *side = *((side_t **)luaL_checkudata(L, 1, META_SIDE));
@ -805,6 +839,10 @@ static int side_num(lua_State *L)
return 1;
}
//////////////
// vertex_t //
//////////////
static int vertex_get(lua_State *L)
{
vertex_t *vertex = *((vertex_t **)luaL_checkudata(L, 1, META_VERTEX));
@ -845,6 +883,11 @@ static int vertex_num(lua_State *L)
}
#ifdef HAVE_LUA_SEGS
///////////
// seg_t //
///////////
static int seg_get(lua_State *L)
{
seg_t *seg = *((seg_t **)luaL_checkudata(L, 1, META_SEG));
@ -902,6 +945,10 @@ static int seg_num(lua_State *L)
return 1;
}
////////////
// node_t //
////////////
static int node_get(lua_State *L)
{
node_t *node = *((node_t **)luaL_checkudata(L, 1, META_NODE));
@ -949,6 +996,11 @@ static int node_num(lua_State *L)
lua_pushinteger(L, node-nodes);
return 1;
}
///////////////
// node.bbox //
///////////////
/*
// node.bbox[i][j]: i = 0 or 1, j = 0 1 2 or 3
// NOTE: 2D arrays are NOT double pointers,
@ -1028,6 +1080,10 @@ static int nodebbox_call(lua_State *L)
return 1;
}
/////////////////////
// node.children[] //
/////////////////////
// node.children[i]: i = 0 or 1
static int nodechildren_get(lua_State *L)
{
@ -1063,6 +1119,10 @@ static int nodechildren_get(lua_State *L)
}
#endif
//////////
// bbox //
//////////
// bounding box (aka fixed_t array with four elements)
// NOTE: may be useful for polyobjects or other things later
static int bbox_get(lua_State *L)
@ -1100,9 +1160,15 @@ static int bbox_get(lua_State *L)
return 1;
}
///////////////
// sectors[] //
///////////////
static int lib_iterateSectors(lua_State *L)
{
size_t i = 0;
if (gamestate != GS_LEVEL)
return luaL_error(L, "This function can only be used in a level!");
if (lua_gettop(L) < 2)
return luaL_error(L, "Don't call sectors.iterate() directly, use it as 'for sector in sectors.iterate do <block> end'.");
lua_settop(L, 2);
@ -1120,6 +1186,8 @@ static int lib_iterateSectors(lua_State *L)
static int lib_getSector(lua_State *L)
{
int field;
if (gamestate != GS_LEVEL)
return luaL_error(L, "You cannot access this outside of a level!");
lua_settop(L, 2);
lua_remove(L, 1); // dummy userdata table is unused.
if (lua_isnumber(L, 1))
@ -1146,9 +1214,15 @@ static int lib_numsectors(lua_State *L)
return 1;
}
//////////////////
// subsectors[] //
//////////////////
static int lib_iterateSubsectors(lua_State *L)
{
size_t i = 0;
if (gamestate != GS_LEVEL)
return luaL_error(L, "This function can only be used in a level!");
if (lua_gettop(L) < 2)
return luaL_error(L, "Don't call subsectors.iterate() directly, use it as 'for subsector in subsectors.iterate do <block> end'.");
lua_settop(L, 2);
@ -1166,6 +1240,8 @@ static int lib_iterateSubsectors(lua_State *L)
static int lib_getSubsector(lua_State *L)
{
int field;
if (gamestate != GS_LEVEL)
return luaL_error(L, "You cannot access this outside of a level!");
lua_settop(L, 2);
lua_remove(L, 1); // dummy userdata table is unused.
if (lua_isnumber(L, 1))
@ -1192,9 +1268,15 @@ static int lib_numsubsectors(lua_State *L)
return 1;
}
/////////////
// lines[] //
/////////////
static int lib_iterateLines(lua_State *L)
{
size_t i = 0;
if (gamestate != GS_LEVEL)
return luaL_error(L, "This function can only be used in a level!");
if (lua_gettop(L) < 2)
return luaL_error(L, "Don't call lines.iterate() directly, use it as 'for line in lines.iterate do <block> end'.");
lua_settop(L, 2);
@ -1212,6 +1294,8 @@ static int lib_iterateLines(lua_State *L)
static int lib_getLine(lua_State *L)
{
int field;
if (gamestate != GS_LEVEL)
return luaL_error(L, "You cannot access this outside of a level!");
lua_settop(L, 2);
lua_remove(L, 1); // dummy userdata table is unused.
if (lua_isnumber(L, 1))
@ -1238,9 +1322,15 @@ static int lib_numlines(lua_State *L)
return 1;
}
/////////////
// sides[] //
/////////////
static int lib_iterateSides(lua_State *L)
{
size_t i = 0;
if (gamestate != GS_LEVEL)
return luaL_error(L, "This function can only be used in a level!");
if (lua_gettop(L) < 2)
return luaL_error(L, "Don't call sides.iterate() directly, use it as 'for side in sides.iterate do <block> end'.");
lua_settop(L, 2);
@ -1258,6 +1348,8 @@ static int lib_iterateSides(lua_State *L)
static int lib_getSide(lua_State *L)
{
int field;
if (gamestate != GS_LEVEL)
return luaL_error(L, "You cannot access this outside of a level!");
lua_settop(L, 2);
lua_remove(L, 1); // dummy userdata table is unused.
if (lua_isnumber(L, 1))
@ -1284,9 +1376,15 @@ static int lib_numsides(lua_State *L)
return 1;
}
////////////////
// vertexes[] //
////////////////
static int lib_iterateVertexes(lua_State *L)
{
size_t i = 0;
if (gamestate != GS_LEVEL)
return luaL_error(L, "This function can only be used in a level!");
if (lua_gettop(L) < 2)
return luaL_error(L, "Don't call vertexes.iterate() directly, use it as 'for vertex in vertexes.iterate do <block> end'.");
lua_settop(L, 2);
@ -1304,6 +1402,8 @@ static int lib_iterateVertexes(lua_State *L)
static int lib_getVertex(lua_State *L)
{
int field;
if (gamestate != GS_LEVEL)
return luaL_error(L, "You cannot access this outside of a level!");
lua_settop(L, 2);
lua_remove(L, 1); // dummy userdata table is unused.
if (lua_isnumber(L, 1))
@ -1331,9 +1431,16 @@ static int lib_numvertexes(lua_State *L)
}
#ifdef HAVE_LUA_SEGS
////////////
// segs[] //
////////////
static int lib_iterateSegs(lua_State *L)
{
size_t i = 0;
if (gamestate != GS_LEVEL)
return luaL_error(L, "This function can only be used in a level!");
if (lua_gettop(L) < 2)
return luaL_error(L, "Don't call segs.iterate() directly, use it as 'for seg in segs.iterate do <block> end'.");
lua_settop(L, 2);
@ -1351,6 +1458,8 @@ static int lib_iterateSegs(lua_State *L)
static int lib_getSeg(lua_State *L)
{
int field;
if (gamestate != GS_LEVEL)
return luaL_error(L, "You cannot access this outside of a level!");
lua_settop(L, 2);
lua_remove(L, 1); // dummy userdata table is unused.
if (lua_isnumber(L, 1))
@ -1377,9 +1486,15 @@ static int lib_numsegs(lua_State *L)
return 1;
}
/////////////
// nodes[] //
/////////////
static int lib_iterateNodes(lua_State *L)
{
size_t i = 0;
if (gamestate != GS_LEVEL)
return luaL_error(L, "This function can only be used in a level!");
if (lua_gettop(L) < 2)
return luaL_error(L, "Don't call nodes.iterate() directly, use it as 'for node in nodes.iterate do <block> end'.");
lua_settop(L, 2);
@ -1397,6 +1512,8 @@ static int lib_iterateNodes(lua_State *L)
static int lib_getNode(lua_State *L)
{
int field;
if (gamestate != GS_LEVEL)
return luaL_error(L, "You cannot access this outside of a level!");
lua_settop(L, 2);
lua_remove(L, 1); // dummy userdata table is unused.
if (lua_isnumber(L, 1))
@ -1424,6 +1541,10 @@ static int lib_numnodes(lua_State *L)
}
#endif
//////////////
// ffloor_t //
//////////////
static int ffloor_get(lua_State *L)
{
ffloor_t *ffloor = *((ffloor_t **)luaL_checkudata(L, 1, META_FFLOOR));
@ -1567,6 +1688,10 @@ static int ffloor_set(lua_State *L)
return 0;
}
/////////////////////
// mapheaderinfo[] //
/////////////////////
static int lib_getMapheaderinfo(lua_State *L)
{
// i -> mapheaderinfo[i-1]
@ -1599,6 +1724,10 @@ static int lib_nummapheaders(lua_State *L)
return 1;
}
/////////////////
// mapheader_t //
/////////////////
static int mapheaderinfo_get(lua_State *L)
{
mapheader_t *header = *((mapheader_t **)luaL_checkudata(L, 1, META_MAPHEADER));

View file

@ -751,6 +751,8 @@ static int mapthing_set(lua_State *L)
static int lib_iterateMapthings(lua_State *L)
{
size_t i = 0;
if (gamestate != GS_LEVEL)
return luaL_error(L, "This function can only be used in a level!");
if (lua_gettop(L) < 2)
return luaL_error(L, "Don't call mapthings.iterate() directly, use it as 'for mapthing in mapthings.iterate do <block> end'.");
lua_settop(L, 2);
@ -768,6 +770,8 @@ static int lib_iterateMapthings(lua_State *L)
static int lib_getMapthing(lua_State *L)
{
int field;
if (gamestate != GS_LEVEL)
return luaL_error(L, "You cannot access this outside of a level!");
lua_settop(L, 2);
lua_remove(L, 1); // dummy userdata table is unused.
if (lua_isnumber(L, 1))

View file

@ -25,6 +25,8 @@
static int lib_iteratePlayers(lua_State *L)
{
INT32 i = -1;
if (gamestate != GS_LEVEL)
return luaL_error(L, "This function can only be used in a level!");
if (lua_gettop(L) < 2)
{
//return luaL_error(L, "Don't call players.iterate() directly, use it as 'for player in players.iterate do <block> end'.");
@ -51,6 +53,8 @@ static int lib_getPlayer(lua_State *L)
{
const char *field;
// i -> players[i]
if (gamestate != GS_LEVEL)
return luaL_error(L, "You cannot access this outside of a level!");
if (lua_type(L, 2) == LUA_TNUMBER)
{
lua_Integer i = luaL_checkinteger(L, 2);

View file

@ -29,6 +29,9 @@ static int lib_iterateThinkers(lua_State *L)
actionf_p1 searchFunc;
const char *searchMeta;
if (gamestate != GS_LEVEL)
return luaL_error(L, "This function can only be used in a level!");
lua_settop(L, 2);
lua_remove(L, 1); // remove state now.
@ -84,6 +87,8 @@ static int lib_iterateThinkers(lua_State *L)
static int lib_startIterate(lua_State *L)
{
if (gamestate != GS_LEVEL)
return luaL_error(L, "This function can only be used in a level!");
luaL_checkoption(L, 1, iter_opt[0], iter_opt);
lua_pushcfunction(L, lib_iterateThinkers);
lua_pushvalue(L, 1);

View file

@ -2117,7 +2117,8 @@ void P_XYMovement(mobj_t *mo)
if (CheckForBustableBlocks && mo->flags & MF_PUSHABLE)
P_PushableCheckBustables(mo);
if (!P_TryMove(mo, mo->x + xmove, mo->y + ymove, true) && !(mo->eflags & MFE_SPRUNG))
if (!P_TryMove(mo, mo->x + xmove, mo->y + ymove, true)
&& !(P_MobjWasRemoved(mo) || mo->eflags & MFE_SPRUNG))
{
// blocked move
moved = false;
@ -2127,7 +2128,17 @@ void P_XYMovement(mobj_t *mo)
B_MoveBlocked(player);
}
if (mo->flags & MF_BOUNCE)
#ifdef HAVE_BLUA
if (LUAh_MobjMoveBlocked(mo))
{
if (P_MobjWasRemoved(mo))
return;
}
else
#endif
if (P_MobjWasRemoved(mo))
return;
else if (mo->flags & MF_BOUNCE)
{
P_BounceMove(mo);
xmove = ymove = 0;