mirror of
				https://github.com/KartKrewDev/RingRacers.git
				synced 2025-10-30 08:01:28 +00:00 
			
		
		
		
	P_TryMove: sweep collided lines to find nearest normal
This commit is contained in:
		
							parent
							
								
									5a62a07e54
								
							
						
					
					
						commit
						7861d51a7f
					
				
					 6 changed files with 238 additions and 54 deletions
				
			
		| 
						 | 
				
			
			@ -65,6 +65,7 @@ add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32
 | 
			
		|||
	p_user.c
 | 
			
		||||
	p_slopes.c
 | 
			
		||||
	p_sweep.cpp
 | 
			
		||||
	p_test.cpp
 | 
			
		||||
	tables.c
 | 
			
		||||
	r_bsp.cpp
 | 
			
		||||
	r_data.c
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -806,6 +806,7 @@ consvar_t cv_numlaps = OnlineCheat("numlaps", "Map default").values(numlaps_cons
 | 
			
		|||
 | 
			
		||||
consvar_t cv_restrictskinchange = OnlineCheat("restrictskinchange", "Yes").yes_no().description("Don't let players change their skin in the middle of gameplay");
 | 
			
		||||
consvar_t cv_spbtest = OnlineCheat("spbtest", "Off").on_off().description("SPB can never target a player");
 | 
			
		||||
consvar_t cv_showgremlins = OnlineCheat("showgremlins", "No").yes_no().description("Show line collision errors");
 | 
			
		||||
consvar_t cv_timescale = OnlineCheat(cvlist_timer)("timescale", "1.0").floating_point().min_max(FRACUNIT/20, 20*FRACUNIT).description("Overclock or slow down the game");
 | 
			
		||||
consvar_t cv_ufo_follow = OnlineCheat("ufo_follow", "0").min_max(0, MAXPLAYERS).description("Make UFO Catcher folow this player");
 | 
			
		||||
consvar_t cv_ufo_health = OnlineCheat("ufo_health", "-1").min_max(-1, 100).description("Override UFO Catcher health -- applied at spawn or when value is changed");
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -387,9 +387,16 @@ struct tm_t
 | 
			
		|||
	// so missiles don't explode against sky hack walls
 | 
			
		||||
	line_t *ceilingline;
 | 
			
		||||
 | 
			
		||||
	// set by PIT_CheckLine() for any line that stopped the PIT_CheckLine()
 | 
			
		||||
	// that is, for any line which is 'solid'
 | 
			
		||||
	line_t *blockingline;
 | 
			
		||||
	// P_CheckPosition: this position blocks movement
 | 
			
		||||
	boolean blocking;
 | 
			
		||||
 | 
			
		||||
	// P_CheckPosition: set this before each call to
 | 
			
		||||
	// P_CheckPosition to enable a line sweep on collided
 | 
			
		||||
	// lines
 | 
			
		||||
	boolean sweep;
 | 
			
		||||
 | 
			
		||||
	// sweep: max step up at tm.x, tm.y
 | 
			
		||||
	fixed_t maxstep;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
extern tm_t tm;
 | 
			
		||||
| 
						 | 
				
			
			@ -415,6 +422,7 @@ struct TryMoveResult_t
 | 
			
		|||
	boolean success;
 | 
			
		||||
	line_t *line;
 | 
			
		||||
	mobj_t *mo;
 | 
			
		||||
	vector2_t normal;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y, TryMoveResult_t *result);
 | 
			
		||||
| 
						 | 
				
			
			@ -422,6 +430,10 @@ boolean P_CheckMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff, T
 | 
			
		|||
boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff, TryMoveResult_t *result);
 | 
			
		||||
boolean P_SceneryTryMove(mobj_t *thing, fixed_t x, fixed_t y, TryMoveResult_t *result);
 | 
			
		||||
 | 
			
		||||
void P_TestLine(line_t *ld);
 | 
			
		||||
void P_ClearTestLines(void);
 | 
			
		||||
line_t *P_SweepTestLines(fixed_t ax, fixed_t ay, fixed_t bx, fixed_t by, fixed_t r, vector2_t *return_normal);
 | 
			
		||||
 | 
			
		||||
