Merge branch 'neutral-explosion-hitlag' into 'master'

Add half hitlag to invulnerable players if they would normally take damage

Closes #364

See merge request KartKrew/Kart!814
This commit is contained in:
Sal 2022-12-22 08:37:47 +00:00
commit 1662414e0e
11 changed files with 129 additions and 9 deletions

View file

@ -466,6 +466,7 @@ struct player_t
UINT16 spinouttimer; // Spin-out from a banana peel or oil slick (was "pw_bananacam")
UINT8 spinouttype; // Determines the mode of spinout/wipeout, see kartspinoutflags_t
UINT8 instashield; // Instashield no-damage animation timer
INT32 invulnhitlag; // Numbers of tics of hitlag added this tic for "potential" damage -- not real damage
UINT8 wipeoutslow; // Timer before you slowdown when getting wiped out
UINT8 justbumped; // Prevent players from endlessly bumping into each other
UINT8 tumbleBounces;
@ -615,7 +616,12 @@ struct player_t
INT16 lastsidehit, lastlinehit;
//UINT8 timeshit; // That's TIMES HIT, not TIME SHIT, you doofus! -- in memoriam
// These track how many things tried to damage you, not
// whether you actually took damage.
UINT8 timeshit; // times hit this tic
UINT8 timeshitprev; // times hit before
// That's TIMES HIT, not TIME SHIT, you doofus! -- in memoriam
// No longer in memoriam =P -jart
INT32 onconveyor; // You are on a conveyor belt if nonzero

View file

