/ source / blood / src / map2d.cpp
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;