From 8e20ca4c042755c39b51e9cba94068996bb19944 Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 28 Nov 2021 02:57:45 -0800 Subject: [PATCH] TRIPWIRE Set a sidedef's midtexture to "TRIPWIRE" to turn that line into a tripwire. Players can't drive through a tripwire and will bounce back at high speed if they're in one of the following states: 1. Invincibility / Grow 2. Sneakers 3. Flame Shield dash 4. >200% on the speedometer Hitting a tripwire plays a sound, sends you into hitlag, then plays another sound when the hitlag is over. The sounds used depend on whether you can drive through the tripwire. --- src/d_player.h | 9 +++++++++ src/g_game.c | 1 + src/k_kart.c | 34 ++++++++++++++++++++++++++++++++++ src/k_kart.h | 2 ++ src/p_local.h | 1 + src/p_map.c | 37 ++++++++++++++++++++++++++++++++----- src/p_maputl.c | 3 ++- src/p_saveg.c | 2 ++ src/p_spec.c | 7 +++++++ 9 files changed, 90 insertions(+), 6 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index 3d9ac11dc..be16320cd 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -198,6 +198,13 @@ typedef enum #undef KSPIN_TYPE } kartspinoutflags_t; +typedef enum +{ + TRIP_NONE, + TRIP_PASSED, + TRIP_BLOCKED, +} tripwirestate_t; + typedef enum { // Unsynced, HUD or clientsided effects @@ -470,6 +477,8 @@ typedef struct player_s SINT8 glanceDir; // Direction the player is trying to look backwards in + UINT8 tripWireState; // see tripwirestate_t + // SINT8 lives; diff --git a/src/g_game.c b/src/g_game.c index c675e9a22..e964fb65d 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2287,6 +2287,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) p->karthud[khud_fault] = khudfault; p->nocontrol = nocontrol; p->kickstartaccel = kickstartaccel; + p->tripWireState = TRIP_NONE; memcpy(&p->respawn, &respawn, sizeof (p->respawn)); diff --git a/src/k_kart.c b/src/k_kart.c index 4ab844c2d..7ee285fed 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2673,6 +2673,19 @@ boolean K_SlopeResistance(player_t *player) return false; } +boolean K_TripwirePass(player_t *player) +{ + if ( + player->invincibilitytimer || + player->sneakertimer || + player->growshrinktimer > 0 || + player->flamedash || + player->speed > 2 * K_GetKartSpeed(player, false) + ) + return true; + return false; +} + static fixed_t K_FlameShieldDashVar(INT32 val) { // 1 second = 75% + 50% top speed @@ -3300,6 +3313,17 @@ static void K_HandleTumbleSound(player_t *player) } } +void K_ApplyTripWire(player_t *player, tripwirestate_t state) +{ + if (state == TRIP_PASSED) + S_StartSound(player->mo, sfx_ssa015); + else if (state == TRIP_BLOCKED) + S_StartSound(player->mo, sfx_kc40); + + player->tripWireState = state; + K_AddHitLag(player->mo, 10, false); +} + INT32 K_ExplodePlayer(player_t *player, mobj_t *inflictor, mobj_t *source) // A bit of a hack, we just throw the player up higher here and extend their spinout timer { INT32 ringburst = 10; @@ -6983,6 +7007,16 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) // Handle invincibility sfx K_UpdateInvincibilitySounds(player); // Also thanks, VAda! + + if (player->tripWireState != TRIP_NONE) + { + if (player->tripWireState == TRIP_PASSED) + S_StartSound(player->mo, sfx_cdfm63); + else if (player->tripWireState == TRIP_BLOCKED) + S_StartSound(player->mo, sfx_kc4c); + + player->tripWireState = TRIP_NONE; + } } void K_KartPlayerAfterThink(player_t *player) diff --git a/src/k_kart.h b/src/k_kart.h index 540e6845c..b8e74539b 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -105,6 +105,8 @@ void K_StripOther(player_t *player); void K_MomentumToFacing(player_t *player); boolean K_ApplyOffroad(player_t *player); boolean K_SlopeResistance(player_t *player); +boolean K_TripwirePass(player_t *player); +void K_ApplyTripWire(player_t *player, tripwirestate_t state); INT16 K_GetSpindashChargeTime(player_t *player); fixed_t K_GetSpindashChargeSpeed(player_t *player); fixed_t K_GetKartSpeedFromStat(UINT8 kartspeed); diff --git a/src/p_local.h b/src/p_local.h index 9c282499f..f97f31810 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -398,6 +398,7 @@ void P_SetThingPosition(mobj_t *thing); void P_SetUnderlayPosition(mobj_t *thing); boolean P_IsLineBlocking(const line_t *ld, const mobj_t *thing); +boolean P_IsLineTripWire(const line_t *ld); boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y); boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam); boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff); diff --git a/src/p_map.c b/src/p_map.c index acb47ab63..631f41ac9 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -1552,6 +1552,12 @@ boolean P_IsLineBlocking(const line_t *ld, const mobj_t *thing) } } +boolean P_IsLineTripWire(const line_t *ld) +{ + return (sides[ld->sidenum[0]].midtexture == + R_TextureNumForName("TRIPWIRE")); +} + // // PIT_CheckLine // Adjusts tmfloorz and tmceilingz as lines are contacted @@ -1666,7 +1672,8 @@ static boolean PIT_CheckLine(line_t *ld) tmdropoffz = lowfloor; // we've crossed the line - if (P_SpecialIsLinedefCrossType(ld->special)) + if (P_SpecialIsLinedefCrossType(ld->special) || + P_IsLineTripWire(ld)) { add_spechit(ld); } @@ -3022,6 +3029,7 @@ static void P_PlayerHitBounceLine(line_t *ld) INT32 side; angle_t lineangle; fixed_t movelen; + fixed_t x, y; side = P_PointOnLineSide(slidemo->x, slidemo->y, ld); lineangle = R_PointToAngle2(0, 0, ld->dx, ld->dy)-ANGLE_90; @@ -3036,8 +3044,19 @@ static void P_PlayerHitBounceLine(line_t *ld) if (slidemo->player && movelen < (15*mapobjectscale)) movelen = (15*mapobjectscale); - tmxmove += FixedMul(movelen, FINECOSINE(lineangle)); - tmymove += FixedMul(movelen, FINESINE(lineangle)); + x = FixedMul(movelen, FINECOSINE(lineangle)); + y = FixedMul(movelen, FINESINE(lineangle)); + + if (P_IsLineTripWire(ld)) + { + tmxmove = x * 4; + tmymove = y * 4; + } + else + { + tmxmove += x; + tmymove += y; + } } // @@ -3675,6 +3694,11 @@ void P_BouncePlayerMove(mobj_t *mo) tmymove = FixedMul(mmomy, (FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3))); } + if (P_IsLineTripWire(bestslideline)) + { + K_ApplyTripWire(mo->player, TRIP_BLOCKED); + } + else { mobj_t *fx = P_SpawnMobj(mo->x, mo->y, mo->z, MT_BUMP); if (mo->eflags & MFE_VERTICALFLIP) @@ -3694,8 +3718,11 @@ void P_BouncePlayerMove(mobj_t *mo) mo->player->cmomx = tmxmove; mo->player->cmomy = tmymove; - if (!P_TryMove(mo, mo->x + tmxmove, mo->y + tmymove, true)) { - P_TryMove(mo, mo->x - oldmomx, mo->y - oldmomy, true); + if (!P_IsLineTripWire(bestslideline)) + { + if (!P_TryMove(mo, mo->x + tmxmove, mo->y + tmymove, true)) { + P_TryMove(mo, mo->x - oldmomx, mo->y - oldmomy, true); + } } } diff --git a/src/p_maputl.c b/src/p_maputl.c index 5cf2e81fe..2e21f5ee3 100644 --- a/src/p_maputl.c +++ b/src/p_maputl.c @@ -15,6 +15,7 @@ #include "doomdef.h" #include "doomstat.h" +#include "k_kart.h" #include "p_local.h" #include "r_main.h" #include "r_data.h" @@ -588,7 +589,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) if (mobj) { // Check for collision with front side's midtexture if Effect 4 is set - if (linedef->flags & ML_EFFECT4 + if ((linedef->flags & ML_EFFECT4 || (mobj->player && P_IsLineTripWire(linedef) && !K_TripwirePass(mobj->player))) && !linedef->polyobj // don't do anything for polyobjects! ...for now ) { side_t *side = &sides[linedef->sidenum[0]]; diff --git a/src/p_saveg.c b/src/p_saveg.c index c13220afb..ce1093061 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -318,6 +318,7 @@ static void P_NetArchivePlayers(void) WRITEINT16(save_p, players[i].spheres); WRITESINT8(save_p, players[i].glanceDir); + WRITEUINT8(save_p, players[i].tripWireState); WRITEUINT8(save_p, players[i].typing_timer); WRITEUINT8(save_p, players[i].typing_duration); @@ -573,6 +574,7 @@ static void P_NetUnArchivePlayers(void) players[i].spheres = READINT16(save_p); players[i].glanceDir = READSINT8(save_p); + players[i].tripWireState = READUINT8(save_p); players[i].typing_timer = READUINT8(save_p); players[i].typing_duration = READUINT8(save_p); diff --git a/src/p_spec.c b/src/p_spec.c index 16823916e..7099cf79f 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2018,6 +2018,13 @@ void P_CrossSpecialLine(line_t *line, INT32 side, mobj_t *thing) return; { player_t *player = thing->player; + + if (P_IsLineTripWire(line)) + { + K_ApplyTripWire(player, TRIP_PASSED); + return; + } + switch (line->special) { case 2001: // Finish Line