From b73bbd3712cdda0b89190c4d73e3db20d6beef90 Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 19 Dec 2022 15:25:15 -0800 Subject: [PATCH 1/4] Add invulnhitlag, timeshit and timeshitprev fields to player_t --- src/d_player.h | 8 +++++++- src/lua_playerlib.c | 12 ++++++++++++ src/p_saveg.c | 8 ++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/d_player.h b/src/d_player.h index af6e75517..265bd13cb 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -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 diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 3bc7e1584..7195c90f0 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -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")) diff --git a/src/p_saveg.c b/src/p_saveg.c index f36d94319..b7d3802ff 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -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); From ba2a7744d170cfb3257d0f4c4a208921ae996ff3 Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 16 Dec 2022 23:49:05 -0800 Subject: [PATCH 2/4] Add half hitlag to invincible players if they would've been damaged --- src/k_collide.c | 1 + src/k_kart.c | 26 ++++++++++++++++++++++++++ src/p_inter.c | 21 ++++++++++++++++++++- src/p_mobj.c | 3 ++- src/p_mobj.h | 3 ++- src/p_user.c | 6 ++++++ 6 files changed, 57 insertions(+), 3 deletions(-) diff --git a/src/k_collide.c b/src/k_collide.c index 8ac2f68bf..f85b3a236 100644 --- a/src/k_collide.c +++ b/src/k_collide.c @@ -403,6 +403,7 @@ boolean K_LandMineCollide(mobj_t *t1, mobj_t *t2) { // Melt item S_StartSound(t2, sfx_s3k43); + K_SetHitLagForObjects(t2, t1, 3, false); } else { diff --git a/src/k_kart.c b/src/k_kart.c index 429c70762..968147a06 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -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; + } } /*-------------------------------------------------- diff --git a/src/p_inter.c b/src/p_inter.c index 7909c3116..609a77610 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -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; @@ -2092,6 +2104,13 @@ 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) { + const INT32 oldhitlag = target->hitlag; + + laglength = max(laglength / 2, 1); + K_SetHitLagForObjects(target, inflictor, laglength, false); + + player->invulnhitlag += (target->hitlag - oldhitlag); + // Full invulnerability K_DoInstashield(player); return false; diff --git a/src/p_mobj.c b/src/p_mobj.c index b2c4cdb3b..f0bc4927b 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -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); diff --git a/src/p_mobj.h b/src/p_mobj.h index 0f163236b..8e2686900 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -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; // diff --git a/src/p_user.c b/src/p_user.c index 57f4b2af9..ac96ea345 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -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)) { From 9ddf10c9a59affbd5464954cf27ff4e999be3614 Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 16 Dec 2022 23:49:59 -0800 Subject: [PATCH 3/4] Broly: detect added hitlag even if damage call didn't deal real damage --- src/k_collide.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/k_collide.c b/src/k_collide.c index f85b3a236..06d6900e6 100644 --- a/src/k_collide.c +++ b/src/k_collide.c @@ -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; @@ -411,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 From d496e0f298d2ca60927b35a083adf2aadee68eaa Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 19 Dec 2022 15:42:44 -0800 Subject: [PATCH 4/4] Add Tyron's invinc/grow blocked hit sfx --- src/p_inter.c | 25 ++++++++++++++++++++++++- src/sounds.c | 4 ++++ src/sounds.h | 4 ++++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/p_inter.c b/src/p_inter.c index 609a77610..09f098e4b 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2083,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) @@ -2102,7 +2105,22 @@ 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; @@ -2111,6 +2129,11 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da player->invulnhitlag += (target->hitlag - oldhitlag); + if (player->timeshit > player->timeshitprev) + { + S_StartSound(target, sfx); + } + // Full invulnerability K_DoInstashield(player); return false; diff --git a/src/sounds.c b/src/sounds.c index 016cf5029..b18670667 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -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, ""}, diff --git a/src/sounds.h b/src/sounds.h index 01dfbfc2b..51aecb94a 100644 --- a/src/sounds.h +++ b/src/sounds.h @@ -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,