/* 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 #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; iv1 = &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; ifloorheight = SHORT(ms->floorheight)<ceilingheight = SHORT(ms->ceilingheight)<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; ix = SHORT(mn->x)<y = SHORT(mn->y)<dx = SHORT(mn->dx)<dy = SHORT(mn->dy)<children[j] = SHORT(mn->children[j]); for (k=0 ; k<4 ; k++) no->bbox[j][k] = SHORT(mn->bbox[j][k])<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; iflags = 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;jtag) // 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; itextureoffset = SHORT(msd->textureoffset)<rowoffset = SHORT(msd->rowoffset)<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<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 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;inum = -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;ix>>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>blkshift; // block row number int yp = (y-yorg)&blkmask; // y position within block if (yb<0 || yb>nrows-1) // outside blockmap, continue continue; if (xmaxx) // 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 && miny0 && minx0 && j>0 && minx0 && minx0 && minx>blkshift; // block column number int xp = (x-xorg)&blkmask; // x position within block if (xb<0 || xb>ncols-1) // outside blockmap, continue continue; if (ymaxy) // 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 && miny0 && minx0 && miny0 && j>0 && miny0 && minynext; 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 ; iblockbox; 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 ; isidedef) { 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; ifrontsector->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; ilines = linebuffer; linebuffer += sector->linecount; sector->linecount = 0; M_ClearBox(sector->blockbox); } } // Enter those lines for (i=0,li=lines; ifrontsector); if (li->backsector && li->backsector != li->frontsector) P_AddLineToSector(li, li->backsector); } for (i=0, sector = sectors; iblockbox; // 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; idx && 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