mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
Respawn slightly before a waypoint, in the direction you came from, if the waypoint is exactly on a line
See notably the finish line. Basically respawning exactly on a line can let you cross it twice, if you crossed it before respawning, or NOT cross it, depending on which direction you drive after landing. So this just respawns very slightly before the line so you can cross (or not cross) it normally.
This commit is contained in:
parent
4f96fead3a
commit
82718216cc
6 changed files with 134 additions and 22 deletions
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
@ -1700,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;
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
typedef struct waypoint_s
|
||||
{
|
||||
mobj_t *mobj;
|
||||
boolean onaline;
|
||||
struct waypoint_s **nextwaypoints;
|
||||
struct waypoint_s **prevwaypoints;
|
||||
UINT32 *nextwaypointdistances;
|
||||
|
|
|
|||
|
|
@ -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 * near,
|
||||
line_t ** near_line,
|
||||
const fixed_t x,
|
||||
const fixed_t y)
|
||||
{
|
||||
const fixed_t d = dist2line(line, x, y);
|
||||
|
||||
if (d < *near)
|
||||
{
|
||||
*near = 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 near = 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], &near, &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], &near, &near_line, x, y);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while ((line = P_FindSpecialLineFromTag(special, -1, line)) != -1)
|
||||
{
|
||||
checknearline(&lines[line], &near, &near_line, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
return near_line;
|
||||
}
|
||||
|
||||
//
|
||||
// P_LineOpening
|
||||
// Sets opentop and openbottom to the window through a two sided line.
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
26
src/p_mobj.c
26
src/p_mobj.c
|
|
@ -11325,32 +11325,14 @@ static boolean P_SetupBooster(mapthing_t* mthing, mobj_t* mobj, boolean strong)
|
|||
return true;
|
||||
}
|
||||
|
||||
static fixed_t dist2vert(const vertex_t *v, const mobj_t *o)
|
||||
{
|
||||
return abs(FixedHypot(v->x - o->x, v->y - o->y));
|
||||
}
|
||||
|
||||
static void P_SnapToFinishLine(mobj_t *mobj)
|
||||
{
|
||||
INT32 i = -1;
|
||||
fixed_t d;
|
||||
fixed_t nearest = INT32_MAX;
|
||||
line_t *nearest_line = NULL;
|
||||
// case 2001: Finish Line
|
||||
while ((i = P_FindSpecialLineFromTag(2001, -1, i)) != -1)
|
||||
{
|
||||
if (
|
||||
(d = dist2vert(lines[i].v1, mobj)) < nearest ||
|
||||
(d = dist2vert(lines[i].v2, mobj)) < nearest
|
||||
){
|
||||
nearest = d;
|
||||
nearest_line = &lines[i];
|
||||
}
|
||||
}
|
||||
if (nearest < INT32_MAX)
|
||||
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, nearest_line, (vertex_t *)&mobj->x);
|
||||
P_ClosestPointOnLine(mobj->x, mobj->y, finishline, (vertex_t *)&mobj->x);
|
||||
P_SetThingPosition(mobj);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue