Separated the damage hooks into multiple more precise hooks for players.

This commit is contained in:
Latapostrophe 2018-11-27 18:27:43 +01:00
parent ec279da272
commit ed4477705d
8 changed files with 340 additions and 20 deletions

View File

@ -1845,11 +1845,11 @@ void K_SpawnBattlePoints(player_t *source, player_t *victim, UINT8 amount)
void K_SpinPlayer(player_t *player, mobj_t *source, INT32 type, boolean trapitem, mobj_t *inflictor)
{
(void)inflictor; // in case some weirdo doesn't want Lua.
// PS: Inflictor is unused for all purposes here and is actually only ever relevant to Lua. It may be nil too.
#ifdef HAVE_BLUA
boolean force = false; // Used to check if Lua ShouldDamage should get us damaged reguardless of flashtics or heck knows what.
UINT8 shouldForce = LUAh_ShouldDamage(player->mo, inflictor, source, 1);
boolean force = false; // Used to check if Lua ShouldSpin should get us damaged reguardless of flashtics or heck knows what.
UINT8 shouldForce = LUAh_ShouldSpin(player, inflictor, source);
if (P_MobjWasRemoved(player->mo))
return; // mobj was removed (in theory that shouldn't happen)
if (shouldForce == 1)
@ -1884,7 +1884,7 @@ void K_SpinPlayer(player_t *player, mobj_t *source, INT32 type, boolean trapitem
}
}
if (LUAh_MobjDamage(player->mo, inflictor, source, 1))
if (LUAh_PlayerSpin(player, inflictor, source)) // Let Lua do its thing or overwrite if it wants to. Make sure to let any possible instashield happen because we didn't get "damaged" in this case.
return;
if (source && source != player->mo && source->player)
@ -1963,8 +1963,24 @@ void K_SpinPlayer(player_t *player, mobj_t *source, INT32 type, boolean trapitem
return;
}
void K_SquishPlayer(player_t *player, mobj_t *source)
void K_SquishPlayer(player_t *player, mobj_t *source, mobj_t *inflictor)
{
(void)inflictor; // Please stop forgetting to put inflictor in yer functions thank -Lat'
// PS: Inflictor is unused for all purposes here and is actually only ever relevant to Lua. It may be nil too.
#ifdef HAVE_BLUA
boolean force = false; // Used to check if Lua ShouldSquish should get us damaged reguardless of flashtics or heck knows what.
UINT8 shouldForce = LUAh_ShouldSquish(player, inflictor, source);
if (P_MobjWasRemoved(player->mo))
return; // mobj was removed (in theory that shouldn't happen)
if (shouldForce == 1)
force = true;
else if (shouldForce == 2)
return;
#else
static const boolean force = false;
#endif
UINT8 scoremultiply = 1;
if (G_BattleGametype())
{
@ -1981,10 +1997,16 @@ void K_SquishPlayer(player_t *player, mobj_t *source)
|| player->kartstuff[k_growshrinktimer] > 0 || player->kartstuff[k_hyudorotimer] > 0
|| (G_BattleGametype() && ((player->kartstuff[k_bumper] <= 0 && player->kartstuff[k_comebacktimer]) || player->kartstuff[k_comebackmode] == 1)))
{
K_DoInstashield(player);
return;
if (!force) // You know the drill by now.
{
K_DoInstashield(player);
return;
}
}
if (LUAh_PlayerSquish(player, inflictor, source)) // Let Lua do its thing or overwrite if it wants to. Make sure to let any possible instashield happen because we didn't get "damaged" in this case.
return;
player->kartstuff[k_sneakertimer] = 0;
player->kartstuff[k_driftboost] = 0;
@ -2054,8 +2076,8 @@ void K_ExplodePlayer(player_t *player, mobj_t *source, mobj_t *inflictor) // A b
{
#ifdef HAVE_BLUA
boolean force = false; // Used to check if Lua ShouldDamage should get us damaged reguardless of flashtics or heck knows what.
UINT8 shouldForce = LUAh_ShouldDamage(player->mo, inflictor, source, 1);
boolean force = false; // Used to check if Lua ShouldExplode should get us damaged reguardless of flashtics or heck knows what.
UINT8 shouldForce = LUAh_ShouldExplode(player, inflictor, source);
if (P_MobjWasRemoved(player->mo))
return; // mobj was removed (in theory that shouldn't happen)
if (shouldForce == 1)
@ -2089,7 +2111,7 @@ void K_ExplodePlayer(player_t *player, mobj_t *source, mobj_t *inflictor) // A b
}
}
if (LUAh_MobjDamage(player->mo, inflictor, source, 1))
if (LUAh_PlayerExplode(player, inflictor, source)) // Same thing. Also make sure to let Instashield happen blah blah
return;
if (source && source != player->mo && source->player)

View File

@ -29,7 +29,7 @@ void K_KartPlayerAfterThink(player_t *player);
void K_DoInstashield(player_t *player);
void K_SpawnBattlePoints(player_t *source, player_t *victim, UINT8 amount);
void K_SpinPlayer(player_t *player, mobj_t *source, INT32 type, boolean trapitem, mobj_t *inflictor);
void K_SquishPlayer(player_t *player, mobj_t *source);
void K_SquishPlayer(player_t *player, mobj_t *source, mobj_t *inflictor);
void K_ExplodePlayer(player_t *player, mobj_t *source, mobj_t *inflictor);
void K_StealBumper(player_t *player, player_t *victim, boolean force);
void K_SpawnKartExplosion(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 number, mobjtype_t type, angle_t rotangle, boolean spawncenter, boolean ghostit, mobj_t *source);

View File

@ -2207,12 +2207,15 @@ static int lib_kSquishPlayer(lua_State *L)
{
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
mobj_t *source = NULL;
mobj_t *inflictor = NULL;
NOHUD
if (!player)
return LUA_ErrInvalid(L, "player_t");
if (!lua_isnone(L, 2) && lua_isuserdata(L, 2))
source = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
K_SquishPlayer(player, source);
if (!lua_isnone(L, 2) && lua_isuserdata(L, 2))
inflictor = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
K_SquishPlayer(player, source, inflictor);
return 0;
}

View File

@ -44,6 +44,12 @@ enum hook {
hook_HurtMsg,
hook_PlayerSpawn,
hook_PlayerQuit,
hook_ShouldSpin, //SRB2KART
hook_ShouldExplode, //SRB2KART
hook_ShouldSquish, //SRB2KART
hook_PlayerSpin, //SRB2KART
hook_PlayerExplode, //SRB2KART
hook_PlayerSquish, //SRB2KART
hook_MAX // last hook
};
@ -80,4 +86,11 @@ boolean LUAh_HurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source); // Ho
#define LUAh_PlayerSpawn(player) LUAh_PlayerHook(player, hook_PlayerSpawn) // Hook for G_SpawnPlayer
void LUAh_PlayerQuit(player_t *plr, int reason); // Hook for player quitting
UINT8 LUAh_ShouldSpin(player_t *player, mobj_t *inflictor, mobj_t *source); // SRB2KART: Should player be spun out?
UINT8 LUAh_ShouldExplode(player_t *player, mobj_t *inflictor, mobj_t *source); // SRB2KART: Should player be exploded?
UINT8 LUAh_ShouldSquish(player_t *player, mobj_t *inflictor, mobj_t *source); // SRB2KART: Should player be squished?
boolean LUAh_PlayerSpin(player_t *player, mobj_t *inflictor, mobj_t *source); // SRB2KART: Hook for K_SpinPlayer. Allows Lua to execute code and/or overwrite its behavior.
boolean LUAh_PlayerExplode(player_t *player, mobj_t *inflictor, mobj_t *source); // SRB2KART: Hook for K_ExplodePlayer. Allows Lua to execute code and/or overwrite its behavior.
boolean LUAh_PlayerSquish(player_t *player, mobj_t *inflictor, mobj_t *source); // SRB2KART: Hook for K_SquishPlayer. Allows Lua to execute code and/or overwrite its behavior.
#endif

View File

