Exemple #1
0
        public FloorType HitFloor(Mobj thing)
        {
            if (thing.FloorZ != thing.Subsector.Sector.FloorHeight)
            {
                // don't splash if landing on the edge above water
                return(FloorType.Solid);
            }
            switch (world.ThingAllocation.GetThingFloorType(thing))
            {
            case FloorType.Water:
                world.ThingAllocation.SpawnMobj(thing.X, thing.Y, Mobj.OnFloorZ, MobjType.SplashBase);
                var mo = world.ThingAllocation.SpawnMobj(thing.X, thing.Y, Mobj.OnFloorZ, MobjType.Splash);
                mo.Target = thing;
                mo.MomX   = Fixed.FromInt((world.Random.Next() - world.Random.Next()) << 8);
                mo.MomY   = Fixed.FromInt((world.Random.Next() - world.Random.Next()) << 8);
                mo.MomZ   = Fixed.FromInt(2) * Fixed.One + (Fixed.FromInt(world.Random.Next()) << 8);
                world.StartSound(thing, Sfx.GLOOP, SfxType.Misc);
                return(FloorType.Water);

            case FloorType.Lava: break;

            case FloorType.Sludge: break;
            }

            return(FloorType.Solid);
        }
            private static int UnArchiveLine(LineDef line, byte[] data, int p)
            {
                line.Flags   = (LineFlags)BitConverter.ToInt16(data, p);
                line.Special = (LineSpecial)BitConverter.ToInt16(data, p + 2);
                line.Tag     = BitConverter.ToInt16(data, p + 4);
                p           += 6;

                if (line.FrontSide != null)
                {
                    var side = line.FrontSide;
                    side.TextureOffset = Fixed.FromInt(BitConverter.ToInt16(data, p));
                    side.RowOffset     = Fixed.FromInt(BitConverter.ToInt16(data, p + 2));
                    side.TopTexture    = BitConverter.ToInt16(data, p + 4);
                    side.BottomTexture = BitConverter.ToInt16(data, p + 6);
                    side.MiddleTexture = BitConverter.ToInt16(data, p + 8);
                    p += 10;
                }

                if (line.BackSide != null)
                {
                    var side = line.BackSide;
                    side.TextureOffset = Fixed.FromInt(BitConverter.ToInt16(data, p));
                    side.RowOffset     = Fixed.FromInt(BitConverter.ToInt16(data, p + 2));
                    side.TopTexture    = BitConverter.ToInt16(data, p + 4);
                    side.BottomTexture = BitConverter.ToInt16(data, p + 6);
                    side.MiddleTexture = BitConverter.ToInt16(data, p + 8);
                    p += 10;
                }

                return(p);
            }
Exemple #3
0
        /// <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);
        }
Exemple #4
0
        public static BlockMap FromWad(Wad wad, int lump, LineDef[] lines)
        {
            var data = wad.ReadLump(lump);

            var table = new short[data.Length / 2];

            for (var i = 0; i < table.Length; i++)
            {
                var offset = 2 * i;
                table[i] = BitConverter.ToInt16(data, offset);
            }

            var originX = Fixed.FromInt(table[0]);
            var originY = Fixed.FromInt(table[1]);
            var width   = table[2];
            var height  = table[3];

            return(new BlockMap(
                       originX,
                       originY,
                       width,
                       height,
                       table,
                       lines));
        }
Exemple #5
0
        /// <summary>
        /// Spawn blood.
        /// </summary>
        public void SpawnBlood(Fixed x, Fixed y, Fixed z, int damage)
        {
            var random = world.Random;

            z += new Fixed((random.Next() - random.Next()) << 10);

            var thing = world.ThingAllocation.SpawnMobj(x, y, z, MobjType.Blood);

            thing.MomZ  = Fixed.FromInt(2);
            thing.Tics -= random.Next() & 3;

            if (thing.Tics < 1)
            {
                thing.Tics = 1;
            }

            if (damage <= 12 && damage >= 9)
            {
                thing.SetState(MobjState.Blood2);
            }
            else if (damage < 9)
            {
                thing.SetState(MobjState.Blood3);
            }
        }
Exemple #6
0
        public static Vertex FromData(byte[] data, int offset)
        {
            var x = BitConverter.ToInt16(data, offset);
            var y = BitConverter.ToInt16(data, offset + 2);

            return(new Vertex(Fixed.FromInt(x), Fixed.FromInt(y)));
        }
