Пример #1
0
        public static MapThing[] FromWad(Wad wad, int lump)
        {
            var length = wad.GetLumpSize(lump);

            if (length % DataSize != 0)
            {
                throw new Exception();
            }

            var data   = wad.ReadLump(lump);
            var count  = length / DataSize;
            var things = new MapThing[count];

            for (var i = 0; i < count; i++)
            {
                var offset = DataSize * i;
                things[i] = FromData(data, offset);
            }

            return(things);
        }
Пример #2
0
        public Map(Wad wad, TextureLookup textures, FlatLookup flats, World world)
        {
            this.textures = textures;
            this.flats    = flats;
            this.world    = world;

            var options = world.Options;

            string name;

            if (wad.Names.Contains("doom") || wad.Names.Contains("doom1"))
            {
                name = "E" + options.Episode + "M" + options.Map;
            }
            else
            {
                name = "MAP" + options.Map.ToString("00");
            }

            var map = wad.GetLumpNumber(name);

            vertices   = Vertex.FromWad(wad, map + 4);
            sectors    = Sector.FromWad(wad, map + 8, flats);
            sides      = SideDef.FromWad(wad, map + 3, textures, sectors);
            lines      = LineDef.FromWad(wad, map + 2, vertices, sides);
            segs       = Seg.FromWad(wad, map + 5, vertices, lines);
            subsectors = Subsector.FromWad(wad, map + 6, segs);
            nodes      = Node.FromWad(wad, map + 7, subsectors);
            things     = MapThing.FromWad(wad, map + 1);
            blockMap   = BlockMap.FromWad(wad, map + 10, lines);
            reject     = Reject.FromWad(wad, map + 9, sectors);

            GroupLines();

            skyTexture = GetSkyTextureByMapName(name);
        }
Пример #3
0
        public void SpawnMapThing(MapThing mt)
        {
            // Count deathmatch start positions.
            if (mt.Type == 11)
            {
                if (deathmatchStarts.Count < 10)
                {
                    deathmatchStarts.Add(mt);
                }

                return;
            }

            // Check for players specially.
            if (mt.Type <= 4)
            {
                var playerNumber = mt.Type - 1;

                // This check is neccesary in Plutonia MAP12,
                // which contains an unknown thing with type 0.
                if (playerNumber < 0)
                {
                    return;
                }

                // Save spots for respawning in network games.
                playerStarts[playerNumber] = mt;

                if (world.Options.Deathmatch == 0)
                {
                    SpawnPlayer(mt);
                }

                return;
            }

            if (mt.Type == 11 || mt.Type <= 4)
            {
                return;
            }

            // Check for apropriate skill level.
            if (!world.Options.NetGame && ((int)mt.Flags & 16) != 0)
            {
                return;
            }

            int bit;

            if (world.Options.Skill == GameSkill.Baby)
            {
                bit = 1;
            }
            else if (world.Options.Skill == GameSkill.Nightmare)
            {
                bit = 4;
            }
            else
            {
                bit = 1 << ((int)world.Options.Skill - 1);
            }

            if (((int)mt.Flags & bit) == 0)
            {
                return;
            }

            // Find which type to spawn.
            int i;

            for (i = 0; i < DoomInfo.MobjInfos.Length; i++)
            {
                if (mt.Type == DoomInfo.MobjInfos[i].DoomEdNum)
                {
                    break;
                }
            }

            if (i == DoomInfo.MobjInfos.Length)
            {
                throw new Exception("P_SpawnMapThing: Unknown type!");
            }

            // Don't spawn keycards and players in deathmatch.
            if (world.Options.Deathmatch != 0 &&
                (DoomInfo.MobjInfos[i].Flags & MobjFlags.NotDeathmatch) != 0)
            {
                return;
            }

            // Don't spawn any monsters if -nomonsters.
            if (world.Options.NoMonsters && (i == (int)MobjType.Skull ||
                                             (DoomInfo.MobjInfos[i].Flags & MobjFlags.CountKill) != 0))
            {
                return;
            }

            // Spawn it.
            Fixed x = mt.X;
            Fixed y = mt.Y;
            Fixed z;

            if ((DoomInfo.MobjInfos[i].Flags & MobjFlags.SpawnCeiling) != 0)
            {
                z = Mobj.OnCeilingZ;
            }
            else
            {
                z = Mobj.OnFloorZ;
            }

            var mobj = SpawnMobj(x, y, z, (MobjType)i);

            mobj.SpawnPoint = mt;

            if (mobj.Tics > 0)
            {
                mobj.Tics = 1 + (world.Random.Next() % mobj.Tics);
            }

            if ((mobj.Flags & MobjFlags.CountKill) != 0)
            {
                world.totalKills++;
            }

            if ((mobj.Flags & MobjFlags.CountItem) != 0)
            {
                world.totalItems++;
            }

            mobj.Angle = mt.Angle;

            if ((mt.Flags & ThingFlags.Ambush) != 0)
            {
                mobj.Flags |= MobjFlags.Ambush;
            }
        }
Пример #4
0
        public void SpawnPlayer(MapThing mt)
        {
            var playerNumber = mt.Type - 1;

            // Not playing?
            if (!world.Players[playerNumber].InGame)
            {
                return;
            }

            var player = world.Players[playerNumber];

            if (player.PlayerState == PlayerState.Reborn)
            {
                world.Players[playerNumber].Reborn();
            }

            var x    = mt.X;
            var y    = mt.Y;
            var z    = Mobj.OnFloorZ;
            var mobj = SpawnMobj(x, y, z, MobjType.Player);

            // Set color translations for player sprites.
            if (playerNumber >= 1)
            {
                mobj.Flags |= (MobjFlags)((mt.Type - 1) << (int)MobjFlags.TransShift);
            }

            mobj.Angle  = mt.Angle;
            mobj.Player = player;
            mobj.Health = player.Health;

            player.Mobj          = mobj;
            player.PlayerState   = PlayerState.Live;
            player.Refire        = 0;
            player.Message       = null;
            player.DamageCount   = 0;
            player.BonusCount    = 0;
            player.ExtraLight    = 0;
            player.FixedColorMap = 0;
            player.ViewHeight    = Player.VIEWHEIGHT;

            // Setup gun psprite.
            world.PlayerBehavior.SetupPsprites(player);

            // Give all cards in death match mode.
            if (world.Options.Deathmatch != 0)
            {
                for (var i = 0; i < (int)CardType.Count; i++)
                {
                    player.Cards[i] = true;
                }
            }

            if (mt.Type - 1 == world.Options.ConsolePlayer)
            {
                // Wake up the status bar.
                world.StatusBar.Reset();

                // Wake up the heads up text.
                // HU_Start();
            }
        }
Пример #5
0
        public Map(Wad wad, ITextureLookup textures, IFlatLookup flats, TextureAnimation animation, World world)
        {
            try
            {
                this.textures  = textures;
                this.flats     = flats;
                this.animation = animation;
                this.world     = world;

                var options = world.Options;

                string name;
                if (wad.GameMode == GameMode.Commercial)
                {
                    name = "MAP" + options.Map.ToString("00");
                }
                else
                {
                    name = "E" + options.Episode + "M" + options.Map;
                }

                Console.Write("Load map '" + name + "': ");

                var map = wad.GetLumpNumber(name);

                if (map == -1)
                {
                    throw new Exception("Map '" + name + "' was not found!");
                }

                vertices   = Vertex.FromWad(wad, map + 4);
                sectors    = Sector.FromWad(wad, map + 8, flats);
                sides      = SideDef.FromWad(wad, map + 3, textures, sectors);
                lines      = LineDef.FromWad(wad, map + 2, vertices, sides);
                segs       = Seg.FromWad(wad, map + 5, vertices, lines);
                subsectors = Subsector.FromWad(wad, map + 6, segs);
                nodes      = Node.FromWad(wad, map + 7, subsectors);
                things     = MapThing.FromWad(wad, map + 1);
                blockMap   = BlockMap.FromWad(wad, map + 10, lines);
                reject     = Reject.FromWad(wad, map + 9, sectors);

                GroupLines();

                skyTexture = GetSkyTextureByMapName(name);

                if (options.GameMode == GameMode.Commercial)
                {
                    switch (options.MissionPack)
                    {
                    case MissionPack.Plutonia:
                        title = DoomInfo.MapTitles.Plutonia[options.Map - 1];
                        break;

                    case MissionPack.Tnt:
                        title = DoomInfo.MapTitles.Tnt[options.Map - 1];
                        break;

                    default:
                        title = DoomInfo.MapTitles.Doom2[options.Map - 1];
                        break;
                    }
                }
                else
                {
                    title = DoomInfo.MapTitles.Doom[options.Episode - 1][options.Map - 1];
                }

                Console.WriteLine("OK");
            }
            catch (Exception e)
            {
                Console.WriteLine("Failed");
                ExceptionDispatchInfo.Throw(e);
            }
        }