@ -55,6 +55,12 @@ const char *const hookNames[hook_MAX+1] = {
"HurtMsg",
"PlayerSpawn",
"PlayerQuit",
"ShouldSpin",
"ShouldExplode",
"ShouldSquish",
"PlayerSpin",
"PlayerExplode",
"PlayerSquish",
NULL
};
@ -154,6 +160,12 @@ static int lib_addHook(lua_State *L)
*p = 0;
}
break;
case hook_ShouldSpin:
case hook_ShouldExplode:
case hook_ShouldSquish:
case hook_PlayerSpin:
case hook_PlayerExplode:
case hook_PlayerSquish:
default:
break;
}
@ -195,6 +207,12 @@ static int lib_addHook(lua_State *L)
case hook_LinedefExecute:
lastp = &linedefexecutorhooks;
break;
case hook_ShouldSpin:
case hook_ShouldExplode:
case hook_ShouldSquish:
case hook_PlayerSpin:
case hook_PlayerExplode:
case hook_PlayerSquish:
default:
lastp = &roothook;
break;
@ -953,7 +971,7 @@ boolean LUAh_LinedefExecute(line_t *line, mobj_t *mo, sector_t *sector)
}
// Hook for player chat
// Added the "mute" field. It's set to true if the message was supposed to be eaten by spam protection.
// Added the "mute" field. It's set to true if the message was supposed to be eaten by spam protection.
// But for netgame consistency purposes, this hook is ran first reguardless, so this boolean allows for modders to adapt if they so desire.
boolean LUAh_PlayerMsg(int source, int target, int flags, char *msg, int mute)
{
@ -987,7 +1005,7 @@ boolean LUAh_PlayerMsg(int source, int target, int flags, char *msg, int mute)
if (mute)
lua_pushboolean(gL, true); // the message was supposed to be eaten by spamprotecc.
else
lua_pushboolean(gL, false);
lua_pushboolean(gL, false);
}
lua_pushfstring(gL, FMT_HOOKID, hookp->id);
lua_gettable(gL, LUA_REGISTRYINDEX);
@ -1108,4 +1126,268 @@ void LUAh_PlayerQuit(player_t *plr, int reason)
lua_settop(gL, 0);
}
// Hook for K_SpinPlayer. Determines if yes or no we should get damaged reguardless of circumstances.
UINT8 LUAh_ShouldSpin(player_t *player, mobj_t *inflictor, mobj_t *source)
{
hook_p hookp;
UINT8 shouldDamage = 0; // 0 = default, 1 = force yes, 2 = force no.
if (!gL || !(hooksAvailable[hook_ShouldSpin/8] & (1<<(hook_ShouldSpin%8))))
return 0;
lua_settop(gL, 0);
// We can afford not to check for mobj type because it will always be MT_PLAYER in this case.
for (hookp = roothook; hookp; hookp = hookp->next)
if (hookp->type == hook_ShouldSpin)
{
if (lua_gettop(gL) == 0)
{
LUA_PushUserdata(gL, player, META_PLAYER);
LUA_PushUserdata(gL, inflictor, META_MOBJ);
LUA_PushUserdata(gL, source, META_MOBJ);
}
lua_pushfstring(gL, FMT_HOOKID, hookp->id);
lua_gettable(gL, LUA_REGISTRYINDEX);
lua_pushvalue(gL, -4);
lua_pushvalue(gL, -4);
lua_pushvalue(gL, -4);
if (lua_pcall(gL, 3, 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 (lua_toboolean(gL, -1))
shouldDamage = 1; // Force yes
else
shouldDamage = 2; // Force no
}
lua_pop(gL, 1);
}
lua_settop(gL, 0);
return shouldDamage;
}
// Hook for K_ExplodePlayer. Determines if yes or no we should get damaged reguardless of circumstances.
UINT8 LUAh_ShouldExplode(player_t *player, mobj_t *inflictor, mobj_t *source)
{
hook_p hookp;
UINT8 shouldDamage = 0; // 0 = default, 1 = force yes, 2 = force no.
if (!gL || !(hooksAvailable[hook_ShouldExplode/8] & (1<<(hook_ShouldExplode%8))))
return 0;
lua_settop(gL, 0);
// We can afford not to check for mobj type because it will always be MT_PLAYER in this case.
for (hookp = roothook; hookp; hookp = hookp->next)
if (hookp->type == hook_ShouldExplode)
{
if (lua_gettop(gL) == 0)
{
LUA_PushUserdata(gL, player, META_PLAYER);
LUA_PushUserdata(gL, inflictor, META_MOBJ);
LUA_PushUserdata(gL, source, META_MOBJ);
}
lua_pushfstring(gL, FMT_HOOKID, hookp->id);
lua_gettable(gL, LUA_REGISTRYINDEX);
lua_pushvalue(gL, -4);
lua_pushvalue(gL, -4);
lua_pushvalue(gL, -4);
if (lua_pcall(gL, 3, 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 (lua_toboolean(gL, -1))
shouldDamage = 1; // Force yes
else
shouldDamage = 2; // Force no
}
lua_pop(gL, 1);
}
lua_settop(gL, 0);
return shouldDamage;
}
// Hook for K_SquishPlayer. Determines if yes or no we should get damaged reguardless of circumstances.
UINT8 LUAh_ShouldSquish(player_t *player, mobj_t *inflictor, mobj_t *source)
{
hook_p hookp;
UINT8 shouldDamage = 0; // 0 = default, 1 = force yes, 2 = force no.
if (!gL || !(hooksAvailable[hook_ShouldSquish/8] & (1<<(hook_ShouldSquish%8))))
return 0;
lua_settop(gL, 0);
// We can afford not to check for mobj type because it will always be MT_PLAYER in this case.
for (hookp = roothook; hookp; hookp = hookp->next)
if (hookp->type == hook_ShouldSquish)
{
if (lua_gettop(gL) == 0)
{
LUA_PushUserdata(gL, player, META_PLAYER);
LUA_PushUserdata(gL, inflictor, META_MOBJ);
LUA_PushUserdata(gL, source, META_MOBJ);
}
lua_pushfstring(gL, FMT_HOOKID, hookp->id);
lua_gettable(gL, LUA_REGISTRYINDEX);
lua_pushvalue(gL, -4);
lua_pushvalue(gL, -4);
lua_pushvalue(gL, -4);
if (lua_pcall(gL, 3, 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 (lua_toboolean(gL, -1))
shouldDamage = 1; // Force yes
else
shouldDamage = 2; // Force no
}
lua_pop(gL, 1);
}
lua_settop(gL, 0);
return shouldDamage;
}
// Hook for K_SpinPlayer. This is used when the player has actually been spun out, but before anything has actually been done. This allows Lua to overwrite the behavior or to just perform actions.
boolean LUAh_PlayerSpin(player_t *player, mobj_t *inflictor, mobj_t *source)
{
hook_p hookp;
boolean hooked = false;
if (!gL || !(hooksAvailable[hook_PlayerSpin/8] & (1<<(hook_PlayerSpin%8))))
return 0;
lua_settop(gL, 0);
// We can afford not to look for target->type because it will always be MT_PLAYER.
for (hookp = roothook; hookp; hookp = hookp->next)
if (hookp->type == hook_PlayerSpin)
{
if (lua_gettop(gL) == 0)
{
LUA_PushUserdata(gL, player, META_PLAYER);
LUA_PushUserdata(gL, inflictor, META_MOBJ);
LUA_PushUserdata(gL, source, META_MOBJ);
}
lua_pushfstring(gL, FMT_HOOKID, hookp->id);
lua_gettable(gL, LUA_REGISTRYINDEX);
lua_pushvalue(gL, -4);
lua_pushvalue(gL, -4);
lua_pushvalue(gL, -4);
if (lua_pcall(gL, 3, 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;
}
// Hook for K_SquishPlayer. This is used when the player has actually been spun out, but before anything has actually been done. This allows Lua to overwrite the behavior or to just perform actions.
boolean LUAh_PlayerSquish(player_t *player, mobj_t *inflictor, mobj_t *source)
{
hook_p hookp;
boolean hooked = false;
if (!gL || !(hooksAvailable[hook_PlayerSquish/8] & (1<<(hook_PlayerSquish%8))))
return 0;
lua_settop(gL, 0);
// We can afford not to look for target->type because it will always be MT_PLAYER.
for (hookp = roothook; hookp; hookp = hookp->next)
if (hookp->type == hook_PlayerSquish)
{
if (lua_gettop(gL) == 0)
{
LUA_PushUserdata(gL, player, META_PLAYER);
LUA_PushUserdata(gL, inflictor, META_MOBJ);
LUA_PushUserdata(gL, source, META_MOBJ);
}
lua_pushfstring(gL, FMT_HOOKID, hookp->id);
lua_gettable(gL, LUA_REGISTRYINDEX);
lua_pushvalue(gL, -4);
lua_pushvalue(gL, -4);
lua_pushvalue(gL, -4);
if (lua_pcall(gL, 3, 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;
}
// Hook for K_ExplodePlayer. This is used when the player has actually been spun out, but before anything has actually been done. This allows Lua to overwrite the behavior or to just perform actions.
boolean LUAh_PlayerExplode(player_t *player, mobj_t *inflictor, mobj_t *source)
{
hook_p hookp;
boolean hooked = false;
if (!gL || !(hooksAvailable[hook_PlayerExplode/8] & (1<<(hook_PlayerExplode%8))))
return 0;
lua_settop(gL, 0);
// We can afford not to look for target->type because it will always be MT_PLAYER.
for (hookp = roothook; hookp; hookp = hookp->next)
if (hookp->type == hook_PlayerExplode)
{
if (lua_gettop(gL) == 0)
{
LUA_PushUserdata(gL, player, META_PLAYER);
LUA_PushUserdata(gL, inflictor, META_MOBJ);
LUA_PushUserdata(gL, source, META_MOBJ);
}
lua_pushfstring(gL, FMT_HOOKID, hookp->id);
lua_gettable(gL, LUA_REGISTRYINDEX);
lua_pushvalue(gL, -4);
lua_pushvalue(gL, -4);
lua_pushvalue(gL, -4);
if (lua_pcall(gL, 3, 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

@ -590,7 +590,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
P_RemoveMobj(special);
}
else
K_SpinPlayer(player, special, 0, false, NULL);
K_SpinPlayer(player, NULL, 0, false, special);
return;
/*case MT_EERIEFOG:
special->frame &= ~FF_TRANS80;

View File

@ -1425,9 +1425,9 @@ static boolean PIT_CheckThing(mobj_t *thing)
{
if (tmthing->scale > thing->scale + (mapheaderinfo[gamemap-1]->mobj_scale/8)) // SRB2kart - Handle squishes first!
K_SquishPlayer(thing->player, tmthing);
K_SquishPlayer(thing->player, tmthing, tmthing);
else if (thing->scale > tmthing->scale + (mapheaderinfo[gamemap-1]->mobj_scale/8))
K_SquishPlayer(tmthing->player, thing);
K_SquishPlayer(tmthing->player, thing, tmthing);
else if (tmthing->player->kartstuff[k_invincibilitytimer] && !thing->player->kartstuff[k_invincibilitytimer]) // SRB2kart - Then invincibility!
P_DamageMobj(thing, tmthing, tmthing, 1);
else if (thing->player->kartstuff[k_invincibilitytimer] && !tmthing->player->kartstuff[k_invincibilitytimer])
@ -1664,7 +1664,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
// collide
if (tmthing->z < thing->z && thing->momz < 0)
K_SquishPlayer(tmthing->player, thing);
K_SquishPlayer(tmthing->player, thing, thing);
else
{
if (thing->flags2 & MF2_AMBUSH)
@ -4262,7 +4262,7 @@ static boolean PIT_ChangeSector(mobj_t *thing, boolean realcrush)
if (!thing->player)
P_DamageMobj(thing, killer, killer, 10000);
else
K_SquishPlayer(thing->player, killer); // SRB2kart - Squish instead of kill
K_SquishPlayer(thing->player, killer, killer); // SRB2kart - Squish instead of kill
}
}
}

View File

@ -7242,7 +7242,7 @@ static void P_MovePlayer(player_t *player)
P_DamageMobj(player->mo, NULL, NULL, 42000); // Respawn crushed spectators
else
{
K_SquishPlayer(player, NULL); // SRB2kart - we don't kill when squished, we squish when squished.
K_SquishPlayer(player, NULL, NULL); // SRB2kart - we don't kill when squished, we squish when squished.
/*
mobj_t *killer = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_NULL);
killer->threshold = 44; // Special flag that it was crushing which killed you.