Exemple #7
0
        public static Node FromData(byte[] data, int offset)
        {
            var x  = BitConverter.ToInt16(data, offset);
            var y  = BitConverter.ToInt16(data, offset + 2);
            var dx = BitConverter.ToInt16(data, offset + 4);
            var dy = BitConverter.ToInt16(data, offset + 6);
            var frontBoundingBoxTop    = BitConverter.ToInt16(data, offset + 8);
            var frontBoundingBoxBottom = BitConverter.ToInt16(data, offset + 10);
            var frontBoundingBoxLeft   = BitConverter.ToInt16(data, offset + 12);
            var frontBoundingBoxRight  = BitConverter.ToInt16(data, offset + 14);
            var backBoundingBoxTop     = BitConverter.ToInt16(data, offset + 16);
            var backBoundingBoxBottom  = BitConverter.ToInt16(data, offset + 18);
            var backBoundingBoxLeft    = BitConverter.ToInt16(data, offset + 20);
            var backBoundingBoxRight   = BitConverter.ToInt16(data, offset + 22);
            var frontChild             = BitConverter.ToInt16(data, offset + 24);
            var backChild = BitConverter.ToInt16(data, offset + 26);

            return(new Node(
                       Fixed.FromInt(x),
                       Fixed.FromInt(y),
                       Fixed.FromInt(dx),
                       Fixed.FromInt(dy),
                       Fixed.FromInt(frontBoundingBoxTop),
                       Fixed.FromInt(frontBoundingBoxBottom),
                       Fixed.FromInt(frontBoundingBoxLeft),
                       Fixed.FromInt(frontBoundingBoxRight),
                       Fixed.FromInt(backBoundingBoxTop),
                       Fixed.FromInt(backBoundingBoxBottom),
                       Fixed.FromInt(backBoundingBoxLeft),
                       Fixed.FromInt(backBoundingBoxRight),
                       frontChild,
                       backChild));
        }
Exemple #8
0
        public void Fire(Mobj actor)
        {
            var dest = actor.Tracer;

            if (dest == null)
            {
                return;
            }

            // Don't move it if the vile lost sight.
            if (!world.VisibilityCheck.CheckSight(actor.Target, dest))
            {
                return;
            }

            world.ThingMovement.UnsetThingPosition(actor);

            var angle = dest.Angle;

            actor.X = dest.X + Fixed.FromInt(24) * Trig.Cos(angle);
            actor.Y = dest.Y + Fixed.FromInt(24) * Trig.Sin(angle);
            actor.Z = dest.Z;

            world.ThingMovement.SetThingPosition(actor);
        }
Exemple #9
0
        public void VileAttack(Mobj actor)
        {
            if (actor.Target == null)
            {
                return;
            }

            FaceTarget(actor);

            if (!world.VisibilityCheck.CheckSight(actor, actor.Target))
            {
                return;
            }

            world.StartSound(actor, Sfx.BAREXP);
            world.ThingInteraction.DamageMobj(actor.Target, actor, actor, 20);
            actor.Target.MomZ = Fixed.FromInt(1000) / actor.Target.Info.Mass;

            var fire = actor.Tracer;

            if (fire == null)
            {
                return;
            }

            var angle = actor.Angle;

            // Move the fire between the vile and the player.
            fire.X = actor.Target.X - Fixed.FromInt(24) * Trig.Cos(angle);
            fire.Y = actor.Target.Y - Fixed.FromInt(24) * Trig.Sin(angle);
            world.ThingInteraction.RadiusAttack(fire, actor, 70);
        }
Exemple #10
0
        private bool SlideTraverse(Intercept intercept)
        {
            var mc = world.MapCollision;

            if (intercept.Line == null)
            {
                throw new Exception("ThingMovement.SlideTraverse: Not a line?");
            }

            var line = intercept.Line;

            if ((line.Flags & LineFlags.TwoSided) == 0)
            {
                if (Geometry.PointOnLineSide(slideThing.X, slideThing.Y, line) != 0)
                {
                    // Don't hit the back side.
                    return(true);
                }

                goto isBlocking;
            }

            // Set openrange, opentop, openbottom.
            mc.LineOpening(line);

            if (mc.OpenRange < slideThing.Height)
            {
                // Doesn't fit.
                goto isBlocking;
            }

            if (mc.OpenTop - slideThing.Z < slideThing.Height)
            {
                // Mobj is too high.
                goto isBlocking;
            }

            if (mc.OpenBottom - slideThing.Z > Fixed.FromInt(24))
            {
                // Too big a step up.
                goto isBlocking;
            }

            // This line doesn't block movement.
            return(true);

            // The line does block movement, see if it is closer than best so far.
isBlocking:
            if (intercept.Frac < bestSlideFrac)
            {
                secondSlideFrac = bestSlideFrac;
                secondSlideLine = bestSlideLine;
                bestSlideFrac   = intercept.Frac;
                bestSlideLine   = line;
            }

            // Stop.
            return(false);
        }
        /// <summary>
        /// Fall on your face when dying.
        /// Decrease POV height to floor height.
        /// </summary>
        private void DeathThink(Player player)
        {
            MovePlayerSprites(player);

            // Fall to the ground.
            if (player.ViewHeight > Fixed.FromInt(6))
            {
                player.ViewHeight -= Fixed.One;
            }

            if (player.ViewHeight < Fixed.FromInt(6))
            {
                player.ViewHeight = Fixed.FromInt(6);
            }

            player.DeltaViewHeight = Fixed.Zero;
            onGround = (player.Mobj.Z <= player.Mobj.FloorZ);
            CalcHeight(player);

            if (player.Attacker != null && player.Attacker != player.Mobj)
            {
                var angle = Geometry.PointToAngle(
                    player.Mobj.X, player.Mobj.Y,
                    player.Attacker.X, player.Attacker.Y);

                var delta = angle - player.Mobj.Angle;

                if (delta < ang5 || delta.Data > (-ang5).Data)
                {
                    // Looking at killer, so fade damage flash down.
                    player.Mobj.Angle = angle;

                    if (player.DamageCount > 0)
                    {
                        player.DamageCount--;
                    }
                }
                else if (delta < Angle.Ang180)
                {
                    player.Mobj.Angle += ang5;
                }
                else
                {
                    player.Mobj.Angle -= ang5;
                }
            }
            else if (player.DamageCount > 0)
            {
                player.DamageCount--;
            }

            if ((player.Cmd.Buttons & TicCmdButtons.Use) != 0)
            {
                player.PlayerState = PlayerState.Reborn;
            }
        }
        private bool AddLineIntercepts(LineDef line)
        {
            int s1;
            int s2;

            // Avoid precision problems with two routines.
            if (trace.Dx > Fixed.FromInt(16) ||
                trace.Dy > Fixed.FromInt(16) ||
                trace.Dx < -Fixed.FromInt(16) ||
                trace.Dy < -Fixed.FromInt(16))
            {
                s1 = Geometry.PointOnDivLineSide(line.Vertex1.X, line.Vertex1.Y, trace);
                s2 = Geometry.PointOnDivLineSide(line.Vertex2.X, line.Vertex2.Y, trace);
            }
            else
            {
                s1 = Geometry.PointOnLineSide(trace.X, trace.Y, line);
                s2 = Geometry.PointOnLineSide(trace.X + trace.Dx, trace.Y + trace.Dy, line);
            }

            if (s1 == s2)
            {
                // Line isn't crossed.
                return(true);
            }

            // Hit the line.
            target.MakeFrom(line);

            var frac = InterceptVector(trace, target);

            if (frac < Fixed.Zero)
            {
                // Behind source.
                return(true);
            }

            // Try to early out the check.
            if (earlyOut && frac < Fixed.One && line.BackSector == null)
            {
                // Stop checking.
                return(false);
            }

            intercepts[interceptCount].Frac  = frac;
            intercepts[interceptCount].Line  = line;
            intercepts[interceptCount].Thing = null;
            interceptCount++;

            // Continue.
            return(true);
        }
