// Emacs style mode select -*- C++ -*- //----------------------------------------------------------------------------- // // $Id:$ // // Copyright (C) 1993-1996 by id Software, Inc. // // This source is available for distribution and/or modification // only under the terms of the DOOM Source Code License as // published by id Software. All rights reserved. // // The source is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License // for more details. // // $Log:$ // // DESCRIPTION: // Sector utility functions. // //----------------------------------------------------------------------------- #include "r_data.h" #include "p_spec.h" #include "c_cvars.h" // [RH] // P_NextSpecialSector() // // Returns the next special sector attached to this sector // with a certain special. sector_t *sector_t::NextSpecialSector (int type, sector_t *nogood) const { sector_t *tsec; int i; for (i = 0; i < linecount; i++) { line_t *ln = lines[i]; if (NULL != (tsec = getNextSector (ln, this)) && tsec != nogood && (tsec->special & 0x00ff) == type) { return tsec; } } return NULL; } // // P_FindLowestFloorSurrounding() // FIND LOWEST FLOOR HEIGHT IN SURROUNDING SECTORS // fixed_t sector_t::FindLowestFloorSurrounding (vertex_t **v) const { int i; sector_t *other; line_t *check; fixed_t floor; fixed_t ofloor; vertex_t *spot; if (linecount == 0) return floortexz; spot = lines[0]->v1; floor = floorplane.ZatPoint (spot); for (i = 0; i < linecount; i++) { check = lines[i]; if (NULL != (other = getNextSector (check, this))) { ofloor = other->floorplane.ZatPoint (check->v1); if (ofloor < floor && ofloor < floorplane.ZatPoint (check->v1)) { floor = ofloor; spot = check->v1; } ofloor = other->floorplane.ZatPoint (check->v2); if (ofloor < floor && ofloor < floorplane.ZatPoint (check->v2)) { floor = ofloor; spot = check->v2; } } } if (v != NULL) *v = spot; return floor; } // // P_FindHighestFloorSurrounding() // FIND HIGHEST FLOOR HEIGHT IN SURROUNDING SECTORS // fixed_t sector_t::FindHighestFloorSurrounding (vertex_t **v) const { int i; line_t *check; sector_t *other; fixed_t floor; fixed_t ofloor; vertex_t *spot; if (linecount == 0) return floortexz; spot = lines[0]->v1; floor = FIXED_MIN; for (i = 0; i < linecount; i++) { check = lines[i]; if (NULL != (other = getNextSector (check, this))) { ofloor = other->floorplane.ZatPoint (check->v1); if (ofloor > floor) { floor = ofloor; spot = check->v1; } ofloor = other->floorplane.ZatPoint (check->v2); if (ofloor > floor) { floor = ofloor; spot = check->v2; } } } if (v != NULL) *v = spot; return floor; } // // P_FindNextHighestFloor() // // Passed a sector and a floor height, returns the fixed point value // of the smallest floor height in a surrounding sector larger than // the floor height passed. If no such height exists the floorheight // passed is returned. // // Rewritten by Lee Killough to avoid fixed array and to be faster // fixed_t sector_t::FindNextHighestFloor (vertex_t **v) const { fixed_t height; fixed_t heightdiff; fixed_t ofloor, floor; sector_t *other; vertex_t *spot; line_t *check; int i; if (linecount == 0) return floortexz; spot = lines[0]->v1; height = floorplane.ZatPoint (spot); heightdiff = FIXED_MAX; for (i = 0; i < linecount; i++) { check = lines[i]; if (NULL != (other = getNextSector (check, this))) { ofloor = other->floorplane.ZatPoint (check->v1); floor = floorplane.ZatPoint (check->v1); if (ofloor > floor && ofloor - floor < heightdiff) { heightdiff = ofloor - floor; height = ofloor; spot = check->v1; } ofloor = other->floorplane.ZatPoint (check->v2); floor = floorplane.ZatPoint (check->v2); if (ofloor > floor && ofloor - floor < heightdiff) { heightdiff = ofloor - floor; height = ofloor; spot = check->v2; } } } if (v != NULL) *v = spot; return height; } // // P_FindNextLowestFloor() // // Passed a sector and a floor height, returns the fixed point value // of the largest floor height in a surrounding sector smaller than // the floor height passed. If no such height exists the floorheight // passed is returned. // // jff 02/03/98 Twiddled Lee's P_FindNextHighestFloor to make this // fixed_t sector_t::FindNextLowestFloor (vertex_t **v) const { fixed_t height; fixed_t heightdiff; fixed_t ofloor, floor; sector_t *other; vertex_t *spot; line_t *check; int i; if (linecount == 0) return floortexz; spot = lines[0]->v1; height = floorplane.ZatPoint (spot); heightdiff = FIXED_MAX; for (i = 0; i < linecount; i++) { check = lines[i]; if (NULL != (other = getNextSector (check, this))) { if (other - sectors == 6) other = other; ofloor = other->floorplane.ZatPoint (check->v1); floor = floorplane.ZatPoint (check->v1); if (ofloor < floor && floor - ofloor < heightdiff) { heightdiff = floor - ofloor; height = ofloor; spot = check->v1; } ofloor = other->floorplane.ZatPoint (check->v2); floor = floorplane.ZatPoint (check->v2); if (ofloor < floor && floor - ofloor < heightdiff) { heightdiff = floor - ofloor; height = ofloor; spot = check->v2; } } } if (v != NULL) *v = spot; return height; } // // P_FindNextLowestCeiling() // // Passed a sector and a ceiling height, returns the fixed point value // of the largest ceiling height in a surrounding sector smaller than // the ceiling height passed. If no such height exists the ceiling height // passed is returned. // // jff 02/03/98 Twiddled Lee's P_FindNextHighestFloor to make this // fixed_t sector_t::FindNextLowestCeiling (vertex_t **v) const { fixed_t height; fixed_t heightdiff; fixed_t oceil, ceil; sector_t *other; vertex_t *spot; line_t *check; int i; if (linecount == 0) return ceilingtexz; spot = lines[0]->v1; height = ceilingplane.ZatPoint (spot); heightdiff = FIXED_MAX; for (i = 0; i < linecount; i++) { check = lines[i]; if (NULL != (other = getNextSector (check, this))) { oceil = other->ceilingplane.ZatPoint (check->v1); ceil = ceilingplane.ZatPoint (check->v1); if (oceil < ceil && ceil - oceil < heightdiff) { heightdiff = ceil - oceil; height = oceil; spot = check->v1; } oceil = other->ceilingplane.ZatPoint (check->v2); ceil = ceilingplane.ZatPoint (check->v2); if (oceil < ceil && ceil - oceil < heightdiff) { heightdiff = ceil - oceil; height = oceil; spot = check->v2; } } } if (v != NULL) *v = spot; return height; } // // P_FindNextHighestCeiling() // // Passed a sector and a ceiling height, returns the fixed point value // of the smallest ceiling height in a surrounding sector larger than // the ceiling height passed. If no such height exists the ceiling height // passed is returned. // // jff 02/03/98 Twiddled Lee's P_FindNextHighestFloor to make this // fixed_t sector_t::FindNextHighestCeiling (vertex_t **v) const { fixed_t height; fixed_t heightdiff; fixed_t oceil, ceil; sector_t *other; vertex_t *spot; line_t *check; int i; if (linecount == 0) return ceilingtexz; spot = lines[0]->v1; height = ceilingplane.ZatPoint (spot); heightdiff = FIXED_MAX; for (i = 0; i < linecount; i++) { check = lines[i]; if (NULL != (other = getNextSector (check, this))) { oceil = other->ceilingplane.ZatPoint (check->v1); ceil = ceilingplane.ZatPoint (check->v1); if (oceil > ceil && oceil - ceil < heightdiff) { heightdiff = oceil - ceil; height = oceil; spot = check->v1; } oceil = other->ceilingplane.ZatPoint (check->v2); ceil = ceilingplane.ZatPoint (check->v2); if (oceil > ceil && oceil - ceil < heightdiff) { heightdiff = oceil - ceil; height = oceil; spot = check->v2; } } } if (v != NULL) *v = spot; return height; } // // FIND LOWEST CEILING IN THE SURROUNDING SECTORS // fixed_t sector_t::FindLowestCeilingSurrounding (vertex_t **v) const { fixed_t height; fixed_t oceil; sector_t *other; vertex_t *spot; line_t *check; int i; if (linecount == 0) return ceilingtexz; spot = lines[0]->v1; height = FIXED_MAX; for (i = 0; i < linecount; i++) { check = lines[i]; if (NULL != (other = getNextSector (check, this))) { oceil = other->ceilingplane.ZatPoint (check->v1); if (oceil < height) { height = oceil; spot = check->v1; } oceil = other->ceilingplane.ZatPoint (check->v2); if (oceil < height) { height = oceil; spot = check->v2; } } } if (v != NULL) *v = spot; return height; } // // FIND HIGHEST CEILING IN THE SURROUNDING SECTORS // fixed_t sector_t::FindHighestCeilingSurrounding (vertex_t **v) const { fixed_t height; fixed_t oceil; sector_t *other; vertex_t *spot; line_t *check; int i; if (linecount == 0) return ceilingtexz; spot = lines[0]->v1; height = FIXED_MIN; for (i = 0; i < linecount; i++) { check = lines[i]; if (NULL != (other = getNextSector (check, this))) { oceil = other->ceilingplane.ZatPoint (check->v1); if (oceil > height) { height = oceil; spot = check->v1; } oceil = other->ceilingplane.ZatPoint (check->v2); if (oceil > height) { height = oceil; spot = check->v2; } } } if (v != NULL) *v = spot; return height; } // // P_FindShortestTextureAround() // // Passed a sector number, returns the shortest lower texture on a // linedef bounding the sector. // // jff 02/03/98 Add routine to find shortest lower texture // static inline void CheckShortestTex (int texnum, fixed_t &minsize) { if (texnum > 0 || (texnum == 0 && (compatflags & COMPATF_SHORTTEX))) { FTexture *tex = TexMan[texnum]; int yscale = tex->ScaleY ? tex->ScaleY : 8; fixed_t h = DivScale19 (tex->GetHeight(), yscale); if (h < minsize) { minsize = h; } } } fixed_t sector_t::FindShortestTextureAround () const { fixed_t minsize = FIXED_MAX; for (int i = 0; i < linecount; i++) { if (lines[i]->flags & ML_TWOSIDED) { CheckShortestTex (sides[lines[i]->sidenum[0]].bottomtexture, minsize); CheckShortestTex (sides[lines[i]->sidenum[1]].bottomtexture, minsize); } } return minsize < FIXED_MAX ? minsize : TexMan[0]->GetHeight() * FRACUNIT; } // // P_FindShortestUpperAround() // // Passed a sector number, returns the shortest upper texture on a // linedef bounding the sector. // // Note: If no upper texture exists MAXINT is returned. // // jff 03/20/98 Add routine to find shortest upper texture // fixed_t sector_t::FindShortestUpperAround () const { fixed_t minsize = FIXED_MAX; for (int i = 0; i < linecount; i++) { if (lines[i]->flags & ML_TWOSIDED) { CheckShortestTex (sides[lines[i]->sidenum[0]].toptexture, minsize); CheckShortestTex (sides[lines[i]->sidenum[1]].toptexture, minsize); } } return minsize < FIXED_MAX ? minsize : TexMan[0]->GetHeight() * FRACUNIT; } // // P_FindModelFloorSector() // // Passed a floor height and a sector number, return a pointer to a // a sector with that floor height across the lowest numbered two sided // line surrounding the sector. // // Note: If no sector at that height bounds the sector passed, return NULL // // jff 02/03/98 Add routine to find numeric model floor // around a sector specified by sector number // jff 3/14/98 change first parameter to plain height to allow call // from routine not using floormove_t // sector_t *sector_t::FindModelFloorSector (fixed_t floordestheight) const { int i; sector_t *sec; //jff 5/23/98 don't disturb sec->linecount while searching // but allow early exit in old demos for (i = 0; i < linecount; i++) { sec = getNextSector (lines[i], this); if (sec != NULL && (sec->floorplane.ZatPoint (lines[i]->v1) == floordestheight || sec->floorplane.ZatPoint (lines[i]->v2) == floordestheight)) { return sec; } } return NULL; } // // P_FindModelCeilingSector() // // Passed a ceiling height and a sector number, return a pointer to a // a sector with that ceiling height across the lowest numbered two sided // line surrounding the sector. // // Note: If no sector at that height bounds the sector passed, return NULL // // jff 02/03/98 Add routine to find numeric model ceiling // around a sector specified by sector number // used only from generalized ceiling types // jff 3/14/98 change first parameter to plain height to allow call // from routine not using ceiling_t // sector_t *sector_t::FindModelCeilingSector (fixed_t floordestheight) const { int i; sector_t *sec; //jff 5/23/98 don't disturb sec->linecount while searching // but allow early exit in old demos for (i = 0; i < linecount; i++) { sec = getNextSector (lines[i], this); if (sec != NULL && (sec->ceilingplane.ZatPoint (lines[i]->v1) == floordestheight || sec->ceilingplane.ZatPoint (lines[i]->v2) == floordestheight)) { return sec; } } return NULL; } // // Find minimum light from an adjacent sector // int sector_t::FindMinSurroundingLight (int min) const { int i; line_t* line; sector_t* check; for (i = 0; i < linecount; i++) { line = lines[i]; if (NULL != (check = getNextSector (line, this)) && check->lightlevel < min) { min = check->lightlevel; } } return min; } // // Find the highest point on the floor of the sector // fixed_t sector_t::FindHighestFloorPoint (vertex_t **v) const { int i; line_t *line; fixed_t height = FIXED_MIN; fixed_t probeheight; vertex_t *spot = NULL; if ((floorplane.a | floorplane.b) == 0) { if (v != NULL) { if (linecount == 0) *v = &vertexes[0]; else *v = lines[0]->v1; } return -floorplane.d; } for (i = 0; i < linecount; i++) { line = lines[i]; probeheight = floorplane.ZatPoint (line->v1); if (probeheight > height) { height = probeheight; spot = line->v1; } probeheight = floorplane.ZatPoint (line->v2); if (probeheight > height) { height = probeheight; spot = line->v2; } } if (v != NULL) *v = spot; return height; } // // Find the lowest point on the ceiling of the sector // fixed_t sector_t::FindLowestCeilingPoint (vertex_t **v) const { int i; line_t *line; fixed_t height = FIXED_MAX; fixed_t probeheight; vertex_t *spot = NULL; if ((ceilingplane.a | ceilingplane.b) == 0) { if (v != NULL) { if (linecount == 0) *v = &vertexes[0]; else *v = lines[0]->v1; } return ceilingplane.d; } for (i = 0; i < linecount; i++) { line = lines[i]; probeheight = ceilingplane.ZatPoint (line->v1); if (probeheight < height) { height = probeheight; spot = line->v1; } probeheight = ceilingplane.ZatPoint (line->v2); if (probeheight < height) { height = probeheight; spot = line->v2; } } if (v != NULL) *v = spot; return height; }