"PlayerCanDamage" hook!

* Takes function(player, mo) input.
* Return TRUE for stating that yes, the player is in a state that can cause contact damage, do with that what you will.
* Return FALSE for stating that no, the player is weak and vulnerable and cannot cause contact damage, do with that what you will.
* Return NIL for allowing the function to continue regular operation.

Fills a different ideological niche than ShouldDamage - that's for determining whether damage dished between two objects should happen, this is for determining which way around damage should be dished when considering a player-object interaction.

Or, in other words, think of it as "ShouldDamage is whether damage that has been requested should be granted, for object-object interaction, while PlayerCanDamage is for whether global player properties should cause damage to enemies and monitors in the first place, like spinning, hammering or stomping."
This commit is contained in:
toaster 2019-06-19 12:55:05 +01:00
parent 28dfeb344b
commit 3eb9b85fd4
4 changed files with 63 additions and 2 deletions

View File

@ -956,7 +956,7 @@ static int lib_pPlayerCanDamage(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
mobj_t *thing = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
//HUDSAFE
NOHUD // was hud safe but then i added a lua hook
INLEVEL
if (!player)
return LUA_ErrInvalid(L, "player_t");

View File

@ -48,6 +48,7 @@ enum hook {
hook_MobjMoveBlocked,
hook_MapThingSpawn,
hook_FollowMobj,
hook_PlayerCanDamage,
hook_PlayerQuit,
hook_MAX // last hook
@ -87,7 +88,8 @@ boolean LUAh_HurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source, UINT8
#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
boolean LUAh_FollowMobj(player_t *player, mobj_t *mo); // Hook for P_PlayerAfterThink Smiles mobj-following
boolean LUAh_FollowMobj(player_t *player, mobj_t *mobj); // Hook for P_PlayerAfterThink Smiles mobj-following
UINT8 LUAh_PlayerCanDamage(player_t *player, mobj_t *mobj); // Hook for P_PlayerCanDamage
void LUAh_PlayerQuit(player_t *plr, int reason); // Hook for player quitting
#endif

View File

@ -59,6 +59,7 @@ const char *const hookNames[hook_MAX+1] = {
"MobjMoveBlocked",
"MapThingSpawn",
"FollowMobj",
"PlayerCanDamage",
"PlayerQuit",
NULL
};
@ -200,6 +201,7 @@ static int lib_addHook(lua_State *L)
case hook_JumpSpinSpecial:
case hook_PlayerSpawn:
case hook_FollowMobj:
case hook_PlayerCanDamage:
case hook_ShieldSpawn:
case hook_ShieldSpecial:
lastp = &playerhooks;
@ -1247,6 +1249,51 @@ boolean LUAh_FollowMobj(player_t *player, mobj_t *mobj)
return hooked;
}
// Hook for P_PlayerCanDamage
UINT8 LUAh_PlayerCanDamage(player_t *player, mobj_t *mobj)
{
hook_p hookp;
UINT8 shouldCollide = 0; // 0 = default, 1 = force yes, 2 = force no.
if (!gL || !(hooksAvailable[hook_PlayerCanDamage/8] & (1<<(hook_PlayerCanDamage%8))))
return 0;
lua_settop(gL, 0);
for (hookp = playerhooks; hookp; hookp = hookp->next)
{
if (hookp->type != hook_PlayerCanDamage)
continue;
if (lua_gettop(gL) == 0)
{
LUA_PushUserdata(gL, player, META_PLAYER);
LUA_PushUserdata(gL, mobj, META_MOBJ);
}
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_isnil(gL, -1))
{ // if nil, leave shouldCollide = 0.
if (lua_toboolean(gL, -1))
shouldCollide = 1; // Force yes
else
shouldCollide = 2; // Force no
}
lua_pop(gL, 1);
}
lua_settop(gL, 0);
return shouldCollide;
}
void LUAh_PlayerQuit(player_t *plr, int reason)
{
hook_p hookp;

View File

@ -987,6 +987,18 @@ boolean P_PlayerCanDamage(player_t *player, mobj_t *thing)
if (!player->mo || player->spectator || !thing || P_MobjWasRemoved(thing))
return false;
#ifdef HAVE_BLUA
{
UINT8 shouldCollide = LUAh_PlayerCanDamage(player, thing);
if (P_MobjWasRemoved(thing))
return false; // removed???
if (shouldCollide == 1)
return true; // force yes
else if (shouldCollide == 2)
return false; // force no
}
#endif
if ((player->powers[pw_carry] == CR_NIGHTSMODE) && (player->pflags & PF_DRILLING))
return true;