Exemple #13
0
 private static int UnArchiveSector(Sector sector, byte[] data, int p)
 {
     sector.FloorHeight   = Fixed.FromInt(BitConverter.ToInt16(data, p));
     sector.CeilingHeight = Fixed.FromInt(BitConverter.ToInt16(data, p + 2));
     sector.FloorFlat     = BitConverter.ToInt16(data, p + 4);
     sector.CeilingFlat   = BitConverter.ToInt16(data, p + 6);
     sector.LightLevel    = BitConverter.ToInt16(data, p + 8);
     sector.Special       = (SectorSpecial)BitConverter.ToInt16(data, p + 10);
     sector.Tag           = BitConverter.ToInt16(data, p + 12);
     sector.SpecialData   = null;
     sector.SoundTarget   = null;
     return(p + 14);
 }
        public Mobj SpawnMissile(Mobj source, Mobj dest, MobjType type)
        {
            var missile = SpawnMobj(
                source.X,
                source.Y,
                source.Z + Fixed.FromInt(32), type);

            if (missile.Info.SeeSound != 0)
            {
                world.StartSound(missile, missile.Info.SeeSound);
            }

            // Where it came from?
            missile.Target = source;

            var angle = Geometry.PointToAngle(
                source.X, source.Y,
                dest.X, dest.Y);

            // Fuzzy player.
            if ((dest.Flags & MobjFlags.Shadow) != 0)
            {
                var random = world.Random;
                angle += new Angle((random.Next() - random.Next()) << 20);
            }

            var speed = GetMissileSpeed(missile.Type);

            missile.Angle = angle;
            missile.MomX  = new Fixed(speed) * Trig.Cos(angle);
            missile.MomY  = new Fixed(speed) * Trig.Sin(angle);

            var dist = Geometry.AproxDistance(
                dest.X - source.X,
                dest.Y - source.Y);

            var num = (dest.Z - source.Z).Data;
            var den = (dist / speed).Data;

            if (den < 1)
            {
                den = 1;
            }

            missile.MomZ = new Fixed(num / den);

            CheckMissileSpawn(missile);

            return(missile);
        }
Exemple #15
0
        public static MapThing FromData(byte[] data, int offset)
        {
            var x     = BitConverter.ToInt16(data, offset);
            var y     = BitConverter.ToInt16(data, offset + 2);
            var angle = BitConverter.ToInt16(data, offset + 4);
            var type  = BitConverter.ToInt16(data, offset + 6);
            var flags = BitConverter.ToInt16(data, offset + 8);

            return(new MapThing(
                       Fixed.FromInt(x),
                       Fixed.FromInt(y),
                       new Angle(ManagedDoom.Angle.Ang45.Data * (uint)(angle / 45)),
                       type,
                       (ThingFlags)flags));
        }
