//------------------------------------------------------------------------- /* Copyright (C) 1997, 2005 - 3D Realms Entertainment This file is part of Shadow Warrior version 1.2 Shadow Warrior 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. Original Source: 1997 - Frank Maddin and Jim Norwood Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms */ //------------------------------------------------------------------------- #include "ns.h" #include "build.h" #include "game.h" #include "menus.h" #include "network.h" #include "pal.h" #include "v_draw.h" BEGIN_SW_NS extern SWBOOL mapcheat; enum { MAP_WHITE_SECTOR = (LT_GREY + 2), MAP_RED_SECTOR = (RED + 6), MAP_FLOOR_SPRITE = (RED + 8), MAP_ENEMY = (RED + 10), MAP_SPRITE = (FIRE + 8), MAP_PLAYER = (GREEN + 6), MAP_BLOCK_SPRITE = (DK_BLUE + 6), }; void drawoverheadmap(int cposx, int cposy, int czoom, short cang) { int i, j, k, l, x1, y1, x2, y2, x3, y3, x4, y4, ox, oy, xoff, yoff; int dax, day, cosang, sinang, xspan, yspan, sprx, spry; int xrepeat, yrepeat, z1, z2, startwall, endwall, tilenum, daang; int xvect, yvect, xvect2, yvect2; char col; walltype *wal, *wal2; spritetype *spr; short p; static int pspr_ndx[8]= {0,0,0,0,0,0,0,0}; SWBOOL sprisplayer = FALSE; short txt_x, txt_y; int32_t tmpydim = (xdim * 5) / 8; renderSetAspect(65536, divscale16(tmpydim * 320, xdim * 200)); xvect = sintable[(2048 - cang) & 2047] * czoom; yvect = sintable[(1536 - cang) & 2047] * czoom; xvect2 = mulscale16(xvect, yxaspect); yvect2 = mulscale16(yvect, yxaspect); // Draw red lines for (i = 0; i < numsectors; i++) { startwall = sector[i].wallptr; endwall = sector[i].wallptr + sector[i].wallnum - 1; z1 = sector[i].ceilingz; z2 = sector[i].floorz; for (j = startwall, wal = &wall[startwall]; j <= endwall; j++, wal++) { k = wal->nextwall; if ((unsigned)k >= MAXWALLS) continue; if (!mapcheat) { if ((show2dwall[j >> 3] & (1 << (j & 7))) == 0) continue; if ((k > j) && ((show2dwall[k >> 3] & (1 << (k & 7))) > 0)) continue; } if (sector[wal->nextsector].ceilingz == z1) if (sector[wal->nextsector].floorz == z2) if (((wal->cstat | wall[wal->nextwall].cstat) & (16 + 32)) == 0) continue; col = 152; if (automapMode == am_full) { if (sector[i].floorz != sector[i].ceilingz) if (sector[wal->nextsector].floorz != sector[wal->nextsector].ceilingz) if (((wal->cstat | wall[wal->nextwall].cstat) & (16 + 32)) == 0) if (sector[i].floorz == sector[wal->nextsector].floorz) continue; if (sector[i].floorpicnum != sector[wal->nextsector].floorpicnum) continue; if (sector[i].floorshade != sector[wal->nextsector].floorshade) continue; col = 12; // 1=white / 31=black / 44=green / 56=pink / 128=yellow / 210=blue / 248=orange / 255=purple } ox = wal->x - cposx; oy = wal->y - cposy; x1 = mulscale16(ox, xvect) - mulscale16(oy, yvect); y1 = mulscale16(oy, xvect2) + mulscale16(ox, yvect2); wal2 = &wall[wal->point2]; ox = wal2->x - cposx; oy = wal2->y - cposy; x2 = mulscale16(ox, xvect) - mulscale16(oy, yvect); y2 = mulscale16(oy, xvect2) + mulscale16(ox, yvect2); renderDrawLine(x1 + (xdim << 11), y1 + (ydim << 11), x2 + (xdim << 11), y2 + (ydim << 11), col); } } // Draw sprites k = Player[screenpeek].PlayerSprite; for (i = 0; i < numsectors; i++) for (j = headspritesect[i]; j >= 0; j = nextspritesect[j]) { for (p=connecthead; p >= 0; p=connectpoint2[p]) { if (Player[p].PlayerSprite == j) { if (sprite[Player[p].PlayerSprite].xvel > 16) pspr_ndx[myconnectindex] = ((gameclock >> 4)&3); sprisplayer = TRUE; goto SHOWSPRITE; } } if (mapcheat || (show2dsprite[j >> 3] & (1 << (j & 7))) > 0) { SHOWSPRITE: spr = &sprite[j]; col = 56; // 1=white / 31=black / 44=green / 56=pink / 128=yellow / 210=blue / 248=orange / 255=purple if ((spr->cstat & 1) > 0) col = 248; if (j == k) col = 31; sprx = spr->x; spry = spr->y; k = spr->statnum; if ((k >= 1) && (k <= 8) && (k != 2)) // Interpolate moving { sprx = sprite[j].x; spry = sprite[j].y; } switch (spr->cstat & 48) { case 0: // Regular sprite if (Player[p].PlayerSprite == j) { ox = sprx - cposx; oy = spry - cposy; x1 = mulscale16(ox, xvect) - mulscale16(oy, yvect); y1 = mulscale16(oy, xvect2) + mulscale16(ox, yvect2); if (automapMode == am_overlay && (gNet.MultiGameType != MULTI_GAME_COMMBAT || j == Player[screenpeek].PlayerSprite)) { ox = (sintable[(spr->ang + 512) & 2047] >> 7); oy = (sintable[(spr->ang) & 2047] >> 7); x2 = mulscale16(ox, xvect) - mulscale16(oy, yvect); y2 = mulscale16(oy, xvect) + mulscale16(ox, yvect); if (j == Player[screenpeek].PlayerSprite) { x2 = 0L; y2 = -(czoom << 5); } x3 = mulscale16(x2, yxaspect); y3 = mulscale16(y2, yxaspect); renderDrawLine(x1 - x2 + (xdim << 11), y1 - y3 + (ydim << 11), x1 + x2 + (xdim << 11), y1 + y3 + (ydim << 11), col); renderDrawLine(x1 - y2 + (xdim << 11), y1 + x3 + (ydim << 11), x1 + x2 + (xdim << 11), y1 + y3 + (ydim << 11), col); renderDrawLine(x1 + y2 + (xdim << 11), y1 - x3 + (ydim << 11), x1 + x2 + (xdim << 11), y1 + y3 + (ydim << 11), col); } else { if (((gotsector[i >> 3] & (1 << (i & 7))) > 0) && (czoom > 192)) { daang = (spr->ang - cang) & 2047; if (j == Player[screenpeek].PlayerSprite) { x1 = 0; //y1 = (yxaspect << 2); y1 = 0; daang = 0; } // Special case tiles if (spr->picnum == 3123) break; int spnum = -1; if (sprisplayer) { if (gNet.MultiGameType != MULTI_GAME_COMMBAT || j == Player[screenpeek].PlayerSprite) spnum = 1196 + pspr_ndx[myconnectindex]; } else spnum = spr->picnum; double xd = ((x1 << 4) + (xdim << 15)) / 65536.; double yd = ((y1 << 4) + (ydim << 15)) / 65536.; double sc = mulscale16(czoom * (spr->yrepeat), yxaspect) / 65536.; if (spnum >= 0) { DrawTexture(twod, tileGetTexture(5407, true), xd, yd, DTA_FullscreenScale, FSMode_Fit320x200, DTA_CenterOffsetRel, true, DTA_TranslationIndex, TRANSLATION(Translation_Remap, spr->pal), DTA_Color, shadeToLight(spr->shade), DTA_Alpha, (spr->cstat & 2) ? 0.33 : 1., TAG_DONE); } } } } break; case 16: // Rotated sprite x1 = sprx; y1 = spry; tilenum = spr->picnum; xoff = (int)tileLeftOffset(tilenum) + (int)spr->xoffset; if ((spr->cstat & 4) > 0) xoff = -xoff; k = spr->ang; l = spr->xrepeat; dax = sintable[k & 2047] * l; day = sintable[(k + 1536) & 2047] * l; l = tilesiz[tilenum].x; k = (l >> 1) + xoff; x1 -= mulscale16(dax, k); x2 = x1 + mulscale16(dax, l); y1 -= mulscale16(day, k); y2 = y1 + mulscale16(day, l); ox = x1 - cposx; oy = y1 - cposy; x1 = mulscale16(ox, xvect) - mulscale16(oy, yvect); y1 = mulscale16(oy, xvect2) + mulscale16(ox, yvect2); ox = x2 - cposx; oy = y2 - cposy; x2 = mulscale16(ox, xvect) - mulscale16(oy, yvect); y2 = mulscale16(oy, xvect2) + mulscale16(ox, yvect2); renderDrawLine(x1 + (xdim << 11), y1 + (ydim << 11), x2 + (xdim << 11), y2 + (ydim << 11), col); break; case 32: // Floor sprite if (automapMode == am_overlay) { tilenum = spr->picnum; xoff = (int)tileLeftOffset(tilenum) + (int)spr->xoffset; yoff = (int)tileTopOffset(tilenum) + (int)spr->yoffset; if ((spr->cstat & 4) > 0) xoff = -xoff; if ((spr->cstat & 8) > 0) yoff = -yoff; k = spr->ang; cosang = sintable[(k + 512) & 2047]; sinang = sintable[k]; xspan = tilesiz[tilenum].x; xrepeat = spr->xrepeat; yspan = tilesiz[tilenum].y; yrepeat = spr->yrepeat; dax = ((xspan >> 1) + xoff) * xrepeat; day = ((yspan >> 1) + yoff) * yrepeat; x1 = sprx + mulscale16(sinang, dax) + mulscale16(cosang, day); y1 = spry + mulscale16(sinang, day) - mulscale16(cosang, dax); l = xspan * xrepeat; x2 = x1 - mulscale16(sinang, l); y2 = y1 + mulscale16(cosang, l); l = yspan * yrepeat; k = -mulscale16(cosang, l); x3 = x2 + k; x4 = x1 + k; k = -mulscale16(sinang, l); y3 = y2 + k; y4 = y1 + k; ox = x1 - cposx; oy = y1 - cposy; x1 = mulscale16(ox, xvect) - mulscale16(oy, yvect); y1 = mulscale16(oy, xvect2) + mulscale16(ox, yvect2); ox = x2 - cposx; oy = y2 - cposy; x2 = mulscale16(ox, xvect) - mulscale16(oy, yvect); y2 = mulscale16(oy, xvect2) + mulscale16(ox, yvect2); ox = x3 - cposx; oy = y3 - cposy; x3 = mulscale16(ox, xvect) - mulscale16(oy, yvect); y3 = mulscale16(oy, xvect2) + mulscale16(ox, yvect2); ox = x4 - cposx; oy = y4 - cposy; x4 = mulscale16(ox, xvect) - mulscale16(oy, yvect); y4 = mulscale16(oy, xvect2) + mulscale16(ox, yvect2); renderDrawLine(x1 + (xdim << 11), y1 + (ydim << 11), x2 + (xdim << 11), y2 + (ydim << 11), col); renderDrawLine(x2 + (xdim << 11), y2 + (ydim << 11), x3 + (xdim << 11), y3 + (ydim << 11), col); renderDrawLine(x3 + (xdim << 11), y3 + (ydim << 11), x4 + (xdim << 11), y4 + (ydim << 11), col); renderDrawLine(x4 + (xdim << 11), y4 + (ydim << 11), x1 + (xdim << 11), y1 + (ydim << 11), col); } break; } } } // Draw white lines for (i = 0; i < numsectors; i++) { startwall = sector[i].wallptr; endwall = sector[i].wallptr + sector[i].wallnum - 1; for (j = startwall, wal = &wall[startwall]; j <= endwall; j++, wal++) { if ((uint16_t)wal->nextwall < MAXWALLS) continue; if (!mapcheat && (show2dwall[j >> 3] & (1 << (j & 7))) == 0) continue; if (!tileGetTexture(wal->picnum)->isValid()) continue; ox = wal->x - cposx; oy = wal->y - cposy; x1 = mulscale16(ox, xvect) - mulscale16(oy, yvect); y1 = mulscale16(oy, xvect2) + mulscale16(ox, yvect2); wal2 = &wall[wal->point2]; ox = wal2->x - cposx; oy = wal2->y - cposy; x2 = mulscale16(ox, xvect) - mulscale16(oy, yvect); y2 = mulscale16(oy, xvect2) + mulscale16(ox, yvect2); renderDrawLine(x1 + (xdim << 11), y1 + (ydim << 11), x2 + (xdim << 11), y2 + (ydim << 11), 24); } } videoSetCorrectedAspect(); } END_SW_NS