@ -204,7 +204,7 @@ boolean K_EggItemCollide(mobj_t *t1, mobj_t *t2)
static mobj_t *grenade;
static fixed_t explodedist;
static boolean explodespin;
static tic_t minehitlag;
static INT32 minehitlag;
static inline boolean PIT_SSMineChecks(mobj_t *thing)
{
@ -272,6 +272,9 @@ void K_DoMineSearch(mobj_t *actor, fixed_t size)
static inline BlockItReturn_t PIT_SSMineExplode(mobj_t *thing)
{
const INT32 oldhitlag = thing->hitlag;
INT32 lagadded;
if (grenade == NULL || P_MobjWasRemoved(grenade))
return BMIT_ABORT; // There's the possibility these can chain react onto themselves after they've already died if there are enough all in one spot
@ -283,9 +286,13 @@ static inline BlockItReturn_t PIT_SSMineExplode(mobj_t *thing)
if (PIT_SSMineChecks(thing) == true)
return BMIT_CONTINUE;
if (P_DamageMobj(thing, grenade, grenade->target, 1, (explodespin ? DMG_NORMAL : DMG_EXPLODE)))
P_DamageMobj(thing, grenade, grenade->target, 1, (explodespin ? DMG_NORMAL : DMG_EXPLODE));
lagadded = (thing->hitlag - oldhitlag);
if (lagadded > 0)
{
minehitlag = thing->hitlag;
minehitlag = lagadded;
}
return BMIT_CONTINUE;
@ -392,6 +399,8 @@ boolean K_LandMineCollide(mobj_t *t1, mobj_t *t2)
if (t2->player)
{
const INT32 oldhitlag = t2->hitlag;
if (t2->player->flashing)
return true;
@ -403,6 +412,7 @@ boolean K_LandMineCollide(mobj_t *t1, mobj_t *t2)
{
// Melt item
S_StartSound(t2, sfx_s3k43);
K_SetHitLagForObjects(t2, t1, 3, false);
}
else
{
@ -410,7 +420,7 @@ boolean K_LandMineCollide(mobj_t *t1, mobj_t *t2)
P_DamageMobj(t2, t1, t1->target, 1, DMG_TUMBLE);
}
t1->reactiontime = t2->hitlag;
t1->reactiontime = (t2->hitlag - oldhitlag);
P_KillMobj(t1, t2, t2, DMG_NORMAL);
}
else if (t2->type == MT_BANANA || t2->type == MT_BANANA_SHIELD

View file

@ -7983,6 +7983,32 @@ void K_KartPlayerAfterThink(player_t *player)
{
K_LookForRings(player->mo);
}
if (player->invulnhitlag > 0)
{
// Hitlag from what would normally be damage but the
// player was invulnerable.
//
// If we're constantly getting hit the same number of
// times, we're probably standing on a damage floor.
//
// Checking if we're hit more than before ensures
// that:
//
// 1) repeating damage doesn't count
// 2) new damage sources still count
if (player->timeshit <= player->timeshitprev)
{
if (!P_MobjWasRemoved(player->mo))
{
player->mo->hitlag -= player->invulnhitlag;
player->mo->eflags &= ~(MFE_DAMAGEHITLAG);
}
}
player->invulnhitlag = 0;
}
}
/*--------------------------------------------------

View file

@ -232,6 +232,8 @@ static int player_get(lua_State *L)
lua_pushinteger(L, plr->spinouttimer);
else if (fastcmp(field,"instashield"))
lua_pushinteger(L, plr->instashield);
else if (fastcmp(field,"invulnhitlag"))
lua_pushinteger(L, plr->invulnhitlag);
else if (fastcmp(field,"wipeoutslow"))
lua_pushinteger(L, plr->wipeoutslow);
else if (fastcmp(field,"justbumped"))
@ -472,6 +474,10 @@ static int player_get(lua_State *L)
lua_pushinteger(L, plr->lastsidehit);
else if (fastcmp(field,"lastlinehit"))
lua_pushinteger(L, plr->lastlinehit);
else if (fastcmp(field,"timeshit"))
lua_pushinteger(L, plr->timeshit);
else if (fastcmp(field,"timeshitprev"))
lua_pushinteger(L, plr->timeshitprev);
else if (fastcmp(field,"onconveyor"))
lua_pushinteger(L, plr->onconveyor);
else if (fastcmp(field,"awayviewmobj"))
@ -604,6 +610,8 @@ static int player_set(lua_State *L)
plr->spinouttimer = luaL_checkinteger(L, 3);
else if (fastcmp(field,"instashield"))
plr->instashield = luaL_checkinteger(L, 3);
else if (fastcmp(field,"invulnhitlag"))
plr->invulnhitlag = luaL_checkinteger(L, 3);
else if (fastcmp(field,"wipeoutslow"))
plr->wipeoutslow = luaL_checkinteger(L, 3);
else if (fastcmp(field,"justbumped"))
@ -830,6 +838,10 @@ static int player_set(lua_State *L)
plr->lastsidehit = (INT16)luaL_checkinteger(L, 3);
else if (fastcmp(field,"lastlinehit"))
plr->lastlinehit = (INT16)luaL_checkinteger(L, 3);
else if (fastcmp(field,"timeshit"))
plr->timeshit = (UINT8)luaL_checkinteger(L, 3);
else if (fastcmp(field,"timeshitprev"))
plr->timeshitprev = (UINT8)luaL_checkinteger(L, 3);
else if (fastcmp(field,"onconveyor"))
plr->onconveyor = (INT32)luaL_checkinteger(L, 3);
else if (fastcmp(field,"awayviewmobj"))

View file

@ -2015,7 +2015,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
if (!(target->flags & MF_SHOOTABLE))
return false; // shouldn't happen...
if (!(damagetype & DMG_DEATHMASK) && target->hitlag > 0 && inflictor == NULL)
if (!(damagetype & DMG_DEATHMASK) && (target->eflags & MFE_PAUSED))
return false;
}
@ -2038,6 +2038,18 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
if (player) // Player is the target
{
{
const INT32 oldtimeshit = player->timeshit;
player->timeshit++;
// overflow prevention
if (player->timeshit < oldtimeshit)
{
player->timeshit = oldtimeshit;
}
}
if (player->pflags & PF_GODMODE)
return false;
@ -2071,6 +2083,9 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
// If not, then spawn the instashield effect instead.
if (!force)
{
boolean invincible = true;
sfxenum_t sfx = sfx_None;
if (gametyperules & GTR_BUMPERS)
{
if (player->bumpers <= 0 && player->karmadelay)
@ -2090,8 +2105,35 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
}
}
if (player->invincibilitytimer > 0 || K_IsBigger(target, inflictor) == true || player->hyudorotimer > 0)
if (player->invincibilitytimer > 0)
{
sfx= sfx_invind;
}
else if (K_IsBigger(target, inflictor) == true)
{
sfx = sfx_grownd;
}
else if (player->hyudorotimer > 0)
;
else
{
invincible = false;
}
if (invincible)
{
const INT32 oldhitlag = target->hitlag;
laglength = max(laglength / 2, 1);
K_SetHitLagForObjects(target, inflictor, laglength, false);
player->invulnhitlag += (target->hitlag - oldhitlag);
if (player->timeshit > player->timeshitprev)
{
S_StartSound(target, sfx);
}
// Full invulnerability
K_DoInstashield(player);
return false;

View file

@ -9665,6 +9665,7 @@ void P_MobjThinker(mobj_t *mobj)
// Don't run any thinker code while in hitlag
if (mobj->hitlag > 0)
{
mobj->eflags |= MFE_PAUSED;
mobj->hitlag--;
if (mobj->type == MT_DROPTARGET && mobj->reactiontime > 0 && mobj->hitlag == 2)
@ -9684,7 +9685,7 @@ void P_MobjThinker(mobj_t *mobj)
return;
}
mobj->eflags &= ~(MFE_PUSHED|MFE_SPRUNG|MFE_JUSTBOUNCEDWALL|MFE_DAMAGEHITLAG|MFE_SLOPELAUNCHED);
mobj->eflags &= ~(MFE_PUSHED|MFE_SPRUNG|MFE_JUSTBOUNCEDWALL|MFE_DAMAGEHITLAG|MFE_SLOPELAUNCHED|MFE_PAUSED);
// sal: what the hell? is there any reason this isn't done, like, literally ANYWHERE else?
P_SetTarget(&tm.floorthing, NULL);

View file

@ -255,7 +255,8 @@ typedef enum
MFE_DAMAGEHITLAG = 1<<13,
// Slope physics sent you airborne
MFE_SLOPELAUNCHED = 1<<14,
// free: to and including 1<<15
// Thinker is paused due to hitlag
MFE_PAUSED = 1<<15,
} mobjeflag_t;
//

View file

@ -190,6 +190,9 @@ static void P_NetArchivePlayers(void)
WRITEINT32(save_p, players[i].onconveyor);
WRITEUINT8(save_p, players[i].timeshit);
WRITEUINT8(save_p, players[i].timeshitprev);
WRITEUINT32(save_p, players[i].jointime);
WRITEUINT8(save_p, players[i].splitscreenindex);
@ -266,6 +269,7 @@ static void P_NetArchivePlayers(void)
WRITEUINT16(save_p, players[i].spinouttimer);
WRITEUINT8(save_p, players[i].spinouttype);
WRITEUINT8(save_p, players[i].instashield);
WRITEINT32(save_p, players[i].invulnhitlag);
WRITEUINT8(save_p, players[i].wipeoutslow);
WRITEUINT8(save_p, players[i].justbumped);
WRITEUINT8(save_p, players[i].tumbleBounces);
@ -557,6 +561,9 @@ static void P_NetUnArchivePlayers(void)
players[i].lastsidehit = READINT16(save_p);
players[i].lastlinehit = READINT16(save_p);
players[i].timeshit = READUINT8(save_p);
players[i].timeshitprev = READUINT8(save_p);
players[i].onconveyor = READINT32(save_p);
players[i].jointime = READUINT32(save_p);
@ -615,6 +622,7 @@ static void P_NetUnArchivePlayers(void)
players[i].spinouttimer = READUINT16(save_p);
players[i].spinouttype = READUINT8(save_p);
players[i].instashield = READUINT8(save_p);
players[i].invulnhitlag = READINT32(save_p);
players[i].wipeoutslow = READUINT8(save_p);
players[i].justbumped = READUINT8(save_p);
players[i].tumbleBounces = READUINT8(save_p);

View file

@ -4341,6 +4341,12 @@ void P_PlayerAfterThink(player_t *player)
// so a lag value of 1 is exactly attached to the player.
K_HandleFollower(player);
if (P_MobjWasRemoved(player->mo) || (player->mo->eflags & MFE_PAUSED) == 0)
{
player->timeshitprev = player->timeshit;
player->timeshit = 0;
}
if (K_PlayerUsesBotMovement(player))
{

View file

@ -1148,6 +1148,10 @@ sfxinfo_t S_sfx[NUMSFX] =
{"pass15", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"pass16", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
// SRB2Kart - Blocked damage
{"grownd", false, 64, 16, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // SF_X8AWAYSOUND
{"invind", false, 64, 16, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // SF_X8AWAYSOUND
// SRB2Kart - Engine sounds
// Engine class A
{"krta00", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""},

View file

@ -1212,6 +1212,10 @@ typedef enum
sfx_pass15,
sfx_pass16,
// Blocked damage SFX
sfx_grownd,
sfx_invind,
// Next up: UNIQUE ENGINE SOUNDS! Hoooooo boy...
// Engine class A - Low Speed, Low Weight
sfx_krta00,