Exemple #16
0
        public static SideDef FromData(byte[] data, int offset, TextureLookup textures, Sector[] sectors)
        {
            var textureOffset     = BitConverter.ToInt16(data, offset);
            var rowOffset         = BitConverter.ToInt16(data, offset + 2);
            var topTextureName    = DoomInterop.ToString(data, offset + 4, 8);
            var bottomTextureName = DoomInterop.ToString(data, offset + 12, 8);
            var middleTextureName = DoomInterop.ToString(data, offset + 20, 8);
            var sectorNum         = BitConverter.ToInt16(data, offset + 28);

            return(new SideDef(
                       Fixed.FromInt(textureOffset),
                       Fixed.FromInt(rowOffset),
                       textures.GetNumber(topTextureName),
                       textures.GetNumber(bottomTextureName),
                       textures.GetNumber(middleTextureName),
                       sectorNum != -1 ? sectors[sectorNum] : null));
        }
Exemple #17
0
        /// <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 void SpawnPlayerMissile(Mobj source, MobjType type)
        {
            var hs = world.Hitscan;

            // See which target is to be aimed at.
            var angle = source.Angle;
            var slope = hs.AimLineAttack(source, angle, Fixed.FromInt(16 * 64));

            if (hs.LineTarget == null)
            {
                angle += new Angle(1 << 26);
                slope  = hs.AimLineAttack(source, angle, Fixed.FromInt(16 * 64));

                if (hs.LineTarget == null)
                {
                    angle -= new Angle(2 << 26);
                    slope  = hs.AimLineAttack(source, angle, Fixed.FromInt(16 * 64));
                }

                if (hs.LineTarget == null)
                {
                    angle = source.Angle;
                    slope = Fixed.Zero;
                }
            }

            var x = source.X;
            var y = source.Y;
            var z = source.Z + Fixed.FromInt(32);

            var missile = SpawnMobj(x, y, z, type);

            if (missile.Info.SeeSound != 0)
            {
                world.StartSound(missile, missile.Info.SeeSound);
            }

            missile.Target = source;
            missile.Angle  = angle;
            missile.MomX   = new Fixed(missile.Info.Speed) * Trig.Cos(angle);
            missile.MomY   = new Fixed(missile.Info.Speed) * Trig.Sin(angle);
            missile.MomZ   = new Fixed(missile.Info.Speed) * slope;

            CheckMissileSpawn(missile);
        }
Exemple #19
0
        public void PainShootSkull(Mobj actor, Angle angle)
        {
            // Count total number of skull currently on the level.
            var count = 0;

            foreach (var thinker in world.Thinkers)
            {
                var mobj = thinker as Mobj;
                if (mobj != null && mobj.Type == MobjType.Skull)
                {
                    count++;
                }
            }

            // If there are allready 20 skulls on the level,
            // don't spit another one.
            if (count > 20)
            {
                return;
            }

            // Okay, there's playe for another one.

            var preStep = Fixed.FromInt(4) +
                          3 * (actor.Info.Radius + DoomInfo.MobjInfos[(int)MobjType.Skull].Radius) / 2;

            var x = actor.X + preStep * Trig.Cos(angle);
            var y = actor.Y + preStep * Trig.Sin(angle);
            var z = actor.Z + Fixed.FromInt(8);

            var skull = world.ThingAllocation.SpawnMobj(x, y, z, MobjType.Skull);

            // Check for movements.
            if (!world.ThingMovement.TryMove(skull, skull.X, skull.Y))
            {
                // Kill it immediately.
                world.ThingInteraction.DamageMobj(skull, actor, actor, 10000);
                return;
            }

            skull.Target = actor.Target;

            SkullAttack(skull);
        }
Exemple #20
0
        private void BulletSlope(Mobj mo)
        {
            var hs = world.Hitscan;

            // See which target is to be aimed at.
            var angle = mo.Angle;

            currentBulletSlope = hs.AimLineAttack(mo, angle, Fixed.FromInt(1024));

            if (hs.LineTarget == null)
            {
                angle += new Angle(1 << 26);
                currentBulletSlope = hs.AimLineAttack(mo, angle, Fixed.FromInt(1024));
                if (hs.LineTarget == null)
                {
                    angle -= new Angle(2 << 26);
                    currentBulletSlope = hs.AimLineAttack(mo, angle, Fixed.FromInt(1024));
                }
            }
        }
Exemple #21
0
        public static Sector FromData(byte[] data, int offset, int number, FlatLookup flats)
        {
            var floorHeight     = BitConverter.ToInt16(data, offset);
            var ceilingHeight   = BitConverter.ToInt16(data, offset + 2);
            var floorFlatName   = DoomInterop.ToString(data, offset + 4, 8);
            var ceilingFlatName = DoomInterop.ToString(data, offset + 12, 8);
            var lightLevel      = BitConverter.ToInt16(data, offset + 20);
            var special         = BitConverter.ToInt16(data, offset + 22);
            var tag             = BitConverter.ToInt16(data, offset + 24);

            return(new Sector(
                       number,
                       Fixed.FromInt(floorHeight),
                       Fixed.FromInt(ceilingHeight),
                       flats.GetNumber(floorFlatName),
                       flats.GetNumber(ceilingFlatName),
                       lightLevel,
                       (SectorSpecial)special,
                       tag));
        }
Exemple #22
0
        public void SkelMissile(Mobj actor)
        {
            if (actor.Target == null)
            {
                return;
            }

            FaceTarget(actor);

            // Missile spawns higher.
            actor.Z += Fixed.FromInt(16);

            var missile = world.ThingAllocation.SpawnMissile(actor, actor.Target, MobjType.Tracer);

            // Back to normal.
            actor.Z -= Fixed.FromInt(16);

            missile.X     += missile.MomX;
            missile.Y     += missile.MomY;
            missile.Tracer = actor.Target;
        }
        /// <summary>
        /// Change the player's weapon sprite.
        /// </summary>
        public void SetPlayerSprite(Player player, PlayerSprite position, MobjState state)
        {
            var psp = player.PlayerSprites[(int)position];

            do
            {
                if (state == MobjState.Null)
                {
                    // Object removed itself.
                    psp.State = null;
                    break;
                }

                var stateDef = DoomInfo.States[(int)state];
                psp.State = stateDef;
                psp.Tics  = stateDef.Tics; // Could be 0.

                if (stateDef.Misc1 != 0)
                {
                    // Coordinate set.
                    psp.Sx = Fixed.FromInt(stateDef.Misc1);
                    psp.Sy = Fixed.FromInt(stateDef.Misc2);
                }

                // Call action routine.
                // Modified handling.
                if (stateDef.PlayerAction != null)
                {
                    stateDef.PlayerAction(world, player, psp);
                    if (psp.State == null)
                    {
                        break;
                    }
                }

                state = psp.State.Next;
            } while (psp.Tics == 0);
            // An initial state of 0 could cycle through.
        }
Exemple #24
0
        public static Seg FromData(byte[] data, int offset, Vertex[] vertices, LineDef[] lines)
        {
            var vertex1Number = BitConverter.ToInt16(data, offset);
            var vertex2Number = BitConverter.ToInt16(data, offset + 2);
            var angle         = BitConverter.ToInt16(data, offset + 4);
            var lineNumber    = BitConverter.ToInt16(data, offset + 6);
            var side          = BitConverter.ToInt16(data, offset + 8);
            var segOffset     = BitConverter.ToInt16(data, offset + 10);

            var lineDef   = lines[lineNumber];
            var frontSide = side == 0 ? lineDef.Side0 : lineDef.Side1;
            var backSide  = side == 0 ? lineDef.Side1 : lineDef.Side0;

            return(new Seg(
                       vertices[vertex1Number],
                       vertices[vertex2Number],
                       Fixed.FromInt(segOffset),
                       new Angle((uint)angle << 16),
                       frontSide,
                       lineDef,
                       frontSide.Sector,
                       (lineDef.Flags & LineFlags.TwoSided) != 0 ? backSide?.Sector : null));
        }
Exemple #25
0
        private bool CheckMeleeRange(Mobj actor)
        {
            if (actor.Target == null)
            {
                return(false);
            }

            var target = actor.Target;

            var dist = Geometry.AproxDistance(target.X - actor.X, target.Y - actor.Y);

            if (dist >= World.MELEERANGE - Fixed.FromInt(20) + target.Info.Radius)
            {
                return(false);
            }

            if (!world.VisibilityCheck.CheckSight(actor, actor.Target))
            {
                return(false);
            }

            return(true);
        }
        /// <summary>
        /// Source is the creature that caused the explosion at spot.
        /// </summary>
        public void RadiusAttack(Mobj spot, Mobj source, int damage)
        {
            var bm = world.Map.BlockMap;

            var dist = Fixed.FromInt(damage + GameConst.MaxThingRadius.Data);

            var blockY1 = bm.GetBlockY(spot.Y - dist);
            var blockY2 = bm.GetBlockY(spot.Y + dist);
            var blockX1 = bm.GetBlockX(spot.X - dist);
            var blockX2 = bm.GetBlockX(spot.X + dist);

            bombSpot   = spot;
            bombSource = source;
            bombDamage = damage;

            for (var by = blockY1; by <= blockY2; by++)
            {
                for (var bx = blockX1; bx <= blockX2; bx++)
                {
                    bm.IterateThings(bx, by, radiusAttackFunc);
                }
            }
        }
Exemple #27
0
        public void BFGSpray(Mobj bfgBall)
        {
            var hs     = world.Hitscan;
            var random = world.Random;

            // Offset angles from its attack angle.
            for (var i = 0; i < 40; i++)
            {
                var an = bfgBall.Angle - Angle.Ang90 / 2 + Angle.Ang90 / 40 * (uint)i;

                // bfgBall.Target is the originator (player) of the missile.
                hs.AimLineAttack(bfgBall.Target, an, Fixed.FromInt(16 * 64));

                if (hs.LineTarget == null)
                {
                    continue;
                }

                //* world.ThingAllocation.SpawnMobj(
                //     hs.LineTarget.X,
                //     hs.LineTarget.Y,
                //     hs.LineTarget.Z + (hs.LineTarget.Height >> 2),
                //     MobjType.Extrabfg);

                var damage = 0;
                for (var j = 0; j < 15; j++)
                {
                    damage += (random.Next() & 7) + 1;
                }

                world.ThingInteraction.DamageMobj(
                    hs.LineTarget,
                    bfgBall.Target,
                    bfgBall.Target,
                    damage);
            }
        }
