Merge branch 'jumping-finish-line-distance' into 'master'

Finish line waypoint issues

See merge request KartKrew/Kart!384
This commit is contained in:
Sal 2021-02-18 18:23:08 -05:00
commit 8853a4b8e3
7 changed files with 195 additions and 20 deletions

View file

@ -6553,8 +6553,12 @@ static waypoint_t *K_GetPlayerNextWaypoint(player_t *player)
if (bestwaypoint == K_GetFinishLineWaypoint())
{
waypoint_t *nextwaypoint = waypoint->nextwaypoints[0];
angle_t angletonextwaypoint =
R_PointToAngle2(waypoint->mobj->x, waypoint->mobj->y, nextwaypoint->mobj->x, nextwaypoint->mobj->y);
// facing towards the finishline
if (angledelta <= ANGLE_90)
if (abs(AngleDifference(angletonextwaypoint, angletowaypoint)) <= ANGLE_90)
{
finishlinehack = true;
}
@ -6698,6 +6702,7 @@ static waypoint_t *K_GetPlayerNextWaypoint(player_t *player)
return bestwaypoint;
}
#if 0
static boolean K_PlayerCloserToNextWaypoints(waypoint_t *const waypoint, player_t *const player)
{
boolean nextiscloser = true;
@ -6758,6 +6763,7 @@ static boolean K_PlayerCloserToNextWaypoints(waypoint_t *const waypoint, player_
return nextiscloser;
}
#endif
/*--------------------------------------------------
void K_UpdateDistanceFromFinishLine(player_t *const player)
@ -6837,6 +6843,7 @@ void K_UpdateDistanceFromFinishLine(player_t *const player)
player->distancetofinish += numfulllapsleft * K_GetCircuitLength();
#if 0
// 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
@ -6847,6 +6854,7 @@ void K_UpdateDistanceFromFinishLine(player_t *const player)
player->distancetofinish += K_GetCircuitLength();
}
}
#endif
}
}
}

View file

@ -54,6 +54,21 @@ fixed_t K_RespawnOffset(player_t *player, boolean flip)
return z;
}
/*--------------------------------------------------
static void K_FudgeRespawn(player_t *player, const waypoint_t *const waypoint)
Fudges respawn coordinates to slightly before the waypoint if it would
be exactly on a line. See K_GetWaypointIsOnLine.
--------------------------------------------------*/
static void K_FudgeRespawn(player_t *player, const waypoint_t *const waypoint)
{
const angle_t from = R_PointToAngle2(waypoint->mobj->x, waypoint->mobj->y,
player->mo->x, player->mo->y) >> ANGLETOFINESHIFT;
player->respawn.pointx += FixedMul(16, FINECOSINE(from));
player->respawn.pointy += FixedMul(16, FINESINE(from));
}
/*--------------------------------------------------
static void K_RespawnAtWaypoint(player_t *player, waypoint_t *waypoint)
@ -83,6 +98,11 @@ static void K_RespawnAtWaypoint(player_t *player, waypoint_t *waypoint)
player->respawn.pointz = waypoint->mobj->z;
player->respawn.flip = (waypoint->mobj->flags2 & MF2_OBJECTFLIP) ? true : false; // K_RespawnOffset wants a boolean!
player->respawn.pointz += K_RespawnOffset(player, player->respawn.flip);
if (waypoint->onaline)
{
K_FudgeRespawn(player, waypoint);
}
}
/*--------------------------------------------------

View file

@ -153,6 +153,38 @@ boolean K_GetWaypointIsSpawnpoint(waypoint_t *waypoint)
return waypointisspawnpoint;
}
/*--------------------------------------------------
static boolean K_GetWaypointIsOnLine(waypoint_t *const waypoint)
Checks if a waypoint is exactly on a line. Moving to an exact point
on a line won't count as crossing it. Moving off of that point does.
Respawning to a waypoint which is exactly on a line is the easiest
way to for this to occur.
Return:-
Whether the waypoint is exactly on a line.
--------------------------------------------------*/
static boolean K_GetWaypointIsOnLine(waypoint_t *const waypoint)
{
const fixed_t x = waypoint->mobj->x;
const fixed_t y = waypoint->mobj->y;
line_t *line = P_FindNearestLine(x, y,
waypoint->mobj->subsector->sector, -1);
vertex_t point;
if (line != NULL)
{
P_ClosestPointOnLine(x, y, line, &point);
if (x == point.x && y == point.y)
return true;
}
return false;
}
/*--------------------------------------------------
INT32 K_GetWaypointNextID(waypoint_t *waypoint)
@ -253,6 +285,40 @@ waypoint_t *K_GetClosestWaypointToMobj(mobj_t *const mobj)
return closestwaypoint;
}
/*--------------------------------------------------
static void K_CompareOverlappingWaypoint
( waypoint_t *const checkwaypoint,
waypoint_t **const bestwaypoint,
fixed_t *const bestfindist)
Solves touching overlapping waypoint radiuses by sorting by distance to
finish line.
--------------------------------------------------*/
static void K_CompareOverlappingWaypoint
( waypoint_t *const checkwaypoint,
waypoint_t **const bestwaypoint,
fixed_t *const bestfindist)
{
const boolean useshortcuts = false;
const boolean huntbackwards = false;
boolean pathfindsuccess = false;
path_t pathtofinish = {};
pathfindsuccess =
K_PathfindToWaypoint(checkwaypoint, finishline, &pathtofinish, useshortcuts, huntbackwards);
if (pathfindsuccess == true)
{
if ((INT32)(pathtofinish.totaldist) < *bestfindist)
{
*bestwaypoint = checkwaypoint;
*bestfindist = pathtofinish.totaldist;
}
Z_Free(pathtofinish.array);
}
}
/*--------------------------------------------------
waypoint_t *K_GetBestWaypointForMobj(mobj_t *const mobj)
@ -292,30 +358,18 @@ waypoint_t *K_GetBestWaypointForMobj(mobj_t *const mobj)
rad = (checkwaypoint->mobj->radius / FRACUNIT);
if (closestdist < rad && checkdist < rad && finishline != NULL)
// remember: huge radius
if (closestdist <= rad && checkdist <= rad && finishline != NULL)
{
const boolean useshortcuts = false;
const boolean huntbackwards = false;
boolean pathfindsuccess = false;
path_t pathtofinish = {};
// If the mobj is touching multiple waypoints at once,
// then solve ties by taking the one closest to the finish line.
// Prevents position from flickering wildly when taking turns.
pathfindsuccess =
K_PathfindToWaypoint(checkwaypoint, finishline, &pathtofinish, useshortcuts, huntbackwards);
// For the first couple overlapping, check the previous best too.
if (bestfindist == INT32_MAX)
K_CompareOverlappingWaypoint(bestwaypoint, &bestwaypoint, &bestfindist);
if (pathfindsuccess == true)
{
if ((INT32)(pathtofinish.totaldist) < bestfindist)
{
bestwaypoint = checkwaypoint;
bestfindist = pathtofinish.totaldist;
}
Z_Free(pathtofinish.array);
}
K_CompareOverlappingWaypoint(checkwaypoint, &bestwaypoint, &bestfindist);
}
else if (checkdist < closestdist && bestfindist == INT32_MAX)
{
@ -1678,6 +1732,12 @@ static waypoint_t *K_SetupWaypoint(mobj_t *const mobj)
finishline = thiswaypoint;
}
/* only relevant for respawning */
if (K_GetWaypointIsSpawnpoint(thiswaypoint))
{
thiswaypoint->onaline = K_GetWaypointIsOnLine(thiswaypoint);
}
if (thiswaypoint->numnextwaypoints > 0)
{
waypoint_t *nextwaypoint = NULL;

View file

@ -23,6 +23,7 @@
typedef struct waypoint_s
{
mobj_t *mobj;
boolean onaline;
struct waypoint_s **nextwaypoints;
struct waypoint_s **prevwaypoints;
UINT32 *nextwaypointdistances;

View file

@ -259,6 +259,76 @@ fixed_t P_InterceptVector(divline_t *v2, divline_t *v1)
return frac;
}
static fixed_t dist2line(const line_t *ld, const fixed_t x, const fixed_t y)
{
return FixedHypot
(
ld->v1->x + (ld->dx / 2) - x,
ld->v1->y + (ld->dy / 2) - y
);
}
static void checknearline
( line_t * line,
fixed_t * nearest,
line_t ** near_line,
const fixed_t x,
const fixed_t y)
{
const fixed_t d = dist2line(line, x, y);
if (d < *nearest)
{
*nearest = d;
*near_line = line;
}
}
//
// P_FindNearestLine
// Returns the nearest line to a point which
// is in a sector and/or a specific type.
//
line_t * P_FindNearestLine
( const fixed_t x,
const fixed_t y,
const sector_t * sector,
const INT32 special)
{
fixed_t nearest = INT32_MAX;
line_t *near_line = NULL;
size_t i;
INT32 line = -1;
if (special == -1)
{
if (sector == NULL)
sector = R_PointInSubsector(x, y)->sector;
for (i = 0; i < sector->linecount; ++i)
{
checknearline(sector->lines[i], &nearest, &near_line, x, y);
}
}
else if (sector != NULL)
{
for (i = 0; i < sector->linecount; ++i)
{
if (sector->lines[i]->special == special)
checknearline(sector->lines[i], &nearest, &near_line, x, y);
}
}
else
{
while ((line = P_FindSpecialLineFromTag(special, -1, line)) != -1)
{
checknearline(&lines[line], &nearest, &near_line, x, y);
}
}
return near_line;
}
//
// P_LineOpening
// Sets opentop and openbottom to the window through a two sided line.

View file

@ -49,6 +49,7 @@ void P_MakeDivline(line_t *li, divline_t *dl);
void P_CameraLineOpening(line_t *plinedef);
fixed_t P_InterceptVector(divline_t *v2, divline_t *v1);
INT32 P_BoxOnLineSide(fixed_t *tmbox, line_t *ld);
line_t * P_FindNearestLine(const fixed_t x, const fixed_t y, const sector_t *, const INT32 special);
void P_UnsetPrecipThingPosition(precipmobj_t *thing);
void P_SetPrecipitationThingPosition(precipmobj_t *thing);
void P_CreatePrecipSecNodeList(precipmobj_t *thing, fixed_t x,fixed_t y);

View file

@ -11334,6 +11334,18 @@ static boolean P_SetupBooster(mapthing_t* mthing, mobj_t* mobj, boolean strong)
return true;
}
static void P_SnapToFinishLine(mobj_t *mobj)
{
line_t *finishline = P_FindNearestLine(mobj->x, mobj->y,
mobj->subsector->sector, 2001); // case 2001: Finish Line
if (finishline != NULL)
{
P_UnsetThingPosition(mobj);
P_ClosestPointOnLine(mobj->x, mobj->y, finishline, (vertex_t *)&mobj->x);
P_SetThingPosition(mobj);
}
}
static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean *doangle)
{
boolean override = LUAh_MapThingSpawn(mobj, mthing);
@ -11717,7 +11729,10 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean
}
if (mthing->args[2] == 1)
{
mobj->extravalue2 = 1; // args[1] of 1 means the waypoint is at the finish line
mobj->extravalue2 = 1; // args[2] of 1 means the waypoint is at the finish line
mobj->reactiontime = 0; // Also don't respawn at finish lines
P_SnapToFinishLine(mobj);
}
else
{