/// <summary> /// Find a target on the aiming line. /// Sets LineTaget when a target is aimed at. /// </summary> public Fixed AimLineAttack(Mobj shooter, Angle angle, Fixed range) { currentShooter = shooter; currentShooterZ = shooter.Z + (shooter.Height >> 1) + Fixed.FromInt(8); currentRange = range; var targetX = shooter.X + range.ToIntFloor() * Trig.Cos(angle); var targetY = shooter.Y + range.ToIntFloor() * Trig.Sin(angle); // Can't shoot outside view angles. topSlope = Fixed.FromInt(100) / 160; bottomSlope = Fixed.FromInt(-100) / 160; lineTarget = null; world.PathTraversal.PathTraverse( shooter.X, shooter.Y, targetX, targetY, PathTraverseFlags.AddLines | PathTraverseFlags.AddThings, aimTraverseFunc); if (lineTarget != null) { return(currentAimSlope); } return(Fixed.Zero); }
/// <summary> /// Looks for special lines in front of the player to activate. /// </summary> public void UseLines(Player player) { var pt = world.PathTraversal; useThing = player.Mobj; var angle = player.Mobj.Angle; var x1 = player.Mobj.X; var y1 = player.Mobj.Y; var x2 = x1 + useRange.ToIntFloor() * Trig.Cos(angle); var y2 = y1 + useRange.ToIntFloor() * Trig.Sin(angle); pt.PathTraverse(x1, y1, x2, y2, PathTraverseFlags.AddLines, useTraverseFunc); }
/// <summary> /// Fire a hitscan bullet. /// If damage == 0, it is just a test trace that will leave linetarget set. /// </summary> public void LineAttack(Mobj shooter, Angle angle, Fixed range, Fixed slope, int damage) { currentShooter = shooter; currentShooterZ = shooter.Z + (shooter.Height >> 1) + Fixed.FromInt(8); currentRange = range; currentAimSlope = slope; currentDamage = damage; var targetX = shooter.X + range.ToIntFloor() * Trig.Cos(angle); var targetY = shooter.Y + range.ToIntFloor() * Trig.Sin(angle); world.PathTraversal.PathTraverse( shooter.X, shooter.Y, targetX, targetY, PathTraverseFlags.AddLines | PathTraverseFlags.AddThings, shootTraverseFunc); }
public bool PathTraverse(Fixed x1, Fixed y1, Fixed x2, Fixed y2, PathTraverseFlags flags, Func <Intercept, bool> trav) { earlyOut = (flags & PathTraverseFlags.EarlyOut) != 0; var validCount = world.GetNewValidCount(); var bm = world.Map.BlockMap; interceptCount = 0; if (((x1 - bm.OriginX).Data & (BlockMap.MapBlockSize.Data - 1)) == 0) { // Don't side exactly on a line. x1 += Fixed.One; } if (((y1 - bm.OriginY).Data & (BlockMap.MapBlockSize.Data - 1)) == 0) { // Don't side exactly on a line. y1 += Fixed.One; } trace.X = x1; trace.Y = y1; trace.Dx = x2 - x1; trace.Dy = y2 - y1; x1 -= bm.OriginX; y1 -= bm.OriginY; var blockX1 = x1.Data >> BlockMap.MapBlockShift; var blockY1 = y1.Data >> BlockMap.MapBlockShift; x2 -= bm.OriginX; y2 -= bm.OriginY; var blockX2 = x2.Data >> BlockMap.MapBlockShift; var blockY2 = y2.Data >> BlockMap.MapBlockShift; Fixed stepX; Fixed stepY; Fixed partial; int blockStepX; int blockStepY; if (blockX2 > blockX1) { blockStepX = 1; partial = new Fixed(Fixed.FracUnit - ((x1.Data >> BlockMap.MapBToFrac) & (Fixed.FracUnit - 1))); stepY = (y2 - y1) / Fixed.Abs(x2 - x1); } else if (blockX2 < blockX1) { blockStepX = -1; partial = new Fixed((x1.Data >> BlockMap.MapBToFrac) & (Fixed.FracUnit - 1)); stepY = (y2 - y1) / Fixed.Abs(x2 - x1); } else { blockStepX = 0; partial = Fixed.One; stepY = Fixed.FromInt(256); } var interceptY = new Fixed(y1.Data >> BlockMap.MapBToFrac) + (partial * stepY); if (blockY2 > blockY1) { blockStepY = 1; partial = new Fixed(Fixed.FracUnit - ((y1.Data >> BlockMap.MapBToFrac) & (Fixed.FracUnit - 1))); stepX = (x2 - x1) / Fixed.Abs(y2 - y1); } else if (blockY2 < blockY1) { blockStepY = -1; partial = new Fixed((y1.Data >> BlockMap.MapBToFrac) & (Fixed.FracUnit - 1)); stepX = (x2 - x1) / Fixed.Abs(y2 - y1); } else { blockStepY = 0; partial = Fixed.One; stepX = Fixed.FromInt(256); } var interceptX = new Fixed(x1.Data >> BlockMap.MapBToFrac) + (partial * stepX); // Step through map blocks. // Count is present to prevent a round off error from skipping the break. var bx = blockX1; var by = blockY1; for (var count = 0; count < 64; count++) { if ((flags & PathTraverseFlags.AddLines) != 0) { if (!bm.IterateLines(bx, by, lineInterceptFunc, validCount)) { // Early out. return(false); } } if ((flags & PathTraverseFlags.AddThings) != 0) { if (!bm.IterateThings(bx, by, thingInterceptFunc)) { // Early out. return(false); } } if (bx == blockX2 && by == blockY2) { break; } if ((interceptY.ToIntFloor()) == by) { interceptY += stepY; bx += blockStepX; } else if ((interceptX.ToIntFloor()) == bx) { interceptX += stepX; by += blockStepY; } } // Go through the sorted list. return(TraverseIntercepts(trav, Fixed.One)); }