Exemple #28
0
        public static Node FromData(byte[] data, int offset)
        {
            var x           = BitConverter.ToInt16(data, offset);
            var y           = BitConverter.ToInt16(data, offset + 2);
            var dx          = BitConverter.ToInt16(data, offset + 4);
            var dy          = BitConverter.ToInt16(data, offset + 6);
            var bbox0Top    = BitConverter.ToInt16(data, offset + 8);
            var bbox0Bottom = BitConverter.ToInt16(data, offset + 10);
            var bbox0Left   = BitConverter.ToInt16(data, offset + 12);
            var bbox0Right  = BitConverter.ToInt16(data, offset + 14);
            var bbox1Top    = BitConverter.ToInt16(data, offset + 16);
            var bbox1Bottom = BitConverter.ToInt16(data, offset + 18);
            var bbox1Left   = BitConverter.ToInt16(data, offset + 20);
            var bbox1Right  = BitConverter.ToInt16(data, offset + 22);
            var children0   = BitConverter.ToInt16(data, offset + 24);
            var children1   = BitConverter.ToInt16(data, offset + 26);

            return(new Node(
                       Fixed.FromInt(x), Fixed.FromInt(y),
                       Fixed.FromInt(dx), Fixed.FromInt(dy),
                       Fixed.FromInt(bbox0Top), Fixed.FromInt(bbox0Bottom), Fixed.FromInt(bbox0Left), Fixed.FromInt(bbox0Right),
                       Fixed.FromInt(bbox1Top), Fixed.FromInt(bbox1Bottom), Fixed.FromInt(bbox1Left), Fixed.FromInt(bbox1Right),
                       children0, children1));
        }
        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));
        }