Пример #6
0
        /// <summary>
        /// Returns false if the player cannot be respawned at the given
        /// mapthing spot because something is occupying it.
        /// </summary>
        public bool CheckSpot(int playernum, MapThing mthing)
        {
            var players = world.Options.Players;

            if (players[playernum].Mobj == null)
            {
                // First spawn of level, before corpses.
                for (var i = 0; i < playernum; i++)
                {
                    if (players[i].Mobj.X == mthing.X && players[i].Mobj.Y == mthing.Y)
                    {
                        return(false);
                    }
                }
                return(true);
            }

            var x = mthing.X;
            var y = mthing.Y;

            if (!world.ThingMovement.CheckPosition(players[playernum].Mobj, x, y))
            {
                return(false);
            }

            // Flush an old corpse if needed.
            if (bodyQueSlot >= bodyQueSize)
            {
                RemoveMobj(bodyQue[bodyQueSlot % bodyQueSize]);
            }
            bodyQue[bodyQueSlot % bodyQueSize] = players[playernum].Mobj;
            bodyQueSlot++;

            // Spawn a teleport fog.
            var subsector = Geometry.PointInSubsector(x, y, world.Map);

            var angle = (Angle.Ang45.Data >> Trig.AngleToFineShift) *
                        ((int)Math.Round(mthing.Angle.ToDegree()) / 45);

            //
            // The code below to reproduce respawn fog bug in deathmath
            // is based on Chocolate Doom's implementation.
            //

            Fixed xa;
            Fixed ya;

            switch (angle)
            {
            case 4096:               // -4096:
                xa = Trig.Tan(2048); // finecosine[-4096]
                ya = Trig.Tan(0);    // finesine[-4096]
                break;

            case 5120:               // -3072:
                xa = Trig.Tan(3072); // finecosine[-3072]
                ya = Trig.Tan(1024); // finesine[-3072]
                break;

            case 6144:               // -2048:
                xa = Trig.Sin(0);    // finecosine[-2048]
                ya = Trig.Tan(2048); // finesine[-2048]
                break;

            case 7168:               // -1024:
                xa = Trig.Sin(1024); // finecosine[-1024]
                ya = Trig.Tan(3072); // finesine[-1024]
                break;

            case 0:
            case 1024:
            case 2048:
            case 3072:
                xa = Trig.Cos((int)angle);
                ya = Trig.Sin((int)angle);
                break;

            default:
                throw new Exception("Unexpected angle: " + angle);
            }

            var mo = SpawnMobj(
                x + 20 * xa, y + 20 * ya,
                subsector.Sector.FloorHeight,
                MobjType.Tfog);

            if (!world.FirstTicIsNotYetDone)
            {
                // Don't start sound on first frame.
                world.StartSound(mo, Sfx.TELEPT, SfxType.Misc);
            }

            return(true);
        }
Пример #7
0
        //
        // G_CheckSpot
        // Returns false if the player cannot be respawned
        // at the given mapthing_t spot
        // because something is occupying it
        //
        public bool G_CheckSpot(int playernum, MapThing mthing)
        {
            if (Players[playernum].Mobj == null)
            {
                // first spawn of level, before corpses
                for (var i = 0; i < playernum; i++)
                {
                    if (Players[i].Mobj.X == mthing.X && Players[i].Mobj.Y == mthing.Y)
                    {
                        return(false);
                    }
                }
                return(true);
            }

            var x = mthing.X;
            var y = mthing.Y;

            if (!thingMovement.CheckPosition(Players[playernum].Mobj, x, y))
            {
                return(false);
            }

            // flush an old corpse if needed
            if (bodyqueslot >= BODYQUESIZE)
            {
                thingAllocation.RemoveMobj(bodyque[bodyqueslot % BODYQUESIZE]);
            }
            bodyque[bodyqueslot % BODYQUESIZE] = Players[playernum].Mobj;
            bodyqueslot++;

            // spawn a teleport fog
            var ss = Geometry.PointInSubsector(x, y, map);

            var an = (Angle.Ang45.Data >> Trig.AngleToFineShift) * ((int)Math.Round(mthing.Angle.ToDegree()) / 45);

            Fixed xa;
            Fixed ya;

            switch (an)
            {
            case 4096:               // -4096:
                xa = Trig.Tan(2048); // finecosine[-4096]
                ya = Trig.Tan(0);    // finesine[-4096]
                break;

            case 5120:               // -3072:
                xa = Trig.Tan(3072); // finecosine[-3072]
                ya = Trig.Tan(1024); // finesine[-3072]
                break;

            case 6144:               // -2048:
                xa = Trig.Sin(0);    // finecosine[-2048]
                ya = Trig.Tan(2048); // finesine[-2048]
                break;

            case 7168:               // -1024:
                xa = Trig.Sin(1024); // finecosine[-1024]
                ya = Trig.Tan(3072); // finesine[-1024]
                break;

            case 0:
            case 1024:
            case 2048:
            case 3072:
                xa = Trig.Cos((int)an);
                ya = Trig.Sin((int)an);
                break;

            default:
                throw new Exception("G_CheckSpot: unexpected angle " + an);
            }

            var mo = thingAllocation.SpawnMobj(
                x + 20 * xa, y + 20 * ya,
                ss.Sector.FloorHeight,
                MobjType.Tfog);

            if (Players[Options.ConsolePlayer].ViewZ != new Fixed(1))
            {
                // don't start sound on first frame
                StartSound(mo, Sfx.TELEPT);
            }

            return(true);
        }