From 8e20ca4c042755c39b51e9cba94068996bb19944 Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 28 Nov 2021 02:57:45 -0800 Subject: [PATCH 1/7] 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 From 0e6bb7523086762162411acb6efe766970ebc279 Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 28 Nov 2021 04:08:38 -0800 Subject: [PATCH 2/7] Check TRIPWIRE texture at map load So it can be animated. --- src/p_map.c | 3 +-- src/p_setup.c | 8 ++++++++ src/r_defs.h | 2 ++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index 631f41ac9..c1d3d27a6 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -1554,8 +1554,7 @@ 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")); + return ld->tripwire; } // diff --git a/src/p_setup.c b/src/p_setup.c index 654eb6eb1..4acc53e42 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1044,6 +1044,8 @@ static void P_InitializeLinedef(line_t *ld) ld->validcount = 0; ld->polyobj = NULL; + ld->tripwire = false; + ld->text = NULL; ld->callcount = 0; @@ -1941,6 +1943,12 @@ static void P_ProcessLinedefsAfterSidedefs(void) ld->frontsector = sides[ld->sidenum[0]].sector; //e6y: Can't be -1 here ld->backsector = ld->sidenum[1] != 0xffff ? sides[ld->sidenum[1]].sector : 0; + if (sides[ld->sidenum[0]].midtexture == + R_TextureNumForName("TRIPWIRE")) + { + ld->tripwire = true; + } + switch (ld->special) { // Compile linedef 'text' from both sidedefs 'text' for appropriate specials. diff --git a/src/r_defs.h b/src/r_defs.h index 41b0cdaab..7decdfeab 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -420,6 +420,8 @@ typedef struct line_s size_t validcount; // if == validcount, already checked polyobj_t *polyobj; // Belongs to a polyobject? + boolean tripwire; + char *text; // a concatenation of all front and back texture names, for linedef specials that require a string. INT16 callcount; // no. of calls left before triggering, for the "X calls" linedef specials, defaults to 0 } line_t; From 2276304c1d74231abc920d920f7a6a27766af907 Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 28 Nov 2021 04:09:15 -0800 Subject: [PATCH 3/7] Don't skip other line specials if a trip wire is passed --- src/p_spec.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/p_spec.c b/src/p_spec.c index 7099cf79f..07825759c 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2022,7 +2022,6 @@ void P_CrossSpecialLine(line_t *line, INT32 side, mobj_t *thing) if (P_IsLineTripWire(line)) { K_ApplyTripWire(player, TRIP_PASSED); - return; } switch (line->special) From 54aaf6d98e514a05d512f149748d4d048d5c65a5 Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 28 Nov 2021 16:23:37 -0800 Subject: [PATCH 4/7] Apply tripwire effect to TRIPWIRE and 4RIPWIRE --- src/p_setup.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 4acc53e42..fab5429b8 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1938,13 +1938,19 @@ static void P_ProcessLinedefsAfterSidedefs(void) { size_t i = numlines; register line_t *ld = lines; + + const INT32 TEX_TRIPWIRE = R_TextureNumForName("TRIPWIRE"); + const INT32 TEX_4RIPWIRE = R_TextureNumForName("4RIPWIRE"); + for (; i--; ld++) { + INT32 midtexture = sides[ld->sidenum[0]].midtexture; + ld->frontsector = sides[ld->sidenum[0]].sector; //e6y: Can't be -1 here ld->backsector = ld->sidenum[1] != 0xffff ? sides[ld->sidenum[1]].sector : 0; - if (sides[ld->sidenum[0]].midtexture == - R_TextureNumForName("TRIPWIRE")) + if (midtexture == TEX_TRIPWIRE || + midtexture == TEX_4RIPWIRE) { ld->tripwire = true; } From 2cab15c7a397e6c0581659a37b8d5a7c3c8e91fe Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 28 Nov 2021 16:34:46 -0800 Subject: [PATCH 5/7] Automatically apply additive to tripwires --- src/hardware/hw_main.c | 3 ++- src/r_segs.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 3e113bd76..205fc3ff6 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -1478,7 +1478,8 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom transnum_t transtable = R_GetLinedefTransTable(gl_linedef); if (transtable == NUMTRANSMAPS) transtable = 0; - if (gl_linedef->special == 910) + if (gl_linedef->special == 910 || + P_IsLineTripWire(gl_linedef)) blend = AST_ADD; else if (gl_linedef->special == 911) blend = AST_SUBTRACT; diff --git a/src/r_segs.c b/src/r_segs.c index 8d056a295..5c9538e34 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -162,7 +162,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) return; transtable = R_GetLinedefTransTable(ldef); - if (ldef->special == 910) + if (ldef->special == 910 || P_IsLineTripWire(ldef)) { if (transtable == NUMTRANSMAPS) transtable = 0; From 9750e2cd07ae5786168c055b33730f8d6429ee99 Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 28 Nov 2021 17:27:06 -0800 Subject: [PATCH 6/7] Tumble when passing tripwire while spinning out and with >200% speed --- src/k_kart.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 7ee285fed..e8b424179 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -3210,10 +3210,18 @@ void K_TumblePlayer(player_t *player, mobj_t *inflictor, mobj_t *source) player->tumbleBounces = 1; - player->mo->momx = 2 * player->mo->momx / 3; - player->mo->momy = 2 * player->mo->momy / 3; + if (player->tripWireState == TRIP_PASSED) + { + player->tumbleHeight = 50; + } + else + { + player->mo->momx = 2 * player->mo->momx / 3; + player->mo->momy = 2 * player->mo->momy / 3; + + player->tumbleHeight = 30; + } - player->tumbleHeight = 30; player->pflags &= ~PF_TUMBLESOUND; if (inflictor && !P_MobjWasRemoved(inflictor)) @@ -3322,6 +3330,12 @@ void K_ApplyTripWire(player_t *player, tripwirestate_t state) player->tripWireState = state; K_AddHitLag(player->mo, 10, false); + + if (state == TRIP_PASSED && player->spinouttimer && + player->speed > 2* K_GetKartSpeed(player, false)) + { + K_TumblePlayer(player, NULL, NULL); + } } 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 From 332d3bfa121cb7e61ba25b8b4212da1ce9f3d8f9 Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 28 Nov 2021 18:48:27 -0800 Subject: [PATCH 7/7] Fix passing tripwire not triggering SOMETIMES --- src/p_map.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index c1d3d27a6..42fa89b73 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -206,11 +206,14 @@ static void add_spechit(line_t *ld) numspechit++; } -static boolean P_SpecialIsLinedefCrossType(UINT16 ldspecial) +static boolean P_SpecialIsLinedefCrossType(line_t *ld) { boolean linedefcrossspecial = false; - switch (ldspecial) + if (P_IsLineTripWire(ld)) + return true; + + switch (ld->special) { case 2001: // Finish line case 2003: // Respawn line @@ -1671,8 +1674,7 @@ static boolean PIT_CheckLine(line_t *ld) tmdropoffz = lowfloor; // we've crossed the line - if (P_SpecialIsLinedefCrossType(ld->special) || - P_IsLineTripWire(ld)) + if (P_SpecialIsLinedefCrossType(ld)) { add_spechit(ld); } @@ -2666,10 +2668,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) oldside = P_PointOnLineSide(oldx, oldy, ld); if (side != oldside) { - if (ld->special) - { - P_CrossSpecialLine(ld, oldside, thing); - } + P_CrossSpecialLine(ld, oldside, thing); } } } @@ -2751,7 +2750,7 @@ static boolean PTR_GetSpecialLines(intercept_t *in) return true; } - if (P_SpecialIsLinedefCrossType(ld->special)) + if (P_SpecialIsLinedefCrossType(ld)) { add_spechit(ld); } @@ -2821,10 +2820,7 @@ void P_HitSpecialLines(mobj_t *thing, fixed_t x, fixed_t y, fixed_t momx, fixed_ oldside = P_PointOnLineSide(x, y, ld); if (side != oldside) { - if (ld->special) - { - P_CrossSpecialLine(ld, oldside, thing); - } + P_CrossSpecialLine(ld, oldside, thing); } } }