diff --git a/src/info.c b/src/info.c index 7fc319043..f4da59d78 100644 --- a/src/info.c +++ b/src/info.c @@ -15870,7 +15870,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_SPB_DEAD, // deathstate S_NULL, // xdeathstate sfx_s3k5d, // deathsound - 64*FRACUNIT, // speed + 96*FRACUNIT, // speed 24*FRACUNIT, // radius 48*FRACUNIT, // height 0, // display offset diff --git a/src/k_kart.c b/src/k_kart.c index 68bddc224..1740aa862 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -5672,48 +5672,6 @@ static void K_KartDrift(player_t *player, boolean onground) player->kartstuff[k_brakedrift] = 0; } -/*-------------------------------------------------- - static waypoint_t *K_GetPlayerClosestWaypoint(player_t *player) - - Gets the closest waypoint of a player. - - Input Arguments:- - player - The player the closest waypoint is being found for - - Return:- - The waypoint that is the player's closest waypoint ---------------------------------------------------*/ -static waypoint_t *K_GetPlayerClosestWaypoint(player_t *player) -{ - waypoint_t *closestwaypoint = NULL; - if ((player != NULL) && (player->mo != NULL)) - { - mobj_t *wpmobj; - mobj_t *closestwpmobj = NULL; - fixed_t wpdist = INT32_MAX; - fixed_t closestdist = INT32_MAX; - waypoint_t *waypoint = NULL; - - // Find the closest waypoint mobj to the player - for (wpmobj = waypointcap; wpmobj; wpmobj = wpmobj->tracer) - { - wpdist = P_AproxDistance(wpmobj->x - player->mo->x, wpmobj->y - player->mo->y); - wpdist = P_AproxDistance(wpdist, wpmobj->z - player->mo->z); - - if (wpdist < closestdist) - { - closestdist = wpdist; - closestwpmobj = wpmobj; - } - } - - waypoint = K_SearchWaypointGraphForMobj(closestwpmobj); - closestwaypoint = waypoint; - } - - return closestwaypoint; -} - /*-------------------------------------------------- static waypoint_t *K_GetPlayerNextWaypoint(player_t *player) @@ -5729,11 +5687,11 @@ static waypoint_t *K_GetPlayerClosestWaypoint(player_t *player) static waypoint_t *K_GetPlayerNextWaypoint(player_t *player) { waypoint_t *bestwaypoint = NULL; - if ((player != NULL) && (player->mo != NULL)) + if ((player != NULL) && (player->mo != NULL) && (P_MobjWasRemoved(player->mo) == false)) { waypoint_t *waypoint = NULL; - waypoint = K_GetPlayerClosestWaypoint(player); + waypoint = K_GetClosestWaypointToMobj(player->mo); bestwaypoint = waypoint; // check the waypoint's location in relation to the player diff --git a/src/k_waypoint.c b/src/k_waypoint.c index 0ef3d9c32..f58d11bf9 100644 --- a/src/k_waypoint.c +++ b/src/k_waypoint.c @@ -173,6 +173,43 @@ UINT32 K_GetCircuitLength(void) return circuitlength; } +/*-------------------------------------------------- + waypoint_t *K_GetClosestWaypointToMobj(mobj_t *const mobj) + + See header file for description. +--------------------------------------------------*/ +waypoint_t *K_GetClosestWaypointToMobj(mobj_t *const mobj) +{ + waypoint_t *closestwaypoint = NULL; + + if ((mobj == NULL) || P_MobjWasRemoved(mobj)) + { + CONS_Debug(DBG_GAMELOGIC, "NULL mobj in K_GetClosestWaypointToMobj.\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 - checkwaypoint->mobj->x, mobj->y - checkwaypoint->mobj->y); + checkdist = P_AproxDistance(checkdist, mobj->z - checkwaypoint->mobj->z); + + if (checkdist < closestdist) + { + closestwaypoint = checkwaypoint; + closestdist = checkdist; + } + } + } + + return closestwaypoint; +} + /*-------------------------------------------------- size_t K_GetWaypointHeapIndex(waypoint_t *waypoint) diff --git a/src/k_waypoint.h b/src/k_waypoint.h index d797d2116..e0dffdbda 100644 --- a/src/k_waypoint.h +++ b/src/k_waypoint.h @@ -122,6 +122,20 @@ INT32 K_GetWaypointID(waypoint_t *waypoint); UINT32 K_GetCircuitLength(void); +/*-------------------------------------------------- + waypoint_t *K_GetClosestWaypointToMobj(mobj_t *const mobj) + + Returns the closest waypoint to an mobj + + Input Arguments:- + mobj - mobj to get the closest waypoint of. + + Return:- + The closest waypoint to the mobj +--------------------------------------------------*/ +waypoint_t *K_GetClosestWaypointToMobj(mobj_t *const mobj); + + /*-------------------------------------------------- boolean K_PathfindToWaypoint( waypoint_t *const sourcewaypoint, diff --git a/src/p_enemy.c b/src/p_enemy.c index 7baca2adc..2a7a80829 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -24,6 +24,7 @@ #include "i_video.h" #include "lua_hook.h" #include "k_kart.h" // SRB2kart +#include "k_waypoint.h" #ifdef HW3SOUND #include "hardware/hw3sound.h" @@ -8387,6 +8388,20 @@ void A_JawzExplode(mobj_t *actor) return; } +static void SpawnSPBTrailRings(mobj_t *actor) +{ + if (actor != NULL) + { + if (leveltime % 6 == 0) + { + 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; + } + } +} + void A_SPBChase(mobj_t *actor) { player_t *player = NULL; @@ -8543,13 +8558,7 @@ void A_SPBChase(mobj_t *actor) actor->momz = FixedMul(zspeed, FINESINE(actor->movedir>>ANGLETOFINESHIFT)); // Spawn a trail of rings behind the SPB! - if (leveltime % 6 == 0) - { - 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; - } + SpawnSPBTrailRings(actor); // Red speed lines for when it's gaining on its target. A tell for when you're starting to lose too much speed! if (R_PointToDist2(0, 0, actor->momx, actor->momy) > (actor->tracer->player ? (16*actor->tracer->player->speed)/15 @@ -8610,6 +8619,8 @@ void A_SPBChase(mobj_t *actor) } else // MODE: SEEKING { + waypoint_t *closestwaypoint = 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]) @@ -8623,16 +8634,43 @@ void A_SPBChase(mobj_t *actor) // Found someone, now get close enough to initiate the slaughter... - // don't hurt players that have nothing to do with this: - actor->flags |= MF_NOCLIPTHING; + // Seeking SPB can now hurt people + actor->flags &= ~MF_NOCLIPTHING; 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); - hang = R_PointToAngle2(actor->x, actor->y, actor->tracer->x, actor->tracer->y); - vang = R_PointToAngle2(0, actor->z, dist, actor->tracer->z); + closestwaypoint = K_GetClosestWaypointToMobj(actor); + if (closestwaypoint != NULL) + { + const boolean huntbackwards = false; + boolean useshortcuts = false; + + // If the player is on a shortcut, use shortcuts. No escape. + if (K_GetWaypointIsShortcut(player->nextwaypoint)) + { + useshortcuts = true; + } + + nextwaypoint = K_GetNextWaypointToDestination( + closestwaypoint, player->nextwaypoint, useshortcuts, huntbackwards); + } + + 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); + } + else + { + // continue straight ahead... Shouldn't happen. + hang = actor->angle; + vang = 0U; + } { // Smoothly rotate horz angle @@ -8670,6 +8708,9 @@ void A_SPBChase(mobj_t *actor) actor->momy = FixedMul(FixedMul(xyspeed, FINESINE(actor->angle>>ANGLETOFINESHIFT)), FINECOSINE(actor->movedir>>ANGLETOFINESHIFT)); actor->momz = FixedMul(zspeed, FINESINE(actor->movedir>>ANGLETOFINESHIFT)); + // Spawn a trail of rings behind the SPB! + SpawnSPBTrailRings(actor); + if (dist <= (3072*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.