예제 #1
0
        /// <summary>
        /// Returns true if a straight line between the looker and target is unobstructed.
        /// </summary>
        public bool CheckSight(Mobj looker, Mobj target)
        {
            var map = world.Map;

            // First check for trivial rejection.
            // Check in REJECT table.
            if (map.Reject.Check(looker.Subsector.Sector, target.Subsector.Sector))
            {
                // Can't possibly be connected.
                return(false);
            }

            // An unobstructed LOS is possible.
            // Now look from eyes of t1 to any part of t2.

            sightZStart = looker.Z + looker.Height - (looker.Height >> 2);
            topSlope    = (target.Z + target.Height) - sightZStart;
            bottomSlope = (target.Z) - sightZStart;

            trace.X  = looker.X;
            trace.Y  = looker.Y;
            trace.Dx = target.X - looker.X;
            trace.Dy = target.Y - looker.Y;

            targetX = target.X;
            targetY = target.Y;

            // The head node is the last node output.
            return(CrossBspNode(map.Nodes.Length - 1, world.GetNewValidCount()));
        }
예제 #2
0
 private void NoiseAlert(Mobj target, Mobj emmiter)
 {
     RecursiveSound(
         emmiter.Subsector.Sector,
         0,
         target,
         world.GetNewValidCount());
 }
예제 #3
0
        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));
        }
예제 #4
0
        /// <summary>
        /// This is purely informative, nothing is modified
        /// (except things picked up).
        ///
        /// In:
        ///     A Mobj (can be valid or invalid)
        ///     A position to be checked
        ///     (doesn't need to be related to the mobj.X and Y)
        ///
        /// During:
        ///     Special things are touched if MobjFlags.PickUp
        ///     Early out on solid lines?
        ///
        /// Out:
        ///     New subsector
        ///     CurrentFloorZ
        ///     CurrentCeilingZ
        ///     CurrentDropoffZ
        ///     The lowest point contacted
        ///     (monsters won't move to a dropoff)
        ///     crossedSpecials[]
        ///     crossedSpecialCount
        /// </summary>
        public bool CheckPosition(Mobj thing, Fixed x, Fixed y)
        {
            var map = world.Map;
            var bm  = map.BlockMap;

            currentThing = thing;
            currentFlags = thing.Flags;

            currentX = x;
            currentY = y;

            currentBox[Box.Top]    = y + currentThing.Radius;
            currentBox[Box.Bottom] = y - currentThing.Radius;
            currentBox[Box.Right]  = x + currentThing.Radius;
            currentBox[Box.Left]   = x - currentThing.Radius;

            var newSubsector = Geometry.PointInSubsector(x, y, map);

            currentCeilingLine = null;

            // The base floor / ceiling is from the subsector that contains the point.
            // Any contacted lines the step closer together will adjust them.
            currentFloorZ   = currentDropoffZ = newSubsector.Sector.FloorHeight;
            currentCeilingZ = newSubsector.Sector.CeilingHeight;

            var validCount = world.GetNewValidCount();

            crossedSpecialCount = 0;

            if ((currentFlags & MobjFlags.NoClip) != 0)
            {
                return(true);
            }

            // Check things first, possibly picking things up.
            // The bounding box is extended by MaxThingRadius because mobj_ts are grouped into
            // mapblocks based on their origin point, and can overlap into adjacent blocks by up
            // to MaxThingRadius units.
            {
                var blockX1 = bm.GetBlockX(currentBox[Box.Left] - GameConst.MaxThingRadius);
                var blockX2 = bm.GetBlockX(currentBox[Box.Right] + GameConst.MaxThingRadius);
                var blockY1 = bm.GetBlockY(currentBox[Box.Bottom] - GameConst.MaxThingRadius);
                var blockY2 = bm.GetBlockY(currentBox[Box.Top] + GameConst.MaxThingRadius);

                for (var bx = blockX1; bx <= blockX2; bx++)
                {
                    for (var by = blockY1; by <= blockY2; by++)
                    {
                        if (!map.BlockMap.IterateThings(bx, by, checkThingFunc))
                        {
                            return(false);
                        }
                    }
                }
            }

            // Check lines.
            {
                var blockX1 = bm.GetBlockX(currentBox[Box.Left]);
                var blockX2 = bm.GetBlockX(currentBox[Box.Right]);
                var blockY1 = bm.GetBlockY(currentBox[Box.Bottom]);
                var blockY2 = bm.GetBlockY(currentBox[Box.Top]);

                for (var bx = blockX1; bx <= blockX2; bx++)
                {
                    for (var by = blockY1; by <= blockY2; by++)
                    {
                        if (!map.BlockMap.IterateLines(bx, by, checkLineFunc, validCount))
                        {
                            return(false);
                        }
                    }
                }
            }

            return(true);
        }