private bool StompThing(Mobj thing) { if ((thing.Flags & MobjFlags.Shootable) == 0) { return(true); } var blockDist = thing.Radius + this.currentThing.Radius; var dx = Fixed.Abs(thing.X - this.currentX); var dy = Fixed.Abs(thing.Y - this.currentY); if (dx >= blockDist || dy >= blockDist) { // Didn't hit it. return(true); } // Don't clip against self. if (thing == this.currentThing) { return(true); } // Monsters don't stomp things except on boss level. if (this.currentThing.Player == null && this.world.Options.Map != 30) { return(false); } this.world.ThingInteraction.DamageMobj(thing, this.currentThing, this.currentThing, 10000); return(true); }
public void Abs2() { var random = new Random(666); for (var i = 0; i < 100; i++) { var a = 666 * random.NextDouble() - 333; var b = Math.Abs(a); var fa = Fixed.FromDouble(a); var fb = Fixed.Abs(fa); Assert.AreEqual(b, fb.ToDouble(), delta); } }
/// <summary> /// "bombSource" is the creature that caused the explosion at "bombSpot". /// </summary> private bool DoRadiusAttack(Mobj thing) { if ((thing.Flags & MobjFlags.Shootable) == 0) { return(true); } // Boss spider and cyborg take no damage from concussion. if (thing.Type == MobjType.Cyborg || thing.Type == MobjType.Spider) { return(true); } var dx = Fixed.Abs(thing.X - this.bombSpot.X); var dy = Fixed.Abs(thing.Y - this.bombSpot.Y); var dist = dx > dy ? dx : dy; dist = new Fixed((dist - thing.Radius).Data >> Fixed.FracBits); if (dist < Fixed.Zero) { dist = Fixed.Zero; } if (dist.Data >= this.bombDamage) { // Out of range. return(true); } if (this.world.VisibilityCheck.CheckSight(thing, this.bombSpot)) { // Must be in direct path. this.DamageMobj(thing, this.bombSpot, this.bombSource, this.bombDamage - dist.Data); } return(true); }
/// <summary> /// Traces a line from x1, y1 to x2, y2, calling the traverser function for each. /// Returns true if the traverser function returns true for all lines. /// </summary> public bool PathTraverse(Fixed x1, Fixed y1, Fixed x2, Fixed y2, PathTraverseFlags flags, Func <Intercept, bool> trav) { this.earlyOut = (flags & PathTraverseFlags.EarlyOut) != 0; var validCount = this.world.GetNewValidCount(); var bm = this.world.Map.BlockMap; this.interceptCount = 0; if (((x1 - bm.OriginX).Data & (BlockMap.BlockSize.Data - 1)) == 0) { // Don't side exactly on a line. x1 += Fixed.One; } if (((y1 - bm.OriginY).Data & (BlockMap.BlockSize.Data - 1)) == 0) { // Don't side exactly on a line. y1 += Fixed.One; } this.trace.X = x1; this.trace.Y = y1; this.trace.Dx = x2 - x1; this.trace.Dy = y2 - y1; x1 -= bm.OriginX; y1 -= bm.OriginY; var blockX1 = x1.Data >> BlockMap.FracToBlockShift; var blockY1 = y1.Data >> BlockMap.FracToBlockShift; x2 -= bm.OriginX; y2 -= bm.OriginY; var blockX2 = x2.Data >> BlockMap.FracToBlockShift; var blockY2 = y2.Data >> BlockMap.FracToBlockShift; Fixed stepX; Fixed stepY; Fixed partial; int blockStepX; int blockStepY; if (blockX2 > blockX1) { blockStepX = 1; partial = new Fixed(Fixed.FracUnit - ((x1.Data >> BlockMap.BlockToFracShift) & (Fixed.FracUnit - 1))); stepY = (y2 - y1) / Fixed.Abs(x2 - x1); } else if (blockX2 < blockX1) { blockStepX = -1; partial = new Fixed((x1.Data >> BlockMap.BlockToFracShift) & (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.BlockToFracShift) + (partial * stepY); if (blockY2 > blockY1) { blockStepY = 1; partial = new Fixed(Fixed.FracUnit - ((y1.Data >> BlockMap.BlockToFracShift) & (Fixed.FracUnit - 1))); stepX = (x2 - x1) / Fixed.Abs(y2 - y1); } else if (blockY2 < blockY1) { blockStepY = -1; partial = new Fixed((y1.Data >> BlockMap.BlockToFracShift) & (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.BlockToFracShift) + (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, this.lineInterceptFunc, validCount)) { // Early out. return(false); } } if ((flags & PathTraverseFlags.AddThings) != 0) { if (!bm.IterateThings(bx, by, this.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(this.TraverseIntercepts(trav, Fixed.One)); }
private bool CheckThing(Mobj thing) { if ((thing.Flags & (MobjFlags.Solid | MobjFlags.Special | MobjFlags.Shootable)) == 0) { return(true); } var blockDist = thing.Radius + this.currentThing.Radius; if (Fixed.Abs(thing.X - this.currentX) >= blockDist || Fixed.Abs(thing.Y - this.currentY) >= blockDist) { // Didn't hit it. return(true); } // Don't clip against self. if (thing == this.currentThing) { return(true); } // Check for skulls slamming into things. if ((this.currentThing.Flags & MobjFlags.SkullFly) != 0) { var damage = ((this.world.Random.Next() % 8) + 1) * this.currentThing.Info.Damage; this.world.ThingInteraction.DamageMobj(thing, this.currentThing, this.currentThing, damage); this.currentThing.Flags &= ~MobjFlags.SkullFly; this.currentThing.MomX = this.currentThing.MomY = this.currentThing.MomZ = Fixed.Zero; this.currentThing.SetState(this.currentThing.Info.SpawnState); // Stop moving. return(false); } // Missiles can hit other things. if ((this.currentThing.Flags & MobjFlags.Missile) != 0) { // See if it went over / under. if (this.currentThing.Z > thing.Z + thing.Height) { // Overhead. return(true); } if (this.currentThing.Z + this.currentThing.Height < thing.Z) { // Underneath. return(true); } if (this.currentThing.Target != null && (this.currentThing.Target.Type == thing.Type || (this.currentThing.Target.Type == MobjType.Knight && thing.Type == MobjType.Bruiser) || (this.currentThing.Target.Type == MobjType.Bruiser && thing.Type == MobjType.Knight))) { // Don't hit same species as originator. if (thing == this.currentThing.Target) { return(true); } if (thing.Type != MobjType.Player) { // Explode, but do no damage. // Let players missile other players. return(false); } } if ((thing.Flags & MobjFlags.Shootable) == 0) { // Didn't do any damage. return((thing.Flags & MobjFlags.Solid) == 0); } // Damage / explode. var damage = ((this.world.Random.Next() % 8) + 1) * this.currentThing.Info.Damage; this.world.ThingInteraction.DamageMobj(thing, this.currentThing, this.currentThing.Target, damage); // Don't traverse any more. return(false); } // Check for special pickup. if ((thing.Flags & MobjFlags.Special) != 0) { var solid = (thing.Flags & MobjFlags.Solid) != 0; if ((this.currentFlags & MobjFlags.PickUp) != 0) { // Can remove thing. this.world.ItemPickup.TouchSpecialThing(thing, this.currentThing); } return(!solid); } return((thing.Flags & MobjFlags.Solid) == 0); }
public Fixed Abs() { return(Fixed.Abs(this)); }