mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2026-01-17 04:02:50 +00:00
Improvements to player finish distances
Figure out the circuit length on map load player->distancetofinish is now a total distance on circuit maps some hacky alterations around circuit finish lines to correctly calculate distancetofinish
This commit is contained in:
parent
04966f5613
commit
10adecb4a6
3 changed files with 252 additions and 40 deletions
205
src/k_kart.c
205
src/k_kart.c
|
|
@ -5673,20 +5673,19 @@ static void K_KartDrift(player_t *player, boolean onground)
|
|||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static waypoint_t *K_GetPlayerNextWaypoint(player_t *player)
|
||||
static waypoint_t *K_GetPlayerClosestWaypoint(player_t *player)
|
||||
|
||||
Gets the next waypoint of a player, by finding their closest waypoint, then checking which of itself and next or
|
||||
previous waypoints are infront of the player.
|
||||
Gets the closest waypoint of a player.
|
||||
|
||||
Input Arguments:-
|
||||
player - The player the next waypoint is being found for
|
||||
player - The player the closest waypoint is being found for
|
||||
|
||||
Return:-
|
||||
The waypoint that is the player's next waypoint
|
||||
The waypoint that is the player's closest waypoint
|
||||
--------------------------------------------------*/
|
||||
static waypoint_t *K_GetPlayerNextWaypoint(player_t *player)
|
||||
static waypoint_t *K_GetPlayerClosestWaypoint(player_t *player)
|
||||
{
|
||||
waypoint_t *bestwaypoint = NULL;
|
||||
waypoint_t *closestwaypoint = NULL;
|
||||
if ((player != NULL) && (player->mo != NULL))
|
||||
{
|
||||
mobj_t *wpmobj;
|
||||
|
|
@ -5709,23 +5708,62 @@ static waypoint_t *K_GetPlayerNextWaypoint(player_t *player)
|
|||
}
|
||||
|
||||
waypoint = K_SearchWaypointGraphForMobj(closestwpmobj);
|
||||
closestwaypoint = waypoint;
|
||||
}
|
||||
|
||||
return closestwaypoint;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static waypoint_t *K_GetPlayerNextWaypoint(player_t *player)
|
||||
|
||||
Gets the next waypoint of a player, by finding their closest waypoint, then checking which of itself and next or
|
||||
previous waypoints are infront of the player.
|
||||
|
||||
Input Arguments:-
|
||||
player - The player the next waypoint is being found for
|
||||
|
||||
Return:-
|
||||
The waypoint that is the player's next waypoint
|
||||
--------------------------------------------------*/
|
||||
static waypoint_t *K_GetPlayerNextWaypoint(player_t *player)
|
||||
{
|
||||
waypoint_t *bestwaypoint = NULL;
|
||||
if ((player != NULL) && (player->mo != NULL))
|
||||
{
|
||||
waypoint_t *waypoint = NULL;
|
||||
|
||||
waypoint = K_GetPlayerClosestWaypoint(player);
|
||||
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.
|
||||
// Otherwise it breaks the distance calculations.
|
||||
if (waypoint != NULL)
|
||||
{
|
||||
angle_t playerangle = player->mo->angle;
|
||||
boolean finishlinehack = false;
|
||||
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 = playerangle - angletowaypoint;
|
||||
|
||||
|
||||
if (angledelta > ANGLE_180)
|
||||
{
|
||||
angledelta = InvAngle(angletowaypoint);
|
||||
angledelta = InvAngle(angledelta);
|
||||
}
|
||||
|
||||
if (angledelta > ANGLE_90)
|
||||
if (bestwaypoint == K_GetFinishLineWaypoint())
|
||||
{
|
||||
// facing towards the finishline
|
||||
if (angledelta <= ANGLE_90)
|
||||
{
|
||||
finishlinehack = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ((angledelta > ANGLE_45) && (finishlinehack == false))
|
||||
{
|
||||
angle_t nextbestdelta = angledelta;
|
||||
size_t i = 0U;
|
||||
|
|
@ -5780,8 +5818,69 @@ static waypoint_t *K_GetPlayerNextWaypoint(player_t *player)
|
|||
return bestwaypoint;
|
||||
}
|
||||
|
||||
static boolean K_PlayerCloserToNextWaypoints(waypoint_t *const waypoint, player_t *const player)
|
||||
{
|
||||
boolean nextiscloser = true;
|
||||
|
||||
if ((waypoint != NULL) && (player != NULL) && (player->mo != NULL))
|
||||
{
|
||||
size_t i = 0U;
|
||||
waypoint_t *currentwpcheck = NULL;
|
||||
angle_t angletoplayer = ANGLE_MAX;
|
||||
angle_t currentanglecheck = ANGLE_MAX;
|
||||
angle_t bestangle = ANGLE_MAX;
|
||||
|
||||
angletoplayer = R_PointToAngle2(waypoint->mobj->x, waypoint->mobj->y,
|
||||
player->mo->x, player->mo->y);
|
||||
|
||||
for (i = 0U; i < waypoint->numnextwaypoints; i++)
|
||||
{
|
||||
currentwpcheck = waypoint->nextwaypoints[i];
|
||||
currentanglecheck = R_PointToAngle2(
|
||||
waypoint->mobj->x, waypoint->mobj->y, currentwpcheck->mobj->x, currentwpcheck->mobj->y);
|
||||
|
||||
// Get delta angle
|
||||
currentanglecheck = currentanglecheck - angletoplayer;
|
||||
|
||||
if (currentanglecheck > ANGLE_180)
|
||||
{
|
||||
currentanglecheck = InvAngle(currentanglecheck);
|
||||
}
|
||||
|
||||
if (currentanglecheck < bestangle)
|
||||
{
|
||||
bestangle = currentanglecheck;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0U; i < waypoint->numprevwaypoints; i++)
|
||||
{
|
||||
currentwpcheck = waypoint->prevwaypoints[i];
|
||||
currentanglecheck = R_PointToAngle2(
|
||||
waypoint->mobj->x, waypoint->mobj->y, currentwpcheck->mobj->x, currentwpcheck->mobj->y);
|
||||
|
||||
// Get delta angle
|
||||
currentanglecheck = currentanglecheck - angletoplayer;
|
||||
|
||||
if (currentanglecheck > ANGLE_180)
|
||||
{
|
||||
currentanglecheck = InvAngle(currentanglecheck);
|
||||
}
|
||||
|
||||
if (currentanglecheck < bestangle)
|
||||
{
|
||||
bestangle = currentanglecheck;
|
||||
nextiscloser = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nextiscloser;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static void K_UpdateDistanceFromFinishLine(player_t *player)
|
||||
static void K_UpdateDistanceFromFinishLine(player_t *const player)
|
||||
|
||||
Updates the distance a player has to the finish line.
|
||||
|
||||
|
|
@ -5791,40 +5890,70 @@ static waypoint_t *K_GetPlayerNextWaypoint(player_t *player)
|
|||
Return:-
|
||||
None
|
||||
--------------------------------------------------*/
|
||||
static void K_UpdateDistanceFromFinishLine(player_t *player)
|
||||
static void K_UpdateDistanceFromFinishLine(player_t *const player)
|
||||
{
|
||||
if ((player != NULL) && (player->mo != NULL))
|
||||
{
|
||||
waypoint_t *finishline = K_GetFinishLineWaypoint();
|
||||
player->nextwaypoint = K_GetPlayerNextWaypoint(player);
|
||||
|
||||
// bestwaypoint is now the waypoint that is in front of us
|
||||
if ((player->nextwaypoint != NULL) && (finishline != NULL))
|
||||
if (player->exiting)
|
||||
{
|
||||
const boolean useshortcuts = false;
|
||||
const boolean huntbackwards = false;
|
||||
boolean pathfindsuccess = false;
|
||||
path_t pathtofinish = {};
|
||||
player->nextwaypoint = K_GetFinishLineWaypoint();
|
||||
player->distancetofinish = 0U;
|
||||
}
|
||||
else
|
||||
{
|
||||
waypoint_t *finishline = K_GetFinishLineWaypoint();
|
||||
player->nextwaypoint = K_GetPlayerNextWaypoint(player);
|
||||
|
||||
pathfindsuccess =
|
||||
K_PathfindToWaypoint(player->nextwaypoint, finishline, &pathtofinish, useshortcuts, huntbackwards);
|
||||
|
||||
// Update the player's distance to the finish line if a path was found.
|
||||
// Using shortcuts won't find a path, so the distance won't be updated until the player gets back on track
|
||||
if (pathfindsuccess == true)
|
||||
// nextwaypoint is now the waypoint that is in front of us
|
||||
if ((player->nextwaypoint != NULL) && (finishline != NULL))
|
||||
{
|
||||
// Add euclidean distance to the next waypoint to the distancetofinish
|
||||
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);
|
||||
const boolean useshortcuts = false;
|
||||
const boolean huntbackwards = false;
|
||||
boolean pathfindsuccess = false;
|
||||
path_t pathtofinish = {};
|
||||
|
||||
adddist = ((UINT32)disttowaypoint) >> FRACBITS;
|
||||
pathfindsuccess =
|
||||
K_PathfindToWaypoint(player->nextwaypoint, finishline, &pathtofinish, useshortcuts, huntbackwards);
|
||||
|
||||
player->distancetofinish = pathtofinish.totaldist + adddist;
|
||||
Z_Free(pathtofinish.array);
|
||||
// Update the player's distance to the finish line if a path was found.
|
||||
// Using shortcuts won't find a path, so distance won't be updated until the player gets back on track
|
||||
if (pathfindsuccess == true)
|
||||
{
|
||||
// Add euclidean distance to the next waypoint to the distancetofinish
|
||||
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);
|
||||
|
||||
adddist = ((UINT32)disttowaypoint) >> FRACBITS;
|
||||
|
||||
player->distancetofinish = pathtofinish.totaldist + adddist;
|
||||
Z_Free(pathtofinish.array);
|
||||
|
||||
// distancetofinish is currently a flat distance to the finish line, but in order to be fully
|
||||
// correct we need to add to it the length of the entire circuit multiplied by the number of laps
|
||||
// left after this one. This will give us the total distance to the finish line, and allow item
|
||||
// distance calculation to work easily
|
||||
if ((mapheaderinfo[gamemap - 1]->levelflags & LF_SECTIONRACE) == 0U)
|
||||
{
|
||||
const UINT8 numfulllapsleft = ((UINT8)cv_numlaps.value - player->laps);
|
||||
|
||||
player->distancetofinish += numfulllapsleft * K_GetCircuitLength();
|
||||
|
||||
// An additional HACK, to fix looking backwards towards the finish line
|
||||
// If the player's next waypoint is the finishline and the angle distance from player to
|
||||
// connectin waypoints implies they're closer to a next waypoint, add a full track distance
|
||||
if (player->nextwaypoint == finishline)
|
||||
{
|
||||
if (K_PlayerCloserToNextWaypoints(player->nextwaypoint, player) == true)
|
||||
{
|
||||
player->distancetofinish += K_GetCircuitLength();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#include "p_local.h"
|
||||
#include "p_tick.h"
|
||||
#include "z_zone.h"
|
||||
#include "g_game.h"
|
||||
|
||||
// The number of sparkles per waypoint connection in the waypoint visualisation
|
||||
static const UINT32 SPARKLES_PER_CONNECTION = 16U;
|
||||
|
|
@ -18,6 +19,8 @@ static waypoint_t *waypointheap = NULL;
|
|||
static waypoint_t *firstwaypoint = NULL;
|
||||
static waypoint_t *finishline = NULL;
|
||||
|
||||
static UINT32 circuitlength = 0U;
|
||||
|
||||
static size_t numwaypoints = 0U;
|
||||
static size_t numwaypointmobjs = 0U;
|
||||
static size_t baseopensetsize = OPENSET_BASE_SIZE;
|
||||
|
|
@ -160,6 +163,15 @@ INT32 K_GetWaypointID(waypoint_t *waypoint)
|
|||
return waypointid;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
UINT32 K_GetCircuitLength(void)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
UINT32 K_GetCircuitLength(void)
|
||||
{
|
||||
return circuitlength;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
size_t K_GetWaypointHeapIndex(waypoint_t *waypoint)
|
||||
|
|
@ -306,6 +318,10 @@ void K_DebugWaypointsVisualise(void)
|
|||
{
|
||||
debugmobj->color = SKINCOLOR_ORANGE;
|
||||
}
|
||||
else if (waypoint == players[displayplayers[0]].nextwaypoint)
|
||||
{
|
||||
debugmobj->color = SKINCOLOR_YELLOW;
|
||||
}
|
||||
else
|
||||
{
|
||||
debugmobj->color = SKINCOLOR_BLUE;
|
||||
|
|
@ -1267,6 +1283,56 @@ waypoint_t *K_SearchWaypointHeapForMobj(mobj_t *const mobj)
|
|||
return foundwaypoint;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static UINT32 K_SetupCircuitLength(void)
|
||||
|
||||
Sets up the Circuit Length by getting the best path from the finishwaypoint back to itself.
|
||||
On sprint maps, circuitlength is 0.
|
||||
|
||||
Input Arguments:-
|
||||
None
|
||||
|
||||
Return:-
|
||||
Length of the circuit
|
||||
--------------------------------------------------*/
|
||||
static UINT32 K_SetupCircuitLength(void)
|
||||
{
|
||||
if ((firstwaypoint == NULL) || (numwaypoints == 0U))
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "K_SetupCircuitLength called with no waypoints.\n");
|
||||
}
|
||||
else if (finishline == NULL)
|
||||
{
|
||||
CONS_Debug(DBG_GAMELOGIC, "K_SetupCircuitLength called with no finishline waypoint.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
// The circuit length only makes sense in circuit maps, sprint maps do not need to use it
|
||||
// The main usage of the circuit length is to add onto a player's distance to finish line so crossing the finish
|
||||
// line places people correctly relative to each other
|
||||
if ((mapheaderinfo[gamemap - 1]->levelflags & LF_SECTIONRACE) == LF_SECTIONRACE)
|
||||
{
|
||||
circuitlength = 0U;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create a fake finishline waypoint, then try and pathfind to the finishline from it
|
||||
waypoint_t fakefinishline = *finishline;
|
||||
path_t bestcircuitpath = {};
|
||||
const boolean useshortcuts = false;
|
||||
const boolean huntbackwards = false;
|
||||
|
||||
K_PathfindToWaypoint(&fakefinishline, finishline, &bestcircuitpath, useshortcuts, huntbackwards);
|
||||
|
||||
circuitlength = bestcircuitpath.totaldist;
|
||||
|
||||
Z_Free(bestcircuitpath.array);
|
||||
}
|
||||
}
|
||||
|
||||
return circuitlength;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static void K_AddPrevToWaypoint(waypoint_t *const waypoint, waypoint_t *const prevwaypoint)
|
||||
|
||||
|
|
@ -1616,6 +1682,9 @@ boolean K_SetupWaypointList(void)
|
|||
K_GetWaypointID(firstwaypoint));
|
||||
finishline = firstwaypoint;
|
||||
}
|
||||
|
||||
(void)K_SetupCircuitLength();
|
||||
|
||||
setupsuccessful = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -1634,6 +1703,7 @@ void K_ClearWaypoints(void)
|
|||
waypointheap = NULL;
|
||||
firstwaypoint = NULL;
|
||||
finishline = NULL;
|
||||
numwaypoints = 0;
|
||||
numwaypointmobjs = 0;
|
||||
numwaypoints = 0U;
|
||||
numwaypointmobjs = 0U;
|
||||
circuitlength = 0U;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -109,6 +109,19 @@ INT32 K_GetWaypointNextID(waypoint_t *waypoint);
|
|||
INT32 K_GetWaypointID(waypoint_t *waypoint);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
UINT32 K_GetCircuitLength(void)
|
||||
|
||||
Returns the circuit length, 0 on sprint maps.
|
||||
|
||||
Input Arguments:-
|
||||
|
||||
Return:-
|
||||
The circuit length.
|
||||
--------------------------------------------------*/
|
||||
UINT32 K_GetCircuitLength(void);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
boolean K_PathfindToWaypoint(
|
||||
waypoint_t *const sourcewaypoint,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue