Exemple #1
0
        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);
        }
Exemple #2
0
        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);
        }
Exemple #4
0
        /// <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));
        }
Exemple #5
0
        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);
        }
Exemple #6
0
 public Fixed Abs()
 {
     return(Fixed.Abs(this));
 }