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); }
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); }
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; } }
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(); } }
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); } }
/// <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); }
// // 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); }