Merge branch 'mapthing-spawn-hook' into 'master'

"MapThingSpawn" hook for Lua

A hook for adding special stuff to mobjs spawned via a map thing on level load, like special features depending on the map thing's flags, angle, z position, extrainfo, or anything else I didn't think of.

**Function syntax:**
`functionname(mobj, mapthing)`

where `mobj` is the spawned mobj (type mobj_t obviously), and `mapthing` is its corresponding map thing (type mapthing_t also obviously). Note that `mapthing.mobj` will not yet be set to `mobj` at this point (it's set afterwards, provided you don't remove the mobj or something stupid).

Returning `true` overrides features in place for existing mobj types (currently not all existing features are overridden, I may change this; see the source code for what IS overridable for now), returning `false` runs them as normal.

**Hook syntax:**
`addHook("MapThingSpawn", functionname, MT_OBJECTTYPE)`

where `MT_OBJECTTYPE` is the object type to apply the hooked function for. As usual, if this argument is omitted or set to MT_NULL, the function runs for all object types.

**Test resources and where to find them:**

* srb2win-mapthingspawn.exe, my folder on the FTP - test exe, obviously
* luatest-mapthingspawn.lua, same place - a simple Lua script that changes the scale of MT_GFZFLOWER1 (the orange flower) based on the map thing's angle (0 degrees is normal, 90 degrees is 2x bigger, 180 is 3x bigger, 270 is 4x, etc etc)

See merge request !83
This commit is contained in:
Monster Iestyn 2017-07-02 09:46:11 -04:00
commit 64b3861168
3 changed files with 77 additions and 0 deletions

View File

@ -46,6 +46,7 @@ enum hook {
hook_ShieldSpawn,
hook_ShieldSpecial,
hook_MobjMoveBlocked,
hook_MapThingSpawn,
hook_MAX // last hook
};
@ -83,5 +84,6 @@ boolean LUAh_HurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source, UINT8
#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)
boolean LUAh_MapThingSpawn(mobj_t *mo, mapthing_t *mthing); // Hook for P_SpawnMapThing by mobj type
#endif

View File

@ -57,6 +57,7 @@ const char *const hookNames[hook_MAX+1] = {
"ShieldSpawn",
"ShieldSpecial",
"MobjMoveBlocked",
"MapThingSpawn",
NULL
};
@ -128,6 +129,7 @@ static int lib_addHook(lua_State *L)
case hook_MobjRemoved:
case hook_HurtMsg:
case hook_MobjMoveBlocked:
case hook_MapThingSpawn:
hook.s.mt = MT_NULL;
if (lua_isnumber(L, 2))
hook.s.mt = lua_tonumber(L, 2);
@ -187,6 +189,7 @@ static int lib_addHook(lua_State *L)
case hook_BossDeath:
case hook_MobjRemoved:
case hook_MobjMoveBlocked:
case hook_MapThingSpawn:
lastp = &mobjhooks[hook.s.mt];
break;
case hook_JumpSpecial:
@ -1073,4 +1076,66 @@ void LUAh_NetArchiveHook(lua_CFunction archFunc)
// stack: tables
}
boolean LUAh_MapThingSpawn(mobj_t *mo, mapthing_t *mthing)
{
hook_p hookp;
boolean hooked = false;
if (!gL || !(hooksAvailable[hook_MapThingSpawn/8] & (1<<(hook_MapThingSpawn%8))))
return false;
lua_settop(gL, 0);
// Look for all generic mobj map thing spawn hooks
for (hookp = mobjhooks[MT_NULL]; hookp; hookp = hookp->next)
if (hookp->type == hook_MapThingSpawn)
{
if (lua_gettop(gL) == 0)
{
LUA_PushUserdata(gL, mo, META_MOBJ);
LUA_PushUserdata(gL, mthing, META_MAPTHING);
}
lua_pushfstring(gL, FMT_HOOKID, hookp->id);
lua_gettable(gL, LUA_REGISTRYINDEX);
lua_pushvalue(gL, -3);
lua_pushvalue(gL, -3);
if (lua_pcall(gL, 2, 1, 0)) {
if (!hookp->error || cv_debug & DBG_LUA)
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
lua_pop(gL, 1);
hookp->error = true;
continue;
}
if (lua_toboolean(gL, -1))
hooked = true;
lua_pop(gL, 1);
}
for (hookp = mobjhooks[mo->type]; hookp; hookp = hookp->next)
if (hookp->type == hook_MapThingSpawn)
{
if (lua_gettop(gL) == 0)
{
LUA_PushUserdata(gL, mo, META_MOBJ);
LUA_PushUserdata(gL, mthing, META_MAPTHING);
}
lua_pushfstring(gL, FMT_HOOKID, hookp->id);
lua_gettable(gL, LUA_REGISTRYINDEX);
lua_pushvalue(gL, -3);
lua_pushvalue(gL, -3);
if (lua_pcall(gL, 2, 1, 0)) {
if (!hookp->error || cv_debug & DBG_LUA)
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1));
lua_pop(gL, 1);
hookp->error = true;
continue;
}
if (lua_toboolean(gL, -1))
hooked = true;
lua_pop(gL, 1);
}
lua_settop(gL, 0);
return hooked;
}
#endif

View File

@ -9729,6 +9729,16 @@ void P_SpawnMapThing(mapthing_t *mthing)
mobj = P_SpawnMobj(x, y, z, i);
mobj->spawnpoint = mthing;
#ifdef HAVE_BLUA
if (LUAh_MapThingSpawn(mobj, mthing))
{
if (P_MobjWasRemoved(mobj))
return;
}
else if (P_MobjWasRemoved(mobj))
return;
else
#endif
switch(mobj->type)
{
case MT_SKYBOX: