1256 lines
39 KiB
C
1256 lines
39 KiB
C
|
/* Emacs style mode select -*- C++ -*-
|
||
|
*-----------------------------------------------------------------------------
|
||
|
*
|
||
|
*
|
||
|
* PrBoom a Doom port merged with LxDoom and LSDLDoom
|
||
|
* based on BOOM, a modified and improved DOOM engine
|
||
|
* Copyright (C) 1999 by
|
||
|
* id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
|
||
|
* Copyright (C) 1999-2000 by
|
||
|
* Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
|
||
|
*
|
||
|
* 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., 59 Temple Place - Suite 330, Boston, MA
|
||
|
* 02111-1307, USA.
|
||
|
*
|
||
|
* DESCRIPTION:
|
||
|
* Do all the WAD I/O, get map description,
|
||
|
* set up initial state and misc. LUTs.
|
||
|
*
|
||
|
*-----------------------------------------------------------------------------*/
|
||
|
|
||
|
#include <math.h>
|
||
|
|
||
|
#include "doomstat.h"
|
||
|
#include "m_bbox.h"
|
||
|
#include "m_argv.h"
|
||
|
#include "g_game.h"
|
||
|
#include "w_wad.h"
|
||
|
#include "r_main.h"
|
||
|
#include "r_things.h"
|
||
|
#include "p_maputl.h"
|
||
|
#include "p_map.h"
|
||
|
#include "p_setup.h"
|
||
|
#include "p_spec.h"
|
||
|
#include "p_tick.h"
|
||
|
#include "p_enemy.h"
|
||
|
#include "s_sound.h"
|
||
|
#include "i_system.h"
|
||
|
#include "m_swap.h"
|
||
|
|
||
|
#include "rockmacros.h"
|
||
|
//
|
||
|
// MAP related Lookup tables.
|
||
|
// Store VERTEXES, LINEDEFS, SIDEDEFS, etc.
|
||
|
//
|
||
|
|
||
|
int numvertexes;
|
||
|
vertex_t *vertexes;
|
||
|
|
||
|
int numsegs;
|
||
|
seg_t *segs;
|
||
|
|
||
|
int numsectors;
|
||
|
sector_t *sectors;
|
||
|
|
||
|
int numsubsectors;
|
||
|
subsector_t *subsectors;
|
||
|
|
||
|
int numnodes;
|
||
|
node_t *nodes;
|
||
|
|
||
|
int numlines;
|
||
|
line_t *lines;
|
||
|
|
||
|
int numsides;
|
||
|
side_t *sides;
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
// figgi 08/21/00 -- constants and globals for glBsp support
|
||
|
#define gNd2 0x32644E67 // figgi -- suppport for new GL_VERT format v2.0
|
||
|
#define GL_VERT_OFFSET 4
|
||
|
|
||
|
int firstglvertex = 0;
|
||
|
boolean usingGLNodes = false;
|
||
|
boolean forceOldBsp = false;
|
||
|
|
||
|
enum
|
||
|
{
|
||
|
ML_GL_LABEL=0, // A separator name, GL_ExMx or GL_MAPxx
|
||
|
ML_GL_VERTS, // Extra Vertices
|
||
|
ML_GL_SEGS, // Segs, from linedefs & minisegs
|
||
|
ML_GL_SSECT, // SubSectors, list of segs
|
||
|
ML_GL_NODES // GL BSP nodes
|
||
|
};
|
||
|
////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
|
||
|
// 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.
|
||
|
//
|
||
|
// Blockmap size.
|
||
|
|
||
|
int bmapwidth, bmapheight; // size in mapblocks
|
||
|
|
||
|
// killough 3/1/98: remove blockmap limit internally:
|
||
|
long *blockmap; // was short -- killough
|
||
|
|
||
|
// offsets in blockmap are from here
|
||
|
long *blockmaplump; // was short -- killough
|
||
|
|
||
|
fixed_t bmaporgx, bmaporgy; // origin of block map
|
||
|
|
||
|
mobj_t **blocklinks; // for thing chains
|
||
|
|
||
|
//
|
||
|
// REJECT
|
||
|
// For fast sight rejection.
|
||
|
// Speeds up enemy AI by skipping detailed
|
||
|
// LineOf Sight calculation.
|
||
|
// Without the special effect, this could
|
||
|
// be used as a PVS lookup as well.
|
||
|
//
|
||
|
|
||
|
static int rejectlump = -1;// cph - store reject lump num if cached
|
||
|
const byte *rejectmatrix; // cph - const*
|
||
|
|
||
|
// Maintain single and multi player starting spots.
|
||
|
|
||
|
// 1/11/98 killough: Remove limit on deathmatch starts
|
||
|
mapthing_t *deathmatchstarts; // killough
|
||
|
size_t num_deathmatchstarts; // killough
|
||
|
|
||
|
mapthing_t *deathmatch_p;
|
||
|
mapthing_t playerstarts[MAXPLAYERS];
|
||
|
|
||
|
//
|
||
|
// P_LoadVertexes
|
||
|
//
|
||
|
// killough 5/3/98: reformatted, cleaned up
|
||
|
//
|
||
|
static void P_LoadVertexes (int lump)
|
||
|
{
|
||
|
const byte *data; // cph - const
|
||
|
int i;
|
||
|
|
||
|
// Determine number of lumps:
|
||
|
// total lump length / vertex record length.
|
||
|
numvertexes = W_LumpLength(lump) / sizeof(mapvertex_t);
|
||
|
|
||
|
// Allocate zone memory for buffer.
|
||
|
vertexes = Z_Malloc(numvertexes*sizeof(vertex_t),PU_LEVEL,0);
|
||
|
|
||
|
// Load data into cache.
|
||
|
data = W_CacheLumpNum(lump); // cph - wad handling updated
|
||
|
|
||
|
// Copy and convert vertex coordinates,
|
||
|
// internal representation as fixed.
|
||
|
for (i=0; i<numvertexes; i++)
|
||
|
{
|
||
|
vertexes[i].x = SHORT(((mapvertex_t *) data)[i].x)<<FRACBITS;
|
||
|
vertexes[i].y = SHORT(((mapvertex_t *) data)[i].y)<<FRACBITS;
|
||
|
}
|
||
|
|
||
|
// Free buffer memory.
|
||
|
W_UnlockLumpNum(lump);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// P_LoadSegs
|
||
|
//
|
||
|
// killough 5/3/98: reformatted, cleaned up
|
||
|
|
||
|
static void P_LoadSegs (int lump)
|
||
|
{
|
||
|
int i;
|
||
|
const byte *data; // cph - const
|
||
|
|
||
|
numsegs = W_LumpLength(lump) / sizeof(mapseg_t);
|
||
|
segs = Z_Calloc(numsegs,sizeof(seg_t),PU_LEVEL,0);
|
||
|
data = W_CacheLumpNum(lump); // cph - wad lump handling updated
|
||
|
|
||
|
for (i=0; i<numsegs; i++)
|
||
|
{
|
||
|
seg_t *li = segs+i;
|
||
|
mapseg_t *ml = (mapseg_t *) data + i;
|
||
|
|
||
|
int side, linedef;
|
||
|
line_t *ldef;
|
||
|
|
||
|
li->v1 = &vertexes[SHORT(ml->v1)];
|
||
|
li->v2 = &vertexes[SHORT(ml->v2)];
|
||
|
|
||
|
li->miniseg = false; // figgi -- there are no minisegs in classic BSP nodes
|
||
|
|
||
|
li->angle = (SHORT(ml->angle))<<16;
|
||
|
li->offset =(SHORT(ml->offset))<<16;
|
||
|
linedef = SHORT(ml->linedef);
|
||
|
ldef = &lines[linedef];
|
||
|
li->linedef = ldef;
|
||
|
side = SHORT(ml->side);
|
||
|
li->sidedef = &sides[ldef->sidenum[side]];
|
||
|
li->frontsector = sides[ldef->sidenum[side]].sector;
|
||
|
|
||
|
// killough 5/3/98: ignore 2s flag if second sidedef missing:
|
||
|
if (ldef->flags & ML_TWOSIDED && ldef->sidenum[side^1]!=-1)
|
||
|
li->backsector = sides[ldef->sidenum[side^1]].sector;
|
||
|
else
|
||
|
li->backsector = 0;
|
||
|
}
|
||
|
|
||
|
W_UnlockLumpNum(lump); // cph - release the data
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// P_LoadSubsectors
|
||
|
//
|
||
|
// killough 5/3/98: reformatted, cleaned up
|
||
|
|
||
|
static void P_LoadSubsectors (int lump)
|
||
|
{
|
||
|
const byte *data; // cph - const*
|
||
|
int i;
|
||
|
|
||
|
numsubsectors = W_LumpLength (lump) / sizeof(mapsubsector_t);
|
||
|
subsectors = Z_Calloc(numsubsectors,sizeof(subsector_t),PU_LEVEL,0);
|
||
|
data = W_CacheLumpNum(lump); // cph - wad lump handling updated
|
||
|
|
||
|
for (i=0; i<numsubsectors; i++)
|
||
|
{
|
||
|
subsectors[i].numlines = (unsigned short)SHORT(((mapsubsector_t *) data)[i].numsegs );
|
||
|
subsectors[i].firstline = (unsigned short)SHORT(((mapsubsector_t *) data)[i].firstseg);
|
||
|
}
|
||
|
|
||
|
W_UnlockLumpNum(lump); // cph - release the data
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// P_LoadSectors
|
||
|
//
|
||
|
// killough 5/3/98: reformatted, cleaned up
|
||
|
|
||
|
static void P_LoadSectors (int lump)
|
||
|
{
|
||
|
const byte *data; // cph - const*
|
||
|
int i;
|
||
|
|
||
|
numsectors = W_LumpLength (lump) / sizeof(mapsector_t);
|
||
|
sectors = Z_Calloc (numsectors,sizeof(sector_t),PU_LEVEL,0);
|
||
|
data = W_CacheLumpNum (lump); // cph - wad lump handling updated
|
||
|
|
||
|
for (i=0; i<numsectors; i++)
|
||
|
{
|
||
|
sector_t *ss = sectors + i;
|
||
|
const mapsector_t *ms = (mapsector_t *) data + i;
|
||
|
|
||
|
ss->floorheight = SHORT(ms->floorheight)<<FRACBITS;
|
||
|
ss->ceilingheight = SHORT(ms->ceilingheight)<<FRACBITS;
|
||
|
ss->floorpic = R_FlatNumForName(ms->floorpic);
|
||
|
ss->ceilingpic = R_FlatNumForName(ms->ceilingpic);
|
||
|
ss->lightlevel = SHORT(ms->lightlevel);
|
||
|
ss->special = SHORT(ms->special);
|
||
|
ss->oldspecial = SHORT(ms->special);
|
||
|
ss->tag = SHORT(ms->tag);
|
||
|
ss->thinglist = NULL;
|
||
|
ss->touching_thinglist = NULL; // phares 3/14/98
|
||
|
|
||
|
ss->nextsec = -1; //jff 2/26/98 add fields to support locking out
|
||
|
ss->prevsec = -1; // stair retriggering until build completes
|
||
|
|
||
|
// killough 3/7/98:
|
||
|
ss->floor_xoffs = 0;
|
||
|
ss->floor_yoffs = 0; // floor and ceiling flats offsets
|
||
|
ss->ceiling_xoffs = 0;
|
||
|
ss->ceiling_yoffs = 0;
|
||
|
ss->heightsec = -1; // sector used to get floor and ceiling height
|
||
|
ss->floorlightsec = -1; // sector used to get floor lighting
|
||
|
// killough 3/7/98: end changes
|
||
|
|
||
|
// killough 4/11/98 sector used to get ceiling lighting:
|
||
|
ss->ceilinglightsec = -1;
|
||
|
|
||
|
// killough 4/4/98: colormaps:
|
||
|
ss->bottommap = ss->midmap = ss->topmap = 0;
|
||
|
|
||
|
// killough 10/98: sky textures coming from sidedefs:
|
||
|
ss->sky = 0;
|
||
|
}
|
||
|
|
||
|
W_UnlockLumpNum(lump); // cph - release the data
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// P_LoadNodes
|
||
|
//
|
||
|
// killough 5/3/98: reformatted, cleaned up
|
||
|
|
||
|
static void P_LoadNodes (int lump)
|
||
|
{
|
||
|
const byte *data; // cph - const*
|
||
|
int i;
|
||
|
|
||
|
numnodes = W_LumpLength (lump) / sizeof(mapnode_t);
|
||
|
nodes = Z_Malloc (numnodes*sizeof(node_t),PU_LEVEL,0);
|
||
|
data = W_CacheLumpNum (lump); // cph - wad lump handling updated
|
||
|
|
||
|
for (i=0; i<numnodes; i++)
|
||
|
{
|
||
|
node_t *no = nodes + i;
|
||
|
mapnode_t *mn = (mapnode_t *) data + i;
|
||
|
int j;
|
||
|
|
||
|
no->x = SHORT(mn->x)<<FRACBITS;
|
||
|
no->y = SHORT(mn->y)<<FRACBITS;
|
||
|
no->dx = SHORT(mn->dx)<<FRACBITS;
|
||
|
no->dy = SHORT(mn->dy)<<FRACBITS;
|
||
|
|
||
|
for (j=0 ; j<2 ; j++)
|
||
|
{
|
||
|
int k;
|
||
|
no->children[j] = SHORT(mn->children[j]);
|
||
|
for (k=0 ; k<4 ; k++)
|
||
|
no->bbox[j][k] = SHORT(mn->bbox[j][k])<<FRACBITS;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
W_UnlockLumpNum(lump); // cph - release the data
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// P_LoadThings
|
||
|
//
|
||
|
// killough 5/3/98: reformatted, cleaned up
|
||
|
|
||
|
static void P_LoadThings (int lump)
|
||
|
{
|
||
|
mapthing_t tempthing; // this needed to be added as the SHORT calls were overwriting eachother on reload
|
||
|
int i, numthings = W_LumpLength (lump) / sizeof(mapthing_t);
|
||
|
const byte *data = W_CacheLumpNum (lump); // cph - wad lump handling updated, const*
|
||
|
|
||
|
for (i=0; i<numthings; i++)
|
||
|
{
|
||
|
mapthing_t *mt = (mapthing_t *) data + i;
|
||
|
|
||
|
// Do not spawn cool, new monsters if !commercial
|
||
|
if (gamemode != commercial)
|
||
|
switch(mt->type)
|
||
|
{
|
||
|
case 68: // Arachnotron
|
||
|
case 64: // Archvile
|
||
|
case 88: // Boss Brain
|
||
|
case 89: // Boss Shooter
|
||
|
case 69: // Hell Knight
|
||
|
case 67: // Mancubus
|
||
|
case 71: // Pain Elemental
|
||
|
case 65: // Former Human Commando
|
||
|
case 66: // Revenant
|
||
|
case 84: // Wolf SS
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// Do spawn all other stuff.
|
||
|
tempthing.x = SHORT(mt->x);
|
||
|
tempthing.y = SHORT(mt->y);
|
||
|
tempthing.angle = SHORT(mt->angle);
|
||
|
tempthing.type = SHORT(mt->type);
|
||
|
tempthing.options = SHORT(mt->options);
|
||
|
|
||
|
P_SpawnMapThing (&tempthing);
|
||
|
}
|
||
|
|
||
|
W_UnlockLumpNum(lump); // cph - release the data
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// P_LoadLineDefs
|
||
|
// Also counts secret lines for intermissions.
|
||
|
// ^^^
|
||
|
// ??? killough ???
|
||
|
// Does this mean secrets used to be linedef-based, rather than sector-based?
|
||
|
//
|
||
|
// killough 4/4/98: split into two functions, to allow sidedef overloading
|
||
|
//
|
||
|
// killough 5/3/98: reformatted, cleaned up
|
||
|
|
||
|
static void P_LoadLineDefs (int lump)
|
||
|
{
|
||
|
const byte *data; // cph - const*
|
||
|
int i;
|
||
|
|
||
|
numlines = W_LumpLength (lump) / sizeof(maplinedef_t);
|
||
|
lines = Z_Calloc (numlines,sizeof(line_t),PU_LEVEL,0);
|
||
|
data = W_CacheLumpNum (lump); // cph - wad lump handling updated
|
||
|
|
||
|
for (i=0; i<numlines; i++)
|
||
|
{
|
||
|
maplinedef_t *mld = (maplinedef_t *) data + i;
|
||
|
line_t *ld = lines+i;
|
||
|
vertex_t *v1, *v2;
|
||
|
|
||
|
ld->flags = SHORT(mld->flags);
|
||
|
ld->special = SHORT(mld->special);
|
||
|
ld->tag = SHORT(mld->tag);
|
||
|
v1 = ld->v1 = &vertexes[SHORT(mld->v1)];
|
||
|
v2 = ld->v2 = &vertexes[SHORT(mld->v2)];
|
||
|
ld->dx = v2->x - v1->x;
|
||
|
ld->dy = v2->y - v1->y;
|
||
|
|
||
|
ld->tranlump = -1; // killough 4/11/98: no translucency by default
|
||
|
|
||
|
ld->slopetype = !ld->dx ? ST_VERTICAL : !ld->dy ? ST_HORIZONTAL :
|
||
|
FixedDiv(ld->dy, ld->dx) > 0 ? ST_POSITIVE : ST_NEGATIVE;
|
||
|
|
||
|
if (v1->x < v2->x)
|
||
|
{
|
||
|
ld->bbox[BOXLEFT] = v1->x;
|
||
|
ld->bbox[BOXRIGHT] = v2->x;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ld->bbox[BOXLEFT] = v2->x;
|
||
|
ld->bbox[BOXRIGHT] = v1->x;
|
||
|
}
|
||
|
|
||
|
if (v1->y < v2->y)
|
||
|
{
|
||
|
ld->bbox[BOXBOTTOM] = v1->y;
|
||
|
ld->bbox[BOXTOP] = v2->y;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ld->bbox[BOXBOTTOM] = v2->y;
|
||
|
ld->bbox[BOXTOP] = v1->y;
|
||
|
}
|
||
|
|
||
|
ld->sidenum[0] = SHORT(mld->sidenum[0]);
|
||
|
ld->sidenum[1] = SHORT(mld->sidenum[1]);
|
||
|
|
||
|
// killough 4/4/98: support special sidedef interpretation below
|
||
|
if (ld->sidenum[0] != -1 && ld->special)
|
||
|
sides[*ld->sidenum].special = ld->special;
|
||
|
}
|
||
|
|
||
|
W_UnlockLumpNum(lump); // cph - release the lump
|
||
|
}
|
||
|
|
||
|
// killough 4/4/98: delay using sidedefs until they are loaded
|
||
|
// killough 5/3/98: reformatted, cleaned up
|
||
|
|
||
|
static void P_LoadLineDefs2(int lump)
|
||
|
{
|
||
|
(void)lump;
|
||
|
int i = numlines;
|
||
|
register line_t *ld = lines;
|
||
|
for (;i--;ld++)
|
||
|
{
|
||
|
{ // cph 2002/07/20 - these errors are fatal if not fixed, so apply them in compatibility mode - a desync is better than a crash!
|
||
|
// killough 11/98: fix common wad errors (missing sidedefs):
|
||
|
|
||
|
if (ld->sidenum[0] == -1) {
|
||
|
ld->sidenum[0] = 0; // Substitute dummy sidedef for missing right side
|
||
|
// cph - print a warning about the bug
|
||
|
printf("P_LoadSegs: linedef %d missing first sidedef\n",numlines-i);
|
||
|
}
|
||
|
|
||
|
if ((ld->sidenum[1] == -1) && (ld->flags & ML_TWOSIDED)) {
|
||
|
ld->flags &= ~ML_TWOSIDED; // Clear 2s flag for missing left side
|
||
|
// cph - print a warning about the bug
|
||
|
printf("P_LoadSegs: linedef %d has two-sided flag set, but no second sidedef\n",numlines-i);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ld->frontsector = ld->sidenum[0]!=-1 ? sides[ld->sidenum[0]].sector : 0;
|
||
|
ld->backsector = ld->sidenum[1]!=-1 ? sides[ld->sidenum[1]].sector : 0;
|
||
|
switch (ld->special)
|
||
|
{ // killough 4/11/98: handle special types
|
||
|
int lump, j;
|
||
|
|
||
|
case 260: // killough 4/11/98: translucent 2s textures
|
||
|
lump = sides[*ld->sidenum].special; // translucency from sidedef
|
||
|
if (!ld->tag) // if tag==0,
|
||
|
ld->tranlump = lump; // affect this linedef only
|
||
|
else
|
||
|
for (j=0;j<numlines;j++) // if tag!=0,
|
||
|
if (lines[j].tag == ld->tag) // affect all matching linedefs
|
||
|
lines[j].tranlump = lump;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// P_LoadSideDefs
|
||
|
//
|
||
|
// killough 4/4/98: split into two functions
|
||
|
|
||
|
static void P_LoadSideDefs (int lump)
|
||
|
{
|
||
|
numsides = W_LumpLength(lump) / sizeof(mapsidedef_t);
|
||
|
sides = Z_Calloc(numsides,sizeof(side_t),PU_LEVEL,0);
|
||
|
}
|
||
|
|
||
|
// killough 4/4/98: delay using texture names until
|
||
|
// after linedefs are loaded, to allow overloading.
|
||
|
// killough 5/3/98: reformatted, cleaned up
|
||
|
|
||
|
static void P_LoadSideDefs2(int lump)
|
||
|
{
|
||
|
const byte *data = W_CacheLumpNum(lump); // cph - const*, wad lump handling updated
|
||
|
int i;
|
||
|
|
||
|
for (i=0; i<numsides; i++)
|
||
|
{
|
||
|
register mapsidedef_t *msd = (mapsidedef_t *) data + i;
|
||
|
register side_t *sd = sides + i;
|
||
|
register sector_t *sec;
|
||
|
|
||
|
sd->textureoffset = SHORT(msd->textureoffset)<<FRACBITS;
|
||
|
sd->rowoffset = SHORT(msd->rowoffset)<<FRACBITS;
|
||
|
|
||
|
// killough 4/4/98: allow sidedef texture names to be overloaded
|
||
|
// killough 4/11/98: refined to allow colormaps to work as wall
|
||
|
// textures if invalid as colormaps but valid as textures.
|
||
|
|
||
|
sd->sector = sec = §ors[SHORT(msd->sector)];
|
||
|
switch (sd->special)
|
||
|
{
|
||
|
case 242: // variable colormap via 242 linedef
|
||
|
sd->bottomtexture =
|
||
|
(sec->bottommap = R_ColormapNumForName(msd->bottomtexture)) < 0 ?
|
||
|
sec->bottommap = 0, R_TextureNumForName(msd->bottomtexture): 0 ;
|
||
|
sd->midtexture =
|
||
|
(sec->midmap = R_ColormapNumForName(msd->midtexture)) < 0 ?
|
||
|
sec->midmap = 0, R_TextureNumForName(msd->midtexture) : 0 ;
|
||
|
sd->toptexture =
|
||
|
(sec->topmap = R_ColormapNumForName(msd->toptexture)) < 0 ?
|
||
|
sec->topmap = 0, R_TextureNumForName(msd->toptexture) : 0 ;
|
||
|
break;
|
||
|
|
||
|
case 260: // killough 4/11/98: apply translucency to 2s normal texture
|
||
|
sd->midtexture = strncasecmp("TRANMAP", msd->midtexture, 8) ?
|
||
|
(sd->special = W_CheckNumForName(msd->midtexture)) < 0 ||
|
||
|
W_LumpLength(sd->special) != 65536 ?
|
||
|
sd->special=0, R_TextureNumForName(msd->midtexture) :
|
||
|
(sd->special++, 0) : (sd->special=0);
|
||
|
sd->toptexture = R_TextureNumForName(msd->toptexture);
|
||
|
sd->bottomtexture = R_TextureNumForName(msd->bottomtexture);
|
||
|
break;
|
||
|
|
||
|
default: // normal cases
|
||
|
sd->midtexture = R_TextureNumForName(msd->midtexture);
|
||
|
sd->toptexture = R_TextureNumForName(msd->toptexture);
|
||
|
sd->bottomtexture = R_TextureNumForName(msd->bottomtexture);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
W_UnlockLumpNum(lump); // cph - release the lump
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// jff 10/6/98
|
||
|
// New code added to speed up calculation of internal blockmap
|
||
|
// Algorithm is order of nlines*(ncols+nrows) not nlines*ncols*nrows
|
||
|
//
|
||
|
|
||
|
#define blkshift 7 /* places to shift rel position for cell num */
|
||
|
#define blkmask ((1<<blkshift)-1)/* mask for rel position within cell */
|
||
|
#define blkmargin 0 /* size guardband around map used */
|
||
|
// jff 10/8/98 use guardband>0
|
||
|
// jff 10/12/98 0 ok with + 1 in rows,cols
|
||
|
|
||
|
typedef struct linelist_t // type used to list lines in each block
|
||
|
{
|
||
|
long num;
|
||
|
struct linelist_t *next;
|
||
|
} linelist_t;
|
||
|
|
||
|
//
|
||
|
// Subroutine to add a line number to a block list
|
||
|
// It simply returns if the line is already in the block
|
||
|
//
|
||
|
|
||
|
static void AddBlockLine
|
||
|
(
|
||
|
linelist_t **lists,
|
||
|
int *count,
|
||
|
int *done,
|
||
|
int blockno,
|
||
|
long lineno
|
||
|
)
|
||
|
{
|
||
|
linelist_t *l;
|
||
|
|
||
|
if (done[blockno])
|
||
|
return;
|
||
|
|
||
|
l = malloc(sizeof(linelist_t));
|
||
|
l->num = lineno;
|
||
|
l->next = lists[blockno];
|
||
|
lists[blockno] = l;
|
||
|
count[blockno]++;
|
||
|
done[blockno] = 1;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Actually construct the blockmap lump from the level data
|
||
|
//
|
||
|
// This finds the intersection of each linedef with the column and
|
||
|
// row lines at the left and bottom of each blockmap cell. It then
|
||
|
// adds the line to all block lists touching the intersection.
|
||
|
//
|
||
|
|
||
|
void P_CreateBlockMap()
|
||
|
{
|
||
|
int xorg,yorg; // blockmap origin (lower left)
|
||
|
int nrows,ncols; // blockmap dimensions
|
||
|
linelist_t **blocklists=NULL; // array of pointers to lists of lines
|
||
|
int *blockcount=NULL; // array of counters of line lists
|
||
|
int *blockdone=NULL; // array keeping track of blocks/line
|
||
|
int NBlocks; // number of cells = nrows*ncols
|
||
|
long linetotal=0; // total length of all blocklists
|
||
|
int i,j;
|
||
|
int map_minx=INT_MAX; // init for map limits search
|
||
|
int map_miny=INT_MAX;
|
||
|
int map_maxx=INT_MIN;
|
||
|
int map_maxy=INT_MIN;
|
||
|
|
||
|
// scan for map limits, which the blockmap must enclose
|
||
|
|
||
|
for (i=0;i<numvertexes;i++)
|
||
|
{
|
||
|
fixed_t t;
|
||
|
|
||
|
if ((t=vertexes[i].x) < map_minx)
|
||
|
map_minx = t;
|
||
|
else if (t > map_maxx)
|
||
|
map_maxx = t;
|
||
|
if ((t=vertexes[i].y) < map_miny)
|
||
|
map_miny = t;
|
||
|
else if (t > map_maxy)
|
||
|
map_maxy = t;
|
||
|
}
|
||
|
map_minx >>= FRACBITS; // work in map coords, not fixed_t
|
||
|
map_maxx >>= FRACBITS;
|
||
|
map_miny >>= FRACBITS;
|
||
|
map_maxy >>= FRACBITS;
|
||
|
|
||
|
// set up blockmap area to enclose level plus margin
|
||
|
|
||
|
xorg = map_minx-blkmargin;
|
||
|
yorg = map_miny-blkmargin;
|
||
|
ncols = (map_maxx+blkmargin-xorg+1+blkmask)>>blkshift; //jff 10/12/98
|
||
|
nrows = (map_maxy+blkmargin-yorg+1+blkmask)>>blkshift; //+1 needed for
|
||
|
NBlocks = ncols*nrows; //map exactly 1 cell
|
||
|
|
||
|
// create the array of pointers on NBlocks to blocklists
|
||
|
// also create an array of linelist counts on NBlocks
|
||
|
// finally make an array in which we can mark blocks done per line
|
||
|
|
||
|
// CPhipps - calloc's
|
||
|
blocklists = calloc(NBlocks,sizeof(linelist_t *));
|
||
|
blockcount = calloc(NBlocks,sizeof(int));
|
||
|
blockdone = malloc(NBlocks*sizeof(int));
|
||
|
|
||
|
// initialize each blocklist, and enter the trailing -1 in all blocklists
|
||
|
// note the linked list of lines grows backwards
|
||
|
|
||
|
for (i=0;i<NBlocks;i++)
|
||
|
{
|
||
|
blocklists[i] = malloc(sizeof(linelist_t));
|
||
|
blocklists[i]->num = -1;
|
||
|
blocklists[i]->next = NULL;
|
||
|
blockcount[i]++;
|
||
|
}
|
||
|
|
||
|
// For each linedef in the wad, determine all blockmap blocks it touches,
|
||
|
// and add the linedef number to the blocklists for those blocks
|
||
|
|
||
|
for (i=0;i<numlines;i++)
|
||
|
{
|
||
|
int x1 = lines[i].v1->x>>FRACBITS; // lines[i] map coords
|
||
|
int y1 = lines[i].v1->y>>FRACBITS;
|
||
|
int x2 = lines[i].v2->x>>FRACBITS;
|
||
|
int y2 = lines[i].v2->y>>FRACBITS;
|
||
|
int dx = x2-x1;
|
||
|
int dy = y2-y1;
|
||
|
int vert = !dx; // lines[i] slopetype
|
||
|
int horiz = !dy;
|
||
|
int spos = (dx^dy) > 0;
|
||
|
int sneg = (dx^dy) < 0;
|
||
|
int bx,by; // block cell coords
|
||
|
int minx = x1>x2? x2 : x1; // extremal lines[i] coords
|
||
|
int maxx = x1>x2? x1 : x2;
|
||
|
int miny = y1>y2? y2 : y1;
|
||
|
int maxy = y1>y2? y1 : y2;
|
||
|
|
||
|
// no blocks done for this linedef yet
|
||
|
|
||
|
memset(blockdone,0,NBlocks*sizeof(int));
|
||
|
|
||
|
// The line always belongs to the blocks containing its endpoints
|
||
|
|
||
|
bx = (x1-xorg)>>blkshift;
|
||
|
by = (y1-yorg)>>blkshift;
|
||
|
AddBlockLine(blocklists,blockcount,blockdone,by*ncols+bx,i);
|
||
|
bx = (x2-xorg)>>blkshift;
|
||
|
by = (y2-yorg)>>blkshift;
|
||
|
AddBlockLine(blocklists,blockcount,blockdone,by*ncols+bx,i);
|
||
|
|
||
|
|
||
|
// For each column, see where the line along its left edge, which
|
||
|
// it contains, intersects the Linedef i. Add i to each corresponding
|
||
|
// blocklist.
|
||
|
|
||
|
if (!vert) // don't interesect vertical lines with columns
|
||
|
{
|
||
|
for (j=0;j<ncols;j++)
|
||
|
{
|
||
|
// intersection of Linedef with x=xorg+(j<<blkshift)
|
||
|
// (y-y1)*dx = dy*(x-x1)
|
||
|
// y = dy*(x-x1)+y1*dx;
|
||
|
|
||
|
int x = xorg+(j<<blkshift); // (x,y) is intersection
|
||
|
int y = (dy*(x-x1))/dx+y1;
|
||
|
int yb = (y-yorg)>>blkshift; // block row number
|
||
|
int yp = (y-yorg)&blkmask; // y position within block
|
||
|
|
||
|
if (yb<0 || yb>nrows-1) // outside blockmap, continue
|
||
|
continue;
|
||
|
|
||
|
if (x<minx || x>maxx) // line doesn't touch column
|
||
|
continue;
|
||
|
|
||
|
// The cell that contains the intersection point is always added
|
||
|
|
||
|
AddBlockLine(blocklists,blockcount,blockdone,ncols*yb+j,i);
|
||
|
|
||
|
// if the intersection is at a corner it depends on the slope
|
||
|
// (and whether the line extends past the intersection) which
|
||
|
// blocks are hit
|
||
|
|
||
|
if (yp==0) // intersection at a corner
|
||
|
{
|
||
|
if (sneg) // \ - blocks x,y-, x-,y
|
||
|
{
|
||
|
if (yb>0 && miny<y)
|
||
|
AddBlockLine(blocklists,blockcount,blockdone,ncols*(yb-1)+j,i);
|
||
|
if (j>0 && minx<x)
|
||
|
AddBlockLine(blocklists,blockcount,blockdone,ncols*yb+j-1,i);
|
||
|
}
|
||
|
else if (spos) // / - block x-,y-
|
||
|
{
|
||
|
if (yb>0 && j>0 && minx<x)
|
||
|
AddBlockLine(blocklists,blockcount,blockdone,ncols*(yb-1)+j-1,i);
|
||
|
}
|
||
|
else if (horiz) // - - block x-,y
|
||
|
{
|
||
|
if (j>0 && minx<x)
|
||
|
AddBlockLine(blocklists,blockcount,blockdone,ncols*yb+j-1,i);
|
||
|
}
|
||
|
}
|
||
|
else if (j>0 && minx<x) // else not at corner: x-,y
|
||
|
AddBlockLine(blocklists,blockcount,blockdone,ncols*yb+j-1,i);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// For each row, see where the line along its bottom edge, which
|
||
|
// it contains, intersects the Linedef i. Add i to all the corresponding
|
||
|
// blocklists.
|
||
|
|
||
|
if (!horiz)
|
||
|
{
|
||
|
for (j=0;j<nrows;j++)
|
||
|
{
|
||
|
// intersection of Linedef with y=yorg+(j<<blkshift)
|
||
|
// (x,y) on Linedef i satisfies: (y-y1)*dx = dy*(x-x1)
|
||
|
// x = dx*(y-y1)/dy+x1;
|
||
|
|
||
|
int y = yorg+(j<<blkshift); // (x,y) is intersection
|
||
|
int x = (dx*(y-y1))/dy+x1;
|
||
|
int xb = (x-xorg)>>blkshift; // block column number
|
||
|
int xp = (x-xorg)&blkmask; // x position within block
|
||
|
|
||
|
if (xb<0 || xb>ncols-1) // outside blockmap, continue
|
||
|
continue;
|
||
|
|
||
|
if (y<miny || y>maxy) // line doesn't touch row
|
||
|
continue;
|
||
|
|
||
|
// The cell that contains the intersection point is always added
|
||
|
|
||
|
AddBlockLine(blocklists,blockcount,blockdone,ncols*j+xb,i);
|
||
|
|
||
|
// if the intersection is at a corner it depends on the slope
|
||
|
// (and whether the line extends past the intersection) which
|
||
|
// blocks are hit
|
||
|
|
||
|
if (xp==0) // intersection at a corner
|
||
|
{
|
||
|
if (sneg) // \ - blocks x,y-, x-,y
|
||
|
{
|
||
|
if (j>0 && miny<y)
|
||
|
AddBlockLine(blocklists,blockcount,blockdone,ncols*(j-1)+xb,i);
|
||
|
if (xb>0 && minx<x)
|
||
|
AddBlockLine(blocklists,blockcount,blockdone,ncols*j+xb-1,i);
|
||
|
}
|
||
|
else if (vert) // | - block x,y-
|
||
|
{
|
||
|
if (j>0 && miny<y)
|
||
|
AddBlockLine(blocklists,blockcount,blockdone,ncols*(j-1)+xb,i);
|
||
|
}
|
||
|
else if (spos) // / - block x-,y-
|
||
|
{
|
||
|
if (xb>0 && j>0 && miny<y)
|
||
|
AddBlockLine(blocklists,blockcount,blockdone,ncols*(j-1)+xb-1,i);
|
||
|
}
|
||
|
}
|
||
|
else if (j>0 && miny<y) // else not on a corner: x,y-
|
||
|
AddBlockLine(blocklists,blockcount,blockdone,ncols*(j-1)+xb,i);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Add initial 0 to all blocklists
|
||
|
// count the total number of lines (and 0's and -1's)
|
||
|
|
||
|
memset(blockdone,0,NBlocks*sizeof(int));
|
||
|
for (i=0,linetotal=0;i<NBlocks;i++)
|
||
|
{
|
||
|
AddBlockLine(blocklists,blockcount,blockdone,i,0);
|
||
|
linetotal += blockcount[i];
|
||
|
}
|
||
|
|
||
|
// Create the blockmap lump
|
||
|
|
||
|
blockmaplump = Z_Malloc(sizeof(*blockmaplump) * (4+NBlocks+linetotal),
|
||
|
PU_LEVEL, 0);
|
||
|
// blockmap header
|
||
|
|
||
|
blockmaplump[0] = bmaporgx = xorg << FRACBITS;
|
||
|
blockmaplump[1] = bmaporgy = yorg << FRACBITS;
|
||
|
blockmaplump[2] = bmapwidth = ncols;
|
||
|
blockmaplump[3] = bmapheight = nrows;
|
||
|
|
||
|
// offsets to lists and block lists
|
||
|
|
||
|
for (i=0;i<NBlocks;i++)
|
||
|
{
|
||
|
linelist_t *bl = blocklists[i];
|
||
|
long offs = blockmaplump[4+i] = // set offset to block's list
|
||
|
(i? blockmaplump[4+i-1] : 4+NBlocks) + (i? blockcount[i-1] : 0);
|
||
|
|
||
|
// add the lines in each block's list to the blockmaplump
|
||
|
// delete each list node as we go
|
||
|
|
||
|
while (bl)
|
||
|
{
|
||
|
linelist_t *tmp = bl->next;
|
||
|
blockmaplump[offs++] = bl->num;
|
||
|
free(bl);
|
||
|
bl = tmp;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// free all temporary storage
|
||
|
|
||
|
free (blocklists);
|
||
|
free (blockcount);
|
||
|
free (blockdone);
|
||
|
}
|
||
|
|
||
|
// jff 10/6/98
|
||
|
// End new code added to speed up calculation of internal blockmap
|
||
|
|
||
|
//
|
||
|
// P_LoadBlockMap
|
||
|
//
|
||
|
// killough 3/1/98: substantially modified to work
|
||
|
// towards removing blockmap limit (a wad limitation)
|
||
|
//
|
||
|
// killough 3/30/98: Rewritten to remove blockmap limit,
|
||
|
// though current algorithm is brute-force and unoptimal.
|
||
|
//
|
||
|
|
||
|
static void P_LoadBlockMap (int lump)
|
||
|
{
|
||
|
long count;
|
||
|
|
||
|
if (M_CheckParm("-blockmap") || (count = W_LumpLength(lump)/2) >= 0x10000)
|
||
|
P_CreateBlockMap();
|
||
|
else
|
||
|
{
|
||
|
long i;
|
||
|
// cph - const*, wad lump handling updated
|
||
|
const short *wadblockmaplump = W_CacheLumpNum(lump);
|
||
|
blockmaplump = Z_Malloc(sizeof(*blockmaplump) * count, PU_LEVEL, 0);
|
||
|
|
||
|
// killough 3/1/98: Expand wad blockmap into larger internal one,
|
||
|
// by treating all offsets except -1 as unsigned and zero-extending
|
||
|
// them. This potentially doubles the size of blockmaps allowed,
|
||
|
// because Doom originally considered the offsets as always signed.
|
||
|
|
||
|
blockmaplump[0] = SHORT(wadblockmaplump[0]);
|
||
|
blockmaplump[1] = SHORT(wadblockmaplump[1]);
|
||
|
blockmaplump[2] = (long)(SHORT(wadblockmaplump[2])) & 0xffff;
|
||
|
blockmaplump[3] = (long)(SHORT(wadblockmaplump[3])) & 0xffff;
|
||
|
|
||
|
for (i=4 ; i<count ; i++)
|
||
|
{
|
||
|
short t = SHORT(wadblockmaplump[i]); // killough 3/1/98
|
||
|
blockmaplump[i] = t == -1 ? -1l : (long) t & 0xffff;
|
||
|
}
|
||
|
|
||
|
W_UnlockLumpNum(lump); // cph - unlock the lump
|
||
|
|
||
|
bmaporgx = blockmaplump[0]<<FRACBITS;
|
||
|
bmaporgy = blockmaplump[1]<<FRACBITS;
|
||
|
bmapwidth = blockmaplump[2];
|
||
|
bmapheight = blockmaplump[3];
|
||
|
}
|
||
|
|
||
|
// clear out mobj chains - CPhipps - use calloc
|
||
|
blocklinks = Z_Calloc (bmapwidth*bmapheight,sizeof(*blocklinks),PU_LEVEL,0);
|
||
|
blockmap = blockmaplump+4;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// P_GroupLines
|
||
|
// Builds sector line lists and subsector sector numbers.
|
||
|
// Finds block bounding boxes for sectors.
|
||
|
//
|
||
|
// killough 5/3/98: reformatted, cleaned up
|
||
|
// cph 18/8/99: rewritten to avoid O(numlines * numsectors) section
|
||
|
// It makes things more complicated, but saves seconds on big levels
|
||
|
// figgi 09/18/00 -- adapted for gl-nodes
|
||
|
|
||
|
// cph - convenient sub-function
|
||
|
static void P_AddLineToSector(line_t* li, sector_t* sector)
|
||
|
{
|
||
|
fixed_t *bbox = (void*)sector->blockbox;
|
||
|
|
||
|
sector->lines[sector->linecount++] = li;
|
||
|
M_AddToBox (bbox, li->v1->x, li->v1->y);
|
||
|
M_AddToBox (bbox, li->v2->x, li->v2->y);
|
||
|
}
|
||
|
|
||
|
void P_GroupLines (void)
|
||
|
{
|
||
|
register line_t *li;
|
||
|
register sector_t *sector;
|
||
|
int i,j, total = numlines;
|
||
|
|
||
|
// figgi
|
||
|
for (i=0 ; i<numsubsectors ; i++)
|
||
|
{
|
||
|
seg_t *seg = &segs[subsectors[i].firstline];
|
||
|
subsectors[i].sector = NULL;
|
||
|
for(j=0; j<subsectors[i].numlines; j++)
|
||
|
{
|
||
|
if(seg->sidedef)
|
||
|
{
|
||
|
subsectors[i].sector = seg->sidedef->sector;
|
||
|
break;
|
||
|
}
|
||
|
seg++;
|
||
|
}
|
||
|
if(subsectors[i].sector == NULL)
|
||
|
I_Error("P_GroupLines: Subsector a part of no sector!\n");
|
||
|
}
|
||
|
|
||
|
// count number of lines in each sector
|
||
|
for (i=0,li=lines; i<numlines; i++, li++)
|
||
|
{
|
||
|
li->frontsector->linecount++;
|
||
|
if (li->backsector && li->backsector != li->frontsector)
|
||
|
{
|
||
|
li->backsector->linecount++;
|
||
|
total++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
{ // allocate line tables for each sector
|
||
|
line_t **linebuffer = Z_Malloc(total*sizeof(line_t *), PU_LEVEL, 0);
|
||
|
|
||
|
for (i=0, sector = sectors; i<numsectors; i++, sector++)
|
||
|
{
|
||
|
sector->lines = linebuffer;
|
||
|
linebuffer += sector->linecount;
|
||
|
sector->linecount = 0;
|
||
|
M_ClearBox(sector->blockbox);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Enter those lines
|
||
|
for (i=0,li=lines; i<numlines; i++, li++)
|
||
|
{
|
||
|
P_AddLineToSector(li, li->frontsector);
|
||
|
if (li->backsector && li->backsector != li->frontsector)
|
||
|
P_AddLineToSector(li, li->backsector);
|
||
|
}
|
||
|
|
||
|
for (i=0, sector = sectors; i<numsectors; i++, sector++)
|
||
|
{
|
||
|
fixed_t *bbox = (void*)sector->blockbox; // cph - For convenience, so
|
||
|
// I can sue the old code unchanged
|
||
|
int block;
|
||
|
|
||
|
// set the degenmobj_t to the middle of the bounding box
|
||
|
sector->soundorg.x = (bbox[BOXRIGHT]+bbox[BOXLEFT])/2;
|
||
|
sector->soundorg.y = (bbox[BOXTOP]+bbox[BOXBOTTOM])/2;
|
||
|
|
||
|
// adjust bounding box to map blocks
|
||
|
block = (bbox[BOXTOP]-bmaporgy+MAXRADIUS)>>MAPBLOCKSHIFT;
|
||
|
block = block >= bmapheight ? bmapheight-1 : block;
|
||
|
sector->blockbox[BOXTOP]=block;
|
||
|
|
||
|
block = (bbox[BOXBOTTOM]-bmaporgy-MAXRADIUS)>>MAPBLOCKSHIFT;
|
||
|
block = block < 0 ? 0 : block;
|
||
|
sector->blockbox[BOXBOTTOM]=block;
|
||
|
|
||
|
block = (bbox[BOXRIGHT]-bmaporgx+MAXRADIUS)>>MAPBLOCKSHIFT;
|
||
|
block = block >= bmapwidth ? bmapwidth-1 : block;
|
||
|
sector->blockbox[BOXRIGHT]=block;
|
||
|
|
||
|
block = (bbox[BOXLEFT]-bmaporgx-MAXRADIUS)>>MAPBLOCKSHIFT;
|
||
|
block = block < 0 ? 0 : block;
|
||
|
sector->blockbox[BOXLEFT]=block;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// killough 10/98
|
||
|
//
|
||
|
// Remove slime trails.
|
||
|
//
|
||
|
// Slime trails are inherent to Doom's coordinate system -- i.e. there is
|
||
|
// nothing that a node builder can do to prevent slime trails ALL of the time,
|
||
|
// because it's a product of the integer coodinate system, and just because
|
||
|
// two lines pass through exact integer coordinates, doesn't necessarily mean
|
||
|
// that they will intersect at integer coordinates. Thus we must allow for
|
||
|
// fractional coordinates if we are to be able to split segs with node lines,
|
||
|
// as a node builder must do when creating a BSP tree.
|
||
|
//
|
||
|
// A wad file does not allow fractional coordinates, so node builders are out
|
||
|
// of luck except that they can try to limit the number of splits (they might
|
||
|
// also be able to detect the degree of roundoff error and try to avoid splits
|
||
|
// with a high degree of roundoff error). But we can use fractional coordinates
|
||
|
// here, inside the engine. It's like the difference between square inches and
|
||
|
// square miles, in terms of granularity.
|
||
|
//
|
||
|
// For each vertex of every seg, check to see whether it's also a vertex of
|
||
|
// the linedef associated with the seg (i.e, it's an endpoint). If it's not
|
||
|
// an endpoint, and it wasn't already moved, move the vertex towards the
|
||
|
// linedef by projecting it using the law of cosines. Formula:
|
||
|
//
|
||
|
// 2 2 2 2
|
||
|
// dx x0 + dy x1 + dx dy (y0 - y1) dy y0 + dx y1 + dx dy (x0 - x1)
|
||
|
// {---------------------------------, ---------------------------------}
|
||
|
// 2 2 2 2
|
||
|
// dx + dy dx + dy
|
||
|
//
|
||
|
// (x0,y0) is the vertex being moved, and (x1,y1)-(x1+dx,y1+dy) is the
|
||
|
// reference linedef.
|
||
|
//
|
||
|
// Segs corresponding to orthogonal linedefs (exactly vertical or horizontal
|
||
|
// linedefs), which comprise at least half of all linedefs in most wads, don't
|
||
|
// need to be considered, because they almost never contribute to slime trails
|
||
|
// (because then any roundoff error is parallel to the linedef, which doesn't
|
||
|
// cause slime). Skipping simple orthogonal lines lets the code finish quicker.
|
||
|
//
|
||
|
// Please note: This section of code is not interchangable with TeamTNT's
|
||
|
// code which attempts to fix the same problem.
|
||
|
//
|
||
|
// Firelines (TM) is a Rezistered Trademark of MBF Productions
|
||
|
//
|
||
|
|
||
|
void P_RemoveSlimeTrails(void) // killough 10/98
|
||
|
{
|
||
|
byte *hit = calloc(1, numvertexes); // Hitlist for vertices
|
||
|
int i;
|
||
|
for (i=0; i<numsegs; i++) // Go through each seg
|
||
|
{
|
||
|
const line_t *l;
|
||
|
|
||
|
if (segs[i].miniseg == true) //figgi -- skip minisegs
|
||
|
return;
|
||
|
|
||
|
l = segs[i].linedef; // The parent linedef
|
||
|
if (l->dx && l->dy) // We can ignore orthogonal lines
|
||
|
{
|
||
|
vertex_t *v = segs[i].v1;
|
||
|
do
|
||
|
if (!hit[v - vertexes]) // If we haven't processed vertex
|
||
|
{
|
||
|
hit[v - vertexes] = 1; // Mark this vertex as processed
|
||
|
if (v != l->v1 && v != l->v2) // Exclude endpoints of linedefs
|
||
|
{ // Project the vertex back onto the parent linedef
|
||
|
int_64_t dx2 = (l->dx >> FRACBITS) * (l->dx >> FRACBITS);
|
||
|
int_64_t dy2 = (l->dy >> FRACBITS) * (l->dy >> FRACBITS);
|
||
|
int_64_t dxy = (l->dx >> FRACBITS) * (l->dy >> FRACBITS);
|
||
|
int_64_t s = dx2 + dy2;
|
||
|
int x0 = v->x, y0 = v->y, x1 = l->v1->x, y1 = l->v1->y;
|
||
|
v->x = (int)((dx2 * x0 + dy2 * x1 + dxy * (y0 - y1)) / s);
|
||
|
v->y = (int)((dy2 * y0 + dx2 * y1 + dxy * (x0 - x1)) / s);
|
||
|
}
|
||
|
} // Obsfucated C contest entry: :)
|
||
|
while ((v != segs[i].v2) && (v = segs[i].v2));
|
||
|
}
|
||
|
}
|
||
|
free(hit);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// P_SetupLevel
|
||
|
//
|
||
|
// killough 5/3/98: reformatted, cleaned up
|
||
|
|
||
|
void P_SetupLevel(int episode, int map, int playermask, skill_t skill)
|
||
|
{
|
||
|
(void)playermask;
|
||
|
(void)skill;
|
||
|
int i;
|
||
|
char lumpname[9];
|
||
|
int lumpnum;
|
||
|
|
||
|
|
||
|
totalkills = totalitems = totalsecret = wminfo.maxfrags = 0;
|
||
|
wminfo.partime = 180;
|
||
|
|
||
|
for (i=0; i<MAXPLAYERS; i++)
|
||
|
players[i].killcount = players[i].secretcount = players[i].itemcount = 0;
|
||
|
|
||
|
// Initial height of PointOfView will be set by player think.
|
||
|
players[consoleplayer].viewz = 1;
|
||
|
|
||
|
// Make sure all sounds are stopped before Z_FreeTags.
|
||
|
S_Start();
|
||
|
|
||
|
Z_FreeTags(PU_LEVEL, PU_PURGELEVEL-1);
|
||
|
if (rejectlump != -1) { // cph - unlock the reject table
|
||
|
W_UnlockLumpNum(rejectlump);
|
||
|
rejectlump = -1;
|
||
|
}
|
||
|
|
||
|
P_InitThinkers();
|
||
|
|
||
|
// if working with a devlopment map, reload it
|
||
|
// W_Reload (); killough 1/31/98: W_Reload obsolete
|
||
|
|
||
|
// find map name
|
||
|
if (gamemode == commercial)
|
||
|
{
|
||
|
if (map<10)
|
||
|
snprintf (lumpname,sizeof(lumpname),"map0%d", map);
|
||
|
else
|
||
|
snprintf (lumpname,sizeof(lumpname),"map%d", map);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
snprintf(lumpname,sizeof(lumpname), "E%dM%d", episode, map); // killough 1/24/98: simplify
|
||
|
}
|
||
|
|
||
|
lumpnum = W_GetNumForName(lumpname);
|
||
|
|
||
|
leveltime = 0;
|
||
|
|
||
|
// note: most of this ordering is important
|
||
|
|
||
|
// killough 3/1/98: P_LoadBlockMap call moved down to below
|
||
|
// killough 4/4/98: split load of sidedefs into two parts,
|
||
|
// to allow texture names to be used in special linedefs
|
||
|
|
||
|
usingGLNodes = false;
|
||
|
P_LoadVertexes (lumpnum+ML_VERTEXES);
|
||
|
P_LoadSectors (lumpnum+ML_SECTORS);
|
||
|
P_LoadSideDefs (lumpnum+ML_SIDEDEFS);
|
||
|
P_LoadLineDefs (lumpnum+ML_LINEDEFS);
|
||
|
P_LoadSideDefs2 (lumpnum+ML_SIDEDEFS);
|
||
|
P_LoadLineDefs2 (lumpnum+ML_LINEDEFS);
|
||
|
P_LoadBlockMap (lumpnum+ML_BLOCKMAP);
|
||
|
|
||
|
P_LoadSubsectors(lumpnum + ML_SSECTORS);
|
||
|
P_LoadNodes(lumpnum + ML_NODES);
|
||
|
P_LoadSegs(lumpnum + ML_SEGS);
|
||
|
|
||
|
if (rejectlump != -1)
|
||
|
W_UnlockLumpNum(rejectlump);
|
||
|
rejectlump = lumpnum+ML_REJECT;
|
||
|
{
|
||
|
int rjlen = W_LumpLength(rejectlump);
|
||
|
int rjreq = (numsectors*numsectors+7)/8;
|
||
|
if (rjlen < rjreq) {
|
||
|
printf("P_SetupLevel: REJECT too short (%d<%d) - padded\n",rjlen,rjreq);
|
||
|
rejectmatrix = W_CacheLumpNumPadded(rejectlump,rjreq,0xff);
|
||
|
} else {
|
||
|
rejectmatrix = W_CacheLumpNum(rejectlump);
|
||
|
}
|
||
|
}
|
||
|
P_GroupLines();
|
||
|
|
||
|
P_RemoveSlimeTrails(); // killough 10/98: remove slime trails from wad
|
||
|
|
||
|
// Note: you don't need to clear player queue slots --
|
||
|
// a much simpler fix is in g_game.c -- killough 10/98
|
||
|
|
||
|
bodyqueslot = 0;
|
||
|
deathmatch_p = deathmatchstarts;
|
||
|
P_MapStart();
|
||
|
P_LoadThings(lumpnum+ML_THINGS);
|
||
|
|
||
|
// if deathmatch, randomly spawn the active players
|
||
|
if (deathmatch)
|
||
|
for (i=0; i<MAXPLAYERS; i++)
|
||
|
if (playeringame[i])
|
||
|
{
|
||
|
players[i].mo = NULL;
|
||
|
G_DeathMatchSpawnPlayer(i);
|
||
|
}
|
||
|
|
||
|
// killough 3/26/98: Spawn icon landings:
|
||
|
if (gamemode==commercial)
|
||
|
P_SpawnBrainTargets();
|
||
|
|
||
|
// clear special respawning que
|
||
|
iquehead = iquetail = 0;
|
||
|
|
||
|
// set up world state
|
||
|
P_SpawnSpecials();
|
||
|
|
||
|
P_MapEnd();
|
||
|
|
||
|
// preload graphics
|
||
|
if (precache)
|
||
|
R_PrecacheLevel();
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// P_Init
|
||
|
//
|
||
|
void P_Init (void)
|
||
|
{
|
||
|
P_InitSwitchList();
|
||
|
P_InitPicAnims();
|
||
|
R_InitSprites(sprnames);
|
||
|
}
|