From bca4f30ee38bed7c2fa0d00ac9a0efe7ce9b9ba0 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Wed, 25 Sep 2019 07:17:14 -0400 Subject: [PATCH 01/56] Use defines here instead I got a "initializer element is not constant" error when compiling. From a quick Google search, it seems that const-type variables aren't totally considered constants in C. There may be a better way to fix this error. --- src/k_waypoint.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/k_waypoint.c b/src/k_waypoint.c index 6673cec97..4070e61e6 100644 --- a/src/k_waypoint.c +++ b/src/k_waypoint.c @@ -11,9 +11,9 @@ static const UINT32 SPARKLES_PER_CONNECTION = 16U; // Some defaults for the size of the dynamically allocated sets for pathfinding. These are kept for the purpose of // allocating a size that is less likely to need reallocating again during the pathfinding. -static const size_t OPENSET_BASE_SIZE = 16U; -static const size_t CLOSEDSET_BASE_SIZE = 256U; -static const size_t NODESARRAY_BASE_SIZE = 256U; +#define OPENSET_BASE_SIZE 16U; +#define CLOSEDSET_BASE_SIZE 256U; +#define NODESARRAY_BASE_SIZE 256U; static waypoint_t *waypointheap = NULL; static waypoint_t *firstwaypoint = NULL; From 2c400487a5e1b83ae82f0a944d8651885b1ab5ee Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Fri, 27 Sep 2019 23:11:43 -0400 Subject: [PATCH 02/56] not def 0 --- src/p_map.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_map.c b/src/p_map.c index 719f945e8..e2c7523d9 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -254,7 +254,7 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object) object->eflags |= MFE_SPRUNG; // apply this flag asap! spring->flags &= ~(MF_SOLID|MF_SPECIAL); // De-solidify -#ifdef 0 +#if 0 if (horizspeed && vertispeed) // Mimic SA { object->momx = object->momy = 0; From 9e3b818ccea9841d7df3aaed8bd5c85037f8678a Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Sun, 29 Sep 2019 14:40:23 -0400 Subject: [PATCH 03/56] Fix finish line occasionally failing for small players --- src/p_map.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index e2c7523d9..608f13a2c 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -2080,7 +2080,7 @@ static boolean PIT_CheckLine(line_t *ld) if (P_BoxOnLineSide(tmbbox, ld) != -1) return true; -if (tmthing->flags & MF_PAPERCOLLISION) // Caution! Turning whilst up against a wall will get you stuck. You probably shouldn't give the player this flag. + if (tmthing->flags & MF_PAPERCOLLISION) // Caution! Turning whilst up against a wall will get you stuck. You probably shouldn't give the player this flag. { fixed_t cosradius, sinradius; cosradius = FixedMul(tmthing->radius, FINECOSINE(tmthing->angle>>ANGLETOFINESHIFT)); @@ -2881,9 +2881,6 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) // reset this to 0 at the start of each trymove call as it's only used here numspechitint = 0U; - if (radius < MAXRADIUS/2) - radius = MAXRADIUS/2; - do { if (thing->flags & MF_NOCLIP) { tryx = x; From d1c20c2a5ad420fda551895d1514d727700e416e Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Tue, 15 Oct 2019 21:30:23 -0400 Subject: [PATCH 04/56] Don't allow finish lines to be hit multiple times per tic --- src/d_netcmd.c | 12 +---- src/d_player.h | 2 +- src/dehacked.c | 2 +- src/g_game.c | 2 +- src/p_enemy.c | 10 ----- src/p_local.h | 1 - src/p_map.c | 2 +- src/p_spec.c | 16 +++---- src/p_user.c | 118 +++---------------------------------------------- 9 files changed, 18 insertions(+), 147 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 8bd03dfbf..90ba1b137 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -1873,8 +1873,6 @@ void SendWeaponPref(void) buf[0] = 0; if (cv_flipcam.value) buf[0] |= 1; - if (cv_analog.value) - buf[0] |= 2; SendNetXCmd(XD_WEAPONPREF, buf, 1); } @@ -1885,8 +1883,6 @@ void SendWeaponPref2(void) buf[0] = 0; if (cv_flipcam2.value) buf[0] |= 1; - if (cv_analog2.value) - buf[0] |= 2; SendNetXCmd2(XD_WEAPONPREF, buf, 1); } @@ -1897,8 +1893,6 @@ void SendWeaponPref3(void) buf[0] = 0; if (cv_flipcam3.value) buf[0] |= 1; - if (cv_analog3.value) - buf[0] |= 2; SendNetXCmd3(XD_WEAPONPREF, buf, 1); } @@ -1909,8 +1903,6 @@ void SendWeaponPref4(void) buf[0] = 0; if (cv_flipcam4.value) buf[0] |= 1; - if (cv_analog4.value) - buf[0] |= 2; SendNetXCmd4(XD_WEAPONPREF, buf, 1); } @@ -1918,11 +1910,9 @@ static void Got_WeaponPref(UINT8 **cp,INT32 playernum) { UINT8 prefs = READUINT8(*cp); - players[playernum].pflags &= ~(PF_FLIPCAM|PF_ANALOGMODE); + players[playernum].pflags &= ~(PF_FLIPCAM); if (prefs & 1) players[playernum].pflags |= PF_FLIPCAM; - if (prefs & 2) - players[playernum].pflags |= PF_ANALOGMODE; } void D_SendPlayerConfig(void) diff --git a/src/d_player.h b/src/d_player.h index 536f46ea3..1d9f77c60 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -121,7 +121,7 @@ typedef enum /*** misc ***/ PF_FORCESTRAFE = 1<<29, // Turning inputs are translated into strafing inputs - PF_ANALOGMODE = 1<<30, // Analog mode? + PF_HITFINISHLINE = 1<<30, // Already hit the finish line this tic // free: 1<<30 and 1<<31 } pflags_t; diff --git a/src/dehacked.c b/src/dehacked.c index 81ad3c823..355aa86bd 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -8176,7 +8176,7 @@ static const char *const PLAYERFLAG_LIST[] = { /*** misc ***/ "FORCESTRAFE", // Translate turn inputs into strafe inputs - "ANALOGMODE", // Analog mode? + "HITFINISHLINE", // Already hit the finish line this tic NULL // stop loop here. }; diff --git a/src/g_game.c b/src/g_game.c index 69889e803..282a63215 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2593,7 +2593,7 @@ void G_PlayerReborn(INT32 player) jointime = players[player].jointime; splitscreenindex = players[player].splitscreenindex; spectator = players[player].spectator; - pflags = (players[player].pflags & (PF_TIMEOVER|PF_FLIPCAM|PF_TAGIT|PF_TAGGED|PF_ANALOGMODE|PF_WANTSTOJOIN)); + pflags = (players[player].pflags & (PF_TIMEOVER|PF_FLIPCAM|PF_TAGIT|PF_TAGGED|PF_WANTSTOJOIN)); // As long as we're not in multiplayer, carry over cheatcodes from map to map if (!(netgame || multiplayer)) diff --git a/src/p_enemy.c b/src/p_enemy.c index a1bba0092..c3f316225 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -8554,9 +8554,6 @@ void A_SPBChase(mobj_t *actor) fixed_t range = (160*actor->tracer->scale); fixed_t cx = 0, cy =0; - // we're tailing a player, now's a good time to regain our damage properties - actor->flags &= ~MF_NOCLIPTHING; - // Play the intimidating gurgle if (!S_SoundPlaying(actor, actor->info->activesound)) S_StartSound(actor, actor->info->activesound); @@ -8688,9 +8685,6 @@ void A_SPBChase(mobj_t *actor) { actor->momx = actor->momy = actor->momz = 0; // Stoooop - // don't hurt players that have nothing to do with this: - actor->flags |= MF_NOCLIPTHING; - if (actor->lastlook != -1 && playeringame[actor->lastlook] && !players[actor->lastlook].spectator @@ -8729,10 +8723,6 @@ void A_SPBChase(mobj_t *actor) } // Found someone, now get close enough to initiate the slaughter... - - // Seeking SPB can now hurt people - actor->flags &= ~MF_NOCLIPTHING; - P_SetTarget(&actor->tracer, player->mo); spbplace = bestrank; diff --git a/src/p_local.h b/src/p_local.h index d4da9fe29..220ee1c3d 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -180,7 +180,6 @@ boolean P_LookForEnemies(player_t *player); void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius); void P_HomingAttack(mobj_t *source, mobj_t *enemy); /// \todo doesn't belong in p_user //boolean P_SuperReady(player_t *player); -boolean P_AnalogMove(player_t *player); /*boolean P_TransferToNextMare(player_t *player); UINT8 P_FindLowestMare(void);*/ UINT8 P_FindLowestLap(void); diff --git a/src/p_map.c b/src/p_map.c index 608f13a2c..fe4c160dd 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -1417,7 +1417,7 @@ static boolean PIT_CheckThing(mobj_t *thing) thing->angle = tmthing->angle; - if (!demo.playback || P_AnalogMove(thing->player)) + if (!demo.playback) { if (thing->player == &players[consoleplayer]) localangle[0] = thing->angle; diff --git a/src/p_spec.c b/src/p_spec.c index 66955d0ec..6150aa391 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2283,12 +2283,6 @@ static void K_HandleLapIncrement(player_t *player) P_SetupSignExit(player); } - //player->starpostangle = player->starposttime = player->starpostnum = 0; - //player->starpostx = player->starposty = player->starpostz = 0; - - // Play the starpost sound for 'consistency' - // S_StartSound(player->mo, sfx_strpst); - // Figure out how many are playing on the last lap, to prevent spectate griefing if (!nospectategrief && player->laps > (UINT8)(cv_numlaps.value)) nospectategrief = nump; @@ -2307,7 +2301,7 @@ static void K_HandleLapDecrement(player_t *player) { if (player) { - if (player->laps > 0) + if ((player->starpostnum == 0) && (player->laps > 0)) { player->starpostnum = numstarposts; player->laps--; @@ -2331,7 +2325,7 @@ void P_CrossSpecialLine(line_t *line, INT32 side, mobj_t *thing) { case 2001: // Finish Line { - if (G_RaceGametype() && !(player->exiting)) + if (G_RaceGametype() && !(player->exiting) && !(player->pflags & PF_HITFINISHLINE)) { if (((line->flags & (ML_NOCLIMB)) && (side == 0)) || (!(line->flags & (ML_NOCLIMB)) && (side == 1))) // crossed from behind to infront @@ -2342,6 +2336,8 @@ void P_CrossSpecialLine(line_t *line, INT32 side, mobj_t *thing) { K_HandleLapDecrement(player); } + + player->pflags |= PF_HITFINISHLINE; } } break; @@ -4027,7 +4023,7 @@ DoneSection2: if (player->mo->scale > mapobjectscale) linespeed = FixedMul(linespeed, mapobjectscale + (player->mo->scale - mapobjectscale)); - if (!demo.playback || P_AnalogMove(player)) + if (!demo.playback) { if (player == &players[consoleplayer]) localangle[0] = player->mo->angle; @@ -7935,7 +7931,7 @@ void T_Pusher(pusher_t *p) thing->player->pflags |= PF_SLIDING; thing->angle = R_PointToAngle2 (0, 0, xspeed<<(FRACBITS-PUSH_FACTOR), yspeed<<(FRACBITS-PUSH_FACTOR)); - if (!demo.playback || P_AnalogMove(thing->player)) + if (!demo.playback) { if (thing->player == &players[consoleplayer]) { diff --git a/src/p_user.c b/src/p_user.c index 434091fd7..cffba20bb 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -3716,11 +3716,6 @@ void P_Telekinesis(player_t *player, fixed_t thrust, fixed_t range) player->pflags |= PF_THOKKED; } -boolean P_AnalogMove(player_t *player) -{ - return player->pflags & PF_ANALOGMODE; -} - // // P_GetPlayerControlDirection // @@ -3763,14 +3758,6 @@ boolean P_AnalogMove(player_t *player) origtempangle = tempangle = 0; // relative to the axis rather than the player! controlplayerdirection = R_PointToAngle2(0, 0, player->mo->momx, player->mo->momy); } - else if (P_AnalogMove(player) && thiscam->chase) - { - if (player->awayviewtics) - origtempangle = tempangle = player->awayviewmobj->angle; - else - origtempangle = tempangle = thiscam->angle; - controlplayerdirection = player->mo->angle; - } else { origtempangle = tempangle = player->mo->angle; @@ -3994,7 +3981,6 @@ static void P_3dMovement(player_t *player) angle_t dangle; // replaces old quadrants bits //boolean dangleflip = false; // SRB2kart - toaster //fixed_t normalspd = FixedMul(player->normalspeed, player->mo->scale); - boolean analogmove = false; fixed_t oldMagnitude, newMagnitude; #ifdef ESLOPE vector3_t totalthrust; @@ -4006,8 +3992,6 @@ static void P_3dMovement(player_t *player) // Get the old momentum; this will be needed at the end of the function! -SH oldMagnitude = R_PointToDist2(player->mo->momx - player->cmomx, player->mo->momy - player->cmomy, 0, 0); - analogmove = P_AnalogMove(player); - cmd = &player->cmd; if ((player->exiting || mapreset) || player->pflags & PF_STASIS || player->kartstuff[k_spinouttimer]) // pw_introcam? @@ -4020,19 +4004,13 @@ static void P_3dMovement(player_t *player) if (!(player->pflags & PF_FORCESTRAFE) && !player->kartstuff[k_pogospring]) cmd->sidemove = 0; - if (analogmove) - { - movepushangle = (cmd->angleturn<<16 /* not FRACBITS */); - } + if (player->kartstuff[k_drift] != 0) + movepushangle = player->mo->angle-(ANGLE_45/5)*player->kartstuff[k_drift]; + else if (player->kartstuff[k_spinouttimer] || player->kartstuff[k_wipeoutslow]) // if spun out, use the boost angle + movepushangle = (angle_t)player->kartstuff[k_boostangle]; else - { - if (player->kartstuff[k_drift] != 0) - movepushangle = player->mo->angle-(ANGLE_45/5)*player->kartstuff[k_drift]; - else if (player->kartstuff[k_spinouttimer] || player->kartstuff[k_wipeoutslow]) // if spun out, use the boost angle - movepushangle = (angle_t)player->kartstuff[k_boostangle]; - else - movepushangle = player->mo->angle; - } + movepushangle = player->mo->angle; + movepushsideangle = movepushangle-ANGLE_90; // cmomx/cmomy stands for the conveyor belt speed. @@ -6191,69 +6169,6 @@ static void P_MovePlayer(player_t *player) player->pflags &= ~PF_STARTDASH; */ - ////////////////// - //ANALOG CONTROL// - ////////////////// - -#if 0 - // This really looks like it should be moved to P_3dMovement. -Red - if (P_AnalogMove(player) - && (cmd->forwardmove != 0 || cmd->sidemove != 0) && !player->climbing && !twodlevel && !(player->mo->flags2 & MF2_TWOD)) - { - // If travelling slow enough, face the way the controls - // point and not your direction of movement. - if (player->speed < FixedMul(5*FRACUNIT, player->mo->scale) || player->pflags & PF_GLIDING || !onground) - { - angle_t tempangle; - - tempangle = (cmd->angleturn << 16); - -#ifdef REDSANALOG // Ease to it. Chillax. ~Red - tempangle += R_PointToAngle2(0, 0, cmd->forwardmove*FRACUNIT, -cmd->sidemove*FRACUNIT); - { - fixed_t tweenvalue = max(abs(cmd->forwardmove), abs(cmd->sidemove)); - - if (tweenvalue < 10 && (cmd->buttons & (BT_FORWARD|BT_BACKWARD)) == (BT_FORWARD|BT_BACKWARD)) { - tempangle = (cmd->angleturn << 16); - tweenvalue = 16; - } - - tweenvalue *= tweenvalue*tweenvalue*1536; - - //if (player->pflags & PF_GLIDING) - //tweenvalue >>= 1; - - tempangle -= player->mo->angle; - - if (tempangle < ANGLE_180 && tempangle > tweenvalue) - player->mo->angle += tweenvalue; - else if (tempangle >= ANGLE_180 && InvAngle(tempangle) > tweenvalue) - player->mo->angle -= tweenvalue; - else - player->mo->angle += tempangle; - } -#else - // Less math this way ~Red - player->mo->angle = R_PointToAngle2(0, 0, cmd->forwardmove*FRACUNIT, -cmd->sidemove*FRACUNIT)+tempangle; -#endif - } - // Otherwise, face the direction you're travelling. - else if (player->panim == PA_WALK || player->panim == PA_RUN || player->panim == PA_ROLL - /*|| ((player->mo->state >= &states[S_PLAY_ABL1] && player->mo->state <= &states[S_PLAY_SPC4]) && player->charability == CA_FLY)*/) // SRB2kart - idk - player->mo->angle = R_PointToAngle2(0, 0, player->rmomx, player->rmomy); - - // Update the local angle control. - if (player == &players[consoleplayer]) - localangle[0] = player->mo->angle; - else if (player == &players[displayplayers[1]]) - localangle[1] = player->mo->angle; - else if (player == &players[displayplayers[2]]) - localangle[2] = player->mo->angle; - else if (player == &players[displayplayers[3]]) - localangle[3] = player->mo->angle; - } -#endif - /////////////////////////// //BOMB SHIELD ACTIVATION,// //HOMING, AND OTHER COOL // @@ -8373,26 +8288,7 @@ void P_PlayerThink(player_t *player) player->mo->reactiontime--; else if (player->mo->tracer && player->mo->tracer->type == MT_TUBEWAYPOINT) { - // SRB2kart - don't need no rope hangin' - //if (player->pflags & PF_ROPEHANG) - //{ - // if (!P_AnalogMove(player)) - // player->mo->angle = (cmd->angleturn<<16 /* not FRACBITS */); - - // ticruned++; - // if ((cmd->angleturn & TICCMD_RECEIVED) == 0) - // ticmiss++; - - // P_DoRopeHang(player); - // P_SetPlayerMobjState(player->mo, S_PLAY_CARRY); - // P_DoJumpStuff(player, &player->cmd); - //} - //else - { - P_DoZoomTube(player); - //if (!(player->panim == PA_ROLL) && player->charability2 == CA2_SPINDASH) // SRB2kart - // P_SetPlayerMobjState(player->mo, S_PLAY_ATK1); - } + P_DoZoomTube(player); player->rmomx = player->rmomy = 0; // no actual momentum from your controls P_ResetScore(player); } From e6dc29358e6f12af83cd21bf5fe8c71ed34bacb1 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Tue, 15 Oct 2019 21:46:45 -0400 Subject: [PATCH 05/56] Reduced SPB target distance to 1024 units (previously 3072 units) --- src/p_enemy.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index e185add81..26e757e41 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -8791,9 +8791,9 @@ void A_SPBChase(mobj_t *actor) // Spawn a trail of rings behind the SPB! SpawnSPBTrailRings(actor); - if (dist <= (3072*actor->tracer->scale)) // Close enough to target? + if (dist <= (1024*actor->tracer->scale)) // Close enough to target? { - S_StartSound(actor, actor->info->attacksound); // Siren sound; might not need this anymore, but I'm keeping it for now just for debugging. + S_StartSound(actor, actor->info->attacksound); actor->extravalue1 = 1; // TARGET ACQUIRED actor->extravalue2 = 7*TICRATE; actor->cvmem = wspeed; From a37eb798e0a5593d0b9c1367a49fbd2409f56fae Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Tue, 15 Oct 2019 22:23:01 -0400 Subject: [PATCH 06/56] Fix bad merge --- src/p_spec.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index e3dea0f17..b71d7508c 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2283,10 +2283,6 @@ static void K_HandleLapIncrement(player_t *player) P_SetupSignExit(player); } - // Figure out how many are playing on the last lap, to prevent spectate griefing - if (!nospectategrief && player->laps > (UINT8)(cv_numlaps.value)) - nospectategrief = nump; - thwompsactive = true; // Lap 2 effects } else if (player->starpostnum) From 52624cb6debd558a664d5ef71c975bfedce31298 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Tue, 15 Oct 2019 22:34:22 -0400 Subject: [PATCH 07/56] Properly reset PF_HITFINISHLINE --- src/k_kart.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/k_kart.c b/src/k_kart.c index fc42a925c..00326e057 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -6189,6 +6189,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) boolean NO_HYUDORO = (player->kartstuff[k_stolentimer] == 0 && player->kartstuff[k_stealingtimer] == 0); K_UpdateDistanceFromFinishLine(player); + player->pflags &= ~PF_HITFINISHLINE; if (!player->exiting) { From c91986cc97a63acf4c98344416d0e7b3d01afccb Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Tue, 15 Oct 2019 23:37:20 -0400 Subject: [PATCH 08/56] Fix end-of-race standings --- src/k_kart.c | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 00326e057..89c821975 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -6036,26 +6036,37 @@ void K_KartUpdatePosition(player_t *player) if (G_RaceGametype()) { - // I'm a lap behind this player OR - // My distance to the finish line is higher, so I'm behind - if ((players[i].laps > player->laps) - || (players[i].distancetofinish < player->distancetofinish)) + if (player->exiting) // End of match standings { - position++; + // Only time matters + if (players[i].realtime < player->realtime) + position++; + } + else + { + // I'm a lap behind this player OR + // My distance to the finish line is higher, so I'm behind + if ((players[i].laps > player->laps) + || (players[i].distancetofinish < player->distancetofinish)) + { + position++; + } } } else if (G_BattleGametype()) { if (player->exiting) // End of match standings { - if (players[i].marescore > player->marescore) // Only score matters + // Only score matters + if (players[i].marescore > player->marescore) position++; } else { - if (players[i].kartstuff[k_bumper] == player->kartstuff[k_bumper] && players[i].marescore > player->marescore) - position++; - else if (players[i].kartstuff[k_bumper] > player->kartstuff[k_bumper]) + // I have less points than but the same bumpers as this player OR + // I have less bumpers than this player + if ((players[i].kartstuff[k_bumper] == player->kartstuff[k_bumper] && players[i].marescore > player->marescore) + || (players[i].kartstuff[k_bumper] > player->kartstuff[k_bumper])) position++; } } From a94601a7932ee7de9eac494f690fa79436736a16 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Wed, 16 Oct 2019 00:12:03 -0400 Subject: [PATCH 09/56] fix SPB weirdo distances --- src/k_kart.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 89c821975..5040f4899 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -848,9 +848,7 @@ static INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed, boolean sp if (first != -1 && second != -1) // calculate 2nd's distance from 1st, for SPB { - secondist = P_AproxDistance(P_AproxDistance(players[first].mo->x - players[second].mo->x, - players[first].mo->y - players[second].mo->y), - players[first].mo->z - players[second].mo->z) / mapobjectscale; + secondist = players[second]->distancetofinish - players[first].distancetofinish; if (franticitems) secondist = (15 * secondist) / 14; secondist = ((28 + (8-pingame)) * secondist) / 28; @@ -1088,7 +1086,8 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) for (i = 0; i < MAXPLAYERS; i++) { - if (players[i].kartstuff[k_position] == 1) + if (playeringame[i] && !players[i].spectator + && players[i].kartstuff[k_position] == 1) { // This player is first! Yay! pdis = player->distancetofinish - players[i].distancetofinish; @@ -9979,13 +9978,13 @@ static void K_drawDistributionDebugger(void) // lovely double loop...... for (i = 0; i < MAXPLAYERS; i++) { - if (playeringame[i] && !players[i].spectator && players[i].mo - && players[i].kartstuff[k_position] < stplyr->kartstuff[k_position]) - pdis += P_AproxDistance(P_AproxDistance(players[i].mo->x - stplyr->mo->x, - players[i].mo->y - stplyr->mo->y), - players[i].mo->z - stplyr->mo->z) / mapobjectscale - * (pingame - players[i].kartstuff[k_position]) - / max(1, ((pingame - 1) * (pingame + 1) / 3)); + if (playeringame[i] && !players[i].spectator + && players[i].kartstuff[k_position] == 1) + { + // This player is first! Yay! + pdis = stplyr->distancetofinish - players[i].distancetofinish; + break; + } } if (franticitems) // Frantic items make the distances between everyone artifically higher, for crazier items From 857afbbb49558e6f2c1e685b405e38b88ad7b255 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Wed, 16 Oct 2019 00:16:27 -0400 Subject: [PATCH 10/56] increase DISTVAR --- src/k_kart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_kart.c b/src/k_kart.c index 5040f4899..1b75d523c 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -709,7 +709,7 @@ static INT32 K_KartItemOddsBattle[NUMKARTRESULTS][6] = /*Jawz x2*/ { 0, 0, 1, 2, 4, 2 } // Jawz x2 }; -#define DISTVAR (64*14) +#define DISTVAR (1024) // Magic number distance for use with item roulette tiers /** \brief Item Roulette for Kart From 07fac259e08aff44d9d640e16cb3eaaa760306a2 Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 15 Oct 2019 21:20:28 -0700 Subject: [PATCH 11/56] Not a pointer --- src/k_kart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_kart.c b/src/k_kart.c index 1b75d523c..4752617d0 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -848,7 +848,7 @@ static INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed, boolean sp if (first != -1 && second != -1) // calculate 2nd's distance from 1st, for SPB { - secondist = players[second]->distancetofinish - players[first].distancetofinish; + secondist = players[second].distancetofinish - players[first].distancetofinish; if (franticitems) secondist = (15 * secondist) / 14; secondist = ((28 + (8-pingame)) * secondist) / 28; From 4b04423bbe5256e7796026329bd53a1b24e9bb58 Mon Sep 17 00:00:00 2001 From: James Date: Tue, 22 Oct 2019 08:46:14 -0400 Subject: [PATCH 12/56] Bring this back, but more lenient (not tested) --- src/p_map.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/p_map.c b/src/p_map.c index fe4c160dd..9585849f7 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -2881,6 +2881,11 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) // reset this to 0 at the start of each trymove call as it's only used here numspechitint = 0U; + // This makes sure that there are no freezes from computing extremely small movements. + // Originally was MAXRADIUS/2, but that causes some inconsistencies for small players. + if (radius < mapobjectscale) + radius = mapobjectscale; + do { if (thing->flags & MF_NOCLIP) { tryx = x; From 0fdcc22d939c90dd34dc6dc74f25f6136d24bd0b Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Tue, 22 Oct 2019 16:44:56 -0400 Subject: [PATCH 13/56] - Only update to waypoints you're in the radius of (applies to players & spb) - Player direction value uses momentum angle rather than facing angle (fixes weird nextwaypoint/position flickering while drifting) - Raise default radius to 384 --- src/k_kart.c | 30 ++++++++++++++++----- src/k_waypoint.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++ src/k_waypoint.h | 14 ++++++++++ src/p_enemy.c | 48 +++++++++++++++++++++++++++------ src/p_mobj.c | 2 +- 5 files changed, 148 insertions(+), 16 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 4752617d0..b376ade41 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -5488,28 +5488,33 @@ void K_KartPlayerAfterThink(player_t *player) Input Arguments:- player - The player the next waypoint is being found for + closest - Use closest waypoint algorithm, instead of best touching Return:- The waypoint that is the player's next waypoint --------------------------------------------------*/ -static waypoint_t *K_GetPlayerNextWaypoint(player_t *player) +static waypoint_t *K_GetPlayerNextWaypoint(player_t *player, boolean closest) { waypoint_t *bestwaypoint = NULL; if ((player != NULL) && (player->mo != NULL) && (P_MobjWasRemoved(player->mo) == false)) { waypoint_t *waypoint = NULL; - waypoint = K_GetClosestWaypointToMobj(player->mo); + if (closest) + waypoint = K_GetClosestWaypointToMobj(player->mo); + else + waypoint = K_GetBestWaypointTouchingMobj(player->mo); + bestwaypoint = waypoint; // check the waypoint's location in relation to the player // If it's generally in front, it's fine, otherwise, use the best next/previous waypoint. - // EXCEPTION: If our closest waypoint is the finishline AND we're facing towards it, don't do this. + // EXCEPTION: If our best waypoint is the finishline AND we're facing towards it, don't do this. // Otherwise it breaks the distance calculations. if (waypoint != NULL) { boolean finishlinehack = false; - angle_t playerangle = player->mo->angle; + angle_t playerangle = R_PointToAngle2(0, 0, player->mo->momx, player->mo->momy); //player->mo->angle angle_t angletowaypoint = R_PointToAngle2(player->mo->x, player->mo->y, waypoint->mobj->x, waypoint->mobj->y); angle_t angledelta = playerangle - angletowaypoint; @@ -5667,9 +5672,16 @@ static void K_UpdateDistanceFromFinishLine(player_t *const player) else { waypoint_t *finishline = K_GetFinishLineWaypoint(); - waypoint_t *nextwaypoint = K_GetPlayerNextWaypoint(player); + waypoint_t *nextwaypoint = K_GetPlayerNextWaypoint(player, false); - if ((nextwaypoint != player->nextwaypoint) && + if ((nextwaypoint == NULL) && (player->nextwaypoint == NULL)) + { + // Special case: if player nextwaypoint is still NULL, we want to fix that as soon as possible, so use the closest waypoint instead. + nextwaypoint = K_GetPlayerNextWaypoint(player, true); + } + + if ((nextwaypoint != NULL) && + (nextwaypoint != player->nextwaypoint) && (K_GetWaypointIsShortcut(nextwaypoint) == false) && (K_GetWaypointIsEnabled(nextwaypoint) == true)) { size_t i = 0U; @@ -5699,7 +5711,11 @@ static void K_UpdateDistanceFromFinishLine(player_t *const player) } } - player->nextwaypoint = nextwaypoint; + if (nextwaypoint != NULL) + { + // At this point, we don't want to update the waypoint until we touch another. + player->nextwaypoint = nextwaypoint; + } // nextwaypoint is now the waypoint that is in front of us if ((player->nextwaypoint != NULL) && (finishline != NULL)) diff --git a/src/k_waypoint.c b/src/k_waypoint.c index 4070e61e6..a73487e14 100644 --- a/src/k_waypoint.c +++ b/src/k_waypoint.c @@ -235,6 +235,76 @@ waypoint_t *K_GetClosestWaypointToMobj(mobj_t *const mobj) return closestwaypoint; } +/*-------------------------------------------------- + waypoint_t *K_GetBestWaypointTouchingMobj(mobj_t *const mobj) + + See header file for description. +--------------------------------------------------*/ +waypoint_t *K_GetBestWaypointTouchingMobj(mobj_t *const mobj) +{ + waypoint_t *bestwaypoint = NULL; + + if ((mobj == NULL) || P_MobjWasRemoved(mobj)) + { + CONS_Debug(DBG_GAMELOGIC, "NULL mobj in K_GetBestWaypointTouchingMobj.\n"); + } + else + { + size_t i = 0U; + waypoint_t *checkwaypoint = NULL; + fixed_t bestdist = INT32_MAX; + fixed_t checkdist = INT32_MAX; + + for (i = 0; i < numwaypoints; i++) + { + checkwaypoint = &waypointheap[i]; + checkdist = P_AproxDistance(mobj->x - checkwaypoint->mobj->x, mobj->y - checkwaypoint->mobj->y); + checkdist = P_AproxDistance(checkdist, mobj->z - checkwaypoint->mobj->z); + + // The mobj has to be touching this waypoint to update to it. + if (checkdist <= checkwaypoint->mobj->radius) + { +#if 0 + // This kind of algorithm may or may not be more reliable than what's below. + // But it's a little heavier, computation-wise. + // We'll see if simple closer checks work fine in netgame testing, or if it needs this. + boolean success = false; + path_t pathtofinish = {}; + success = K_PathfindToWaypoint(checkwaypoint, finishline, &pathtofinish, false, false); + + // If you're touching more than 1 waypoint, then we use the closest one to the finish line. + if (success == true) + { + // Add euclidean distance to the next waypoint to the distancetofinish + UINT32 distancetofinish; + UINT32 adddist; + + adddist = ((UINT32)checkdist) >> FRACBITS; + + distancetofinish = pathtofinish.totaldist + adddist; + Z_Free(pathtofinish.array); + + if (distancetofinish < bestdist) + { + bestwaypoint = checkwaypoint; + bestdist = checkdist; + } + } +#else + // Simple closest check + if (checkdist < bestdist) + { + bestwaypoint = checkwaypoint; + bestdist = checkdist; + } +#endif + } + } + } + + return bestwaypoint; +} + /*-------------------------------------------------- size_t K_GetWaypointHeapIndex(waypoint_t *waypoint) diff --git a/src/k_waypoint.h b/src/k_waypoint.h index d79045119..af4ac71a5 100644 --- a/src/k_waypoint.h +++ b/src/k_waypoint.h @@ -151,6 +151,20 @@ UINT32 K_GetCircuitLength(void); waypoint_t *K_GetClosestWaypointToMobj(mobj_t *const mobj); +/*-------------------------------------------------- + waypoint_t *K_GetBestWaypointTouchingMobj(mobj_t *const mobj) + + Returns the waypoint closest to the finish line that an mobj is touching + + Input Arguments:- + mobj - mobj to get the waypoint for. + + Return:- + The best waypoint for the mobj +--------------------------------------------------*/ +waypoint_t *K_GetBestWaypointTouchingMobj(mobj_t *const mobj); + + /*-------------------------------------------------- boolean K_PathfindToWaypoint( waypoint_t *const sourcewaypoint, diff --git a/src/p_enemy.c b/src/p_enemy.c index 26e757e41..a4684b40b 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -8511,9 +8511,9 @@ void A_SPBChase(mobj_t *actor) if (actor->threshold) // Just fired, go straight. { actor->lastlook = -1; + actor->cusval = -1; spbplace = -1; P_InstaThrust(actor, actor->angle, wspeed); - actor->flags &= ~MF_NOCLIPTHING; // just in case. return; } @@ -8539,11 +8539,18 @@ void A_SPBChase(mobj_t *actor) } } + // lastlook = last player num targetted + // cvmem = stored speed + // cusval = next waypoint heap index + // extravalue1 = SPB movement mode + // extravalue2 = mode misc option + if (actor->extravalue1 == 1) // MODE: TARGETING { + actor->cusval = -1; // Reset waypoint + if (actor->tracer && actor->tracer->health) { - fixed_t defspeed = wspeed; fixed_t range = (160*actor->tracer->scale); fixed_t cx = 0, cy =0; @@ -8678,6 +8685,7 @@ void A_SPBChase(mobj_t *actor) else if (actor->extravalue1 == 2) // MODE: WAIT... { actor->momx = actor->momy = actor->momz = 0; // Stoooop + actor->cusval = -1; // Reset waypoint if (actor->lastlook != -1 && playeringame[actor->lastlook] @@ -8703,8 +8711,10 @@ void A_SPBChase(mobj_t *actor) } else // MODE: SEEKING { - waypoint_t *closestwaypoint = NULL; - waypoint_t *nextwaypoint = NULL; + waypoint_t *lastwaypoint = NULL; + waypoint_t *bestwaypoint = NULL; + waypoint_t *nextwaypoint = NULL; + actor->lastlook = -1; // Just make sure this is reset if (!player || !player->mo || player->mo->health <= 0 || player->kartstuff[k_respawn]) @@ -8719,11 +8729,24 @@ void A_SPBChase(mobj_t *actor) // Found someone, now get close enough to initiate the slaughter... P_SetTarget(&actor->tracer, player->mo); spbplace = bestrank; - dist = P_AproxDistance(P_AproxDistance(actor->x-actor->tracer->x, actor->y-actor->tracer->y), actor->z-actor->tracer->z); - closestwaypoint = K_GetClosestWaypointToMobj(actor); - if (closestwaypoint != NULL) + // Move along the waypoints until you get close enough + if (actor->cusval > -1) + { + // Previously set nextwaypoint + lastwaypoint = K_GetWaypointFromIndex((size_t)actor->cusval); + } + + bestwaypoint = K_GetBestWaypointTouchingMobj(actor); + + if (bestwaypoint == NULL && lastwaypoint == NULL) + { + // We have invalid waypoints all around, so use closest to try and make it non-NULL. + bestwaypoint = K_GetClosestWaypointToMobj(actor); + } + + if (bestwaypoint != NULL) { const boolean huntbackwards = false; boolean useshortcuts = false; @@ -8735,15 +8758,24 @@ void A_SPBChase(mobj_t *actor) } nextwaypoint = K_GetNextWaypointToDestination( - closestwaypoint, player->nextwaypoint, useshortcuts, huntbackwards); + bestwaypoint, player->nextwaypoint, useshortcuts, huntbackwards); + } + + if (nextwaypoint == NULL && lastwaypoint != NULL) + { + // Restore to the last nextwaypoint + nextwaypoint = lastwaypoint; } if (nextwaypoint != NULL) { const fixed_t xywaypointdist = P_AproxDistance( actor->x - nextwaypoint->mobj->x, actor->y - nextwaypoint->mobj->y); + hang = R_PointToAngle2(actor->x, actor->y, nextwaypoint->mobj->x, nextwaypoint->mobj->y); vang = R_PointToAngle2(0, actor->z, xywaypointdist, nextwaypoint->mobj->z); + + actor->cusval = (INT32)K_GetWaypointHeapIndex(nextwaypoint); } else { diff --git a/src/p_mobj.c b/src/p_mobj.c index cbe7238b3..b0e378649 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -12289,7 +12289,7 @@ ML_NOCLIMB : Direction not controllable case MT_WAYPOINT: { size_t line; - mobj->radius = 256*FRACUNIT; + mobj->radius = 384*FRACUNIT; // Same reason as for MT_SPINMACEPOINT we can't use the function to find the linedef for (line = 0; line < numlines; line++) { From add1fb87941c20c4c9a71c58f80dab16bf76d116 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Tue, 22 Oct 2019 17:05:46 -0400 Subject: [PATCH 14/56] Reduce precision of distance checks Fixes huge maps, such as Dark Race --- src/k_kart.c | 8 ++++---- src/k_waypoint.c | 12 ++++++++---- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index b376ade41..492b94c72 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -5736,11 +5736,11 @@ static void K_UpdateDistanceFromFinishLine(player_t *const player) UINT32 adddist; fixed_t disttowaypoint = P_AproxDistance( - player->mo->x - player->nextwaypoint->mobj->x, - player->mo->y - player->nextwaypoint->mobj->y); - disttowaypoint = P_AproxDistance(disttowaypoint, player->mo->z - player->nextwaypoint->mobj->z); + (player->mo->x >> FRACBITS) - (player->nextwaypoint->mobj->x >> FRACBITS), + (player->mo->y >> FRACBITS) - (player->nextwaypoint->mobj->y >> FRACBITS)); + disttowaypoint = P_AproxDistance(disttowaypoint, (player->mo->z >> FRACBITS) - (player->nextwaypoint->mobj->z >> FRACBITS)); - adddist = ((UINT32)disttowaypoint) >> FRACBITS; + adddist = (UINT32)disttowaypoint; player->distancetofinish = pathtofinish.totaldist + adddist; Z_Free(pathtofinish.array); diff --git a/src/k_waypoint.c b/src/k_waypoint.c index a73487e14..9ddf713a0 100644 --- a/src/k_waypoint.c +++ b/src/k_waypoint.c @@ -221,8 +221,10 @@ waypoint_t *K_GetClosestWaypointToMobj(mobj_t *const mobj) for (i = 0; i < numwaypoints; i++) { checkwaypoint = &waypointheap[i]; - checkdist = P_AproxDistance(mobj->x - checkwaypoint->mobj->x, mobj->y - checkwaypoint->mobj->y); - checkdist = P_AproxDistance(checkdist, mobj->z - checkwaypoint->mobj->z); + checkdist = P_AproxDistance( + (mobj->x >> FRACBITS) - (checkwaypoint->mobj->x >> FRACBITS), + (mobj->y >> FRACBITS) - (checkwaypoint->mobj->y >> FRACBITS)); + checkdist = P_AproxDistance(checkdist, (mobj->z >> FRACBITS) - (checkwaypoint->mobj->z >> FRACBITS)); if (checkdist < closestdist) { @@ -258,8 +260,10 @@ waypoint_t *K_GetBestWaypointTouchingMobj(mobj_t *const mobj) for (i = 0; i < numwaypoints; i++) { checkwaypoint = &waypointheap[i]; - checkdist = P_AproxDistance(mobj->x - checkwaypoint->mobj->x, mobj->y - checkwaypoint->mobj->y); - checkdist = P_AproxDistance(checkdist, mobj->z - checkwaypoint->mobj->z); + checkdist = P_AproxDistance( + (mobj->x >> FRACBITS) - (checkwaypoint->mobj->x >> FRACBITS), + (mobj->y >> FRACBITS) - (checkwaypoint->mobj->y >> FRACBITS)); + checkdist = P_AproxDistance(checkdist, (mobj->z >> FRACBITS) - (checkwaypoint->mobj->z >> FRACBITS)); // The mobj has to be touching this waypoint to update to it. if (checkdist <= checkwaypoint->mobj->radius) From 3c407d971ede2590c849e3f212f3f18fd866b996 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Tue, 22 Oct 2019 17:27:06 -0400 Subject: [PATCH 15/56] Rudimentary wrong way --- src/d_player.h | 1 + src/dehacked.c | 3 ++- src/k_kart.c | 7 +++++++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/d_player.h b/src/d_player.h index 163e9b7cf..07e0f7a97 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -330,6 +330,7 @@ typedef enum k_springstars, // Spawn stars around a player when they hit a spring k_springcolor, // Color of spring stars k_killfield, // How long have you been in the kill field, stay in too long and lose a bumper + k_wrongway, // Display WRONG WAY on screen NUMKARTSTUFF } kartstufftype_t; diff --git a/src/dehacked.c b/src/dehacked.c index 94b009803..fb6e7ff4f 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -8501,7 +8501,8 @@ static const char *const KARTSTUFF_LIST[] = { "TIREGREASE", "SPRINGSTARS", "SPRINGCOLOR", - "KILLFIELD" + "KILLFIELD", + "WRONGWAY" }; #endif diff --git a/src/k_kart.c b/src/k_kart.c index 492b94c72..363c762b5 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -5556,6 +5556,8 @@ static waypoint_t *K_GetPlayerNextWaypoint(player_t *player, boolean closest) { bestwaypoint = waypoint->nextwaypoints[i]; nextbestdelta = angledelta; + + player->kartstuff[k_wrongway] = 0; } } } @@ -5578,6 +5580,8 @@ static waypoint_t *K_GetPlayerNextWaypoint(player_t *player, boolean closest) { bestwaypoint = waypoint->prevwaypoints[i]; nextbestdelta = angledelta; + + player->kartstuff[k_wrongway] = 1; } } } @@ -10277,6 +10281,9 @@ void K_drawKartHUD(void) K_drawKartFreePlay(leveltime); } + if (stplyr->kartstuff[k_wrongway] && ((leveltime / 8) & 1)) + V_DrawCenteredString(BASEVIDWIDTH>>1, 176, V_REDMAP, "WRONG WAY"); + if (cv_kartdebugdistribution.value) K_drawDistributionDebugger(); From 3137e6e54a033ef076b0f83a7b1f354f9c3d441f Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Tue, 22 Oct 2019 17:41:00 -0400 Subject: [PATCH 16/56] Parathesis for defines Also just caught the ;, which could've mess up the define(?) --- src/k_waypoint.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/k_waypoint.c b/src/k_waypoint.c index 9ddf713a0..6acaadb21 100644 --- a/src/k_waypoint.c +++ b/src/k_waypoint.c @@ -11,9 +11,9 @@ static const UINT32 SPARKLES_PER_CONNECTION = 16U; // Some defaults for the size of the dynamically allocated sets for pathfinding. These are kept for the purpose of // allocating a size that is less likely to need reallocating again during the pathfinding. -#define OPENSET_BASE_SIZE 16U; -#define CLOSEDSET_BASE_SIZE 256U; -#define NODESARRAY_BASE_SIZE 256U; +#define OPENSET_BASE_SIZE (16U) +#define CLOSEDSET_BASE_SIZE (256U) +#define NODESARRAY_BASE_SIZE (256U) static waypoint_t *waypointheap = NULL; static waypoint_t *firstwaypoint = NULL; From a9a7f9c1ec5017f33028fb3639ee9ca7d496a83e Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 24 Oct 2019 08:16:25 -0400 Subject: [PATCH 17/56] Quadruple DISTVAR I picked 4096 because it's around the distance of that end slope in Green Hills, which is about the length I imagine a item block "switch" being. I'm being a little conservative though, and it might need to be even higher -- we'll have to play it by ear. Also changed the types of some of the roulette variables to better match what they are used for. --- src/k_kart.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 363c762b5..0b9eecd3b 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -709,7 +709,7 @@ static INT32 K_KartItemOddsBattle[NUMKARTRESULTS][6] = /*Jawz x2*/ { 0, 0, 1, 2, 4, 2 } // Jawz x2 }; -#define DISTVAR (1024) // Magic number distance for use with item roulette tiers +#define DISTVAR (4096) // Magic number distance for use with item roulette tiers /** \brief Item Roulette for Kart @@ -926,13 +926,13 @@ static INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed, boolean sp return newodds; } -//{ SRB2kart Roulette Code - Distance Based, no waypoints +//{ SRB2kart Roulette Code - Distance Based, yes waypoints -static INT32 K_FindUseodds(player_t *player, fixed_t mashed, INT32 pdis, INT32 bestbumper, boolean spbrush) +static UINT8 K_FindUseodds(player_t *player, fixed_t mashed, UINT32 pdis, UINT8 bestbumper, boolean spbrush) { INT32 i; INT32 n = 0; - INT32 useodds = 0; + UINT8 useodds = 0; UINT8 disttable[14]; UINT8 totallen = 0; UINT8 distlen = 0; @@ -1001,9 +1001,9 @@ static INT32 K_FindUseodds(player_t *player, fixed_t mashed, INT32 pdis, INT32 b SETUPDISTTABLE(6,3); SETUPDISTTABLE(7,1); - if (pdis <= 0) // (64*14) * 0 = 0 + if (pdis == 0) useodds = disttable[0]; - else if (pdis > DISTVAR * ((12 * distlen) / 14)) // (64*14) * 12 = 10752 + else if (pdis > DISTVAR * ((12 * distlen) / 14)) useodds = disttable[distlen-1]; else { @@ -1028,11 +1028,11 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) INT32 i; UINT8 pingame = 0; UINT8 roulettestop; - INT32 pdis = 0; - INT32 useodds = 0; + UINT32 pdis = 0; + UINT8 useodds = 0; INT32 spawnchance[NUMKARTRESULTS]; INT32 totalspawnchance = 0; - INT32 bestbumper = 0; + UINT8 bestbumper = 0; fixed_t mashed = 0; boolean dontforcespb = false; boolean spbrush = false; @@ -6046,7 +6046,12 @@ void K_KartUpdatePosition(player_t *player) fixed_t i; if (player->spectator || !player->mo) + { + // Ensure these are reset for spectators + player->kartstuff[k_position] = 0; + player->kartstuff[k_positiondelay] = 0; return; + } for (i = 0; i < MAXPLAYERS; i++) { @@ -9975,9 +9980,9 @@ static void K_drawDistributionDebugger(void) kp_orbinaut[4], kp_jawz[1] }; - INT32 useodds = 0; - INT32 pingame = 0, bestbumper = 0; - INT32 pdis = 0; + UINT8 useodds = 0; + UINT8 pingame = 0, bestbumper = 0; + UINT32 pdis = 0; INT32 i; INT32 x = -9, y = -9; boolean spbrush = false; From fc03012749b3d93fd6c430232a92b4796353fae9 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 24 Oct 2019 08:21:45 -0400 Subject: [PATCH 18/56] Use facing angle while still Also comment some of my additions a little better --- src/k_kart.c | 22 ++++++++++++++++++---- src/k_waypoint.c | 41 +++++------------------------------------ 2 files changed, 23 insertions(+), 40 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 0b9eecd3b..3e3532561 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -5500,7 +5500,7 @@ static waypoint_t *K_GetPlayerNextWaypoint(player_t *player, boolean closest) { waypoint_t *waypoint = NULL; - if (closest) + if (closest == true) waypoint = K_GetClosestWaypointToMobj(player->mo); else waypoint = K_GetBestWaypointTouchingMobj(player->mo); @@ -5514,10 +5514,18 @@ static waypoint_t *K_GetPlayerNextWaypoint(player_t *player, boolean closest) if (waypoint != NULL) { boolean finishlinehack = false; - angle_t playerangle = R_PointToAngle2(0, 0, player->mo->momx, player->mo->momy); //player->mo->angle + angle_t playerangle = player->mo->angle; angle_t angletowaypoint = R_PointToAngle2(player->mo->x, player->mo->y, waypoint->mobj->x, waypoint->mobj->y); - angle_t angledelta = playerangle - angletowaypoint; + angle_t angledelta = ANGLE_MAX; + + if (player->mo->momx != 0 || player->mo->momy != 0) + { + // Default to facing angle if you're not moving, but use momentum angle otherwise. + playerangle = R_PointToAngle2(0, 0, player->mo->momx, player->mo->momy); + } + + angledelta = playerangle - angletowaypoint; if (angledelta > ANGLE_180) { @@ -5533,6 +5541,7 @@ static waypoint_t *K_GetPlayerNextWaypoint(player_t *player, boolean closest) } } + // The wrong way flag will use its previous value if we're facing sideways if ((angledelta > ANGLE_45) && (finishlinehack == false)) { angle_t nextbestdelta = angledelta; @@ -5557,6 +5566,7 @@ static waypoint_t *K_GetPlayerNextWaypoint(player_t *player, boolean closest) bestwaypoint = waypoint->nextwaypoints[i]; nextbestdelta = angledelta; + // Remove wrong way flag if we're using nextwaypoints player->kartstuff[k_wrongway] = 0; } } @@ -5581,6 +5591,7 @@ static waypoint_t *K_GetPlayerNextWaypoint(player_t *player, boolean closest) bestwaypoint = waypoint->prevwaypoints[i]; nextbestdelta = angledelta; + // Set wrong way flag if we're using prevwaypoints player->kartstuff[k_wrongway] = 1; } } @@ -5681,6 +5692,7 @@ static void K_UpdateDistanceFromFinishLine(player_t *const player) if ((nextwaypoint == NULL) && (player->nextwaypoint == NULL)) { // Special case: if player nextwaypoint is still NULL, we want to fix that as soon as possible, so use the closest waypoint instead. + // This will most likely only happen on map load or player spawn. nextwaypoint = K_GetPlayerNextWaypoint(player, true); } @@ -5695,6 +5707,7 @@ static void K_UpdateDistanceFromFinishLine(player_t *const player) player->starpostz = nextwaypoint->mobj->z >> FRACBITS; // player gravflip determines which way to respawn + // (should waypoints have a flip option?) player->kartstuff[k_starpostflip] = player->mo->flags2 & MF2_OBJECTFLIP; // starpostangle is to the first valid nextwaypoint for simplicity @@ -5717,7 +5730,8 @@ static void K_UpdateDistanceFromFinishLine(player_t *const player) if (nextwaypoint != NULL) { - // At this point, we don't want to update the waypoint until we touch another. + // If nextwaypoint is NULL, it means we don't want to update the waypoint until we touch another one. + // player->nextwaypoint will keep its previous value in this case. player->nextwaypoint = nextwaypoint; } diff --git a/src/k_waypoint.c b/src/k_waypoint.c index 6acaadb21..695d47201 100644 --- a/src/k_waypoint.c +++ b/src/k_waypoint.c @@ -265,43 +265,12 @@ waypoint_t *K_GetBestWaypointTouchingMobj(mobj_t *const mobj) (mobj->y >> FRACBITS) - (checkwaypoint->mobj->y >> FRACBITS)); checkdist = P_AproxDistance(checkdist, (mobj->z >> FRACBITS) - (checkwaypoint->mobj->z >> FRACBITS)); - // The mobj has to be touching this waypoint to update to it. - if (checkdist <= checkwaypoint->mobj->radius) + // The mobj has to be touching this waypoint to use it. + if ((checkdist <= checkwaypoint->mobj->radius) + && (checkdist < bestdist)) { -#if 0 - // This kind of algorithm may or may not be more reliable than what's below. - // But it's a little heavier, computation-wise. - // We'll see if simple closer checks work fine in netgame testing, or if it needs this. - boolean success = false; - path_t pathtofinish = {}; - success = K_PathfindToWaypoint(checkwaypoint, finishline, &pathtofinish, false, false); - - // If you're touching more than 1 waypoint, then we use the closest one to the finish line. - if (success == true) - { - // Add euclidean distance to the next waypoint to the distancetofinish - UINT32 distancetofinish; - UINT32 adddist; - - adddist = ((UINT32)checkdist) >> FRACBITS; - - distancetofinish = pathtofinish.totaldist + adddist; - Z_Free(pathtofinish.array); - - if (distancetofinish < bestdist) - { - bestwaypoint = checkwaypoint; - bestdist = checkdist; - } - } -#else - // Simple closest check - if (checkdist < bestdist) - { - bestwaypoint = checkwaypoint; - bestdist = checkdist; - } -#endif + bestwaypoint = checkwaypoint; + bestdist = checkdist; } } } From acb8d61fb627d4b5eb28ff09e1d1143769d4a1e4 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 24 Oct 2019 08:56:03 -0400 Subject: [PATCH 19/56] These don't need to be INT32s either --- src/k_kart.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 3e3532561..eb6d68a59 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -930,8 +930,8 @@ static INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed, boolean sp static UINT8 K_FindUseodds(player_t *player, fixed_t mashed, UINT32 pdis, UINT8 bestbumper, boolean spbrush) { - INT32 i; - INT32 n = 0; + UINT8 i; + UINT8 n = 0; UINT8 useodds = 0; UINT8 disttable[14]; UINT8 totallen = 0; @@ -940,7 +940,7 @@ static UINT8 K_FindUseodds(player_t *player, fixed_t mashed, UINT32 pdis, UINT8 for (i = 0; i < 8; i++) { - INT32 j; + UINT8 j; boolean available = false; if (G_BattleGametype() && i > 5) From ae72a365f36484c89c00d0ef2879c976eb0b369c Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Thu, 24 Oct 2019 20:50:27 +0200 Subject: [PATCH 20/56] Fix SPB pathing --- src/p_enemy.c | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index a4684b40b..f64acbfd6 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -8714,6 +8714,7 @@ void A_SPBChase(mobj_t *actor) waypoint_t *lastwaypoint = NULL; waypoint_t *bestwaypoint = NULL; waypoint_t *nextwaypoint = NULL; + waypoint_t *tempwaypoint = NULL; actor->lastlook = -1; // Just make sure this is reset @@ -8732,13 +8733,22 @@ void A_SPBChase(mobj_t *actor) dist = P_AproxDistance(P_AproxDistance(actor->x-actor->tracer->x, actor->y-actor->tracer->y), actor->z-actor->tracer->z); // Move along the waypoints until you get close enough - if (actor->cusval > -1) + if (actor->cusval > -1 && actor->extravalue2 > 0) { // Previously set nextwaypoint lastwaypoint = K_GetWaypointFromIndex((size_t)actor->cusval); - } + tempwaypoint = K_GetBestWaypointTouchingMobj(actor); + // check if the tempwaypoint corresponds to lastwaypoint's next ID at least; + // This is to avoid situations where the SPB decides to suicide jump down a bridge because it found a COMPLETELY unrelated waypoint down there. - bestwaypoint = K_GetBestWaypointTouchingMobj(actor); + if (K_GetWaypointID(tempwaypoint) == K_GetWaypointNextID(lastwaypoint) || K_GetWaypointID(tempwaypoint) == K_GetWaypointID(lastwaypoint)) + // either our previous or curr waypoint ID, sure, take it + bestwaypoint = tempwaypoint; + else + bestwaypoint = K_GetWaypointFromIndex((size_t)actor->extravalue2); // keep going from the PREVIOUS wp. + } + else + bestwaypoint = K_GetBestWaypointTouchingMobj(actor); if (bestwaypoint == NULL && lastwaypoint == NULL) { @@ -8761,12 +8771,6 @@ void A_SPBChase(mobj_t *actor) bestwaypoint, player->nextwaypoint, useshortcuts, huntbackwards); } - if (nextwaypoint == NULL && lastwaypoint != NULL) - { - // Restore to the last nextwaypoint - nextwaypoint = lastwaypoint; - } - if (nextwaypoint != NULL) { const fixed_t xywaypointdist = P_AproxDistance( @@ -8776,6 +8780,7 @@ void A_SPBChase(mobj_t *actor) vang = R_PointToAngle2(0, actor->z, xywaypointdist, nextwaypoint->mobj->z); actor->cusval = (INT32)K_GetWaypointHeapIndex(nextwaypoint); + actor->extravalue2 = (INT32)K_GetWaypointHeapIndex(bestwaypoint); // save our last best, used above. } else { @@ -8832,6 +8837,13 @@ void A_SPBChase(mobj_t *actor) } } + // Finally, no matter what, the spb should not be able to be under the ground, or above the ceiling; + if (actor->z < actor->floorz + 8*mapobjectscale) + actor->z = actor->floorz + 8*mapobjectscale; + else if (actor->z > actor->ceilingz - 8*mapobjectscale) + actor->z = actor->ceilingz - 8*mapobjectscale; + + return; } From 08ae2c926edf4696bea11e0256ac3e0200b5ad6a Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Thu, 24 Oct 2019 21:00:58 +0200 Subject: [PATCH 21/56] Accidentally removed a bit of code I shouldn't have removed --- src/p_enemy.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/p_enemy.c b/src/p_enemy.c index f64acbfd6..65a66fdb5 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -8771,6 +8771,13 @@ void A_SPBChase(mobj_t *actor) bestwaypoint, player->nextwaypoint, useshortcuts, huntbackwards); } + if (nextwaypoint == NULL && lastwaypoint != NULL) + { + // Restore to the last nextwaypoint + nextwaypoint = lastwaypoint; + } + + if (nextwaypoint != NULL) { const fixed_t xywaypointdist = P_AproxDistance( From b69d105af3d446e1a537c5beac2aeff650c61153 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 24 Oct 2019 16:35:39 -0400 Subject: [PATCH 22/56] Add respawn animation This commit also fixes MF_NOCLIP not working properly on players. Sink now spawns an SPB explosion on successful hit, since dying is no longer a harsh punishment. --- src/d_netcmd.c | 14 ++-- src/dehacked.c | 5 ++ src/g_game.c | 5 +- src/info.c | 7 +- src/info.h | 5 ++ src/k_kart.c | 185 +++++++++++++++++++++++++++++++++++++++++-------- src/k_kart.h | 1 + src/m_cheat.c | 9 +++ src/p_enemy.c | 4 +- src/p_map.c | 26 +++++-- src/p_mobj.c | 8 ++- src/p_spec.c | 12 ++-- src/p_user.c | 6 -- 13 files changed, 227 insertions(+), 60 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index c19f8e391..39434928b 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -2842,13 +2842,15 @@ static void Got_Respawn(UINT8 **cp, INT32 playernum) return; } - // incase the above checks were modified to allow sending a respawn on these occasions: - if (players[respawnplayer].mo && !P_IsObjectOnGround(players[respawnplayer].mo)) - return; - if (players[respawnplayer].mo) - P_DamageMobj(players[respawnplayer].mo, NULL, NULL, 10000); - demo_extradata[playernum] |= DXD_RESPAWN; + { + // incase the above checks were modified to allow sending a respawn on these occasions: + if (!P_IsObjectOnGround(players[respawnplayer].mo)) + return; + + K_DoIngameRespawn(&players[respawnplayer]); + demo_extradata[playernum] |= DXD_RESPAWN; + } } /** Deals with an ::XD_RANDOMSEED message in a netgame. diff --git a/src/dehacked.c b/src/dehacked.c index fb6e7ff4f..6b99eeb7c 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -6661,6 +6661,11 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit // DEZ respawn laser "S_DEZLASER", + "S_DEZLASER_TRAIL1", + "S_DEZLASER_TRAIL2", + "S_DEZLASER_TRAIL3", + "S_DEZLASER_TRAIL4", + "S_DEZLASER_TRAIL5", // Audience Members "S_RANDOMAUDIENCE", diff --git a/src/g_game.c b/src/g_game.c index 0b58855a0..ad41f13af 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -4915,7 +4915,10 @@ void G_ReadDemoExtraData(void) if (extradata & DXD_RESPAWN) { if (players[p].mo) - P_DamageMobj(players[p].mo, NULL, NULL, 10000); // Is this how this should work..? + { + // Is this how this should work..? + K_DoIngameRespawn(&players[p]); + } } if (extradata & DXD_SKIN) { diff --git a/src/info.c b/src/info.c index 60ffbc626..943c0bbb9 100644 --- a/src/info.c +++ b/src/info.c @@ -2875,7 +2875,12 @@ state_t states[NUMSTATES] = {SPR_KBLN, FF_FULLBRIGHT|1, -1, {NULL}, 0, 0, S_BATTLEBUMPER2}, // S_BATTLEBUMPER2 {SPR_KBLN, FF_FULLBRIGHT|2, -1, {NULL}, 0, 0, S_BATTLEBUMPER3}, // S_BATTLEBUMPER3 - {SPR_DEZL, FF_FULLBRIGHT|FF_PAPERSPRITE, 8, {NULL}, 0, 0, S_NULL}, // S_DEZLASER + {SPR_DEZL, FF_FULLBRIGHT|FF_PAPERSPRITE, 8, {NULL}, 0, 0, S_NULL}, // S_DEZLASER + {SPR_DEZL, FF_FULLBRIGHT|1, 2, {NULL}, 0, 0, S_DEZLASER_TRAIL2}, // S_DEZLASER_TRAIL1 + {SPR_DEZL, FF_FULLBRIGHT|2, 2, {NULL}, 0, 0, S_DEZLASER_TRAIL3}, // S_DEZLASER_TRAIL2 + {SPR_DEZL, FF_FULLBRIGHT|FF_PAPERSPRITE|3, 4, {NULL}, 0, 0, S_DEZLASER_TRAIL4}, // S_DEZLASER_TRAIL3 + {SPR_DEZL, FF_FULLBRIGHT|2, 2, {NULL}, 0, 0, S_DEZLASER_TRAIL5}, // S_DEZLASER_TRAIL4 + {SPR_DEZL, FF_FULLBRIGHT|1, 2, {NULL}, 0, 0, S_NULL}, // S_DEZLASER_TRAIL5 {SPR_NULL, 0, 1, {A_RandomStateRange}, S_AUDIENCE_CHAO_CHEER1, S_AUDIENCE_CHAO_CHEER2, S_RANDOMAUDIENCE}, // S_RANDOMAUDIENCE diff --git a/src/info.h b/src/info.h index 27488d916..f47a4a151 100644 --- a/src/info.h +++ b/src/info.h @@ -3550,6 +3550,11 @@ typedef enum state // DEZ Laser respawn S_DEZLASER, + S_DEZLASER_TRAIL1, + S_DEZLASER_TRAIL2, + S_DEZLASER_TRAIL3, + S_DEZLASER_TRAIL4, + S_DEZLASER_TRAIL5, // Audience Members S_RANDOMAUDIENCE, diff --git a/src/k_kart.c b/src/k_kart.c index eb6d68a59..936259d8f 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1919,6 +1919,29 @@ static void K_SpawnBrakeDriftSparks(player_t *player) // Be sure to update the m sparks->flags2 |= MF2_DONTDRAW; } +/** \brief Preps a player to respawn + + \param player player to respawn + + \return void +*/ +void K_DoIngameRespawn(player_t *player) +{ + if (!player->mo || P_MobjWasRemoved(player->mo)) + return; + + if (player->kartstuff[k_respawn]) + return; + + if (leveltime <= starttime) + return; + + player->mo->flags &= ~(MF_SOLID|MF_SHOOTABLE); + player->mo->flags |= MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOCLIPTHING|MF_NOGRAVITY; + player->mo->flags2 &= ~MF2_DONTDRAW; + player->kartstuff[k_respawn] = 48; +} + /** \brief Calculates the respawn timer and drop-boosting \param player player object passed from K_KartPlayerThink @@ -1934,39 +1957,136 @@ void K_RespawnChecker(player_t *player) if (player->kartstuff[k_respawn] > 1) { - player->kartstuff[k_respawn]--; - player->mo->momz = 0; + fixed_t destx = 0, desty = 0, destz = 0; + + player->mo->momx = player->mo->momy = player->mo->momz = 0; player->powers[pw_flashing] = 2; player->powers[pw_nocontrol] = 2; - if (leveltime % 8 == 0) + + if (leveltime % 8 == 0 && !mapreset) + S_StartSound(player->mo, sfx_s3kcas); + + destx = (player->starpostx << FRACBITS); + desty = (player->starposty << FRACBITS); + destz = (player->starpostz << FRACBITS); + + if (player->kartstuff[k_starpostflip]) + destz -= (128 * mapobjectscale) + (player->mo->height); + else + destz += (128 * mapobjectscale); + + if (player->mo->x != destx || player->mo->y != desty || player->mo->z != destz) { - INT32 i; - if (!mapreset) - S_StartSound(player->mo, sfx_s3kcas); + fixed_t step = 64*mapobjectscale; + fixed_t dist = P_AproxDistance(P_AproxDistance(player->mo->x - destx, player->mo->y - desty), player->mo->z - destz); - for (i = 0; i < 8; i++) + if (dist <= step) // You're ready to respawn { - mobj_t *mo; - angle_t newangle; - fixed_t newx, newy, newz; + P_TryMove(player->mo, destx, desty, true); + player->mo->z = destz; + } + else + { + fixed_t stepx = 0, stepy = 0, stepz = 0; + angle_t stepha = R_PointToAngle2(player->mo->x, player->mo->y, destx, desty); + angle_t stepva = R_PointToAngle2(0, player->mo->z, P_AproxDistance(player->mo->x - destx, player->mo->y - desty), destz); + fixed_t laserx = 0, lasery = 0, laserz = 0; + UINT8 lasersteps = 4; - newangle = FixedAngle(((360/8)*i)*FRACUNIT); - newx = player->mo->x + P_ReturnThrustX(player->mo, newangle, 31<mo->y + P_ReturnThrustY(player->mo, newangle, 31<mo->eflags & MFE_VERTICALFLIP) - newz = player->mo->z + player->mo->height; - else - newz = player->mo->z; + // Move toward the respawn point + stepx = FixedMul(FixedMul(FINECOSINE(stepha >> ANGLETOFINESHIFT), step), FINECOSINE(stepva >> ANGLETOFINESHIFT)); + stepy = FixedMul(FixedMul(FINESINE(stepha >> ANGLETOFINESHIFT), step), FINECOSINE(stepva >> ANGLETOFINESHIFT)); + stepz = FixedMul(FINESINE(stepva >> ANGLETOFINESHIFT), 2*step); - mo = P_SpawnMobj(newx, newy, newz, MT_DEZLASER); - if (mo) + P_TryMove(player->mo, player->mo->x + stepx, player->mo->y + stepy, true); + player->mo->z += stepz; + + // Spawn lasers along the path + laserx = player->mo->x + (stepx / 2); + lasery = player->mo->y + (stepy / 2); + laserz = player->mo->z + (stepz / 2); + dist = P_AproxDistance(P_AproxDistance(laserx - destx, lasery - desty), laserz - destz); + + if (dist > step/2) { + while (lasersteps) + { + + stepha = R_PointToAngle2(laserx, lasery, destx, desty); + stepva = R_PointToAngle2(0, laserz, P_AproxDistance(laserx - destx, lasery - desty), destz); + + stepx = FixedMul(FixedMul(FINECOSINE(stepha >> ANGLETOFINESHIFT), step), FINECOSINE(stepva >> ANGLETOFINESHIFT)); + stepy = FixedMul(FixedMul(FINESINE(stepha >> ANGLETOFINESHIFT), step), FINECOSINE(stepva >> ANGLETOFINESHIFT)); + stepz = FixedMul(FINESINE(stepva >> ANGLETOFINESHIFT), 2*step); + + laserx += stepx; + lasery += stepy; + laserz += stepz; + dist = P_AproxDistance(P_AproxDistance(laserx - destx, lasery - desty), laserz - destz); + + if (dist <= step/2) + break; + + lasersteps--; + } + } + + if (lasersteps == 0) // Don't spawn them beyond the respawn point. + { + mobj_t *laser; + + laser = P_SpawnMobj(laserx, lasery, laserz + (player->mo->height / 2), MT_DEZLASER); + + if (laser && !P_MobjWasRemoved(laser)) + { + P_SetMobjState(laser, S_DEZLASER_TRAIL1); + if (player->mo->eflags & MFE_VERTICALFLIP) + laser->eflags |= MFE_VERTICALFLIP; + P_SetTarget(&laser->target, player->mo); + laser->angle = stepha + ANGLE_90; + P_SetScale(laser, (laser->destscale = FRACUNIT)); + } + } + } + } + else + { + player->kartstuff[k_respawn]--; + + player->mo->flags |= MF_SOLID|MF_SHOOTABLE; + player->mo->flags &= ~(MF_NOCLIPHEIGHT|MF_NOCLIPTHING|MF_NOGRAVITY); + if (!(player->pflags & PF_NOCLIP)) + player->mo->flags &= ~MF_NOCLIP; + + if (leveltime % 8 == 0) + { + INT32 i; + + for (i = 0; i < 8; i++) + { + mobj_t *laser; + angle_t newangle; + fixed_t newx, newy, newz; + + newangle = FixedAngle(((360/8)*i)*FRACUNIT); + newx = player->mo->x + P_ReturnThrustX(player->mo, newangle, 31<mo->y + P_ReturnThrustY(player->mo, newangle, 31<mo->eflags & MFE_VERTICALFLIP) - mo->eflags |= MFE_VERTICALFLIP; - P_SetTarget(&mo->target, player->mo); - mo->angle = newangle+ANGLE_90; - mo->momz = (8<mo); - P_SetScale(mo, (mo->destscale = FRACUNIT)); + newz = player->mo->z + player->mo->height; + else + newz = player->mo->z; + + laser = P_SpawnMobj(newx, newy, newz, MT_DEZLASER); + + if (laser && !P_MobjWasRemoved(laser)) + { + if (player->mo->eflags & MFE_VERTICALFLIP) + laser->eflags |= MFE_VERTICALFLIP; + P_SetTarget(&laser->target, player->mo); + laser->angle = newangle+ANGLE_90; + laser->momz = (8<mo); + P_SetScale(laser, (laser->destscale = FRACUNIT)); + } } } } @@ -5313,8 +5433,15 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) player->kartstuff[k_stolentimer]--; if (player->kartstuff[k_squishedtimer]) + { player->kartstuff[k_squishedtimer]--; + if ((player->kartstuff[k_squishedtimer] == 0) && !(player->pflags & PF_NOCLIP)) + { + player->mo->flags &= ~MF_NOCLIP; + } + } + if (player->kartstuff[k_justbumped]) player->kartstuff[k_justbumped]--; @@ -5698,10 +5825,12 @@ static void K_UpdateDistanceFromFinishLine(player_t *const player) if ((nextwaypoint != NULL) && (nextwaypoint != player->nextwaypoint) && + (player->kartstuff[k_respawn] == 0) && (K_GetWaypointIsShortcut(nextwaypoint) == false) && (K_GetWaypointIsEnabled(nextwaypoint) == true)) { size_t i = 0U; waypoint_t *aimwaypoint = NULL; + player->starpostx = nextwaypoint->mobj->x >> FRACBITS; player->starposty = nextwaypoint->mobj->y >> FRACBITS; player->starpostz = nextwaypoint->mobj->z >> FRACBITS; @@ -6895,13 +7024,9 @@ void K_MoveKartPlayer(player_t *player, boolean onground) // Squishing // If a Grow player or a sector crushes you, get flattened instead of being killed. - if (player->kartstuff[k_squishedtimer] <= 0) + if (player->kartstuff[k_squishedtimer] > 0) { - player->mo->flags &= ~MF_NOCLIP; - } - else - { - player->mo->flags |= MF_NOCLIP; + //player->mo->flags |= MF_NOCLIP; player->mo->momx = 0; player->mo->momy = 0; } diff --git a/src/k_kart.h b/src/k_kart.h index b91e8c8a1..ff6f6fafc 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -27,6 +27,7 @@ void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid) void K_KartPainEnergyFling(player_t *player); void K_FlipFromObject(mobj_t *mo, mobj_t *master); void K_MatchGenericExtraFlags(mobj_t *mo, mobj_t *master); +void K_DoIngameRespawn(player_t *player); void K_RespawnChecker(player_t *player); void K_KartMoveAnimation(player_t *player); void K_KartPlayerHUDUpdate(player_t *player); diff --git a/src/m_cheat.c b/src/m_cheat.c index c24a8014b..d61d22cd0 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -292,9 +292,18 @@ void Command_CheatNoClip_f(void) REQUIRE_NOULTIMATE; plyr = &players[consoleplayer]; + + if (!plyr->mo || P_MobjWasRemoved(plyr->mo)) + return; + plyr->pflags ^= PF_NOCLIP; CONS_Printf(M_GetText("No Clipping %s\n"), plyr->pflags & PF_NOCLIP ? M_GetText("On") : M_GetText("Off")); + if (plyr->pflags & PF_NOCLIP) + plyr->mo->flags |= MF_NOCLIP; + else + plyr->mo->flags &= ~MF_NOCLIP; + G_SetGameModified(multiplayer, true); } diff --git a/src/p_enemy.c b/src/p_enemy.c index a4684b40b..86e615ee8 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -10673,8 +10673,8 @@ void A_RemoteDamage(mobj_t *actor) if (locvar2 == 1) // Kill mobj! { - if (target->player) // players die using P_DamageMobj instead for some reason - P_DamageMobj(target, source, source, 10000); + if (target->player) + K_DoIngameRespawn(target->player); else P_KillMobj(target, source, source); } diff --git a/src/p_map.c b/src/p_map.c index 9585849f7..52a19e1c0 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -1005,12 +1005,20 @@ static boolean PIT_CheckThing(mobj_t *thing) if (thing->type == MT_PLAYER) { - S_StartSound(NULL, sfx_bsnipe); //let all players hear it. + mobj_t *explosion; + + S_StartSound(NULL, sfx_bsnipe); // let all players hear it. + HU_SetCEchoFlags(0); HU_SetCEchoDuration(5); HU_DoCEcho(va("%s\\was hit by a kitchen sink.\\\\\\\\", player_names[thing->player-players])); I_OutputMsg("%s was hit by a kitchen sink.\n", player_names[thing->player-players]); - P_DamageMobj(thing, tmthing, tmthing->target, 10000); + + explosion = P_SpawnMobj(thing->x, thing->y, thing->z, MT_SPBEXPLOSION); + explosion->extravalue1 = 1; // Tell K_ExplodePlayer to use extra knockback + if (tmthing->target && !P_MobjWasRemoved(tmthing->target)) + P_SetTarget(&explosion->target, tmthing->target); + P_KillMobj(tmthing, thing, thing); } @@ -1269,15 +1277,23 @@ static boolean PIT_CheckThing(mobj_t *thing) } else if (thing->type == MT_SINK) { + mobj_t *explosion; + if ((thing->target == tmthing) && (thing->threshold > 0)) return true; - S_StartSound(NULL, sfx_cgot); //let all players hear it. + S_StartSound(NULL, sfx_bsnipe); // let all players hear it. + HU_SetCEchoFlags(0); HU_SetCEchoDuration(5); HU_DoCEcho(va("%s\\was hit by a kitchen sink.\\\\\\\\", player_names[tmthing->player-players])); I_OutputMsg("%s was hit by a kitchen sink.\n", player_names[tmthing->player-players]); - P_DamageMobj(tmthing, thing, thing->target, 10000); + + explosion = P_SpawnMobj(tmthing->x, tmthing->y, tmthing->z, MT_SPBEXPLOSION); + explosion->extravalue1 = 1; // Tell K_ExplodePlayer to use extra knockback + if (thing->target && !P_MobjWasRemoved(thing->target)) + P_SetTarget(&explosion->target, thing->target); + P_KillMobj(thing, tmthing, tmthing); } @@ -1662,7 +1678,7 @@ static boolean PIT_CheckThing(mobj_t *thing) { // Objects kill you if it falls from above. if (thing != tmthing->target) - P_DamageMobj(thing, tmthing, tmthing->target, 10000); + K_DoIngameRespawn(thing->player); tmthing->momz = -tmthing->momz/2; // Bounce, just for fun! // The tmthing->target allows the pusher of the object diff --git a/src/p_mobj.c b/src/p_mobj.c index b0e378649..b04bf717a 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11475,6 +11475,9 @@ void P_SpawnPlayer(INT32 playernum) // Spawn with a pity shield if necessary. //P_DoPityCheck(p); + if (p->kartstuff[k_respawn] != 0) + p->mo->flags |= MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOCLIPTHING|MF_NOGRAVITY; + if (G_BattleGametype()) // SRB2kart { mobj_t *overheadarrow = P_SpawnMobj(mobj->x, mobj->y, mobj->z + P_GetPlayerHeight(p)+16*FRACUNIT, MT_PLAYERARROW); @@ -11691,11 +11694,10 @@ void P_MovePlayerToStarpost(INT32 playernum) sector->ceilingheight; if (mobj->player->kartstuff[k_starpostflip]) - z = (p->starpostz<height; + z = (p->starpostz<height; else - z = (p->starpostz<starpostz<starpostz + 128) << FRACBITS; // reverse gravity exists, pls mobj->player->kartstuff[k_starpostflip] = 0; if (z < floor) diff --git a/src/p_spec.c b/src/p_spec.c index b71d7508c..f83ca79a7 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3777,10 +3777,10 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers case 6: // Death Pit (Camera Mod) case 7: // Death Pit (No Camera Mod) if (roversector || P_MobjReadyToTrigger(player->mo, sector)) - P_DamageMobj(player->mo, NULL, NULL, 10000); + K_DoIngameRespawn(player); break; case 8: // Instant Kill - P_DamageMobj(player->mo, NULL, NULL, 10000); + K_DoIngameRespawn(player); break; case 9: // Ring Drainer (Floor Touch) case 10: // Ring Drainer (No Floor Touch) @@ -6954,8 +6954,8 @@ void T_Scroll(scroll_t *s) height = P_GetSpecialBottomZ(thing, sec, psec); - if (!(thing->flags & MF_NOCLIP)) // Thing must be clipped - if (!(thing->flags & MF_NOGRAVITY || thing->z+thing->height != height)) // Thing must a) be non-floating and have z+height == height + if (!(thing->flags & MF_NOCLIP) && // Thing must be clipped + (!(thing->flags & MF_NOGRAVITY || thing->z+thing->height != height))) // Thing must a) be non-floating and have z+height == height { // Move objects only if on floor // non-floating, and clipped. @@ -7030,8 +7030,8 @@ void T_Scroll(scroll_t *s) height = P_GetSpecialTopZ(thing, sec, psec); - if (!(thing->flags & MF_NOCLIP)) // Thing must be clipped - if (!(thing->flags & MF_NOGRAVITY || thing->z != height))// Thing must a) be non-floating and have z == height + if (!(thing->flags & MF_NOCLIP) && // Thing must be clipped + (!(thing->flags & MF_NOGRAVITY || thing->z != height))) // Thing must a) be non-floating and have z == height { // Move objects only if on floor or underwater, // non-floating, and clipped. diff --git a/src/p_user.c b/src/p_user.c index 16aeeb054..6267559e0 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -8047,12 +8047,6 @@ void P_PlayerThink(player_t *player) // The timer might've reached zero, but we'll run the remote view camera anyway by setting it to -1. } - /// \note do this in the cheat code - if (player->pflags & PF_NOCLIP) - player->mo->flags |= MF_NOCLIP; - else - player->mo->flags &= ~MF_NOCLIP; - cmd = &player->cmd; // SRB2kart From ed007f34ccb183559e44752b1c2b51e567f0750f Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 24 Oct 2019 16:55:13 -0400 Subject: [PATCH 23/56] change colors, since orange & yellow are pretty indistinguishable --- src/k_waypoint.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/k_waypoint.c b/src/k_waypoint.c index 695d47201..ab3bd8be9 100644 --- a/src/k_waypoint.c +++ b/src/k_waypoint.c @@ -421,11 +421,11 @@ void K_DebugWaypointsVisualise(void) } else if (waypoint->numnextwaypoints == 0 || waypoint->numprevwaypoints == 0) { - debugmobj->color = SKINCOLOR_ORANGE; + debugmobj->color = SKINCOLOR_YELLOW; } else if (waypoint == players[displayplayers[0]].nextwaypoint) { - debugmobj->color = SKINCOLOR_YELLOW; + debugmobj->color = SKINCOLOR_GREEN; } else { From 3686445f2f378be529acd43eecbe360a5ba7c9f1 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 24 Oct 2019 17:11:27 -0400 Subject: [PATCH 24/56] Snap to bottom on WRONG WAY --- src/k_kart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_kart.c b/src/k_kart.c index 936259d8f..ccc9ff447 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -10426,7 +10426,7 @@ void K_drawKartHUD(void) } if (stplyr->kartstuff[k_wrongway] && ((leveltime / 8) & 1)) - V_DrawCenteredString(BASEVIDWIDTH>>1, 176, V_REDMAP, "WRONG WAY"); + V_DrawCenteredString(BASEVIDWIDTH>>1, 176, V_REDMAP|V_SNAPTOBOTTOM, "WRONG WAY"); if (cv_kartdebugdistribution.value) K_drawDistributionDebugger(); From 6fbaa72e824426356a77e4ce3b0503d116e3b487 Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Thu, 24 Oct 2019 23:35:05 +0200 Subject: [PATCH 25/56] Lower SPB speed, add SPB on minimap, add slight targetting on SPB against non-1st --- src/info.c | 2 +- src/k_kart.c | 17 ++++++++++++++--- src/p_enemy.c | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 4 deletions(-) diff --git a/src/info.c b/src/info.c index 60ffbc626..19deea636 100644 --- a/src/info.c +++ b/src/info.c @@ -15998,7 +15998,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_SPB_DEAD, // deathstate S_NULL, // xdeathstate sfx_s3k5d, // deathsound - 96*FRACUNIT, // speed + 64*FRACUNIT, // speed 24*FRACUNIT, // radius 48*FRACUNIT, // height 0, // display offset diff --git a/src/k_kart.c b/src/k_kart.c index eb6d68a59..02214a832 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -4985,6 +4985,9 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) K_UpdateDraft(player); K_UpdateEngineSounds(player, cmd); // Thanks, VAda! + if (spbplace == -1) // no spb + player->axis1 = NULL; // remove this + // update boost angle if not spun out if (!player->kartstuff[k_spinouttimer] && !player->kartstuff[k_wipeoutslow]) player->kartstuff[k_boostangle] = (INT32)player->mo->angle; @@ -5519,7 +5522,7 @@ static waypoint_t *K_GetPlayerNextWaypoint(player_t *player, boolean closest) R_PointToAngle2(player->mo->x, player->mo->y, waypoint->mobj->x, waypoint->mobj->y); angle_t angledelta = ANGLE_MAX; - if (player->mo->momx != 0 || player->mo->momy != 0) + if (player->mo->momx != 0 || player->mo->momy != 0) { // Default to facing angle if you're not moving, but use momentum angle otherwise. playerangle = R_PointToAngle2(0, 0, player->mo->momx, player->mo->momy); @@ -9417,7 +9420,11 @@ static void K_drawKartMinimap(void) // Target reticule if ((G_RaceGametype() && players[i].kartstuff[k_position] == spbplace) || (G_BattleGametype() && K_IsPlayerWanted(&players[i]))) - K_drawKartMinimapIcon(players[i].mo->x, players[i].mo->y, x, y, splitflags, kp_wantedreticle, NULL, AutomapPic); + K_drawKartMinimapIcon(players[i].mo->x, players[i].mo->y, x, y, splitflags, kp_wantedreticle, NULL, AutomapPic); + + if (players[i].axis1 && !P_MobjWasRemoved(players[i].axis1)) // SPB after the player? + K_drawKartMinimapIcon(players[i].axis1->x, players[i].axis1->y, x, y, splitflags, kp_ringspblocksmall[14 + leveltime%4 /2], NULL, AutomapPic); + } } @@ -9450,7 +9457,11 @@ static void K_drawKartMinimap(void) // Target reticule if ((G_RaceGametype() && players[localplayers[i]].kartstuff[k_position] == spbplace) || (G_BattleGametype() && K_IsPlayerWanted(&players[localplayers[i]]))) - K_drawKartMinimapIcon(players[localplayers[i]].mo->x, players[localplayers[i]].mo->y, x, y, splitflags, kp_wantedreticle, NULL, AutomapPic); + K_drawKartMinimapIcon(players[localplayers[i]].mo->x, players[localplayers[i]].mo->y, x, y, splitflags, kp_wantedreticle, NULL, AutomapPic); + + if (players[localplayers[i]].axis1 && !P_MobjWasRemoved(players[localplayers[i]].axis1)) // SPB after the player? + K_drawKartMinimapIcon(players[localplayers[i]].axis1->x, players[localplayers[i]].axis1->y, x, y, splitflags, kp_ringspblocksmall[14 + leveltime%4 /2], NULL, AutomapPic); + } } diff --git a/src/p_enemy.c b/src/p_enemy.c index 65a66fdb5..d896aa485 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -8495,11 +8495,15 @@ static void SpawnSPBTrailRings(mobj_t *actor) void A_SPBChase(mobj_t *actor) { player_t *player = NULL; + player_t *scplayer = NULL; // secondary target for seeking UINT8 i; UINT8 bestrank = UINT8_MAX; fixed_t dist; angle_t hang, vang; fixed_t wspeed, xyspeed, zspeed; + fixed_t pdist = 1536<axis1, actor); // axis is the SPB trailing the player. + // lastlook = last player num targetted // cvmem = stored speed // cusval = next waypoint heap index @@ -8828,10 +8835,36 @@ void A_SPBChase(mobj_t *actor) actor->movedir += input; } + actor->momx = FixedMul(FixedMul(xyspeed, FINECOSINE(actor->angle>>ANGLETOFINESHIFT)), FINECOSINE(actor->movedir>>ANGLETOFINESHIFT)); actor->momy = FixedMul(FixedMul(xyspeed, FINESINE(actor->angle>>ANGLETOFINESHIFT)), FINECOSINE(actor->movedir>>ANGLETOFINESHIFT)); actor->momz = FixedMul(zspeed, FINESINE(actor->movedir>>ANGLETOFINESHIFT)); + // see if a player is near us, if they are, try to hit them by slightly thrusting towards them, otherwise, bleh! + for (i=0; i < MAXPLAYERS; i++) + { + if (!playeringame[i] || players[i].spectator || players[i].exiting) + continue; // not in-game + + if (R_PointToDist2(actor->x, actor->y, players[i].mo->x, players[i].mo->y) < pdist) + { + pdist = R_PointToDist2(actor->x, actor->y, players[i].mo->x, players[i].mo->y); + scplayer = &players[i]; // it doesn't matter if we override this guy now. + } + } + + // different player from our main target, try and ram into em~! + if (scplayer && scplayer != player) + { + pangle = actor->angle - R_PointToAngle2(actor->x, actor->y,scplayer->mo->x, scplayer->mo->y); + // check if the angle wouldn't make us LOSE speed... + if ((INT32)pangle/ANG1 >= -80 && (INT32)pangle/ANG1 <= 80) // allow for around 80 degrees + { + // Thrust us towards the guy, try to screw em up! + P_Thrust(actor, R_PointToAngle2(actor->x, actor->y, scplayer->mo->x, scplayer->mo->y), actor->movefactor/4); // not too fast though. + } + } + // Spawn a trail of rings behind the SPB! SpawnSPBTrailRings(actor); From 151e1c9dfe837edd68b02e7a05f5f834d52bc5b4 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 24 Oct 2019 19:15:22 -0400 Subject: [PATCH 26/56] Reduce DISTVAR, don't give SPB toward the end of the track --- src/k_kart.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index ccc9ff447..5d903cbc8 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -709,7 +709,7 @@ static INT32 K_KartItemOddsBattle[NUMKARTRESULTS][6] = /*Jawz x2*/ { 0, 0, 1, 2, 4, 2 } // Jawz x2 }; -#define DISTVAR (4096) // Magic number distance for use with item roulette tiers +#define DISTVAR (2048) // Magic number distance for use with item roulette tiers /** \brief Item Roulette for Kart @@ -897,7 +897,8 @@ static INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed, boolean sp POWERITEMODDS(newodds); break; case KITEM_SPB: - if ((indirectitemcooldown > 0) || (pexiting > 0) || (secondist/DISTVAR < 3)) + if ((indirectitemcooldown > 0) || (secondist/DISTVAR < 3) + || (first != -1 && players[first].distancetofinish > 8*DISTVAR)) // No SPB near the end of the race newodds = 0; else newodds *= min((secondist/DISTVAR)-4, 3); // POWERITEMODDS(newodds); From 55c2fe31bebcc00e9ca6d4c8ea12b12f3d4fc2b5 Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Sat, 26 Oct 2019 13:27:43 +0200 Subject: [PATCH 27/56] SPB on floor --- src/p_enemy.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index 901589dd9..e18f585be 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -8878,10 +8878,10 @@ void A_SPBChase(mobj_t *actor) } // Finally, no matter what, the spb should not be able to be under the ground, or above the ceiling; - if (actor->z < actor->floorz + 8*mapobjectscale) - actor->z = actor->floorz + 8*mapobjectscale; - else if (actor->z > actor->ceilingz - 8*mapobjectscale) - actor->z = actor->ceilingz - 8*mapobjectscale; + if (actor->z < actor->floorz) + actor->z = actor->floorz; + else if (actor->z > actor->ceilingz - actor->height) + actor->z = actor->ceilingz - actor->height; return; From 58bed7d9231dbc85accd8e1f14f83b8585672b12 Mon Sep 17 00:00:00 2001 From: Latapostrophe Date: Sat, 26 Oct 2019 17:08:22 +0200 Subject: [PATCH 28/56] New item list + shrink destroys items --- src/k_kart.c | 66 +++++++++++++++++++++++++++++++++++---------- src/p_enemy.c | 3 --- src/p_mobj.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/p_mobj.h | 9 +++++++ src/p_saveg.c | 28 ++++++++++++++++--- src/p_tick.c | 4 +++ 6 files changed, 164 insertions(+), 21 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index ef71558a2..113012a5d 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2011,7 +2011,7 @@ void K_RespawnChecker(player_t *player) { while (lasersteps) { - + stepha = R_PointToAngle2(laserx, lasery, destx, desty); stepva = R_PointToAngle2(0, laserz, P_AproxDistance(laserx - destx, lasery - desty), destz); @@ -4109,6 +4109,7 @@ void K_DoSneaker(player_t *player, INT32 type) static void K_DoShrink(player_t *user) { INT32 i; + mobj_t *mobj, *next; S_StartSound(user->mo, sfx_kc46); // Sound the BANG! user->pflags |= PF_ATTACKDOWN; @@ -4146,6 +4147,43 @@ static void K_DoShrink(player_t *user) } } } + + // kill everything in the kitem list while we're at it: + for (mobj = kitemcap; mobj; mobj = next) + { + next = mobj->itnext; + + // check if the item is being held by a player behind us before removing it. + // check if the item is a "shield" first, bc i'm p sure thrown items keep the player that threw em as target anyway + + if (mobj->type == MT_BANANA_SHIELD || mobj->type == MT_JAWZ_SHIELD || + mobj->type == MT_SSMINE_SHIELD || mobj->type == MT_EGGMANITEM_SHIELD || + mobj->type == MT_SINK_SHIELD || mobj->type == MT_ORBINAUT_SHIELD) + { + if (mobj->target && mobj->target->player) + { + if (mobj->target->player->kartstuff[k_position] > user->kartstuff[k_position]) + continue; // this guy's behind us, don't take his stuff away! + } + } + + // @TODO: This should probably go into the P_KillMobj code for items? + + if (mobj->eflags & MFE_VERTICALFLIP) + mobj->z -= mobj->height; + else + mobj->z += mobj->height; + + S_StartSound(mobj, mobj->info->deathsound); + P_KillMobj(mobj, user->mo, user->mo); + + P_SetObjectMomZ(mobj, 8*FRACUNIT, false); + P_InstaThrust(mobj, (angle_t)P_RandomRange(0, 359)*ANG1, 16*FRACUNIT); + + if (mobj->type == MT_SPB) + spbplace = -1; + + } } @@ -4318,6 +4356,7 @@ void K_DropHnextList(player_t *player) dropwork = P_SpawnMobj(work->x, work->y, work->z, type); P_SetTarget(&dropwork->target, player->mo); + P_AddKartItem(dropwork); // needs to be called here so shrink can bust items off players in front of the user. dropwork->angle = work->angle; dropwork->flags2 = work->flags2; dropwork->flags |= MF_NOCLIPTHING; @@ -5105,9 +5144,6 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) K_UpdateDraft(player); K_UpdateEngineSounds(player, cmd); // Thanks, VAda! - if (spbplace == -1) // no spb - player->axis1 = NULL; // remove this - // update boost angle if not spun out if (!player->kartstuff[k_spinouttimer] && !player->kartstuff[k_wipeoutslow]) player->kartstuff[k_boostangle] = (INT32)player->mo->angle; @@ -9394,7 +9430,8 @@ static void K_drawKartMinimap(void) UINT8 skin = 0; UINT8 *colormap = NULL; SINT8 localplayers[4]; - SINT8 numlocalplayers = 0; + SINT8 numlocalplayers = 0; + mobj_t *mobj, *next; // for SPB drawing (or any other item(s) we may wanna draw, I dunno!) // Draw the HUD only when playing in a level. // hu_stuff needs this, unlike st_stuff. @@ -9545,11 +9582,7 @@ static void K_drawKartMinimap(void) // Target reticule if ((G_RaceGametype() && players[i].kartstuff[k_position] == spbplace) || (G_BattleGametype() && K_IsPlayerWanted(&players[i]))) - K_drawKartMinimapIcon(players[i].mo->x, players[i].mo->y, x, y, splitflags, kp_wantedreticle, NULL, AutomapPic); - - if (players[i].axis1 && !P_MobjWasRemoved(players[i].axis1)) // SPB after the player? - K_drawKartMinimapIcon(players[i].axis1->x, players[i].axis1->y, x, y, splitflags, kp_ringspblocksmall[14 + leveltime%4 /2], NULL, AutomapPic); - + K_drawKartMinimapIcon(players[i].mo->x, players[i].mo->y, x, y, splitflags, kp_wantedreticle, NULL, AutomapPic); } } @@ -9582,12 +9615,17 @@ static void K_drawKartMinimap(void) // Target reticule if ((G_RaceGametype() && players[localplayers[i]].kartstuff[k_position] == spbplace) || (G_BattleGametype() && K_IsPlayerWanted(&players[localplayers[i]]))) - K_drawKartMinimapIcon(players[localplayers[i]].mo->x, players[localplayers[i]].mo->y, x, y, splitflags, kp_wantedreticle, NULL, AutomapPic); + K_drawKartMinimapIcon(players[localplayers[i]].mo->x, players[localplayers[i]].mo->y, x, y, splitflags, kp_wantedreticle, NULL, AutomapPic); + } - if (players[localplayers[i]].axis1 && !P_MobjWasRemoved(players[localplayers[i]].axis1)) // SPB after the player? - K_drawKartMinimapIcon(players[localplayers[i]].axis1->x, players[localplayers[i]].axis1->y, x, y, splitflags, kp_ringspblocksmall[14 + leveltime%4 /2], NULL, AutomapPic); + // draw SPB(s?) + for (mobj = kitemcap; mobj; mobj = next) + { + next = mobj->itnext; + if (mobj->type == MT_SPB) + K_drawKartMinimapIcon(mobj->x, mobj->y, x, y, splitflags, kp_ringspblocksmall[14 + leveltime%4 /2], NULL, AutomapPic); + } - } } static void K_drawKartStartCountdown(void) diff --git a/src/p_enemy.c b/src/p_enemy.c index e18f585be..ff57b0ffa 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -8543,9 +8543,6 @@ void A_SPBChase(mobj_t *actor) } } - if (player) - P_SetTarget(&player->axis1, actor); // axis is the SPB trailing the player. - // lastlook = last player num targetted // cvmem = stored speed // cusval = next waypoint heap index diff --git a/src/p_mobj.c b/src/p_mobj.c index b04bf717a..5ed7b7447 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -48,6 +48,7 @@ actioncache_t actioncachehead; static mobj_t *overlaycap = NULL; static mobj_t *shadowcap = NULL; +mobj_t *kitemcap = NULL; // Used for Kart offensive items (the ones that can get removed by sizedown) mobj_t *waypointcap = NULL; void P_InitCachedActions(void) @@ -6101,6 +6102,71 @@ static boolean P_AddShield(mobj_t *thing) return true; }*/ + +// Kartitem stuff. +boolean P_IsKartItem(INT32 type) +{ + if (type == MT_EGGMANITEM || type == MT_EGGMANITEM_SHIELD || + type == MT_BANANA || type == MT_BANANA_SHIELD || + type == MT_ORBINAUT || type == MT_ORBINAUT_SHIELD || + type == MT_JAWZ || type == MT_JAWZ_DUD || type == MT_JAWZ_SHIELD || + type == MT_SSMINE || type == MT_SSMINE_SHIELD || + type == MT_SINK || type == MT_SINK_SHIELD || + type == MT_FLOATINGITEM || type == MT_SPB) + return true; + else + return false; +} + +// Called when a kart item "thinks" +void P_AddKartItem(mobj_t *thing) +{ + I_Assert(thing != NULL); + + if (kitemcap == NULL) + P_SetTarget(&kitemcap, thing); + else { + mobj_t *mo; + for (mo = kitemcap; mo && mo->itnext; mo = mo->itnext) + ; + + I_Assert(mo != NULL); + I_Assert(mo->itnext == NULL); + + P_SetTarget(&mo->itnext, thing); + } + P_SetTarget(&thing->itnext, NULL); +} + +// Called only when a kart item is removed +// Keeps the hnext list from corrupting. +static void P_RemoveKartItem(mobj_t *thing) +{ + mobj_t *mo; + for (mo = kitemcap; mo; mo = mo->itnext) + if (mo->itnext == thing) + { + P_SetTarget(&mo->itnext, thing->itnext); + P_SetTarget(&thing->itnext, NULL); + return; + } +} + +// Doesn't actually do anything since items have their own thinkers, +// but this is necessary for the sole purpose of updating kitemcap +void P_RunKartItems(void) +{ + mobj_t *mobj, *next; + + for (mobj = kitemcap; mobj; mobj = next) + { + next = mobj->itnext; + P_SetTarget(&mobj->itnext, NULL); + } + P_SetTarget(&kitemcap, NULL); +} + + void P_RunOverlays(void) { // run overlays @@ -9961,6 +10027,12 @@ for (i = ((mobj->flags2 & MF2_STRONGBOX) ? strongboxamt : weakboxamt); i; --i) s } } + if (P_MobjWasRemoved(mobj)) + return; // obligatory paranoia check + + if (P_IsKartItem(mobj->type)) // mobj is a kart item we want on the list: + P_AddKartItem(mobj); // add to kitem list + // Can end up here if a player dies. if (mobj->player) P_CyclePlayerMobjState(mobj); @@ -10887,6 +10959,9 @@ void P_RemoveMobj(mobj_t *mobj) if (mobj->type == MT_SPB) spbplace = -1; + if (P_IsKartItem(mobj->type)) + P_RemoveKartItem(mobj); + mobj->health = 0; // Just because // unlink from sector and block lists diff --git a/src/p_mobj.h b/src/p_mobj.h index aec2ed951..3ade78aa4 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -321,6 +321,9 @@ typedef struct mobj_s struct mobj_s *hnext; struct mobj_s *hprev; + // One last pointer for kart item lists + struct mobj_s *itnext; + mobjtype_t type; const mobjinfo_t *info; // &mobjinfo[mobj->type] @@ -436,12 +439,18 @@ typedef struct actioncache_s extern actioncache_t actioncachehead; +extern mobj_t *kitemcap; extern mobj_t *waypointcap; void P_InitCachedActions(void); void P_RunCachedActions(void); void P_AddCachedAction(mobj_t *mobj, INT32 statenum); +// kartitem stuff: Returns true if the specified 'type' is one of the kart item constants we want in the kitemcap list +boolean P_IsKartItem(INT32 type); +void P_AddKartItem(mobj_t *thing); // needs to be called in k_kart.c +void P_RunKartItems(void); + // check mobj against water content, before movement code void P_MobjCheckWater(mobj_t *mobj); diff --git a/src/p_saveg.c b/src/p_saveg.c index d51240521..4767b09d1 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -957,9 +957,11 @@ typedef enum MD2_HNEXT = 1<<7, MD2_HPREV = 1<<8, MD2_COLORIZED = 1<<9, - MD2_WAYPOINTCAP = 1<<10 + MD2_WAYPOINTCAP = 1<<10, + MD2_KITEMCAP = 1<<11, + MD2_ITNEXT = 1<<12 #ifdef ESLOPE - , MD2_SLOPE = 1<<11 + , MD2_SLOPE = 1<<13 #endif } mobj_diff2_t; @@ -1151,6 +1153,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) diff2 |= MD2_HNEXT; if (mobj->hprev) diff2 |= MD2_HPREV; + if (mobj->itnext) + diff2 |= MD2_ITNEXT; #ifdef ESLOPE if (mobj->standingslope) diff2 |= MD2_SLOPE; @@ -1159,6 +1163,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) diff2 |= MD2_COLORIZED; if (mobj == waypointcap) diff2 |= MD2_WAYPOINTCAP; + if (mobj == kitemcap) + diff2 |= MD2_KITEMCAP; if (diff2 != 0) diff |= MD_MORE; @@ -1274,6 +1280,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) WRITEUINT32(save_p, mobj->hnext->mobjnum); if (diff2 & MD2_HPREV) WRITEUINT32(save_p, mobj->hprev->mobjnum); + if (diff2 & MD2_ITNEXT) + WRITEUINT32(save_p, mobj->itnext->mobjnum); #ifdef ESLOPE if (diff2 & MD2_SLOPE) WRITEUINT16(save_p, mobj->standingslope->id); @@ -2151,6 +2159,8 @@ static void LoadMobjThinker(actionf_p1 thinker) mobj->hnext = (mobj_t *)(size_t)READUINT32(save_p); if (diff2 & MD2_HPREV) mobj->hprev = (mobj_t *)(size_t)READUINT32(save_p); + if (diff2 & MD2_ITNEXT) + mobj->itnext = (mobj_t *)(size_t)READUINT32(save_p); #ifdef ESLOPE if (diff2 & MD2_SLOPE) { @@ -2192,6 +2202,9 @@ static void LoadMobjThinker(actionf_p1 thinker) if (diff2 & MD2_WAYPOINTCAP) P_SetTarget(&waypointcap, mobj); + if (diff2 & MD2_KITEMCAP) + P_SetTarget(&kitemcap, mobj); + mobj->info = (mobjinfo_t *)next; // temporarily, set when leave this function } @@ -3044,6 +3057,13 @@ static void P_RelinkPointers(void) if (!(mobj->hprev = P_FindNewPosition(temp))) CONS_Debug(DBG_GAMELOGIC, "hprev not found on %d\n", mobj->type); } + if (mobj->itnext) + { + temp = (UINT32)(size_t)mobj->itnext; + mobj->itnext = NULL; + if (!(mobj->itnext = P_FindNewPosition(temp))) + CONS_Debug(DBG_GAMELOGIC, "itnext not found on %d\n", mobj->type); + } if (mobj->player && mobj->player->capsule) { temp = (UINT32)(size_t)mobj->player->capsule; @@ -3324,7 +3344,7 @@ static void P_NetArchiveMisc(void) WRITEUINT32(save_p, hyubgone); WRITEUINT32(save_p, mapreset); - for (i = 0; i < MAXPLAYERS; i++) + for (i = 0; i < MAXPLAYERS; i++) WRITEINT16(save_p, nospectategrief[i]); WRITEUINT8(save_p, thwompsactive); @@ -3447,7 +3467,7 @@ static inline boolean P_NetUnArchiveMisc(void) hyubgone = READUINT32(save_p); mapreset = READUINT32(save_p); - for (i = 0; i < MAXPLAYERS; i++) + for (i = 0; i < MAXPLAYERS; i++) nospectategrief[i] = READINT16(save_p); thwompsactive = (boolean)READUINT8(save_p); diff --git a/src/p_tick.c b/src/p_tick.c index 2e3b17b69..33cc32602 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -183,6 +183,7 @@ void P_InitThinkers(void) { thinkercap.prev = thinkercap.next = &thinkercap; waypointcap = NULL; + kitemcap = NULL; } // @@ -639,6 +640,9 @@ void P_Ticker(boolean run) if (runemeraldmanager) P_EmeraldManager(); // Power stone mode*/ + // formality so kitemcap gets updated properly each frame. + P_RunKartItems(); + if (run) { P_RunThinkers(); From 2ddb6cd082f9a2e23418ec1c3632075089894fa2 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Sat, 26 Oct 2019 23:02:45 -0400 Subject: [PATCH 29/56] set starpost xyz in battle maps --- src/k_kart.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/src/k_kart.c b/src/k_kart.c index 5d903cbc8..b74b516bc 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -12,6 +12,7 @@ #include "m_random.h" #include "p_local.h" #include "p_slopes.h" +#include "p_setup.h" #include "r_draw.h" #include "r_local.h" #include "s_sound.h" @@ -1937,9 +1938,101 @@ void K_DoIngameRespawn(player_t *player) if (leveltime <= starttime) return; + if (player->nextwaypoint == NULL) // Starpost xyz not initalized(?) + { + UINT32 bestdist = UINT32_MAX; + mapthing_t *beststart = NULL; + UINT8 numstarts = 0; + + if (G_RaceGametype()) + { + numstarts = numcoopstarts; + } + else if (G_BattleGametype()) + { + numstarts = numdmstarts; + } + + if (numstarts > 0) + { + UINT8 i = 0; + + for (i = 0; i < numstarts; i++) + { + UINT32 dist = UINT32_MAX; + mapthing_t *checkstart = NULL; + + if (G_RaceGametype()) + { + checkstart = playerstarts[i]; + } + else if (G_BattleGametype()) + { + checkstart = deathmatchstarts[i]; + } + else + { + break; + } + + dist = (UINT32)P_AproxDistance((player->mo->x >> FRACBITS) - checkstart->x, + (player->mo->y >> FRACBITS) - checkstart->y); + + if (dist < bestdist) + { + beststart = checkstart; + bestdist = dist; + } + } + } + + if (beststart == NULL) + { + CONS_Alert(CONS_WARNING, "No respawn points!\n"); + } + else + { + sector_t *s; + fixed_t z = (beststart->options >> ZSHIFT); + + player->starpostx = beststart->x; + player->starposty = beststart->y; + s = R_PointInSubsector(beststart->x << FRACBITS, beststart->y << FRACBITS)->sector; + + if (beststart->options & MTF_OBJECTFLIP) + { + player->starpostz = ( +#ifdef ESLOPE + s->c_slope ? P_GetZAt(s->c_slope, beststart->x << FRACBITS, beststart->y << FRACBITS) : +#endif + s->ceilingheight) >> FRACBITS; + + if (z) + player->starpostz -= z; + + player->starpostz -= mobjinfo[MT_PLAYER].height; + player->kartstuff[k_starpostflip] = 1; + } + else + { + player->starpostz = ( +#ifdef ESLOPE + s->f_slope ? P_GetZAt(s->f_slope, beststart->x << FRACBITS, beststart->y << FRACBITS) : +#endif + s->floorheight) >> FRACBITS; + + if (z) + player->starpostz += z; + + player->kartstuff[k_starpostflip] = 0; + } + } + } + player->mo->flags &= ~(MF_SOLID|MF_SHOOTABLE); player->mo->flags |= MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOCLIPTHING|MF_NOGRAVITY; player->mo->flags2 &= ~MF2_DONTDRAW; + player->kartstuff[k_respawn] = 48; } From 54516aeee97b18ee307024672fe91fc60d55fd30 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Sun, 27 Oct 2019 16:44:41 -0400 Subject: [PATCH 30/56] Don't force SPB in 1v1 --- src/k_kart.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/k_kart.c b/src/k_kart.c index b74b516bc..42067f333 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1057,6 +1057,10 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) bestbumper = players[i].kartstuff[k_bumper]; } + // No forced SPB in 1v1s, it has to be randomly rolled + if (pingame <= 2) + dontforcespb = true; + // This makes the roulette produce the random noises. if ((player->kartstuff[k_itemroulette] % 3) == 1 && P_IsDisplayPlayer(player)) { From 34e0b4b9919e3dc218820287ee25f934e5bc5de0 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Sun, 27 Oct 2019 17:18:22 -0400 Subject: [PATCH 31/56] Radius was not made more coarse when I did the big-maps fix, so you were considered in every waypoint, meaning it worked exactly before I made this change in the first place https://youtu.be/csnS0nszyuA --- src/k_waypoint.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_waypoint.c b/src/k_waypoint.c index ab3bd8be9..68b21520e 100644 --- a/src/k_waypoint.c +++ b/src/k_waypoint.c @@ -266,7 +266,7 @@ waypoint_t *K_GetBestWaypointTouchingMobj(mobj_t *const mobj) checkdist = P_AproxDistance(checkdist, (mobj->z >> FRACBITS) - (checkwaypoint->mobj->z >> FRACBITS)); // The mobj has to be touching this waypoint to use it. - if ((checkdist <= checkwaypoint->mobj->radius) + if ((checkdist <= (checkwaypoint->mobj->radius >> FRACBITS)) && (checkdist < bestdist)) { bestwaypoint = checkwaypoint; From 0afc901d1febfb135e4c804230c3e1683ad81b9d Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Sun, 27 Oct 2019 20:15:27 -0400 Subject: [PATCH 32/56] Shrinking animation --- src/k_kart.c | 28 +++++++--------------------- src/p_mobj.c | 36 +++++++++++++++++++----------------- 2 files changed, 26 insertions(+), 38 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 5c9dd7d8d..3269582e8 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -4225,10 +4225,7 @@ static void K_DoShrink(player_t *user) // Grow should get taken away. if (players[i].kartstuff[k_growshrinktimer] > 0) K_RemoveGrowShrink(&players[i]); - // Don't hit while invulnerable! - else if (!players[i].kartstuff[k_invincibilitytimer] - && players[i].kartstuff[k_growshrinktimer] <= 0 - && !players[i].kartstuff[k_hyudorotimer]) + else { // Start shrinking! K_DropItems(&players[i]); @@ -4261,26 +4258,15 @@ static void K_DoShrink(player_t *user) if (mobj->target && mobj->target->player) { if (mobj->target->player->kartstuff[k_position] > user->kartstuff[k_position]) - continue; // this guy's behind us, don't take his stuff away! + continue; // this guy's behind us, don't take his stuff away! } } - // @TODO: This should probably go into the P_KillMobj code for items? - - if (mobj->eflags & MFE_VERTICALFLIP) - mobj->z -= mobj->height; - else - mobj->z += mobj->height; - - S_StartSound(mobj, mobj->info->deathsound); - P_KillMobj(mobj, user->mo, user->mo); - - P_SetObjectMomZ(mobj, 8*FRACUNIT, false); - P_InstaThrust(mobj, (angle_t)P_RandomRange(0, 359)*ANG1, 16*FRACUNIT); + mobj->destscale = 0; + mobj->flags |= (MF_NOTHINK|MF_NOCLIPTHING); if (mobj->type == MT_SPB) spbplace = -1; - } } @@ -9342,17 +9328,17 @@ static void K_drawKartWanted(void) return; // set X/Y coords depending on splitscreen. - if (splitscreen < 3) // 1P and 2P use the same code. + if (splitscreen < 3) // 1P and 2P use the same code. { basex = WANT_X; basey = WANT_Y; if (splitscreen == 2) { - basey += 16; // slight adjust for 3P + basey += 16; // slight adjust for 3P basex -= 6; } } - else if (splitscreen == 3) // 4P splitscreen... + else if (splitscreen == 3) // 4P splitscreen... { basex = BASEVIDWIDTH/2 - (SHORT(kp_wantedsplit->width)/2); // center on screen basey = BASEVIDHEIGHT - 55; diff --git a/src/p_mobj.c b/src/p_mobj.c index 5ed7b7447..2cdb257d6 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1658,18 +1658,11 @@ void P_XYMovement(mobj_t *mo) { mo->health--; if (mo->health == 0) - mo->destscale = 1; - } - else - { - if (mo->scale < mapobjectscale/16) - { - P_RemoveMobj(mo); - return; - } + mo->destscale = 0; } } //} + if (!P_TryMove(mo, mo->x + xmove, mo->y + ymove, true) && !(mo->eflags & MFE_SPRUNG)) { // blocked move @@ -6112,7 +6105,7 @@ boolean P_IsKartItem(INT32 type) type == MT_JAWZ || type == MT_JAWZ_DUD || type == MT_JAWZ_SHIELD || type == MT_SSMINE || type == MT_SSMINE_SHIELD || type == MT_SINK || type == MT_SINK_SHIELD || - type == MT_FLOATINGITEM || type == MT_SPB) + type == MT_SPB) return true; else return false; @@ -6881,16 +6874,25 @@ void P_MobjThinker(mobj_t *mobj) mobj->z -= mobj->height - oldheight; if (mobj->scale == mobj->destscale) + { /// \todo Lua hook for "reached destscale"? - switch(mobj->type) + + if (mobj->scale == 0) { - case MT_EGGMOBILE_FIRE: - mobj->destscale = FRACUNIT; - mobj->scalespeed = FRACUNIT>>4; - break; - default: - break; + P_RemoveMobj(mobj); + return; } + + switch (mobj->type) + { + case MT_EGGMOBILE_FIRE: + mobj->destscale = FRACUNIT; + mobj->scalespeed = FRACUNIT>>4; + break; + default: + break; + } + } } if (mobj->type == MT_GHOST && mobj->fuse > 0 // Not guaranteed to be MF_SCENERY or not MF_SCENERY! From 7676dfa7137fcd8ecc50370a439bc4942dae43fb Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Sun, 27 Oct 2019 20:54:00 -0400 Subject: [PATCH 33/56] SPB minimap proper order --- src/k_kart.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 3269582e8..1fc525378 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -7538,6 +7538,8 @@ static patch_t *kp_winnernum[NUMPOSFRAMES]; static patch_t *kp_facenum[MAXPLAYERS+1]; static patch_t *kp_facehighlight[8]; +static patch_t *kp_spbminimap; + static patch_t *kp_ringsticker[2]; static patch_t *kp_ringstickersplit[4]; static patch_t *kp_ring[6]; @@ -7690,6 +7692,8 @@ void K_LoadKartHUDGraphics(void) kp_facehighlight[i] = (patch_t *) W_CachePatchName(buffer, PU_HUDGFX); } + kp_spbminimap = W_CachePatchName("SPBMMAP", PU_HUDGFX); + // Rings & Lives kp_ringsticker[0] = W_CachePatchName("RNGBACKA", PU_HUDGFX); kp_ringsticker[1] = W_CachePatchName("RNGBACKB", PU_HUDGFX); @@ -9669,6 +9673,14 @@ static void K_drawKartMinimap(void) K_drawKartMinimapIcon(players[i].mo->x, players[i].mo->y, x, y, splitflags, kp_wantedreticle, NULL, AutomapPic); } } + + // draw SPB(s?) + for (mobj = kitemcap; mobj; mobj = next) + { + next = mobj->itnext; + if (mobj->type == MT_SPB) + K_drawKartMinimapIcon(mobj->x, mobj->y, x, y, splitflags, kp_spbminimap, NULL, AutomapPic); + } // draw our local players here, opaque. splitflags &= ~V_HUDTRANSHALF; @@ -9700,16 +9712,7 @@ static void K_drawKartMinimap(void) if ((G_RaceGametype() && players[localplayers[i]].kartstuff[k_position] == spbplace) || (G_BattleGametype() && K_IsPlayerWanted(&players[localplayers[i]]))) K_drawKartMinimapIcon(players[localplayers[i]].mo->x, players[localplayers[i]].mo->y, x, y, splitflags, kp_wantedreticle, NULL, AutomapPic); - } - - // draw SPB(s?) - for (mobj = kitemcap; mobj; mobj = next) - { - next = mobj->itnext; - if (mobj->type == MT_SPB) - K_drawKartMinimapIcon(mobj->x, mobj->y, x, y, splitflags, kp_ringspblocksmall[14 + leveltime%4 /2], NULL, AutomapPic); - } - + } } static void K_drawKartStartCountdown(void) From 66bef945e82ab4de0233a45876c8c389b54b7d19 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Sun, 27 Oct 2019 21:01:27 -0400 Subject: [PATCH 34/56] Can't do nothink --- src/k_kart.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/k_kart.c b/src/k_kart.c index 1fc525378..2587813c5 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -4263,7 +4263,8 @@ static void K_DoShrink(player_t *user) } mobj->destscale = 0; - mobj->flags |= (MF_NOTHINK|MF_NOCLIPTHING); + mobj->flags &= ~(MF_SOLID|MF_SHOOTABLE|MF_SPECIAL); + mobj->flags |= MF_NOCLIPTHING; // Just for safety if (mobj->type == MT_SPB) spbplace = -1; From e2bc8a0d9733493d0f70bd372e127a839d36e617 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Sun, 27 Oct 2019 21:25:16 -0400 Subject: [PATCH 35/56] color spb icon with who threw it --- src/k_kart.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/k_kart.c b/src/k_kart.c index 2587813c5..dedc6f79a 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -9680,7 +9680,19 @@ static void K_drawKartMinimap(void) { next = mobj->itnext; if (mobj->type == MT_SPB) - K_drawKartMinimapIcon(mobj->x, mobj->y, x, y, splitflags, kp_spbminimap, NULL, AutomapPic); + { + UINT8 *colormap = NULL; + + if (mobj->target && !P_MobjWasRemoved(mobj->target)) + { + if (mobj->player && mobj->player->skincolor) + colormap = R_GetTranslationColormap(TC_RAINBOW, mobj->player->skincolor, GTC_CACHE); + else if (mobj->color) + colormap = R_GetTranslationColormap(TC_RAINBOW, mobj->color, GTC_CACHE); + } + + K_drawKartMinimapIcon(mobj->x, mobj->y, x, y, splitflags, kp_spbminimap, colormap, AutomapPic); + } } // draw our local players here, opaque. From 6acf3e2337979758c171b0b902e4a145ae1df9e7 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Sun, 27 Oct 2019 21:35:27 -0400 Subject: [PATCH 36/56] dont overshadow --- src/k_kart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_kart.c b/src/k_kart.c index dedc6f79a..4aca67aef 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -9681,7 +9681,7 @@ static void K_drawKartMinimap(void) next = mobj->itnext; if (mobj->type == MT_SPB) { - UINT8 *colormap = NULL; + colormap = NULL; if (mobj->target && !P_MobjWasRemoved(mobj->target)) { From 377a155cda1de5a5ebc63c2d7989ad50f38a1ec1 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Mon, 28 Oct 2019 14:20:09 -0400 Subject: [PATCH 37/56] Update Race Lap linedef executors since they stopped working --- src/p_spec.c | 98 ++++++++++++++++++++++++++++------------------------ 1 file changed, 53 insertions(+), 45 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index f83ca79a7..b4f5a9d62 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1705,41 +1705,6 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller if (!(ALL7EMERALDS(emeralds))) return false; } - else if (GETSECSPECIAL(caller->special, 2) == 7) // SRB2Kart: reusing for Race Lap executor - { - UINT8 lap; - - if (actor && actor->player && triggerline->flags & ML_EFFECT4) - { - /*if (maptol & TOL_NIGHTS) - lap = actor->player->mare; - else*/ - lap = actor->player->laps; - } - else - { - /*if (maptol & TOL_NIGHTS) - lap = P_FindLowestMare(); - else*/ - lap = P_FindLowestLap(); - } - - if (triggerline->flags & ML_NOCLIMB) // Need higher than or equal to - { - if (lap < (sides[triggerline->sidenum[0]].textureoffset >> FRACBITS)) - return false; - } - else if (triggerline->flags & ML_BLOCKMONSTERS) // Need lower than or equal to - { - if (lap > (sides[triggerline->sidenum[0]].textureoffset >> FRACBITS)) - return false; - } - else // Need equal to - { - if (lap != (sides[triggerline->sidenum[0]].textureoffset >> FRACBITS)) - return false; - } - } // If we were not triggered by a sector type especially for the purpose, // a Linedef Executor linedef trigger is not handling sector triggers properly, return. @@ -1937,15 +1902,17 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller else // These special types work only once if (specialtype == 302 // Once - || specialtype == 304 // Ring count - Once - || specialtype == 307 // Character ability - Once - || specialtype == 308 // Race only - Once - || specialtype == 315 // No of pushables - Once - || specialtype == 318 // Unlockable trigger - Once - || specialtype == 320 // Unlockable - Once - || specialtype == 321 || specialtype == 322 // Trigger on X calls - Continuous + Each Time - || specialtype == 328 // Encore Load - || specialtype == 399) // Level Load + || specialtype == 304 // Ring count - Once + || specialtype == 307 // Character ability - Once + || specialtype == 308 // Race only - Once + || specialtype == 315 // No of pushables - Once + || specialtype == 318 // Unlockable trigger - Once + || specialtype == 320 // Unlockable - Once + || specialtype == 321 || specialtype == 322 // Trigger on X calls - Continuous + Each Time + || specialtype == 328 // Encore Load + || specialtype == 399 // Level Load + || specialtype == 2002 // SRB2Kart Race Lap + ) triggerline->special = 0; // Clear it out return true; @@ -1981,6 +1948,7 @@ void P_LinedefExecute(INT16 tag, mobj_t *actor, sector_t *caller) if (lines[masterline].special == 313 || lines[masterline].special == 399 || lines[masterline].special == 328 + || lines[masterline].special == 2002 // SRB2Kart race lap trigger // Each-time executors handle themselves, too || lines[masterline].special == 301 // Each time || lines[masterline].special == 306 // Character ability - Each time @@ -2207,7 +2175,7 @@ static void K_HandleLapIncrement(player_t *player) { if ((player->starpostnum == numstarposts) || (player->laps == 0)) { - UINT8 i = 0; + size_t i = 0; UINT8 nump = 0; for (i = 0; i < MAXPLAYERS; i++) @@ -2284,6 +2252,41 @@ static void K_HandleLapIncrement(player_t *player) } thwompsactive = true; // Lap 2 effects + + for (i = 0; i < numlines; i++) + { + if (lines[i].special == 2002) // Race lap trigger + { + UINT8 lap; + + if (lines[i].flags & ML_EFFECT4) + { + lap = player->laps; + } + else + { + lap = P_FindLowestLap(); + } + + if (lines[i].flags & ML_NOCLIMB) // Need higher than or equal to + { + if (lap < (sides[lines[i].sidenum[0]].textureoffset >> FRACBITS)) + continue; + } + else if (lines[i].flags & ML_BLOCKMONSTERS) // Need lower than or equal to + { + if (lap > (sides[lines[i].sidenum[0]].textureoffset >> FRACBITS)) + continue; + } + else // Need equal to + { + if (lap != (sides[lines[i].sidenum[0]].textureoffset >> FRACBITS)) + continue; + } + + P_RunTriggerLinedef(&lines[i], player->mo, NULL); + } + } } else if (player->starpostnum) { @@ -6728,12 +6731,17 @@ void P_SpawnSpecials(INT32 fromnetsave) sectors[s].midmap = lines[i].frontsector->midmap; break; + // SRB2Kart case 2000: // Waypoint Parameters break; case 2001: // Finish Line if (G_RaceGametype()) circuitmap = true; break; + case 2002: // Linedef Trigger: Race Lap + break; + case 2003: // Linedef Executor: Enable/Disable Waypoint + break; default: break; } From fe3d19d15dabf1be5162f90ac4143270da9279dc Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Mon, 28 Oct 2019 14:42:45 -0400 Subject: [PATCH 38/56] Remove this for now --- src/p_spec.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index b4f5a9d62..0af99f163 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6740,8 +6740,6 @@ void P_SpawnSpecials(INT32 fromnetsave) break; case 2002: // Linedef Trigger: Race Lap break; - case 2003: // Linedef Executor: Enable/Disable Waypoint - break; default: break; } From d413b3bcd41e224a3588aec8bb5ddb27fd2e0724 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Mon, 28 Oct 2019 15:52:27 -0400 Subject: [PATCH 39/56] Use both facing & momentum angle for using next/prev waypoints, only update respawn to nextwaypoints --- src/k_kart.c | 121 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 75 insertions(+), 46 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 4aca67aef..b3297527e 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -5749,7 +5749,8 @@ static waypoint_t *K_GetPlayerNextWaypoint(player_t *player, boolean closest) waypoint_t *bestwaypoint = NULL; if ((player != NULL) && (player->mo != NULL) && (P_MobjWasRemoved(player->mo) == false)) { - waypoint_t *waypoint = NULL; + waypoint_t *waypoint = NULL; + boolean updaterespawn = false; if (closest == true) waypoint = K_GetClosestWaypointToMobj(player->mo); @@ -5766,23 +5767,30 @@ static waypoint_t *K_GetPlayerNextWaypoint(player_t *player, boolean closest) { boolean finishlinehack = false; angle_t playerangle = player->mo->angle; + angle_t momangle = player->mo->angle; angle_t angletowaypoint = R_PointToAngle2(player->mo->x, player->mo->y, waypoint->mobj->x, waypoint->mobj->y); angle_t angledelta = ANGLE_MAX; + angle_t momdelta = ANGLE_MAX; if (player->mo->momx != 0 || player->mo->momy != 0) { - // Default to facing angle if you're not moving, but use momentum angle otherwise. - playerangle = R_PointToAngle2(0, 0, player->mo->momx, player->mo->momy); + // Defaults to facing angle if you're not moving. + momangle = R_PointToAngle2(0, 0, player->mo->momx, player->mo->momy); } angledelta = playerangle - angletowaypoint; - if (angledelta > ANGLE_180) { angledelta = InvAngle(angledelta); } + momdelta = momangle - angletowaypoint; + if (momdelta > ANGLE_180) + { + momdelta = InvAngle(momdelta); + } + if (bestwaypoint == K_GetFinishLineWaypoint()) { // facing towards the finishline @@ -5792,10 +5800,14 @@ static waypoint_t *K_GetPlayerNextWaypoint(player_t *player, boolean closest) } } - // The wrong way flag will use its previous value if we're facing sideways - if ((angledelta > ANGLE_45) && (finishlinehack == false)) + // We're using a lot of angle calculations here, because only using facing angle or only using momentum angle both have downsides. + // nextwaypoints will be picked if you're facing OR moving forward. + // prevwaypoints will be picked if you're facing AND moving backward. + if ((angledelta > ANGLE_45 || momdelta > ANGLE_45) + && (finishlinehack == false)) { angle_t nextbestdelta = angledelta; + angle_t nextbestmomdelta = momdelta; size_t i = 0U; if ((waypoint->nextwaypoints != NULL) && (waypoint->numnextwaypoints > 0U)) @@ -5805,20 +5817,29 @@ static waypoint_t *K_GetPlayerNextWaypoint(player_t *player, boolean closest) angletowaypoint = R_PointToAngle2( player->mo->x, player->mo->y, waypoint->nextwaypoints[i]->mobj->x, waypoint->nextwaypoints[i]->mobj->y); - angledelta = playerangle - angletowaypoint; + angledelta = playerangle - angletowaypoint; if (angledelta > ANGLE_180) { angledelta = InvAngle(angledelta); } - if (angledelta < nextbestdelta) + momdelta = momangle - angletowaypoint; + if (momdelta > ANGLE_180) + { + momdelta = InvAngle(momdelta); + } + + if (angledelta < nextbestdelta || momdelta < nextbestmomdelta) { bestwaypoint = waypoint->nextwaypoints[i]; + nextbestdelta = angledelta; + nextbestmomdelta = momdelta; // Remove wrong way flag if we're using nextwaypoints player->kartstuff[k_wrongway] = 0; + updaterespawn = true; } } } @@ -5830,25 +5851,67 @@ static waypoint_t *K_GetPlayerNextWaypoint(player_t *player, boolean closest) angletowaypoint = R_PointToAngle2( player->mo->x, player->mo->y, waypoint->prevwaypoints[i]->mobj->x, waypoint->prevwaypoints[i]->mobj->y); - angledelta = playerangle - angletowaypoint; + angledelta = playerangle - angletowaypoint; if (angledelta > ANGLE_180) { angledelta = InvAngle(angledelta); } - if (angledelta < nextbestdelta) + momdelta = momangle - angletowaypoint; + if (momdelta > ANGLE_180) + { + momdelta = InvAngle(momdelta); + } + + if (angledelta < nextbestdelta && momdelta < nextbestmomdelta) { bestwaypoint = waypoint->prevwaypoints[i]; - nextbestdelta = angledelta; - // Set wrong way flag if we're using prevwaypoints + nextbestdelta = angledelta; + nextbestmomdelta = momdelta; + + // Ser wrong way flag if we're using prevwaypoints player->kartstuff[k_wrongway] = 1; + updaterespawn = false; } } } } } + + // Respawn point should only be updated when we're going to a nextwaypoint + if ((updaterespawn) && + (bestwaypoint != NULL) && + (bestwaypoint != player->nextwaypoint) && + (player->kartstuff[k_respawn] == 0) && + (K_GetWaypointIsShortcut(bestwaypoint) == false) && (K_GetWaypointIsEnabled(bestwaypoint) == true)) + { + size_t i = 0U; + waypoint_t *aimwaypoint = NULL; + + player->starpostx = bestwaypoint->mobj->x >> FRACBITS; + player->starposty = bestwaypoint->mobj->y >> FRACBITS; + player->starpostz = bestwaypoint->mobj->z >> FRACBITS; + player->kartstuff[k_starpostflip] = (bestwaypoint->mobj->flags2 & MF2_OBJECTFLIP); + + // starpostangle is to the first valid nextwaypoint for simplicity + // if we reach the last waypoint and it's still not valid, just use it anyway. Someone needs to fix + // their map! + for (i = 0U; i < bestwaypoint->numnextwaypoints; i++) + { + aimwaypoint = bestwaypoint->nextwaypoints[i]; + + if ((i == bestwaypoint->numnextwaypoints - 1U) + || ((K_GetWaypointIsEnabled(aimwaypoint) == true) + && (K_GetWaypointIsSpawnpoint(aimwaypoint) == true))) + { + player->starpostangle = R_PointToAngle2( + bestwaypoint->mobj->x, bestwaypoint->mobj->y, aimwaypoint->mobj->x, aimwaypoint->mobj->y); + break; + } + } + } } return bestwaypoint; @@ -5947,40 +6010,6 @@ static void K_UpdateDistanceFromFinishLine(player_t *const player) nextwaypoint = K_GetPlayerNextWaypoint(player, true); } - if ((nextwaypoint != NULL) && - (nextwaypoint != player->nextwaypoint) && - (player->kartstuff[k_respawn] == 0) && - (K_GetWaypointIsShortcut(nextwaypoint) == false) && (K_GetWaypointIsEnabled(nextwaypoint) == true)) - { - size_t i = 0U; - waypoint_t *aimwaypoint = NULL; - - player->starpostx = nextwaypoint->mobj->x >> FRACBITS; - player->starposty = nextwaypoint->mobj->y >> FRACBITS; - player->starpostz = nextwaypoint->mobj->z >> FRACBITS; - - // player gravflip determines which way to respawn - // (should waypoints have a flip option?) - player->kartstuff[k_starpostflip] = player->mo->flags2 & MF2_OBJECTFLIP; - - // starpostangle is to the first valid nextwaypoint for simplicity - // if we reach the last waypoint and it's still not valid, just use it anyway. Someone needs to fix - // their map! - for (i = 0U; i < nextwaypoint->numnextwaypoints; i++) - { - aimwaypoint = nextwaypoint->nextwaypoints[i]; - - if ((i == nextwaypoint->numnextwaypoints - 1U) - || ((K_GetWaypointIsEnabled(aimwaypoint) == true) - && (K_GetWaypointIsSpawnpoint(aimwaypoint) == true))) - { - player->starpostangle = R_PointToAngle2( - nextwaypoint->mobj->x, nextwaypoint->mobj->y, aimwaypoint->mobj->x, aimwaypoint->mobj->y); - break; - } - } - } - if (nextwaypoint != NULL) { // If nextwaypoint is NULL, it means we don't want to update the waypoint until we touch another one. From 41f69b3c16b5250a93b1391394f22a36f006a19d Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Mon, 28 Oct 2019 16:25:38 -0400 Subject: [PATCH 40/56] Break SPBChase into a few more functions Not really easy to read still, but it's a tiny bit better than before --- src/p_enemy.c | 311 ++++++++++++++++++++++++-------------------------- 1 file changed, 150 insertions(+), 161 deletions(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index ff57b0ffa..9e31206be 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -8480,11 +8480,11 @@ void A_JawzExplode(mobj_t *actor) static void SpawnSPBTrailRings(mobj_t *actor) { - if (actor != NULL) + if (actor != NULL && !P_MobjWasRemoved(actor)) { if (leveltime % 6 == 0) { - mobj_t *ring = P_SpawnMobj(actor->x - actor->momx, actor->y - actor->momx, + mobj_t *ring = P_SpawnMobj(actor->x - actor->momx, actor->y - actor->momy, actor->z - actor->momz + (24*mapobjectscale), MT_RING); ring->threshold = 10; ring->fuse = 120*TICRATE; @@ -8492,72 +8492,64 @@ static void SpawnSPBTrailRings(mobj_t *actor) } } -void A_SPBChase(mobj_t *actor) +static void ModifySPBSpeedForAngle(mobj_t *actor, angle_t *hang, angle_t *vang, fixed_t *xyspeed, fixed_t *zspeed) { - player_t *player = NULL; - player_t *scplayer = NULL; // secondary target for seeking - UINT8 i; - UINT8 bestrank = UINT8_MAX; - fixed_t dist; - angle_t hang, vang; - fixed_t wspeed, xyspeed, zspeed; - fixed_t pdist = 1536<movefactor; - - if (actor->threshold) // Just fired, go straight. + if (actor != NULL && !P_MobjWasRemoved(actor)) { - actor->lastlook = -1; - actor->cusval = -1; - spbplace = -1; - P_InstaThrust(actor, actor->angle, wspeed); - return; + // Smoothly rotate horz angle + angle_t input = hang - actor->angle; + boolean invert = (input > ANGLE_180); + if (invert) + input = InvAngle(input); + + // Slow down when turning; it looks better and makes U-turns not unfair + xyspeed = FixedMul(actor->cvmem, max(0, (((180<angle += input; + + // Smoothly rotate vert angle + input = vang - actor->movedir; + invert = (input > ANGLE_180); + if (invert) + input = InvAngle(input); + + // Slow down when turning; might as well do it for momz, since we do it above too + zspeed = FixedMul(actor->cvmem, max(0, (((180<movedir += input; } +} - // Find the player with the best rank - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i] || players[i].spectator || players[i].exiting) - continue; // not in-game - - /*if (!players[i].mo) - continue; // no mobj - - if (players[i].mo->health <= 0) - continue; // dead - - if (players[i].kartstuff[k_respawn]) - continue;*/ // respawning - - if (players[i].kartstuff[k_position] < bestrank) - { - bestrank = players[i].kartstuff[k_position]; - player = &players[i]; - } - } - - // lastlook = last player num targetted - // cvmem = stored speed - // cusval = next waypoint heap index - // extravalue1 = SPB movement mode - // extravalue2 = mode misc option - - if (actor->extravalue1 == 1) // MODE: TARGETING +static void SPBTargettingChase(mobj_t *actor, fixed_t wspeed, UINT8 bestrank) +{ + if (actor != NULL && !P_MobjWasRemoved(actor)) { actor->cusval = -1; // Reset waypoint - if (actor->tracer && actor->tracer->health) + if (actor->tracer == NULL || P_MobjWasRemoved(actor->tracer) || !actor->tracer->health) { + // Target's gone, return to SEEKING + P_SetTarget(&actor->tracer, NULL); + actor->extravalue1 = 2; // WAIT... + actor->extravalue2 = 52; // Slightly over the respawn timer length + return; + } + else + { + fixed_t xyspeed, zspeed; + angle_t hang, vang; + fixed_t dist; fixed_t defspeed = wspeed; fixed_t range = (160*actor->tracer->scale); - fixed_t cx = 0, cy =0; + fixed_t cx = 0, cy = 0; // Play the intimidating gurgle if (!S_SoundPlaying(actor, actor->info->activesound)) @@ -8608,7 +8600,6 @@ void A_SPBChase(mobj_t *actor) wspeed = 20*actor->tracer->scale; if (actor->tracer->player->pflags & PF_SLIDING) wspeed = actor->tracer->player->speed/2; - // ^^^^ current section: These are annoying, and grand metropolis in particular needs this. hang = R_PointToAngle2(actor->x, actor->y, actor->tracer->x, actor->tracer->y); vang = R_PointToAngle2(0, actor->z, dist, actor->tracer->z); @@ -8619,37 +8610,7 @@ void A_SPBChase(mobj_t *actor) else actor->cvmem = wspeed; - { - // Smoothly rotate horz angle - angle_t input = hang - actor->angle; - boolean invert = (input > ANGLE_180); - if (invert) - input = InvAngle(input); - - // Slow down when turning; it looks better and makes U-turns not unfair - xyspeed = FixedMul(actor->cvmem, max(0, (((180<angle += input; - - // Smoothly rotate vert angle - input = vang - actor->movedir; - invert = (input > ANGLE_180); - if (invert) - input = InvAngle(input); - - // Slow down when turning; might as well do it for momz, since we do it above too - zspeed = FixedMul(actor->cvmem, max(0, (((180<movedir += input; - } + ModifySPBSpeedForAngle(actor, &hang, &vang, &xyspeed, &zspeed); actor->momx = cx + FixedMul(FixedMul(xyspeed, FINECOSINE(actor->angle>>ANGLETOFINESHIFT)), FINECOSINE(actor->movedir>>ANGLETOFINESHIFT)); actor->momy = cy + FixedMul(FixedMul(xyspeed, FINESINE(actor->angle>>ANGLETOFINESHIFT)), FINECOSINE(actor->movedir>>ANGLETOFINESHIFT)); @@ -8675,46 +8636,21 @@ void A_SPBChase(mobj_t *actor) fast->colorized = true; K_MatchGenericExtraFlags(fast, actor); } - - return; - } - else // Target's gone, return to SEEKING - { - P_SetTarget(&actor->tracer, NULL); - actor->extravalue1 = 2; // WAIT... - actor->extravalue2 = 52; // Slightly over the respawn timer length - return; } } - else if (actor->extravalue1 == 2) // MODE: WAIT... - { - actor->momx = actor->momy = actor->momz = 0; // Stoooop - actor->cusval = -1; // Reset waypoint +} - if (actor->lastlook != -1 - && playeringame[actor->lastlook] - && !players[actor->lastlook].spectator - && !players[actor->lastlook].exiting) - { - spbplace = players[actor->lastlook].kartstuff[k_position]; - players[actor->lastlook].kartstuff[k_ringlock] = 1; - if (actor->extravalue2-- <= 0 && players[actor->lastlook].mo) - { - P_SetTarget(&actor->tracer, players[actor->lastlook].mo); - actor->extravalue1 = 1; // TARGET ACQUIRED - actor->extravalue2 = 7*TICRATE; - actor->cvmem = wspeed; - } - } - else - { - actor->extravalue1 = 0; // SEEKING - actor->extravalue2 = 0; - spbplace = -1; - } - } - else // MODE: SEEKING +static void SPBSeekingChase(mobj_t *actor, player_t *player, fixed_t wspeed, UINT8 bestrank) +{ + if (actor != NULL && !P_MobjWasRemoved(actor)) { +#define TARGETDIST 1536 + fixed_t xyspeed, zspeed; + angle_t hang, vang; + fixed_t dist; + player_t *scplayer = NULL; // secondary target for swerving + fixed_t pdist = TARGETDIST<angle; - boolean invert = (input > ANGLE_180); - if (invert) - input = InvAngle(input); - - // Slow down when turning; it looks better and makes U-turns not unfair - xyspeed = FixedMul(wspeed, max(0, (((180<angle += input; - - // Smoothly rotate vert angle - input = vang - actor->movedir; - invert = (input > ANGLE_180); - if (invert) - input = InvAngle(input); - - // Slow down when turning; might as well do it for momz, since we do it above too - zspeed = FixedMul(wspeed, max(0, (((180<movedir += input; - } - + actor->cvmem = wspeed; + ModifySPBSpeedForAngle(actor, &hang, &vang, &xyspeed, &zspeed); actor->momx = FixedMul(FixedMul(xyspeed, FINECOSINE(actor->angle>>ANGLETOFINESHIFT)), FINECOSINE(actor->movedir>>ANGLETOFINESHIFT)); actor->momy = FixedMul(FixedMul(xyspeed, FINESINE(actor->angle>>ANGLETOFINESHIFT)), FINECOSINE(actor->movedir>>ANGLETOFINESHIFT)); @@ -8846,7 +8752,7 @@ void A_SPBChase(mobj_t *actor) if (R_PointToDist2(actor->x, actor->y, players[i].mo->x, players[i].mo->y) < pdist) { pdist = R_PointToDist2(actor->x, actor->y, players[i].mo->x, players[i].mo->y); - scplayer = &players[i]; // it doesn't matter if we override this guy now. + scplayer = &players[i]; } } @@ -8865,13 +8771,97 @@ void A_SPBChase(mobj_t *actor) // Spawn a trail of rings behind the SPB! SpawnSPBTrailRings(actor); - if (dist <= (1024*actor->tracer->scale)) // Close enough to target? + if (dist <= (TARGETDIST * actor->tracer->scale)) // Close enough to target? { S_StartSound(actor, actor->info->attacksound); actor->extravalue1 = 1; // TARGET ACQUIRED actor->extravalue2 = 7*TICRATE; actor->cvmem = wspeed; } + +#undef TARGETDIST + } +} + +void A_SPBChase(mobj_t *actor) +{ + UINT8 i; + UINT8 bestrank = UINT8_MAX; + player_t *bestplayer = NULL; + fixed_t wspeed; + +#ifdef HAVE_BLUA + if (LUA_CallAction("A_SPBChase", actor)) + return; +#endif + + // Default speed + wspeed = actor->movefactor; + + if (actor->threshold) // Just fired, go straight. + { + actor->lastlook = -1; + actor->cusval = -1; + spbplace = -1; + P_InstaThrust(actor, actor->angle, wspeed); + return; + } + + // Find the player with the best rank + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i] || players[i].spectator || players[i].exiting) + continue; // not in-game + + if (players[i].kartstuff[k_position] < bestrank) + { + bestrank = players[i].kartstuff[k_position]; + bestplayer = &players[i]; + } + } + + // lastlook = last player num targetted + // cvmem = stored speed + // cusval = next waypoint heap index + // extravalue1 = SPB movement mode + // extravalue2 = mode misc option + + switch (actor->extravalue1) + { + case 1: // MODE: TARGETING + SPBTargettingChase(actor, wspeed, bestrank); + break; + + case 2: // MODE: WAIT... + actor->momx = actor->momy = actor->momz = 0; // Stoooop + actor->cusval = -1; // Reset waypoint + + if (actor->lastlook != -1 + && playeringame[actor->lastlook] + && !players[actor->lastlook].spectator + && !players[actor->lastlook].exiting) + { + spbplace = players[actor->lastlook].kartstuff[k_position]; + players[actor->lastlook].kartstuff[k_ringlock] = 1; + if (actor->extravalue2-- <= 0 && players[actor->lastlook].mo) + { + P_SetTarget(&actor->tracer, players[actor->lastlook].mo); + actor->extravalue1 = 1; // TARGET ACQUIRED + actor->extravalue2 = 7*TICRATE; + actor->cvmem = wspeed; + } + } + else + { + actor->extravalue1 = 0; // SEEKING + actor->extravalue2 = 0; + spbplace = -1; + } + break; + + case 0: + SPBSeekingChase(actor, bestplayer, wspeed, bestrank); + break; } // Finally, no matter what, the spb should not be able to be under the ground, or above the ceiling; @@ -8880,7 +8870,6 @@ void A_SPBChase(mobj_t *actor) else if (actor->z > actor->ceilingz - actor->height) actor->z = actor->ceilingz - actor->height; - return; } From 8704d684fc643187d1a28869af02ccc18be668a1 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Mon, 28 Oct 2019 16:27:52 -0400 Subject: [PATCH 41/56] Revert "Break SPBChase into a few more functions" This reverts commit 41f69b3c16b5250a93b1391394f22a36f006a19d. --- src/p_enemy.c | 313 ++++++++++++++++++++++++++------------------------ 1 file changed, 162 insertions(+), 151 deletions(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index 9e31206be..ff57b0ffa 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -8480,11 +8480,11 @@ void A_JawzExplode(mobj_t *actor) static void SpawnSPBTrailRings(mobj_t *actor) { - if (actor != NULL && !P_MobjWasRemoved(actor)) + if (actor != NULL) { if (leveltime % 6 == 0) { - mobj_t *ring = P_SpawnMobj(actor->x - actor->momx, actor->y - actor->momy, + mobj_t *ring = P_SpawnMobj(actor->x - actor->momx, actor->y - actor->momx, actor->z - actor->momz + (24*mapobjectscale), MT_RING); ring->threshold = 10; ring->fuse = 120*TICRATE; @@ -8492,64 +8492,72 @@ static void SpawnSPBTrailRings(mobj_t *actor) } } -static void ModifySPBSpeedForAngle(mobj_t *actor, angle_t *hang, angle_t *vang, fixed_t *xyspeed, fixed_t *zspeed) +void A_SPBChase(mobj_t *actor) { - if (actor != NULL && !P_MobjWasRemoved(actor)) + player_t *player = NULL; + player_t *scplayer = NULL; // secondary target for seeking + UINT8 i; + UINT8 bestrank = UINT8_MAX; + fixed_t dist; + angle_t hang, vang; + fixed_t wspeed, xyspeed, zspeed; + fixed_t pdist = 1536<movefactor; + + if (actor->threshold) // Just fired, go straight. { - // Smoothly rotate horz angle - angle_t input = hang - actor->angle; - boolean invert = (input > ANGLE_180); - if (invert) - input = InvAngle(input); - - // Slow down when turning; it looks better and makes U-turns not unfair - xyspeed = FixedMul(actor->cvmem, max(0, (((180<angle += input; - - // Smoothly rotate vert angle - input = vang - actor->movedir; - invert = (input > ANGLE_180); - if (invert) - input = InvAngle(input); - - // Slow down when turning; might as well do it for momz, since we do it above too - zspeed = FixedMul(actor->cvmem, max(0, (((180<movedir += input; + actor->lastlook = -1; + actor->cusval = -1; + spbplace = -1; + P_InstaThrust(actor, actor->angle, wspeed); + return; } -} -static void SPBTargettingChase(mobj_t *actor, fixed_t wspeed, UINT8 bestrank) -{ - if (actor != NULL && !P_MobjWasRemoved(actor)) + // Find the player with the best rank + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i] || players[i].spectator || players[i].exiting) + continue; // not in-game + + /*if (!players[i].mo) + continue; // no mobj + + if (players[i].mo->health <= 0) + continue; // dead + + if (players[i].kartstuff[k_respawn]) + continue;*/ // respawning + + if (players[i].kartstuff[k_position] < bestrank) + { + bestrank = players[i].kartstuff[k_position]; + player = &players[i]; + } + } + + // lastlook = last player num targetted + // cvmem = stored speed + // cusval = next waypoint heap index + // extravalue1 = SPB movement mode + // extravalue2 = mode misc option + + if (actor->extravalue1 == 1) // MODE: TARGETING { actor->cusval = -1; // Reset waypoint - if (actor->tracer == NULL || P_MobjWasRemoved(actor->tracer) || !actor->tracer->health) + if (actor->tracer && actor->tracer->health) { - // Target's gone, return to SEEKING - P_SetTarget(&actor->tracer, NULL); - actor->extravalue1 = 2; // WAIT... - actor->extravalue2 = 52; // Slightly over the respawn timer length - return; - } - else - { - fixed_t xyspeed, zspeed; - angle_t hang, vang; - fixed_t dist; fixed_t defspeed = wspeed; fixed_t range = (160*actor->tracer->scale); - fixed_t cx = 0, cy = 0; + fixed_t cx = 0, cy =0; // Play the intimidating gurgle if (!S_SoundPlaying(actor, actor->info->activesound)) @@ -8600,6 +8608,7 @@ static void SPBTargettingChase(mobj_t *actor, fixed_t wspeed, UINT8 bestrank) wspeed = 20*actor->tracer->scale; if (actor->tracer->player->pflags & PF_SLIDING) wspeed = actor->tracer->player->speed/2; + // ^^^^ current section: These are annoying, and grand metropolis in particular needs this. hang = R_PointToAngle2(actor->x, actor->y, actor->tracer->x, actor->tracer->y); vang = R_PointToAngle2(0, actor->z, dist, actor->tracer->z); @@ -8610,7 +8619,37 @@ static void SPBTargettingChase(mobj_t *actor, fixed_t wspeed, UINT8 bestrank) else actor->cvmem = wspeed; - ModifySPBSpeedForAngle(actor, &hang, &vang, &xyspeed, &zspeed); + { + // Smoothly rotate horz angle + angle_t input = hang - actor->angle; + boolean invert = (input > ANGLE_180); + if (invert) + input = InvAngle(input); + + // Slow down when turning; it looks better and makes U-turns not unfair + xyspeed = FixedMul(actor->cvmem, max(0, (((180<angle += input; + + // Smoothly rotate vert angle + input = vang - actor->movedir; + invert = (input > ANGLE_180); + if (invert) + input = InvAngle(input); + + // Slow down when turning; might as well do it for momz, since we do it above too + zspeed = FixedMul(actor->cvmem, max(0, (((180<movedir += input; + } actor->momx = cx + FixedMul(FixedMul(xyspeed, FINECOSINE(actor->angle>>ANGLETOFINESHIFT)), FINECOSINE(actor->movedir>>ANGLETOFINESHIFT)); actor->momy = cy + FixedMul(FixedMul(xyspeed, FINESINE(actor->angle>>ANGLETOFINESHIFT)), FINECOSINE(actor->movedir>>ANGLETOFINESHIFT)); @@ -8636,21 +8675,46 @@ static void SPBTargettingChase(mobj_t *actor, fixed_t wspeed, UINT8 bestrank) fast->colorized = true; K_MatchGenericExtraFlags(fast, actor); } + + return; + } + else // Target's gone, return to SEEKING + { + P_SetTarget(&actor->tracer, NULL); + actor->extravalue1 = 2; // WAIT... + actor->extravalue2 = 52; // Slightly over the respawn timer length + return; } } -} - -static void SPBSeekingChase(mobj_t *actor, player_t *player, fixed_t wspeed, UINT8 bestrank) -{ - if (actor != NULL && !P_MobjWasRemoved(actor)) + else if (actor->extravalue1 == 2) // MODE: WAIT... + { + actor->momx = actor->momy = actor->momz = 0; // Stoooop + actor->cusval = -1; // Reset waypoint + + if (actor->lastlook != -1 + && playeringame[actor->lastlook] + && !players[actor->lastlook].spectator + && !players[actor->lastlook].exiting) + { + spbplace = players[actor->lastlook].kartstuff[k_position]; + players[actor->lastlook].kartstuff[k_ringlock] = 1; + if (actor->extravalue2-- <= 0 && players[actor->lastlook].mo) + { + P_SetTarget(&actor->tracer, players[actor->lastlook].mo); + actor->extravalue1 = 1; // TARGET ACQUIRED + actor->extravalue2 = 7*TICRATE; + actor->cvmem = wspeed; + } + } + else + { + actor->extravalue1 = 0; // SEEKING + actor->extravalue2 = 0; + spbplace = -1; + } + } + else // MODE: SEEKING { -#define TARGETDIST 1536 - fixed_t xyspeed, zspeed; - angle_t hang, vang; - fixed_t dist; - player_t *scplayer = NULL; // secondary target for swerving - fixed_t pdist = TARGETDIST<cvmem = wspeed; - ModifySPBSpeedForAngle(actor, &hang, &vang, &xyspeed, &zspeed); + { + // Smoothly rotate horz angle + angle_t input = hang - actor->angle; + boolean invert = (input > ANGLE_180); + if (invert) + input = InvAngle(input); + + // Slow down when turning; it looks better and makes U-turns not unfair + xyspeed = FixedMul(wspeed, max(0, (((180<angle += input; + + // Smoothly rotate vert angle + input = vang - actor->movedir; + invert = (input > ANGLE_180); + if (invert) + input = InvAngle(input); + + // Slow down when turning; might as well do it for momz, since we do it above too + zspeed = FixedMul(wspeed, max(0, (((180<movedir += input; + } + actor->momx = FixedMul(FixedMul(xyspeed, FINECOSINE(actor->angle>>ANGLETOFINESHIFT)), FINECOSINE(actor->movedir>>ANGLETOFINESHIFT)); actor->momy = FixedMul(FixedMul(xyspeed, FINESINE(actor->angle>>ANGLETOFINESHIFT)), FINECOSINE(actor->movedir>>ANGLETOFINESHIFT)); @@ -8752,7 +8846,7 @@ static void SPBSeekingChase(mobj_t *actor, player_t *player, fixed_t wspeed, UIN if (R_PointToDist2(actor->x, actor->y, players[i].mo->x, players[i].mo->y) < pdist) { pdist = R_PointToDist2(actor->x, actor->y, players[i].mo->x, players[i].mo->y); - scplayer = &players[i]; + scplayer = &players[i]; // it doesn't matter if we override this guy now. } } @@ -8771,97 +8865,13 @@ static void SPBSeekingChase(mobj_t *actor, player_t *player, fixed_t wspeed, UIN // Spawn a trail of rings behind the SPB! SpawnSPBTrailRings(actor); - if (dist <= (TARGETDIST * actor->tracer->scale)) // Close enough to target? + if (dist <= (1024*actor->tracer->scale)) // Close enough to target? { S_StartSound(actor, actor->info->attacksound); actor->extravalue1 = 1; // TARGET ACQUIRED actor->extravalue2 = 7*TICRATE; actor->cvmem = wspeed; } - -#undef TARGETDIST - } -} - -void A_SPBChase(mobj_t *actor) -{ - UINT8 i; - UINT8 bestrank = UINT8_MAX; - player_t *bestplayer = NULL; - fixed_t wspeed; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_SPBChase", actor)) - return; -#endif - - // Default speed - wspeed = actor->movefactor; - - if (actor->threshold) // Just fired, go straight. - { - actor->lastlook = -1; - actor->cusval = -1; - spbplace = -1; - P_InstaThrust(actor, actor->angle, wspeed); - return; - } - - // Find the player with the best rank - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i] || players[i].spectator || players[i].exiting) - continue; // not in-game - - if (players[i].kartstuff[k_position] < bestrank) - { - bestrank = players[i].kartstuff[k_position]; - bestplayer = &players[i]; - } - } - - // lastlook = last player num targetted - // cvmem = stored speed - // cusval = next waypoint heap index - // extravalue1 = SPB movement mode - // extravalue2 = mode misc option - - switch (actor->extravalue1) - { - case 1: // MODE: TARGETING - SPBTargettingChase(actor, wspeed, bestrank); - break; - - case 2: // MODE: WAIT... - actor->momx = actor->momy = actor->momz = 0; // Stoooop - actor->cusval = -1; // Reset waypoint - - if (actor->lastlook != -1 - && playeringame[actor->lastlook] - && !players[actor->lastlook].spectator - && !players[actor->lastlook].exiting) - { - spbplace = players[actor->lastlook].kartstuff[k_position]; - players[actor->lastlook].kartstuff[k_ringlock] = 1; - if (actor->extravalue2-- <= 0 && players[actor->lastlook].mo) - { - P_SetTarget(&actor->tracer, players[actor->lastlook].mo); - actor->extravalue1 = 1; // TARGET ACQUIRED - actor->extravalue2 = 7*TICRATE; - actor->cvmem = wspeed; - } - } - else - { - actor->extravalue1 = 0; // SEEKING - actor->extravalue2 = 0; - spbplace = -1; - } - break; - - case 0: - SPBSeekingChase(actor, bestplayer, wspeed, bestrank); - break; } // Finally, no matter what, the spb should not be able to be under the ground, or above the ceiling; @@ -8870,6 +8880,7 @@ void A_SPBChase(mobj_t *actor) else if (actor->z > actor->ceilingz - actor->height) actor->z = actor->ceilingz - actor->height; + return; } From 607d177512b984aee8a2aed919d90e409fcba171 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Mon, 28 Oct 2019 16:28:56 -0400 Subject: [PATCH 42/56] Fix copypaste typo --- src/p_enemy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index ff57b0ffa..6d313f566 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -8484,7 +8484,7 @@ static void SpawnSPBTrailRings(mobj_t *actor) { if (leveltime % 6 == 0) { - mobj_t *ring = P_SpawnMobj(actor->x - actor->momx, actor->y - actor->momx, + mobj_t *ring = P_SpawnMobj(actor->x - actor->momx, actor->y - actor->momy, actor->z - actor->momz + (24*mapobjectscale), MT_RING); ring->threshold = 10; ring->fuse = 120*TICRATE; From d91e8205dc992576766ebf06f51ff52e7174daae Mon Sep 17 00:00:00 2001 From: Sally Cochenour Date: Tue, 3 Mar 2020 14:22:52 -0500 Subject: [PATCH 43/56] Don't update respawn point when mid-air --- src/k_kart.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/k_kart.c b/src/k_kart.c index b3297527e..c37fb6502 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -5880,6 +5880,11 @@ static waypoint_t *K_GetPlayerNextWaypoint(player_t *player, boolean closest) } } + if (P_IsObjectOnGround(player->mo)) + { + updaterespawn = false; + } + // Respawn point should only be updated when we're going to a nextwaypoint if ((updaterespawn) && (bestwaypoint != NULL) && From 597e6820b6a028c9aaae9e2784a8db592d2b94cf Mon Sep 17 00:00:00 2001 From: Sally Cochenour Date: Tue, 3 Mar 2020 14:47:41 -0500 Subject: [PATCH 44/56] Let's try out going back to closest check again --- src/k_kart.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/k_kart.c b/src/k_kart.c index c37fb6502..2597f6138 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -6006,14 +6006,16 @@ static void K_UpdateDistanceFromFinishLine(player_t *const player) else { waypoint_t *finishline = K_GetFinishLineWaypoint(); - waypoint_t *nextwaypoint = K_GetPlayerNextWaypoint(player, false); + waypoint_t *nextwaypoint = K_GetPlayerNextWaypoint(player, true); //false + /* if ((nextwaypoint == NULL) && (player->nextwaypoint == NULL)) { // Special case: if player nextwaypoint is still NULL, we want to fix that as soon as possible, so use the closest waypoint instead. // This will most likely only happen on map load or player spawn. nextwaypoint = K_GetPlayerNextWaypoint(player, true); } + */ if (nextwaypoint != NULL) { From 8a19f6f208f9be03260d0cad4cbdbd1cbee7ad0d Mon Sep 17 00:00:00 2001 From: Sally Cochenour Date: Tue, 3 Mar 2020 15:41:03 -0500 Subject: [PATCH 45/56] Wrong sign here --- src/k_kart.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_kart.c b/src/k_kart.c index 2597f6138..789e271d8 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -5880,7 +5880,7 @@ static waypoint_t *K_GetPlayerNextWaypoint(player_t *player, boolean closest) } } - if (P_IsObjectOnGround(player->mo)) + if (!P_IsObjectOnGround(player->mo)) { updaterespawn = false; } From 1cbb4bea6b2f456031879d946963757e6b9424cc Mon Sep 17 00:00:00 2001 From: Sally Cochenour Date: Tue, 3 Mar 2020 15:47:02 -0500 Subject: [PATCH 46/56] Limited vertical range on player waypoints --- src/k_kart.c | 22 ++++------------------ src/k_waypoint.c | 21 ++++++++++++++------- 2 files changed, 18 insertions(+), 25 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 789e271d8..dd86fe201 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -5739,24 +5739,19 @@ void K_KartPlayerAfterThink(player_t *player) Input Arguments:- player - The player the next waypoint is being found for - closest - Use closest waypoint algorithm, instead of best touching Return:- The waypoint that is the player's next waypoint --------------------------------------------------*/ -static waypoint_t *K_GetPlayerNextWaypoint(player_t *player, boolean closest) +static waypoint_t *K_GetPlayerNextWaypoint(player_t *player) { waypoint_t *bestwaypoint = NULL; + if ((player != NULL) && (player->mo != NULL) && (P_MobjWasRemoved(player->mo) == false)) { - waypoint_t *waypoint = NULL; + waypoint_t *waypoint = K_GetClosestWaypointToMobj(player->mo); boolean updaterespawn = false; - if (closest == true) - waypoint = K_GetClosestWaypointToMobj(player->mo); - else - waypoint = K_GetBestWaypointTouchingMobj(player->mo); - bestwaypoint = waypoint; // check the waypoint's location in relation to the player @@ -6006,16 +6001,7 @@ static void K_UpdateDistanceFromFinishLine(player_t *const player) else { waypoint_t *finishline = K_GetFinishLineWaypoint(); - waypoint_t *nextwaypoint = K_GetPlayerNextWaypoint(player, true); //false - - /* - if ((nextwaypoint == NULL) && (player->nextwaypoint == NULL)) - { - // Special case: if player nextwaypoint is still NULL, we want to fix that as soon as possible, so use the closest waypoint instead. - // This will most likely only happen on map load or player spawn. - nextwaypoint = K_GetPlayerNextWaypoint(player, true); - } - */ + waypoint_t *nextwaypoint = K_GetPlayerNextWaypoint(player); if (nextwaypoint != NULL) { diff --git a/src/k_waypoint.c b/src/k_waypoint.c index 68b21520e..d66076630 100644 --- a/src/k_waypoint.c +++ b/src/k_waypoint.c @@ -221,15 +221,22 @@ waypoint_t *K_GetClosestWaypointToMobj(mobj_t *const mobj) for (i = 0; i < numwaypoints; i++) { checkwaypoint = &waypointheap[i]; - checkdist = P_AproxDistance( - (mobj->x >> FRACBITS) - (checkwaypoint->mobj->x >> FRACBITS), - (mobj->y >> FRACBITS) - (checkwaypoint->mobj->y >> FRACBITS)); - checkdist = P_AproxDistance(checkdist, (mobj->z >> FRACBITS) - (checkwaypoint->mobj->z >> FRACBITS)); - if (checkdist < closestdist) + checkdist = abs((mobj->z >> FRACBITS) - (checkwaypoint->mobj->z >> FRACBITS)); + + // TODO: Keep the old version of this function, + // make this 128 check a separate function. + if (checkdist <= 128) { - closestwaypoint = checkwaypoint; - closestdist = checkdist; + checkdist = P_AproxDistance( + (mobj->x >> FRACBITS) - (checkwaypoint->mobj->x >> FRACBITS), + (mobj->y >> FRACBITS) - (checkwaypoint->mobj->y >> FRACBITS)); + + if (checkdist < closestdist) + { + closestwaypoint = checkwaypoint; + closestdist = checkdist; + } } } } From 04b443d58c738b25577773effd6d7901e221ffc5 Mon Sep 17 00:00:00 2001 From: Sally Cochenour Date: Tue, 3 Mar 2020 15:49:10 -0500 Subject: [PATCH 47/56] 2.2 sight checks backport --- src/p_sight.c | 161 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 142 insertions(+), 19 deletions(-) diff --git a/src/p_sight.c b/src/p_sight.c index 626f8bbef..d607fc9e9 100644 --- a/src/p_sight.c +++ b/src/p_sight.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -14,6 +14,7 @@ #include "doomdef.h" #include "doomstat.h" #include "p_local.h" +#include "p_slopes.h" #include "r_main.h" #include "r_state.h" @@ -103,12 +104,20 @@ static fixed_t P_InterceptVector2(divline_t *v2, divline_t *v1) static boolean P_CrossSubsecPolyObj(polyobj_t *po, register los_t *los) { size_t i; + sector_t *polysec; + + if (!(po->flags & POF_RENDERALL)) + return true; // the polyobject isn't visible, so we can ignore it + + polysec = po->lines[0]->backsector; for (i = 0; i < po->numLines; ++i) { line_t *line = po->lines[i]; divline_t divl; const vertex_t *v1,*v2; + fixed_t frac; + fixed_t topslope, bottomslope; // already checked other side? if (line->validcount == validcount) @@ -140,7 +149,22 @@ static boolean P_CrossSubsecPolyObj(polyobj_t *po, register los_t *los) continue; // stop because it is not two sided - return false; + //if (!(po->flags & POF_TESTHEIGHT)) + //return false; + + frac = P_InterceptVector2(&los->strace, &divl); + + // get slopes of top and bottom of this polyobject line + topslope = FixedDiv(polysec->ceilingheight - los->sightzstart , frac); + bottomslope = FixedDiv(polysec->floorheight - los->sightzstart , frac); + + if (topslope >= los->topslope && bottomslope <= los->bottomslope) + return false; // view completely blocked + + // TODO: figure out if it's worth considering partially blocked cases or not? + // maybe to adjust los's top/bottom slopes if needed + //if (los->topslope <= los->bottomslope) + //return false; } return true; @@ -193,6 +217,15 @@ static boolean P_CrossSubsector(size_t num, register los_t *los) const sector_t *front, *back; const vertex_t *v1,*v2; fixed_t frac; + fixed_t frontf, backf, frontc, backc; +#ifdef ESLOPE + fixed_t fracx, fracy; +#endif + + /* SRB2Kart doesn't have this? + if (seg->glseg) + continue; + */ // already checked other side? if (line->validcount == validcount) @@ -227,36 +260,51 @@ static boolean P_CrossSubsector(size_t num, register los_t *los) if (!(line->flags & ML_TWOSIDED)) return false; + // calculate fractional intercept (how far along we are divided by how far we are from t2) + frac = P_InterceptVector2(&los->strace, &divl); + + front = seg->frontsector; + back = seg->backsector; +#ifdef ESLOPE + // calculate position at intercept + fracx = los->strace.x + FixedMul(los->strace.dx, frac); + fracy = los->strace.y + FixedMul(los->strace.dy, frac); + // calculate sector heights + frontf = (front->f_slope) ? P_GetZAt(front->f_slope, fracx, fracy) : front->floorheight; + frontc = (front->c_slope) ? P_GetZAt(front->c_slope, fracx, fracy) : front->ceilingheight; + backf = (back->f_slope) ? P_GetZAt(back->f_slope, fracx, fracy) : back->floorheight; + backc = (back->c_slope) ? P_GetZAt(back->c_slope, fracx, fracy) : back->ceilingheight; +#else + frontf = front->floorheight; + frontc = front->ceilingheight; + backf = back->floorheight; + backc = back->ceilingheight; +#endif // crosses a two sided line // no wall to block sight with? - if ((front = seg->frontsector)->floorheight == - (back = seg->backsector)->floorheight && - front->ceilingheight == back->ceilingheight) + if (frontf == backf && frontc == backc + && !front->ffloors & !back->ffloors) // (and no FOFs) continue; // possible occluder // because of ceiling height differences - popentop = front->ceilingheight < back->ceilingheight ? - front->ceilingheight : back->ceilingheight ; + popentop = min(frontc, backc); // because of floor height differences - popenbottom = front->floorheight > back->floorheight ? - front->floorheight : back->floorheight ; + popenbottom = max(frontf, backf); // quick test for totally closed doors if (popenbottom >= popentop) return false; - frac = P_InterceptVector2(&los->strace, &divl); - - if (front->floorheight != back->floorheight) + if (frontf != backf) { fixed_t slope = FixedDiv(popenbottom - los->sightzstart , frac); if (slope > los->bottomslope) los->bottomslope = slope; } - if (front->ceilingheight != back->ceilingheight) + if (frontc != backc) { fixed_t slope = FixedDiv(popentop - los->sightzstart , frac); if (slope < los->topslope) @@ -265,6 +313,58 @@ static boolean P_CrossSubsector(size_t num, register los_t *los) if (los->topslope <= los->bottomslope) return false; + + // Monster Iestyn: check FOFs! + if (front->ffloors || back->ffloors) + { + ffloor_t *rover; + fixed_t topslope, bottomslope; + fixed_t topz, bottomz; + // check front sector's FOFs first + for (rover = front->ffloors; rover; rover = rover->next) + { + if (!(rover->flags & FF_EXISTS) + || !(rover->flags & FF_RENDERSIDES) || rover->flags & FF_TRANSLUCENT) + { + continue; + } + +#ifdef ESLOPE + topz = (*rover->t_slope) ? P_GetZAt(*rover->t_slope, fracx, fracy) : *rover->topheight; + bottomz = (*rover->b_slope) ? P_GetZAt(*rover->b_slope, fracx, fracy) : *rover->bottomheight; +#else + topz = *rover->topheight; + bottomz = *rover->bottomheight; +#endif + topslope = FixedDiv(topz - los->sightzstart , frac); + bottomslope = FixedDiv(bottomz - los->sightzstart , frac); + if (topslope >= los->topslope && bottomslope <= los->bottomslope) + return false; // view completely blocked + } + // check back sector's FOFs as well + for (rover = back->ffloors; rover; rover = rover->next) + { + if (!(rover->flags & FF_EXISTS) + || !(rover->flags & FF_RENDERSIDES) || rover->flags & FF_TRANSLUCENT) + { + continue; + } + +#ifdef ESLOPE + topz = (*rover->t_slope) ? P_GetZAt(*rover->t_slope, fracx, fracy) : *rover->topheight; + bottomz = (*rover->b_slope) ? P_GetZAt(*rover->b_slope, fracx, fracy) : *rover->bottomheight; +#else + topz = *rover->topheight; + bottomz = *rover->bottomheight; +#endif + topslope = FixedDiv(topz - los->sightzstart , frac); + bottomslope = FixedDiv(bottomz - los->sightzstart , frac); + if (topslope >= los->topslope && bottomslope <= los->bottomslope) + return false; // view completely blocked + } + // TODO: figure out if it's worth considering partially blocked cases or not? + // maybe to adjust los's top/bottom slopes if needed + } } // passed the subsector ok @@ -375,6 +475,8 @@ boolean P_CheckSight(mobj_t *t1, mobj_t *t2) if (s1 == s2) // Both sectors are the same. { ffloor_t *rover; + fixed_t topz1, bottomz1; // top, bottom heights at t1's position + fixed_t topz2, bottomz2; // likewise but for t2 for (rover = s1->ffloors; rover; rover = rover->next) { @@ -387,9 +489,30 @@ boolean P_CheckSight(mobj_t *t1, mobj_t *t2) continue; } +#ifdef ESLOPE + if (*rover->t_slope) + { + topz1 = P_GetZAt(*rover->t_slope, t1->x, t1->y); + topz2 = P_GetZAt(*rover->t_slope, t2->x, t2->y); + } + else + topz1 = topz2 = *rover->topheight; + + if (*rover->b_slope) + { + bottomz1 = P_GetZAt(*rover->b_slope, t1->x, t1->y); + bottomz2 = P_GetZAt(*rover->b_slope, t2->x, t2->y); + } + else + bottomz1 = bottomz2 = *rover->bottomheight; +#else + topz1 = topz2 = *rover->topheight; + bottomz1 = bottomz2 = *rover->bottomheight; +#endif + // Check for blocking floors here. - if ((los.sightzstart < *rover->bottomheight && t2->z >= *rover->topheight) - || (los.sightzstart >= *rover->topheight && t2->z + t2->height < *rover->bottomheight)) + if ((los.sightzstart < bottomz1 && t2->z >= topz2) + || (los.sightzstart >= topz1 && t2->z + t2->height < bottomz2)) { // no way to see through that return false; @@ -400,19 +523,19 @@ boolean P_CheckSight(mobj_t *t1, mobj_t *t2) if (!(rover->flags & FF_INVERTPLANES)) { - if (los.sightzstart >= *rover->topheight && t2->z + t2->height < *rover->topheight) + if (los.sightzstart >= topz1 && t2->z + t2->height < topz2) return false; // blocked by upper outside plane - if (los.sightzstart < *rover->bottomheight && t2->z >= *rover->bottomheight) + if (los.sightzstart < bottomz1 && t2->z >= bottomz2) return false; // blocked by lower outside plane } if (rover->flags & FF_INVERTPLANES || rover->flags & FF_BOTHPLANES) { - if (los.sightzstart < *rover->topheight && t2->z >= *rover->topheight) + if (los.sightzstart < topz1 && t2->z >= topz2) return false; // blocked by upper inside plane - if (los.sightzstart >= *rover->bottomheight && t2->z + t2->height < *rover->bottomheight) + if (los.sightzstart >= bottomz1 && t2->z + t2->height < bottomz2) return false; // blocked by lower inside plane } } From f068539bad47b4081ee3defe4e8967b9c897c671 Mon Sep 17 00:00:00 2001 From: Sally Cochenour Date: Tue, 3 Mar 2020 16:12:21 -0500 Subject: [PATCH 48/56] Don't sight check through transparent FOFs Maybe this should be a option somehow, like a distinction between "sight" and "ray-tracing", but I'm not sure how to go about that --- src/p_sight.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_sight.c b/src/p_sight.c index d607fc9e9..f230f40f6 100644 --- a/src/p_sight.c +++ b/src/p_sight.c @@ -484,7 +484,7 @@ boolean P_CheckSight(mobj_t *t1, mobj_t *t2) /// \todo Improve by checking fog density/translucency /// and setting a sight limit. if (!(rover->flags & FF_EXISTS) - || !(rover->flags & FF_RENDERPLANES) || rover->flags & FF_TRANSLUCENT) + || !(rover->flags & FF_RENDERPLANES) /*|| (rover->flags & FF_TRANSLUCENT)*/) { continue; } From ac1d40d6c525387fe45019dd63bce081c2c0e31e Mon Sep 17 00:00:00 2001 From: Sally Cochenour Date: Tue, 3 Mar 2020 16:14:19 -0500 Subject: [PATCH 49/56] Sight check for player waypoints --- src/k_waypoint.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/k_waypoint.c b/src/k_waypoint.c index d66076630..1913af0a6 100644 --- a/src/k_waypoint.c +++ b/src/k_waypoint.c @@ -222,10 +222,10 @@ waypoint_t *K_GetClosestWaypointToMobj(mobj_t *const mobj) { checkwaypoint = &waypointheap[i]; + // TODO: Keep the old version of this function, + // make this 128 check & sight checks a separate function. checkdist = abs((mobj->z >> FRACBITS) - (checkwaypoint->mobj->z >> FRACBITS)); - // TODO: Keep the old version of this function, - // make this 128 check a separate function. if (checkdist <= 128) { checkdist = P_AproxDistance( @@ -234,6 +234,12 @@ waypoint_t *K_GetClosestWaypointToMobj(mobj_t *const mobj) if (checkdist < closestdist) { + if (!P_CheckSight(mobj, checkwaypoint->mobj)) + { + // Save sight checks for the end, so we only do it if we have to + continue; + } + closestwaypoint = checkwaypoint; closestdist = checkdist; } From 7fff21acd4aa7a7f34f8c7e9a14962c08cb0e9c5 Mon Sep 17 00:00:00 2001 From: Sally Cochenour Date: Tue, 3 Mar 2020 16:58:09 -0500 Subject: [PATCH 50/56] Instead of vertical cap, quadruple z axis distance Far more natural results! --- src/k_waypoint.c | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/src/k_waypoint.c b/src/k_waypoint.c index 1913af0a6..8d822c3d6 100644 --- a/src/k_waypoint.c +++ b/src/k_waypoint.c @@ -223,26 +223,22 @@ waypoint_t *K_GetClosestWaypointToMobj(mobj_t *const mobj) checkwaypoint = &waypointheap[i]; // TODO: Keep the old version of this function, - // make this 128 check & sight checks a separate function. - checkdist = abs((mobj->z >> FRACBITS) - (checkwaypoint->mobj->z >> FRACBITS)); + // make the vertical axis faking & sight checks a separate function. + checkdist = P_AproxDistance( + (mobj->x >> FRACBITS) - (checkwaypoint->mobj->x >> FRACBITS), + (mobj->y >> FRACBITS) - (checkwaypoint->mobj->y >> FRACBITS)); + checkdist = P_AproxDistance(checkdist, ((mobj->z >> FRACBITS) - (checkwaypoint->mobj->z >> FRACBITS)) << 2); - if (checkdist <= 128) + if (checkdist < closestdist) { - checkdist = P_AproxDistance( - (mobj->x >> FRACBITS) - (checkwaypoint->mobj->x >> FRACBITS), - (mobj->y >> FRACBITS) - (checkwaypoint->mobj->y >> FRACBITS)); - - if (checkdist < closestdist) + if (!P_CheckSight(mobj, checkwaypoint->mobj)) { - if (!P_CheckSight(mobj, checkwaypoint->mobj)) - { - // Save sight checks for the end, so we only do it if we have to - continue; - } - - closestwaypoint = checkwaypoint; - closestdist = checkdist; + // Save sight checks for the end, so we only do it if we have to + continue; } + + closestwaypoint = checkwaypoint; + closestdist = checkdist; } } } From 721fb369fd5920646b363a4890271f1aadebe7a9 Mon Sep 17 00:00:00 2001 From: Sally Cochenour Date: Tue, 3 Mar 2020 18:34:17 -0500 Subject: [PATCH 51/56] Move changes to K_GetBestWaypointForMobj so that K_GetClosestWaypointToMobj can stay the same --- src/k_kart.c | 2 +- src/k_waypoint.c | 85 +++++++++++++++++++++++------------------------- src/k_waypoint.h | 10 +++--- src/p_enemy.c | 5 ++- 4 files changed, 50 insertions(+), 52 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index dd86fe201..0cb8b9d20 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -5749,7 +5749,7 @@ static waypoint_t *K_GetPlayerNextWaypoint(player_t *player) if ((player != NULL) && (player->mo != NULL) && (P_MobjWasRemoved(player->mo) == false)) { - waypoint_t *waypoint = K_GetClosestWaypointToMobj(player->mo); + waypoint_t *waypoint = K_GetBestWaypointForMobj(player->mo); boolean updaterespawn = false; bestwaypoint = waypoint; diff --git a/src/k_waypoint.c b/src/k_waypoint.c index 8d822c3d6..dfa868204 100644 --- a/src/k_waypoint.c +++ b/src/k_waypoint.c @@ -222,8 +222,46 @@ waypoint_t *K_GetClosestWaypointToMobj(mobj_t *const mobj) { checkwaypoint = &waypointheap[i]; - // TODO: Keep the old version of this function, - // make the vertical axis faking & sight checks a separate function. + checkdist = P_AproxDistance( + (mobj->x >> FRACBITS) - (checkwaypoint->mobj->x >> FRACBITS), + (mobj->y >> FRACBITS) - (checkwaypoint->mobj->y >> FRACBITS)); + checkdist = P_AproxDistance(checkdist, (mobj->z >> FRACBITS) - (checkwaypoint->mobj->z >> FRACBITS)); + + if (checkdist < closestdist) + { + closestwaypoint = checkwaypoint; + closestdist = checkdist; + } + } + } + + return closestwaypoint; +} + +/*-------------------------------------------------- + waypoint_t *K_GetBestWaypointForMobj(mobj_t *const mobj) + + See header file for description. +--------------------------------------------------*/ +waypoint_t *K_GetBestWaypointForMobj(mobj_t *const mobj) +{ + waypoint_t *bestwaypoint = NULL; + + if ((mobj == NULL) || P_MobjWasRemoved(mobj)) + { + CONS_Debug(DBG_GAMELOGIC, "NULL mobj in K_GetBestWaypointForMobj.\n"); + } + else + { + size_t i = 0U; + waypoint_t *checkwaypoint = NULL; + fixed_t closestdist = INT32_MAX; + fixed_t checkdist = INT32_MAX; + + for (i = 0; i < numwaypoints; i++) + { + checkwaypoint = &waypointheap[i]; + checkdist = P_AproxDistance( (mobj->x >> FRACBITS) - (checkwaypoint->mobj->x >> FRACBITS), (mobj->y >> FRACBITS) - (checkwaypoint->mobj->y >> FRACBITS)); @@ -237,49 +275,8 @@ waypoint_t *K_GetClosestWaypointToMobj(mobj_t *const mobj) continue; } - closestwaypoint = checkwaypoint; - closestdist = checkdist; - } - } - } - - return closestwaypoint; -} - -/*-------------------------------------------------- - waypoint_t *K_GetBestWaypointTouchingMobj(mobj_t *const mobj) - - See header file for description. ---------------------------------------------------*/ -waypoint_t *K_GetBestWaypointTouchingMobj(mobj_t *const mobj) -{ - waypoint_t *bestwaypoint = NULL; - - if ((mobj == NULL) || P_MobjWasRemoved(mobj)) - { - CONS_Debug(DBG_GAMELOGIC, "NULL mobj in K_GetBestWaypointTouchingMobj.\n"); - } - else - { - size_t i = 0U; - waypoint_t *checkwaypoint = NULL; - fixed_t bestdist = INT32_MAX; - fixed_t checkdist = INT32_MAX; - - for (i = 0; i < numwaypoints; i++) - { - checkwaypoint = &waypointheap[i]; - checkdist = P_AproxDistance( - (mobj->x >> FRACBITS) - (checkwaypoint->mobj->x >> FRACBITS), - (mobj->y >> FRACBITS) - (checkwaypoint->mobj->y >> FRACBITS)); - checkdist = P_AproxDistance(checkdist, (mobj->z >> FRACBITS) - (checkwaypoint->mobj->z >> FRACBITS)); - - // The mobj has to be touching this waypoint to use it. - if ((checkdist <= (checkwaypoint->mobj->radius >> FRACBITS)) - && (checkdist < bestdist)) - { bestwaypoint = checkwaypoint; - bestdist = checkdist; + closestdist = checkdist; } } } diff --git a/src/k_waypoint.h b/src/k_waypoint.h index af4ac71a5..058ff6882 100644 --- a/src/k_waypoint.h +++ b/src/k_waypoint.h @@ -152,17 +152,19 @@ waypoint_t *K_GetClosestWaypointToMobj(mobj_t *const mobj); /*-------------------------------------------------- - waypoint_t *K_GetBestWaypointTouchingMobj(mobj_t *const mobj) + waypoint_t *K_GetBestWaypointForMobj(mobj_t *const mobj) - Returns the waypoint closest to the finish line that an mobj is touching + Similar to K_GetClosestWaypointToMobj, but prioritizes horizontal distance over vertical distance, and + sight checks to ensure that the waypoint and mobj are the in same area. Can potentially return NULL if + there are no visible waypoints. Input Arguments:- mobj - mobj to get the waypoint for. Return:- - The best waypoint for the mobj + The best waypoint for the mobj, or NULL if there were no matches --------------------------------------------------*/ -waypoint_t *K_GetBestWaypointTouchingMobj(mobj_t *const mobj); +waypoint_t *K_GetBestWaypointForMobj(mobj_t *const mobj); /*-------------------------------------------------- diff --git a/src/p_enemy.c b/src/p_enemy.c index 6d313f566..69058db23 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -8741,7 +8741,7 @@ void A_SPBChase(mobj_t *actor) { // Previously set nextwaypoint lastwaypoint = K_GetWaypointFromIndex((size_t)actor->cusval); - tempwaypoint = K_GetBestWaypointTouchingMobj(actor); + tempwaypoint = K_GetBestWaypointForMobj(actor); // check if the tempwaypoint corresponds to lastwaypoint's next ID at least; // This is to avoid situations where the SPB decides to suicide jump down a bridge because it found a COMPLETELY unrelated waypoint down there. @@ -8752,7 +8752,7 @@ void A_SPBChase(mobj_t *actor) bestwaypoint = K_GetWaypointFromIndex((size_t)actor->extravalue2); // keep going from the PREVIOUS wp. } else - bestwaypoint = K_GetBestWaypointTouchingMobj(actor); + bestwaypoint = K_GetBestWaypointForMobj(actor); if (bestwaypoint == NULL && lastwaypoint == NULL) { @@ -8781,7 +8781,6 @@ void A_SPBChase(mobj_t *actor) nextwaypoint = lastwaypoint; } - if (nextwaypoint != NULL) { const fixed_t xywaypointdist = P_AproxDistance( From 2b6ca4a38471fa91efd1ac4b6d559d9d1d9a1982 Mon Sep 17 00:00:00 2001 From: Sally Cochenour Date: Tue, 3 Mar 2020 20:56:57 -0500 Subject: [PATCH 52/56] Increase SPB speed & turn --- src/info.c | 2 +- src/p_enemy.c | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/info.c b/src/info.c index 839debb3b..444d79196 100644 --- a/src/info.c +++ b/src/info.c @@ -16003,7 +16003,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_SPB_DEAD, // deathstate S_NULL, // xdeathstate sfx_s3k5d, // deathsound - 64*FRACUNIT, // speed + 80*FRACUNIT, // speed 24*FRACUNIT, // radius 48*FRACUNIT, // height 0, // display offset diff --git a/src/p_enemy.c b/src/p_enemy.c index 69058db23..03eea951b 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -8806,13 +8806,13 @@ void A_SPBChase(mobj_t *actor) if (invert) input = InvAngle(input); + input = FixedAngle(AngleFixed(input)/8); + // Slow down when turning; it looks better and makes U-turns not unfair xyspeed = FixedMul(wspeed, max(0, (((180<angle += input; // Smoothly rotate vert angle @@ -8821,17 +8821,16 @@ void A_SPBChase(mobj_t *actor) if (invert) input = InvAngle(input); + input = FixedAngle(AngleFixed(input)/8); + // Slow down when turning; might as well do it for momz, since we do it above too zspeed = FixedMul(wspeed, max(0, (((180<movedir += input; } - actor->momx = FixedMul(FixedMul(xyspeed, FINECOSINE(actor->angle>>ANGLETOFINESHIFT)), FINECOSINE(actor->movedir>>ANGLETOFINESHIFT)); actor->momy = FixedMul(FixedMul(xyspeed, FINESINE(actor->angle>>ANGLETOFINESHIFT)), FINECOSINE(actor->movedir>>ANGLETOFINESHIFT)); actor->momz = FixedMul(zspeed, FINESINE(actor->movedir>>ANGLETOFINESHIFT)); @@ -8879,7 +8878,6 @@ void A_SPBChase(mobj_t *actor) else if (actor->z > actor->ceilingz - actor->height) actor->z = actor->ceilingz - actor->height; - return; } From d8e0bf61f64328e2a8853381821126b77ac1e045 Mon Sep 17 00:00:00 2001 From: Sally Cochenour Date: Sun, 8 Mar 2020 00:26:33 -0500 Subject: [PATCH 53/56] Scale item distances with map scale --- src/k_kart.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/k_kart.c b/src/k_kart.c index 0cb8b9d20..853f50a93 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1101,6 +1101,9 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) } } + if (mapobjectscale != FRACUNIT) + pdis = FixedDiv(pdis, mapobjectscale); + if (franticitems) // Frantic items make the distances between everyone artifically higher, for crazier items pdis = (15 * pdis) / 14; From 084901a8b1107a697ea0289818875ade14d50007 Mon Sep 17 00:00:00 2001 From: Sally Cochenour Date: Sun, 15 Mar 2020 19:21:06 -0400 Subject: [PATCH 54/56] Add warnings for old map setups We probably don't want to keep these for release, but we need reminders to get rid of them ourselves :V --- src/p_mobj.c | 4 ++++ src/p_spec.c | 2 ++ 2 files changed, 6 insertions(+) diff --git a/src/p_mobj.c b/src/p_mobj.c index 565ef6fbd..325229de8 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -10650,6 +10650,10 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) } } break; + case MT_BOSS3WAYPOINT: + // Remove before release + CONS_Alert(CONS_WARNING, "Boss waypoints are deprecated. Did you forget to remove the old checkpoints, too?\n"); + break; default: break; } diff --git a/src/p_spec.c b/src/p_spec.c index 0af99f163..8e368d710 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -5801,6 +5801,8 @@ void P_SpawnSpecials(INT32 fromnetsave) switch(GETSECSPECIAL(sector->special, 4)) { case 10: // Circuit finish line (Unused) + // Remove before release + CONS_Alert(CONS_WARNING, "Finish line sector type is deprecated.\n"); break; } } From 5ef433f9c73525128b9125f4e28516b3289321f4 Mon Sep 17 00:00:00 2001 From: Sally Cochenour Date: Tue, 17 Mar 2020 19:54:32 -0400 Subject: [PATCH 55/56] Remove bumper when you respawn in Battle again (This stuff really should be its own function...) --- src/k_kart.c | 39 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index e3b674f33..27a4b1e1f 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2217,12 +2217,45 @@ void K_RespawnChecker(player_t *player) S_StartSound(player->mo, sfx_s23c); player->kartstuff[k_startboost] = 50; K_SpawnDashDustRelease(player); - } + } + player->mo->colorized = false; player->kartstuff[k_dropdash] = 0; - player->kartstuff[k_respawn] = 0; + player->kartstuff[k_respawn] = 0; + //P_PlayRinglossSound(player->mo); - P_PlayerRingBurst(player, 3); + P_PlayerRingBurst(player, 3); + + if (G_BattleGametype()) + { + if (player->kartstuff[k_bumper] > 0) + { + if (player->kartstuff[k_bumper] == 1) + { + mobj_t *karmahitbox = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_KARMAHITBOX); // Player hitbox is too small!! + P_SetTarget(&karmahitbox->target, player->mo); + karmahitbox->destscale = player->mo->scale; + P_SetScale(karmahitbox, player->mo->scale); + CONS_Printf(M_GetText("%s lost all of their bumpers!\n"), player_names[player-players]); + } + player->kartstuff[k_bumper]--; + if (K_IsPlayerWanted(player)) + K_CalculateBattleWanted(); + } + + if (!player->kartstuff[k_bumper]) + { + player->kartstuff[k_comebacktimer] = comebacktime; + if (player->kartstuff[k_comebackmode] == 2) + { + mobj_t *poof = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_EXPLODE); + S_StartSound(poof, mobjinfo[MT_KARMAHITBOX].seesound); + player->kartstuff[k_comebackmode] = 0; + } + } + + K_CheckBumpers(); + } } } } From 263ef8f92cc0f9bdf4d651c7f96aa7d86db0fd82 Mon Sep 17 00:00:00 2001 From: Sally Cochenour Date: Fri, 20 Mar 2020 19:33:41 -0400 Subject: [PATCH 56/56] Use divide/multiply for waypoint closest calculations --- src/k_waypoint.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/k_waypoint.c b/src/k_waypoint.c index dfa868204..849c0e5c7 100644 --- a/src/k_waypoint.c +++ b/src/k_waypoint.c @@ -223,9 +223,9 @@ waypoint_t *K_GetClosestWaypointToMobj(mobj_t *const mobj) checkwaypoint = &waypointheap[i]; checkdist = P_AproxDistance( - (mobj->x >> FRACBITS) - (checkwaypoint->mobj->x >> FRACBITS), - (mobj->y >> FRACBITS) - (checkwaypoint->mobj->y >> FRACBITS)); - checkdist = P_AproxDistance(checkdist, (mobj->z >> FRACBITS) - (checkwaypoint->mobj->z >> FRACBITS)); + (mobj->x / FRACUNIT) - (checkwaypoint->mobj->x / FRACUNIT), + (mobj->y / FRACUNIT) - (checkwaypoint->mobj->y / FRACUNIT)); + checkdist = P_AproxDistance(checkdist, (mobj->z / FRACUNIT) - (checkwaypoint->mobj->z / FRACUNIT)); if (checkdist < closestdist) { @@ -263,9 +263,9 @@ waypoint_t *K_GetBestWaypointForMobj(mobj_t *const mobj) checkwaypoint = &waypointheap[i]; checkdist = P_AproxDistance( - (mobj->x >> FRACBITS) - (checkwaypoint->mobj->x >> FRACBITS), - (mobj->y >> FRACBITS) - (checkwaypoint->mobj->y >> FRACBITS)); - checkdist = P_AproxDistance(checkdist, ((mobj->z >> FRACBITS) - (checkwaypoint->mobj->z >> FRACBITS)) << 2); + (mobj->x / FRACUNIT) - (checkwaypoint->mobj->x / FRACUNIT), + (mobj->y / FRACUNIT) - (checkwaypoint->mobj->y / FRACUNIT)); + checkdist = P_AproxDistance(checkdist, ((mobj->z / FRACUNIT) - (checkwaypoint->mobj->z / FRACUNIT)) * 4); if (checkdist < closestdist) {