Exemple #30
0
        /// <summary>
        /// Check for item pickup.
        /// </summary>
        public void TouchSpecialThing(Mobj special, Mobj toucher)
        {
            var delta = special.Z - toucher.Z;

            if (delta > toucher.Height || delta < Fixed.FromInt(-8))
            {
                // Out of reach.
                return;
            }

            var sound  = Sfx.ITEMUP;
            var player = toucher.Player;

            // Dead thing touching.
            // Can happen with a sliding player corpse.
            if (toucher.Health <= 0)
            {
                return;
            }

            // Identify by sprite.
            switch (special.Sprite)
            {
            // Armor.
            //* case Sprite.ARM1:
            //     if (!GiveArmor(player, DoomInfo.DeHackEdConst.GreenArmorClass))
            //     {
            //         return;
            //     }
            //     player.SendMessage(DoomInfo.Strings.GOTARMOR);
            //     break;

            // case Sprite.ARM2:
            //     if (!GiveArmor(player, DoomInfo.DeHackEdConst.BlueArmorClass))
            //     {
            //         return;
            //     }
            //     player.SendMessage(DoomInfo.Strings.GOTMEGA);
            //     break;

            // // Bonus items.
            // case Sprite.BON1:
            //     // Can go over 100%.
            //     player.Health++;
            //     if (player.Health > DoomInfo.DeHackEdConst.MaxHealth)
            //     {
            //         player.Health = DoomInfo.DeHackEdConst.MaxHealth;
            //     }
            //     player.Mobj.Health = player.Health;
            //     player.SendMessage(DoomInfo.Strings.GOTHTHBONUS);
            //     break;

            // case Sprite.BON2:
            //     // Can go over 100%.
            //     player.ArmorPoints++;
            //     if (player.ArmorPoints > DoomInfo.DeHackEdConst.MaxArmor)
            //     {
            //         player.ArmorPoints = DoomInfo.DeHackEdConst.MaxArmor;
            //     }
            //     if (player.ArmorType == 0)
            //     {
            //         player.ArmorType = DoomInfo.DeHackEdConst.GreenArmorClass;
            //     }
            //     player.SendMessage(DoomInfo.Strings.GOTARMBONUS);
            //     break;

            // case Sprite.SOUL:
            //     player.Health += DoomInfo.DeHackEdConst.SoulsphereHealth;
            //     if (player.Health > DoomInfo.DeHackEdConst.MaxSoulsphere)
            //     {
            //         player.Health = DoomInfo.DeHackEdConst.MaxSoulsphere;
            //     }
            //     player.Mobj.Health = player.Health;
            //     player.SendMessage(DoomInfo.Strings.GOTSUPER);
            //     sound = Sfx.GETPOW;
            //     break;

            // case Sprite.MEGA:
            //     if (world.Options.GameMode != GameMode.Commercial)
            //     {
            //         return;
            //     }

            //     player.Health = DoomInfo.DeHackEdConst.MegasphereHealth;
            //     player.Mobj.Health = player.Health;
            //     GiveArmor(player, DoomInfo.DeHackEdConst.BlueArmorClass);
            //     player.SendMessage(DoomInfo.Strings.GOTMSPHERE);
            //     sound = Sfx.GETPOW;
            //     break;

            // // Cards.
            // // Leave cards for everyone.
            // case Sprite.BKEY:
            //     if (!player.Cards[(int)CardType.BlueCard])
            //     {
            //         player.SendMessage(DoomInfo.Strings.GOTBLUECARD);
            //     }
            //     GiveCard(player, CardType.BlueCard);
            //     if (!world.Options.NetGame)
            //     {
            //         break;
            //     }
            //     return;

            case Sprite.CKYY:
                if (!player.Cards[(int)CardType.YellowCard])
                {
                    player.SendMessage(DoomInfo.Strings.GOTYELWCARD);
                }
                GiveCard(player, CardType.YellowCard);
                if (!world.Options.NetGame)
                {
                    break;
                }
                return;

            // case Sprite.RKEY:
            //     if (!player.Cards[(int)CardType.RedCard])
            //     {
            //         player.SendMessage(DoomInfo.Strings.GOTREDCARD);
            //     }
            //     GiveCard(player, CardType.RedCard);
            //     if (!world.Options.NetGame)
            //     {
            //         break;
            //     }
            //     return;

            // case Sprite.BSKU:
            //     if (!player.Cards[(int)CardType.BlueSkull])
            //     {
            //         player.SendMessage(DoomInfo.Strings.GOTBLUESKUL);
            //     }
            //     GiveCard(player, CardType.BlueSkull);
            //     if (!world.Options.NetGame)
            //     {
            //         break;
            //     }
            //     return;

            // case Sprite.YSKU:
            //     if (!player.Cards[(int)CardType.YellowSkull])
            //     {
            //         player.SendMessage(DoomInfo.Strings.GOTYELWSKUL);
            //     }
            //     GiveCard(player, CardType.YellowSkull);
            //     if (!world.Options.NetGame)
            //     {
            //         break;
            //     }
            //     return;

            // case Sprite.RSKU:
            //     if (!player.Cards[(int)CardType.RedSkull])
            //     {
            //         player.SendMessage(DoomInfo.Strings.GOTREDSKULL);
            //     }
            //     GiveCard(player, CardType.RedSkull);
            //     if (!world.Options.NetGame)
            //     {
            //         break;
            //     }
            //     return;

            // // Medikits, heals.
            // case Sprite.STIM:
            //     if (!GiveHealth(player, 10))
            //     {
            //         return;
            //     }
            //     player.SendMessage(DoomInfo.Strings.GOTSTIM);
            //     break;

            // case Sprite.MEDI:
            //     if (!GiveHealth(player, 25))
            //     {
            //         return;
            //     }
            //     if (player.Health < 25)
            //     {
            //         player.SendMessage(DoomInfo.Strings.GOTMEDINEED);
            //     }
            //     else
            //     {
            //         player.SendMessage(DoomInfo.Strings.GOTMEDIKIT);
            //     }
            //     break;


            // // Power ups.
            // case Sprite.PINV:
            //     if (!GivePower(player, PowerType.Invulnerability))
            //     {
            //         return;
            //     }
            //     player.SendMessage(DoomInfo.Strings.GOTINVUL);
            //     sound = Sfx.GETPOW;
            //     break;

            // case Sprite.PSTR:
            //     if (!GivePower(player, PowerType.Strength))
            //     {
            //         return;
            //     }
            //     player.SendMessage(DoomInfo.Strings.GOTBERSERK);
            //     if (player.ReadyWeapon != WeaponType.Fist)
            //     {
            //         player.PendingWeapon = WeaponType.Fist;
            //     }
            //     sound = Sfx.GETPOW;
            //     break;

            // case Sprite.PINS:
            //     if (!GivePower(player, PowerType.Invisibility))
            //     {
            //         return;
            //     }
            //     player.SendMessage(DoomInfo.Strings.GOTINVIS);
            //     sound = Sfx.GETPOW;
            //     break;

            // case Sprite.SUIT:
            //     if (!GivePower(player, PowerType.IronFeet))
            //     {
            //         return;
            //     }
            //     player.SendMessage(DoomInfo.Strings.GOTSUIT);
            //     sound = Sfx.GETPOW;
            //     break;

            // case Sprite.PMAP:
            //     if (!GivePower(player, PowerType.AllMap))
            //     {
            //         return;
            //     }
            //     player.SendMessage(DoomInfo.Strings.GOTMAP);
            //     sound = Sfx.GETPOW;
            //     break;

            // case Sprite.PVIS:
            //     if (!GivePower(player, PowerType.Infrared))
            //     {
            //         return;
            //     }
            //     player.SendMessage(DoomInfo.Strings.GOTVISOR);
            //     sound = Sfx.GETPOW;
            //     break;

            // // Ammo.
            // case Sprite.CLIP:
            //     if ((special.Flags & MobjFlags.Dropped) != 0)
            //     {
            //         if (!GiveAmmo(player, AmmoType.Clip, 0))
            //         {
            //             return;
            //         }
            //     }
            //     else
            //     {
            //         if (!GiveAmmo(player, AmmoType.Clip, 1))
            //         {
            //             return;
            //         }
            //     }
            //     player.SendMessage(DoomInfo.Strings.GOTCLIP);
            //     break;

            // case Sprite.AMMO:
            //     if (!GiveAmmo(player, AmmoType.Clip, 5))
            //     {
            //         return;
            //     }
            //     player.SendMessage(DoomInfo.Strings.GOTCLIPBOX);
            //     break;

            // case Sprite.ROCK:
            //     if (!GiveAmmo(player, AmmoType.Missile, 1))
            //     {
            //         return;
            //     }
            //     player.SendMessage(DoomInfo.Strings.GOTROCKET);
            //     break;

            // case Sprite.BROK:
            //     if (!GiveAmmo(player, AmmoType.Missile, 5))
            //     {
            //         return;
            //     }
            //     player.SendMessage(DoomInfo.Strings.GOTROCKBOX);
            //     break;

            // case Sprite.CELL:
            //     if (!GiveAmmo(player, AmmoType.Cell, 1))
            //     {
            //         return;
            //     }
            //     player.SendMessage(DoomInfo.Strings.GOTCELL);
            //     break;

            // case Sprite.CELP:
            //     if (!GiveAmmo(player, AmmoType.Cell, 5))
            //     {
            //         return;
            //     }
            //     player.SendMessage(DoomInfo.Strings.GOTCELLBOX);
            //     break;

            // case Sprite.SHEL:
            //     if (!GiveAmmo(player, AmmoType.Shell, 1))
            //     {
            //         return;
            //     }
            //     player.SendMessage(DoomInfo.Strings.GOTSHELLS);
            //     break;

            // case Sprite.SBOX:
            //     if (!GiveAmmo(player, AmmoType.Shell, 5))
            //     {
            //         return;
            //     }
            //     player.SendMessage(DoomInfo.Strings.GOTSHELLBOX);
            //     break;

            // case Sprite.BPAK:
            //     if (!player.Backpack)
            //     {
            //         for (var i = 0; i < (int)AmmoType.Count; i++)
            //         {
            //             player.MaxAmmo[i] *= 2;
            //         }
            //         player.Backpack = true;
            //     }
            //     for (var i = 0; i < (int)AmmoType.Count; i++)
            //     {
            //         GiveAmmo(player, (AmmoType)i, 1);
            //     }
            //     player.SendMessage(DoomInfo.Strings.GOTBACKPACK);
            //     break;

            // // Weapons.
            // case Sprite.BFUG:
            //     if (!GiveWeapon(player, WeaponType.Bfg, false))
            //     {
            //         return;
            //     }
            //     player.SendMessage(DoomInfo.Strings.GOTBFG9000);
            //     sound = Sfx.WPNUP;
            //     break;

            // case Sprite.MGUN:
            //     if (!GiveWeapon(player, WeaponType.Chaingun, (special.Flags & MobjFlags.Dropped) != 0))
            //     {
            //         return;
            //     }
            //     player.SendMessage(DoomInfo.Strings.GOTCHAINGUN);
            //     sound = Sfx.WPNUP;
            //     break;

            // case Sprite.CSAW:
            //     if (!GiveWeapon(player, WeaponType.Chainsaw, false))
            //     {
            //         return;
            //     }
            //     player.SendMessage(DoomInfo.Strings.GOTCHAINSAW);
            //     sound = Sfx.WPNUP;
            //     break;

            // case Sprite.LAUN:
            //     if (!GiveWeapon(player, WeaponType.Missile, false))
            //     {
            //         return;
            //     }
            //     player.SendMessage(DoomInfo.Strings.GOTLAUNCHER);
            //     sound = Sfx.WPNUP;
            //     break;

            // case Sprite.PLAS:
            //     if (!GiveWeapon(player, WeaponType.Plasma, false))
            //     {
            //         return;
            //     }
            //     player.SendMessage(DoomInfo.Strings.GOTPLASMA);
            //     sound = Sfx.WPNUP;
            //     break;

            // case Sprite.SHOT:
            //     if (!GiveWeapon(player, WeaponType.Shotgun, (special.Flags & MobjFlags.Dropped) != 0))
            //     {
            //         return;
            //     }
            //     player.SendMessage(DoomInfo.Strings.GOTSHOTGUN);
            //     sound = Sfx.WPNUP;
            //     break;

            // case Sprite.SGN2:
            //     if (!GiveWeapon(player, WeaponType.SuperShotgun, (special.Flags & MobjFlags.Dropped) != 0))
            //     {
            //         return;
            //     }
            //     player.SendMessage(DoomInfo.Strings.GOTSHOTGUN2);
            //     sound = Sfx.WPNUP;
            //     break;

            default:
                throw new Exception("Unknown gettable thing!");
            }

            if ((special.Flags & MobjFlags.CountItem) != 0)
            {
                player.ItemCount++;
            }

            world.ThingAllocation.RemoveMobj(special);

            player.BonusCount += bonusAdd;

            if (player == world.ConsolePlayer)
            {
                world.StartSound(player.Mobj, sound, SfxType.Misc);
            }
        }