map2d.cpp
1 //------------------------------------------------------------------------- 2 /* 3 Copyright (C) 2010-2019 EDuke32 developers and contributors 4 Copyright (C) 2019 Nuke.YKT 5 6 This file is part of NBlood. 7 8 NBlood is free software; you can redistribute it and/or 9 modify it under the terms of the GNU General Public License version 2 10 as published by the Free Software Foundation. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 15 16 See the GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program; if not, write to the Free Software 20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 21 */ 22 //------------------------------------------------------------------------- 23 #include "build.h" 24 #include "mmulti.h" 25 #include "common_game.h" 26 #include "levels.h" 27 #include "map2d.h" 28 #include "trig.h" 29 #include "view.h" 30 31 void DrawMap(int x, int y, int z, short a) 32 { 33 int tmpydim = (xdim * 5) / 8; 34 renderSetAspect(65536, divscale16(tmpydim * 320, xdim * 200)); 35 int nCos = z*sintable[(0-a)&2047]; 36 int nSin = z*sintable[(1536-a)&2047]; 37 int nCos2 = mulscale16(nCos, yxaspect); 38 int nSin2 = mulscale16(nSin, yxaspect); 39 for (int i = 0; i < numsectors; i++) 40 { 41 if (gFullMap || (show2dsector[i>>3]&(1<<(i&7)))) 42 { 43 int nStartWall = sector[i].wallptr; 44 int nEndWall = nStartWall+sector[i].wallnum; 45 int nZCeil = sector[i].ceilingz; 46 int nZFloor = sector[i].floorz; 47 walltype *pWall = &wall[nStartWall]; 48 for (int j = nStartWall; j < nEndWall; j++, pWall++) 49 { 50 int nNextWall = pWall->nextwall; 51 if (nNextWall < 0) 52 continue; 53 if (sector[pWall->nextsector].ceilingz == nZCeil && sector[pWall->nextsector].floorz == nZFloor 54 && ((wall[nNextWall].cstat | pWall->cstat) & 0x30) == 0) 55 continue; 56 if (gFullMap) 57 continue; 58 if (show2dsector[pWall->nextsector>>3]&(1<<(pWall->nextsector&7))) 59 continue; 60 int wx = pWall->x-x; 61 int wy = pWall->y-y; 62 int cx = xdim<<11; 63 int x1 = cx+dmulscale16(wx, nCos, -wy, nSin); 64 int cy = ydim<<11; 65 int y1 = cy+dmulscale16(wy, nCos2, wx, nSin2); 66 walltype *pWall2 = &wall[pWall->point2]; 67 wx = pWall2->x-x; 68 wy = pWall2->y-y; 69 int x2 = cx+dmulscale16(wx, nCos, -wy, nSin); 70 int y2 = cy+dmulscale16(wy, nCos2, wx, nSin2); 71 renderDrawLine(x1,y1,x2,y2,24); 72 } 73 } 74 } 75 int nPSprite = gView->pSprite->index; 76 for (int i = 0; i < numsectors; i++) 77 { 78 if (gFullMap || (show2dsector[i>>3]&(1<<(i&7)))) 79 { 80 for (int nSprite = headspritesect[i]; nSprite >= 0; nSprite = nextspritesect[nSprite]) 81 { 82 spritetype *pSprite = &sprite[nSprite]; 83 if (nSprite == nPSprite) 84 continue; 85 if (pSprite->cstat&32768) 86 continue; 87 } 88 } 89 } 90 for (int i = 0; i < numsectors; i++) 91 { 92 if (gFullMap || (show2dsector[i>>3]&(1<<(i&7)))) 93 { 94 int nStartWall = sector[i].wallptr; 95 int nEndWall = nStartWall+sector[i].wallnum; 96 walltype *pWall = &wall[nStartWall]; 97 int nNWall = -1; 98 int x1, y1, x2 = 0, y2 = 0; 99 for (int j = nStartWall; j < nEndWall; j++, pWall++) 100 { 101 int nNextWall = pWall->nextwall; 102 if (nNextWall >= 0) 103 continue; 104 if (!tilesiz[pWall->picnum].x || !tilesiz[pWall->picnum].y) 105 continue; 106 if (nNWall == j) 107 { 108 x1 = x2; 109 y1 = y2; 110 } 111 else 112 { 113 int wx = pWall->x-x; 114 int wy = pWall->y-y; 115 x1 = (xdim<<11)+dmulscale16(wx, nCos, -wy, nSin); 116 y1 = (ydim<<11)+dmulscale16(wy, nCos2, wx, nSin2); 117 } 118 nNWall = pWall->point2; 119 walltype *pWall2 = &wall[nNWall]; 120 int wx = pWall2->x-x; 121 int wy = pWall2->y-y; 122 x2 = (xdim<<11)+dmulscale16(wx, nCos, -wy, nSin); 123 y2 = (ydim<<11)+dmulscale16(wy, nCos2, wx, nSin2); 124 renderDrawLine(x1,y1,x2,y2,24); 125 } 126 } 127 } 128 videoSetCorrectedAspect(); 129 130 for (int i = connecthead; i >= 0; i = connectpoint2[i]) 131 { 132 if (gViewMap.bFollowMode || gView->nPlayer != i) 133 { 134 PLAYER *pPlayer = &gPlayer[i]; 135 spritetype *pSprite = pPlayer->pSprite; 136 int px = pSprite->x-x; 137 int py = pSprite->y-y; 138 int pa = (pSprite->ang-a)&kAngMask; 139 if (i == gView->nPlayer) 140 { 141 px = 0; 142 py = 0; 143 pa = 0; 144 } 145 int x1 = dmulscale16(px, nCos, -py, nSin); 146 int y1 = dmulscale16(py, nCos2, px, nSin2); 147 if (i == gView->nPlayer || gGameOptions.nGameType == kGameTypeCoop) 148 { 149 int nTile = pSprite->picnum; 150 int ceilZ, ceilHit, floorZ, floorHit; 151 GetZRange(pSprite, &ceilZ, &ceilHit, &floorZ, &floorHit, (pSprite->clipdist<<2)+16, CLIPMASK0, PARALLAXCLIP_CEILING|PARALLAXCLIP_FLOOR); 152 int nTop, nBottom; 153 GetSpriteExtents(pSprite, &nTop, &nBottom); 154 int nScale = mulscale16((pSprite->yrepeat+((floorZ-nBottom)>>8))*z, yxaspect); 155 nScale = ClipRange(nScale, 8000, 65536<<1); 156 rotatesprite((xdim<<15)+(x1<<4), (ydim<<15)+(y1<<4), nScale, pa, nTile, pSprite->shade, pSprite->pal, (pSprite->cstat&2)>>1, 157 windowxy1.x, windowxy1.y, windowxy2.x, windowxy2.y); 158 } 159 } 160 } 161 } 162 163 CViewMap::CViewMap() 164 { 165 bActive = 0; 166 } 167 168 void CViewMap::Init(int _x, int _y, int _angle, short zoom, char unk1) 169 { 170 bActive = 1; 171 x = _x; 172 y = _y; 173 angle = _angle; 174 nZoom = zoom; 175 FollowMode(unk1); 176 forward = 0; 177 turn = 0; 178 strafe = 0; 179 xoffset = 0; 180 } 181 182 void CViewMap::Draw(void) 183 { 184 char pBuffer[128]; 185 if (!bActive) 186 return; 187 char tm = 0; 188 int viewSize = gViewSize; 189 if (gViewSize > 5) 190 { 191 viewResizeView(5); 192 tm = 1; 193 } 194 videoClearScreen(0); 195 renderDrawMapView(x,y,nZoom>>2,angle); 196 DrawMap(x,y,nZoom>>2,angle); 197 198 if (videoGetRenderMode() == REND_CLASSIC && (MIRRORMODE & 1)) // mirror framebuffer for classic renderer 199 videoMirrorDrawing(); 200 201 char *pTitle = levelGetTitle(); 202 char *pFilename = levelGetFilename(gGameOptions.nEpisode, gGameOptions.nLevel); 203 if (pTitle) 204 sprintf(pBuffer, "%s: %s", pFilename, pTitle); 205 else 206 sprintf(pBuffer, "%s", pFilename); 207 int nViewY; 208 if (gViewSize > 5) 209 nViewY = gViewY1S-16; 210 else 211 nViewY = gViewY0S + (!VanillaMode() && (gGameOptions.nGameType == kGameTypeSinglePlayer) ? 6 : 1); 212 viewDrawText(3, pBuffer, gViewX1S+xoffset, nViewY, -128, 0, 2, 0, 256); 213 214 if (gViewMap.bFollowMode) 215 viewDrawText(3, "MAP FOLLOW MODE", gViewX1S+xoffset, nViewY+8, -128, 0, 2, 0, 256); 216 else 217 viewDrawText(3, "MAP SCROLL MODE", gViewX1S+xoffset, nViewY+8, -128, 0, 2, 0, 256); 218 if (tm) 219 viewResizeView(viewSize); 220 } 221 222 void CViewMap::Process(int nX, int nY, short nAng) 223 { 224 nZoom = scale(gZoom, ydim, 200) >> 1; // scale to display resolution 225 if (bFollowMode) 226 { 227 x = nX; 228 y = nY; 229 angle = nAng; 230 } 231 else 232 { 233 angle += fix16_to_int(turn)>>3; 234 x += mulscale24(forward>>8, Cos(angle)); 235 y += mulscale24(forward>>8, Sin(angle)); 236 x -= mulscale24(strafe>>8, Cos(angle+512)); 237 y -= mulscale24(strafe>>8, Sin(angle+512)); 238 forward = 0; 239 strafe = 0; 240 turn = 0; 241 } 242 Draw(); 243 } 244 245 void CViewMap::SetPos(int *_x, int *_y) 246 { 247 if (_x) 248 *_x = x; 249 if (_y) 250 *_y = y; 251 } 252 253 void CViewMap::FollowMode(char mode) 254 { 255 bFollowMode = mode; 256 } 257 258 CViewMap gViewMap;