note description: "[ p_setup.c Do all the WAD I/O, get map description, set up initial state and misc. LUTs. ]" license: "[ Copyright (C) 1993-1996 by id Software, Inc. Copyright (C) 2005-2014 Simon Howard Copyright (C) 2021 Ilgiz Mustafin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ]" class P_SETUP inherit DOOMDATA_H create make feature i_main: I_MAIN make (a_i_main: like i_main) local i: INTEGER_32 do i_main := a_i_main create deathmatchstarts.make_filled (create {MAPTHING_T}, 0, Max_deathmatch_starts - 1) create nodes.make_empty create subsectors.make_empty create segs.make_empty create blocklinks.make_empty create blockmaplump.make_empty create vertexes.make_empty create sectors.make_empty create sides.make_empty create lines.make_empty create playerstarts.make_filled (create {MAPTHING_T}, 0, {DOOMDEF_H}.maxplayers - 1) from i := 0 until i > playerstarts.upper loop playerstarts [i] := create {MAPTHING_T} i := i + 1 end end feature rejectmatrix: detachable ARRAY [NATURAL_8] Max_deathmatch_starts: INTEGER_32 = 10 deathmatchstarts: ARRAY [MAPTHING_T] deathmatch_p: INTEGER_32 assign set_deathmatch_p -- index in deathmatchstarts set_deathmatch_p (a_deathmatch_p: like deathmatch_p) do deathmatch_p := a_deathmatch_p end numnodes: INTEGER_32 nodes: ARRAY [NODE_T] subsectors: ARRAY [SUBSECTOR_T] numsegs: INTEGER_32 segs: ARRAY [SEG_T] numvertexes: INTEGER_32 vertexes: ARRAY [VERTEX_T] numsectors: INTEGER_32 sectors: ARRAY [SECTOR_T] numsides: INTEGER_32 sides: ARRAY [SIDE_T] numlines: INTEGER_32 lines: ARRAY [LINE_T] playerstarts: ARRAY [MAPTHING_T] feature -- Blockmap -- Created from axis aligned bounding box -- of the map, a rectangular array of -- blocks of size ... -- Used to speed up collision detection -- by spatial subdivision in 2D. bmapwidth: INTEGER_32 bmapheight: INTEGER_32 -- size in mapblocks blockmap: detachable INDEX_IN_ARRAY [INTEGER_16] -- int for larger maps blockmaplump: ARRAY [INTEGER_16] -- offsets in blockmap are from here bmaporgx: FIXED_T -- origin of block map bmaporgy: FIXED_T -- origin of block map blocklinks: ARRAY [detachable MOBJ_T] -- for thing chains feature p_init do i_main.P_switch.p_initswitchlist i_main.P_spec.p_initpicanims i_main.R_things.r_initsprites (i_main.Info.Sprnames) end p_setuplevel (episode, map, playermask, skill: INTEGER_32) local i: INTEGER_32 lumpname: STRING_8 lumpnum: INTEGER_32 reject_mp: MANAGED_POINTER do i_main.G_game.totalkills := 0 i_main.G_game.totalitems := 0 i_main.G_game.totalsecret := 0 i_main.G_game.wminfo.maxfrags := 0 i_main.G_game.wminfo.partime := 180 from i := 0 until i >= {DOOMDEF_H}.maxplayers loop i_main.G_game.Players [i].killcount := 0 i_main.G_game.Players [i].secretcount := 0 i_main.G_game.Players [i].itemcount := 0 i := i + 1 end i_main.G_game.Players [i_main.G_game.consoleplayer].viewz := create {FIXED_T}.from_integer (1) i_main.S_sound.s_start i_main.P_tick.p_initthinkers i_main.W_wad.w_reload if i_main.Doomstat_h.gamemode = {GAME_MODE_T}.commercial then if map < 10 then lumpname := "map0" + map.out else lumpname := "map" + map.out end else lumpname := "E" + episode.out + "M" + map.out end lumpnum := i_main.W_wad.w_getnumforname (lumpname) i_main.P_tick.leveltime := 0 p_loadblockmap (lumpnum + Ml_blockmap) p_loadvertexes (lumpnum + Ml_vertexes) p_loadsectors (lumpnum + Ml_sectors) p_loadsidedefs (lumpnum + Ml_sidedefs) p_loadlinedefs (lumpnum + Ml_linedefs) p_loadsubsectors (lumpnum + Ml_ssectors) p_loadnodes (lumpnum + Ml_nodes) p_loadsegs (lumpnum + Ml_segs) reject_mp := i_main.W_wad.w_cachelumpnum (lumpnum + Ml_reject) rejectmatrix := reject_mp.read_array (0, reject_mp.count) check attached rejectmatrix as rm then rm.rebase (0) end p_grouplines i_main.G_game.bodyqueslot := 0 deathmatch_p := deathmatchstarts.lower p_loadthings (lumpnum + Ml_things) if i_main.G_game.deathmatch then from i := 0 until i >= {DOOMDEF_H}.maxplayers loop i_main.G_game.Players [i].mo := Void i_main.G_game.g_deathmatchspawnplayer (i) i := i + 1 end end i_main.P_mobj.iquehead := 0 i_main.P_mobj.iquetail := 0 i_main.P_spec.p_spawnspecials if i_main.Doomstat_h.precache then i_main.R_data.r_precachelevel end end p_loadblockmap (lump: INTEGER_32) do blockmaplump := {WAD_READER}.read_array_integer_16 (i_main.W_wad.w_cachelumpnum (lump)) create blockmap.make (4, blockmaplump) bmaporgx := create {FIXED_T}.from_integer (blockmaplump [0].to_integer_32 |<< {M_FIXED}.fracbits) bmaporgy := create {FIXED_T}.from_integer (blockmaplump [1].to_integer_32 |<< {M_FIXED}.fracbits) bmapwidth := blockmaplump [2].to_integer_32 bmapheight := blockmaplump [3].to_integer_32 create blocklinks.make_filled (Void, 0, bmapwidth * bmapheight) end p_loadvertexes (lump: INTEGER_32) local data: MANAGED_POINTER i: INTEGER_32 do numvertexes := i_main.W_wad.w_lumplength (lump) // {VERTEX_T}.structure_size create vertexes.make_filled (create {VERTEX_T}.default_create, 0, numvertexes - 1) data := i_main.W_wad.w_cachelumpnum (lump) from i := 0 until i >= vertexes.upper loop vertexes [i] := create {VERTEX_T}.from_pointer (data, i * {VERTEX_T}.structure_size) i := i + 1 end end p_loadsectors (lump: INTEGER_32) local data: MANAGED_POINTER i: INTEGER_32 do numsectors := i_main.W_wad.w_lumplength (lump) // {SECTOR_T}.structure_size create sectors.make_filled (create {SECTOR_T}.make, 0, numsectors - 1) data := i_main.W_wad.w_cachelumpnum (lump) from i := 0 until i > sectors.upper loop sectors [i] := create {SECTOR_T}.from_pointer (data, i * {SECTOR_T}.structure_size, i_main) i := i + 1 end end p_loadsidedefs (lump: INTEGER_32) local data: MANAGED_POINTER i: INTEGER_32 do numsides := i_main.W_wad.w_lumplength (lump) // {SIDE_T}.structure_size create sides.make_filled (create {SIDE_T}, 0, numsides - 1) data := i_main.W_wad.w_cachelumpnum (lump) from i := 0 until i >= numsides loop sides [i] := create {SIDE_T}.from_pointer (data, i * {SIDE_T}.structure_size, i_main) i := i + 1 end end p_loadlinedefs (lump: INTEGER_32) -- Also counts secret lines for intermissions. local data: MANAGED_POINTER i: INTEGER_32 do numlines := i_main.W_wad.w_lumplength (lump) // {LINE_T}.structure_size create lines.make_filled (create {LINE_T}.make, 0, numlines - 1) data := i_main.W_wad.w_cachelumpnum (lump) from i := 0 until i >= numlines loop lines [i] := create {LINE_T}.from_pointer (data, i * {LINE_T}.structure_size, i_main) i := i + 1 end end p_loadsubsectors (lump: INTEGER_32) local data: MANAGED_POINTER i: INTEGER_32 numsubsectors: INTEGER_32 do numsubsectors := i_main.W_wad.w_lumplength (lump) // {SUBSECTOR_T}.structure_size create subsectors.make_filled (create {SUBSECTOR_T}, 0, numsubsectors - 1) data := i_main.W_wad.w_cachelumpnum (lump) from i := 0 until i >= numsubsectors loop subsectors [i] := create {SUBSECTOR_T}.from_pointer (data, i * {SUBSECTOR_T}.structure_size) i := i + 1 end end p_loadnodes (lump: INTEGER_32) local data: MANAGED_POINTER i: INTEGER_32 do numnodes := i_main.W_wad.w_lumplength (lump) // {NODE_T}.structure_size create nodes.make_filled (create {NODE_T}.make, 0, numnodes - 1) data := i_main.W_wad.w_cachelumpnum (lump) from i := 0 until i >= numnodes loop nodes [i] := create {NODE_T}.from_pointer (data, i * {NODE_T}.structure_size) i := i + 1 end end p_loadsegs (lump: INTEGER_32) local data: MANAGED_POINTER i: INTEGER_32 do numsegs := i_main.W_wad.w_lumplength (lump) // {SEG_T}.structure_size create segs.make_filled (create {SEG_T}.make, 0, numsegs - 1) data := i_main.W_wad.w_cachelumpnum (lump) from i := 0 until i >= numsegs loop segs [i] := create {SEG_T}.from_pointer (data, i * {SEG_T}.structure_size, i_main) i := i + 1 end end p_grouplines -- Builds sector line lists and subsector sector numbers. -- Finds block bounding boxes for sectors. local linebuffer: ARRAY [LINE_T] i, j: INTEGER_32 total: INTEGER_32 seg: SEG_T bbox: ARRAY [FIXED_T] block: INTEGER_32 do create bbox.make_filled (create {FIXED_T}.from_integer (0), 0, 3) from i := subsectors.lower until i > subsectors.upper loop seg := segs [subsectors [i].firstline.to_integer_32] subsectors [i].sector := seg.sidedef.sector i := i + 1 end total := 0 from i := 0 until i >= numlines loop total := total + 1 check attached lines [i].frontsector as frontsector then frontsector.linecount := frontsector.linecount + 1 end if attached lines [i].backsector as bs and then bs /= lines [i].frontsector then bs.linecount := bs.linecount + 1 end i := i + 1 end create linebuffer.make_filled (create {LINE_T}.make, 0, total - 1) from i := 0 until i >= numsectors loop {M_BBOX}.m_clearbox (bbox) from j := 0 until j >= numlines loop if lines [j].frontsector = sectors [i] or lines [j].backsector = sectors [i] then sectors [i].lines.extend (lines [j]) {M_BBOX}.m_addtobox (bbox, lines [j].v1.x, lines [j].v1.y) {M_BBOX}.m_addtobox (bbox, lines [j].v2.x, lines [j].v2.y) end j := j + 1 end check sectors [i].lines.count = sectors [i].linecount end sectors [i].soundorg.x := (bbox [{M_BBOX}.boxright] + bbox [{M_BBOX}.boxleft]) // create {FIXED_T}.from_integer (2) sectors [i].soundorg.y := (bbox [{M_BBOX}.boxtop] + bbox [{M_BBOX}.boxbottom]) // create {FIXED_T}.from_integer (2) block := ((bbox [{M_BBOX}.boxtop] - bmaporgy + create {FIXED_T}.from_integer ({P_LOCAL}.maxradius)) |>> {P_LOCAL}.mapblockshift).to_integer_32 block := if block >= bmapheight then bmapheight - 1 else block end sectors [i].blockbox [{M_BBOX}.boxtop] := block block := ((bbox [{M_BBOX}.boxbottom] - bmaporgy - create {FIXED_T}.from_integer ({P_LOCAL}.maxradius)) |>> {P_LOCAL}.mapblockshift).to_integer_32 block := if block < 0 then 0 else block end sectors [i].blockbox [{M_BBOX}.boxbottom] := block block := ((bbox [{M_BBOX}.boxright] - bmaporgx + create {FIXED_T}.from_integer ({P_LOCAL}.maxradius)) |>> {P_LOCAL}.mapblockshift).to_integer_32 block := if block >= bmapwidth then bmapwidth - 1 else block end sectors [i].blockbox [{M_BBOX}.boxright] := block block := ((bbox [{M_BBOX}.boxleft] - bmaporgx - create {FIXED_T}.from_integer ({P_LOCAL}.maxradius)) |>> {P_LOCAL}.mapblockshift).to_integer_32 block := if block < 0 then 0 else block end sectors [i].blockbox [{M_BBOX}.boxleft] := block i := i + 1 end end feature -- P_LoadThings Commercial_monsters: ARRAY [INTEGER_32] once Result := <<68, 64, 88, 89, 69, 67, 71, 65, 66, 84>> ensure instance_free: class end p_loadthings (lump: INTEGER_32) local data: MANAGED_POINTER i: INTEGER_32 mt: MAPTHING_T numthings: INTEGER_32 spawn: BOOLEAN do data := i_main.W_wad.w_cachelumpnum (lump) numthings := i_main.W_wad.w_lumplength (lump) // {MAPTHING_T}.structure_size from i := 0 spawn := True until not spawn or i >= numthings loop spawn := True create mt.from_pointer (data, i * {MAPTHING_T}.structure_size) if i_main.Doomstat_h.gamemode /= {GAME_MODE_T}.commercial then if Commercial_monsters.has (mt.type.to_integer_32) then spawn := False end end if spawn then i_main.P_mobj.p_spawnmapthing (mt) end i := i + 1 end end invariant playerstarts.lower = 0 playerstarts.count = {DOOMDEF_H}.maxplayers deathmatchstarts.lower = 0 and deathmatchstarts.count = Max_deathmatch_starts end -- class P_SETUP
Generated by ISE EiffelStudio