boolean P_IsLineBlocking(const line_t *ld, const mobj_t *thing);
 | 
			
		||||
boolean P_IsLineTripWire(const line_t *ld);
 | 
			
		||||
boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										190
									
								
								src/p_map.c
									
										
									
									
									
								
							
							
						
						
									
										190
									
								
								src/p_map.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1770,7 +1770,6 @@ static BlockItReturn_t PIT_CheckCameraLine(line_t *ld)
 | 
			
		|||
	// could be crossed in either order.
 | 
			
		||||
 | 
			
		||||
	// this line is out of the if so upper and lower textures can be hit by a splat
 | 
			
		||||
	tm.blockingline = ld;
 | 
			
		||||
	if (!ld->backsector) // one sided line
 | 
			
		||||
	{
 | 
			
		||||
		if (P_PointOnLineSide(mapcampointer->x, mapcampointer->y, ld))
 | 
			
		||||
| 
						 | 
				
			
			@ -1841,6 +1840,22 @@ boolean P_IsLineTripWire(const line_t *ld)
 | 
			
		|||
	return ld->tripwire;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static boolean P_UsingStepUp(mobj_t *thing)
 | 
			
		||||
{
 | 
			
		||||
	if (thing->flags & MF_NOCLIP)
 | 
			
		||||
	{
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// orbits have no collision
 | 
			
		||||
	if (thing->player && thing->player->loop.radius)
 | 
			
		||||
	{
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// PIT_CheckLine
 | 
			
		||||
// Adjusts tm.floorz and tm.ceilingz as lines are contacted
 | 
			
		||||
| 
						 | 
				
			
			@ -1898,14 +1913,20 @@ static BlockItReturn_t PIT_CheckLine(line_t *ld)
 | 
			
		|||
	// could be crossed in either order.
 | 
			
		||||
 | 
			
		||||
	// this line is out of the if so upper and lower textures can be hit by a splat
 | 
			
		||||
	tm.blockingline = ld;
 | 
			
		||||
 | 
			
		||||
	{
 | 
			
		||||
		UINT8 shouldCollide = LUA_HookMobjLineCollide(tm.thing, tm.blockingline); // checks hook for thing's type
 | 
			
		||||
		UINT8 shouldCollide = LUA_HookMobjLineCollide(tm.thing, ld); // checks hook for thing's type
 | 
			
		||||
		if (P_MobjWasRemoved(tm.thing))
 | 
			
		||||
			return BMIT_CONTINUE; // one of them was removed???
 | 
			
		||||
		if (shouldCollide == 1)
 | 
			
		||||
			return BMIT_ABORT; // force collide
 | 
			
		||||
		{
 | 
			
		||||
			if (tm.sweep)
 | 
			
		||||
			{
 | 
			
		||||
				P_TestLine(ld);
 | 
			
		||||
			}
 | 
			
		||||
			tm.blocking = true; // force collide
 | 
			
		||||
			return BMIT_CONTINUE;
 | 
			
		||||
		}
 | 
			
		||||
		else if (shouldCollide == 2)
 | 
			
		||||
			return BMIT_CONTINUE; // force no collide
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -1914,15 +1935,55 @@ static BlockItReturn_t PIT_CheckLine(line_t *ld)
 | 
			
		|||
	{
 | 
			
		||||
		if (P_PointOnLineSide(tm.thing->x, tm.thing->y, ld))
 | 
			
		||||
			return BMIT_CONTINUE; // don't hit the back side
 | 
			
		||||
		return BMIT_ABORT;
 | 
			
		||||
 | 
			
		||||
		if (tm.sweep)
 | 
			
		||||
		{
 | 
			
		||||
			P_TestLine(ld);
 | 
			
		||||
		}
 | 
			
		||||
		tm.blocking = true;
 | 
			
		||||
		return BMIT_CONTINUE;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (P_IsLineBlocking(ld, tm.thing))
 | 
			
		||||
		return BMIT_ABORT;
 | 
			
		||||
	{
 | 
			
		||||
		if (tm.sweep)
 | 
			
		||||
		{
 | 
			
		||||
			P_TestLine(ld);
 | 
			
		||||
		}
 | 
			
		||||
		tm.blocking = true;
 | 
			
		||||
		return BMIT_CONTINUE;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// set openrange, opentop, openbottom
 | 
			
		||||
	P_LineOpening(ld, tm.thing, &open);
 | 
			
		||||
 | 
			
		||||
	if (tm.sweep && P_UsingStepUp(tm.thing))
 | 
			
		||||
	{
 | 
			
		||||
		// copied from P_TryMove
 | 
			
		||||
		// TODO: refactor this into one place
 | 
			
		||||
		if (open.range < tm.thing->height)
 | 
			
		||||
		{
 | 
			
		||||
			P_TestLine(ld);
 | 
			
		||||
		}
 | 
			
		||||
		else if (tm.maxstep > 0)
 | 
			
		||||
		{
 | 
			
		||||
			if (tm.thing->z < open.floor)
 | 
			
		||||
			{
 | 
			
		||||
				if (open.floorstep > tm.maxstep)
 | 
			
		||||
				{
 | 
			
		||||
					P_TestLine(ld);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			else if (open.ceiling < tm.thing->z + tm.thing->height)
 | 
			
		||||
			{
 | 
			
		||||
				if (open.ceilingstep > tm.maxstep)
 | 
			
		||||
				{
 | 
			
		||||
					P_TestLine(ld);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// adjust floor / ceiling heights
 | 
			
		||||
	if (open.ceiling < tm.ceilingz)
 | 
			
		||||
	{
 | 
			
		||||
| 
						 | 
				
			
			@ -2042,7 +2103,8 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y, TryMoveResult_t *re
 | 
			
		|||
	tm.bbox[BOXLEFT] = x - tm.thing->radius;
 | 
			
		||||
 | 
			
		||||
	newsubsec = R_PointInSubsector(x, y);
 | 
			
		||||
	tm.ceilingline = tm.blockingline = NULL;
 | 
			
		||||
	tm.ceilingline = NULL;
 | 
			
		||||
	tm.blocking = false;
 | 
			
		||||
 | 
			
		||||
	// The base floor / ceiling is from the subsector
 | 
			
		||||
	// that contains the point.
 | 
			
		||||
| 
						 | 
				
			
			@ -2314,23 +2376,33 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y, TryMoveResult_t *re
 | 
			
		|||
 | 
			
		||||
	validcount++;
 | 
			
		||||
 | 
			
		||||
	P_ClearTestLines();
 | 
			
		||||
 | 
			
		||||
	// check lines
 | 
			
		||||
	for (bx = xl; bx <= xh; bx++)
 | 
			
		||||
	{
 | 
			
		||||
		for (by = yl; by <= yh; by++)
 | 
			
		||||
		{
 | 
			
		||||
			if (!P_BlockLinesIterator(bx, by, PIT_CheckLine))
 | 
			
		||||
			{
 | 
			
		||||
				blockval = false;
 | 
			
		||||
			}
 | 
			
		||||
			P_BlockLinesIterator(bx, by, PIT_CheckLine);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (tm.blocking)
 | 
			
		||||
	{
 | 
			
		||||
		blockval = false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (result != NULL)
 | 
			
		||||
	{
 | 
			
		||||
		result->line = tm.blockingline;
 | 
			
		||||
		result->line = NULL;
 | 
			
		||||
		result->mo = tm.hitthing;
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		P_ClearTestLines();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	tm.sweep = false;
 | 
			
		||||
 | 
			
		||||
	return blockval;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -2379,7 +2451,7 @@ boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam)
 | 
			
		|||
	tm.bbox[BOXLEFT] = x - thiscam->radius;
 | 
			
		||||
 | 
			
		||||
	newsubsec = R_PointInSubsector(x, y);
 | 
			
		||||
	tm.ceilingline = tm.blockingline = NULL;
 | 
			
		||||
	tm.ceilingline = NULL;
 | 
			
		||||
 | 
			
		||||
	mapcampointer = thiscam;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -2753,22 +2825,6 @@ fixed_t P_GetThingStepUp(mobj_t *thing, fixed_t destX, fixed_t destY)
 | 
			
		|||
	return maxstep;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static boolean P_UsingStepUp(mobj_t *thing)
 | 
			
		||||
{
 | 
			
		||||
	if (thing->flags & MF_NOCLIP)
 | 
			
		||||
	{
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// orbits have no collision
 | 
			
		||||
	if (thing->player && thing->player->loop.radius)
 | 
			
		||||
	{
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static boolean
 | 
			
		||||
increment_move
 | 
			
		||||
(		mobj_t * thing,
 | 
			
		||||
| 
						 | 
				
			
			@ -2821,7 +2877,29 @@ increment_move
 | 
			
		|||
				tryy = y;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!P_CheckPosition(thing, tryx, tryy, result))
 | 
			
		||||
		if (P_UsingStepUp(thing))
 | 
			
		||||
		{
 | 
			
		||||
			tm.maxstep = P_GetThingStepUp(thing, tryx, tryy);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (result)
 | 
			
		||||
		{
 | 
			
		||||
			tm.sweep = true;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		boolean move_ok = P_CheckPosition(thing, tryx, tryy, result);
 | 
			
		||||
 | 
			
		||||
		if (P_MobjWasRemoved(thing))
 | 
			
		||||
		{
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (result)
 | 
			
		||||
		{
 | 
			
		||||
			result->line = P_SweepTestLines(thing->x, thing->y, x, y, thing->radius, &result->normal);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!move_ok)
 | 
			
		||||
		{
 | 
			
		||||
			return false; // solid wall or thing
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -3466,30 +3544,27 @@ static void P_HitSlideLine(line_t *ld)
 | 
			
		|||
//
 | 
			
		||||
// HitBounceLine, for players
 | 
			
		||||
//
 | 
			
		||||
static void P_PlayerHitBounceLine(line_t *ld)
 | 
			
		||||
static void P_PlayerHitBounceLine(line_t *ld, vector2_t* normal)
 | 
			
		||||
{
 | 
			
		||||
	INT32 side;
 | 
			
		||||
	angle_t lineangle;
 | 
			
		||||
	fixed_t movelen;
 | 
			
		||||
	fixed_t x, y;
 | 
			
		||||
 | 
			
		||||
	side = P_PointOnLineSide(slidemo->x, slidemo->y, ld);
 | 
			
		||||
	lineangle = ld->angle - ANGLE_90;
 | 
			
		||||
 | 
			
		||||
	if (side == 1)
 | 
			
		||||
		lineangle += ANGLE_180;
 | 
			
		||||
 | 
			
		||||
	lineangle >>= ANGLETOFINESHIFT;
 | 
			
		||||
 | 
			
		||||
	movelen = P_AproxDistance(tmxmove, tmymove);
 | 
			
		||||
 | 
			
		||||
	if (slidemo->player && movelen < (15*mapobjectscale))
 | 
			
		||||
		movelen = (15*mapobjectscale);
 | 
			
		||||
 | 
			
		||||
	x = FixedMul(movelen, FINECOSINE(lineangle));
 | 
			
		||||
	y = FixedMul(movelen, FINESINE(lineangle));
 | 
			
		||||
	if (!ld)
 | 
			
		||||
	{
 | 
			
		||||
		angle_t th = R_PointToAngle2(0, 0, tmxmove, tmymove);
 | 
			
		||||
		normal->x = -FCOS(th);
 | 
			
		||||
		normal->y = -FSIN(th);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (P_IsLineTripWire(ld))
 | 
			
		||||
	x = FixedMul(movelen, normal->x);
 | 
			
		||||
	y = FixedMul(movelen, normal->y);
 | 
			
		||||
 | 
			
		||||
	if (ld && P_IsLineTripWire(ld))
 | 
			
		||||
	{
 | 
			
		||||
		tmxmove = x * 4;
 | 
			
		||||
		tmymove = y * 4;
 | 
			
		||||
| 
						 | 
				
			
			@ -3958,6 +4033,8 @@ papercollision:
 | 
			
		|||
 | 
			
		||||
static void P_BouncePlayerMove(mobj_t *mo, TryMoveResult_t *result)
 | 
			
		||||
{
 | 
			
		||||
	extern consvar_t cv_showgremlins;
 | 
			
		||||
 | 
			
		||||
	fixed_t mmomx = 0, mmomy = 0;
 | 
			
		||||
	fixed_t oldmomx = mo->momx, oldmomy = mo->momy;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -3982,8 +4059,23 @@ static void P_BouncePlayerMove(mobj_t *mo, TryMoveResult_t *result)
 | 
			
		|||
	slidemo = mo;
 | 
			
		||||
	bestslideline = result->line;
 | 
			
		||||
 | 
			
		||||
	if (bestslideline == NULL)
 | 
			
		||||
		return;
 | 
			
		||||
	if (bestslideline == NULL && cv_showgremlins.value)
 | 
			
		||||
	{
 | 
			
		||||
		// debug
 | 
			
		||||
		mobj_t*x = P_SpawnMobj(mo->x, mo->y, mo->z, MT_THOK);
 | 
			
		||||
		x->frame = FF_FULLBRIGHT | FF_ADD;
 | 
			
		||||
		x->renderflags = RF_ALWAYSONTOP;
 | 
			
		||||
		x->color = SKINCOLOR_RED;
 | 
			
		||||
 | 
			
		||||
		CONS_Printf(
 | 
			
		||||
			"GREMLIN: leveltime=%u x=%f y=%f z=%f angle=%f\n",
 | 
			
		||||
			leveltime,
 | 
			
		||||
			FixedToFloat(mo->x),
 | 
			
		||||
			FixedToFloat(mo->y),
 | 
			
		||||
			FixedToFloat(mo->z),
 | 
			
		||||
			AngleToFloat(R_PointToAngle2(0, 0, oldmomx, oldmomy))
 | 
			
		||||
		);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (mo->eflags & MFE_JUSTBOUNCEDWALL) // Stronger push-out
 | 
			
		||||
	{
 | 
			
		||||
| 
						 | 
				
			
			@ -3996,7 +4088,7 @@ static void P_BouncePlayerMove(mobj_t *mo, TryMoveResult_t *result)
 | 
			
		|||
		tmymove = FixedMul(mmomy, (FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3)));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (P_IsLineTripWire(bestslideline))
 | 
			
		||||
	if (bestslideline && P_IsLineTripWire(bestslideline))
 | 
			
		||||
	{
 | 
			
		||||
		// TRIPWIRE CANNOT BE MADE NONBOUNCY
 | 
			
		||||
		K_ApplyTripWire(mo->player, TRIPSTATE_BLOCKED);
 | 
			
		||||
| 
						 | 
				
			
			@ -4014,7 +4106,7 @@ static void P_BouncePlayerMove(mobj_t *mo, TryMoveResult_t *result)
 | 
			
		|||
		K_SpawnBumpEffect(mo);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	P_PlayerHitBounceLine(bestslideline);
 | 
			
		||||
	P_PlayerHitBounceLine(bestslideline, &result->normal);
 | 
			
		||||
	mo->eflags |= MFE_JUSTBOUNCEDWALL;
 | 
			
		||||
 | 
			
		||||
	mo->momx = tmxmove;
 | 
			
		||||
| 
						 | 
				
			
			@ -4022,7 +4114,7 @@ static void P_BouncePlayerMove(mobj_t *mo, TryMoveResult_t *result)
 | 
			
		|||
	mo->player->cmomx = tmxmove;
 | 
			
		||||
	mo->player->cmomy = tmymove;
 | 
			
		||||
 | 
			
		||||
	if (!P_IsLineTripWire(bestslideline))
 | 
			
		||||
	if (!bestslideline || !P_IsLineTripWire(bestslideline))
 | 
			
		||||
	{
 | 
			
		||||
		if (!P_TryMove(mo, mo->x + tmxmove, mo->y + tmymove, true, NULL))
 | 
			
		||||
		{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1671,7 +1671,7 @@ void P_XYMovement(mobj_t *mo)
 | 
			
		|||
		// blocked move
 | 
			
		||||
		moved = false;
 | 
			
		||||
 | 
			
		||||
		if (LUA_HookMobjMoveBlocked(mo, tm.hitthing, tm.blockingline))
 | 
			
		||||
		if (LUA_HookMobjMoveBlocked(mo, tm.hitthing, result.line))
 | 
			
		||||
		{
 | 
			
		||||
			if (P_MobjWasRemoved(mo))
 | 
			
		||||
				return;
 | 
			
		||||
| 
						 | 
				
			
			@ -1679,7 +1679,7 @@ void P_XYMovement(mobj_t *mo)
 | 
			
		|||
		else if (P_MobjWasRemoved(mo))
 | 
			
		||||
			return;
 | 
			
		||||
 | 
			
		||||
		P_PushSpecialLine(tm.blockingline, mo);
 | 
			
		||||
		P_PushSpecialLine(result.line, mo);
 | 
			
		||||
 | 
			
		||||
		if (mo->flags & MF_MISSILE)
 | 
			
		||||
		{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										78
									
								
								src/p_test.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								src/p_test.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,78 @@
 | 
			
		|||
// DR. ROBOTNIK'S RING RACERS
 | 
			
		||||
//-----------------------------------------------------------------------------
 | 
			
		||||
// Copyright (C) 2023 by James Robert Roman
 | 
			
		||||
//
 | 
			
		||||
// This program is free software distributed under the
 | 
			
		||||
// terms of the GNU General Public License, version 2.
 | 
			
		||||
// See the 'LICENSE' file for more details.
 | 
			
		||||
//-----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
#include <optional>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
#include "math/fixed.hpp"
 | 
			
		||||
#include "p_sweep.hpp"
 | 
			
		||||
 | 
			
		||||
#include "p_local.h"
 | 
			
		||||
 | 
			
		||||
namespace
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
std::vector<line_t*> g_lines;
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void P_TestLine(line_t* ld)
 | 
			
		||||
{
 | 
			
		||||
	g_lines.emplace_back(ld);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
line_t* P_SweepTestLines(fixed_t ax, fixed_t ay, fixed_t bx, fixed_t by, fixed_t r, vector2_t* return_normal)
 | 
			
		||||
{
 | 
			
		||||
	using namespace srb2::math;
 | 
			
		||||
	using namespace srb2::sweep;
 | 
			
		||||
 | 
			
		||||
	struct Collision
 | 
			
		||||
	{
 | 
			
		||||
		unit z;
 | 
			
		||||
		vec2 normal;
 | 
			
		||||
		line_t* ld;
 | 
			
		||||
 | 
			
		||||
		bool operator<(const Collision& b) const { return z < b.z; }
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	std::optional<Collision> collision;
 | 
			
		||||
 | 
			
		||||
	LineSegment<Fixed> l{{ax, ay}, {bx, by}};
 | 
			
		||||
	AABBvsLine sweep{r, l};
 | 
			
		||||
 | 
			
		||||
	for (line_t* ld : g_lines)
 | 
			
		||||
	{
 | 
			
		||||
		LineSegment<Fixed> ls{{ld->v1->x, ld->v1->y}, {ld->v2->x, ld->v2->y}};
 | 
			
		||||
		Result rs = sweep(ls);
 | 
			
		||||
		if (rs.hit)
 | 
			
		||||
		{
 | 
			
		||||
			if (!collision || rs.hit->z < collision->z)
 | 
			
		||||
			{
 | 
			
		||||
				collision = {rs.hit->z, rs.hit->n, ld};
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	g_lines.clear();
 | 
			
		||||
 | 
			
		||||
	if (!collision)
 | 
			
		||||
	{
 | 
			
		||||
		return nullptr;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return_normal->x = Fixed {collision->normal.x};
 | 
			
		||||
	return_normal->y = Fixed {collision->normal.y};
 | 
			
		||||
 | 
			
		||||
	return collision->ld;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void P_ClearTestLines(void)
 | 
			
		||||
{
 | 
			
		||||
	g_lines.clear();
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	Add table
		
		Reference in a new issue