/ source / blood / src / endgame.cpp
endgame.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 "common.h"
 25  #include "mmulti.h"
 26  #include "fx_man.h"
 27  #include "common_game.h"
 28  #include "blood.h"
 29  #include "endgame.h"
 30  #include "globals.h"
 31  #include "levels.h"
 32  #include "loadsave.h"
 33  #include "menu.h"
 34  #include "network.h"
 35  #include "player.h"
 36  #include "sound.h"
 37  #include "view.h"
 38  #include "messages.h"
 39  
 40  CEndGameMgr::CEndGameMgr()
 41  {
 42      at0 = 0;
 43  }
 44  
 45  void CEndGameMgr::Draw(void)
 46  {
 47      viewLoadingScreenWide();
 48      int nHeight;
 49      gMenuTextMgr.GetFontInfo(1, NULL, NULL, &nHeight);
 50      rotatesprite(160<<16, 20<<16, 65536, 0, 2038, -128, 0, 6|8, 0, 0, xdim-1, ydim-1);
 51      int nY = 20 - nHeight / 2;
 52      if (gGameOptions.nGameType == kGameTypeSinglePlayer)
 53      {
 54          viewDrawText(1, "LEVEL STATS", 160, nY, -128, 0, 1, 0);
 55          if (CCheatMgr::m_bPlayerCheated)
 56          {
 57              viewDrawText(3, ">>> YOU CHEATED! <<<", 160, 32, -128, 0, 1, 1);
 58          }
 59          gKillMgr.Draw();
 60          gSecretMgr.Draw();
 61      }
 62      else
 63      {
 64          viewDrawText(1, "FRAG STATS", 160, nY, -128, 0, 1, 0);
 65          gKillMgr.Draw();
 66      }
 67      if (gShowCompleteTime && (gGameOptions.nGameType <= kGameTypeCoop))
 68      {
 69          char pBuffer[40];
 70          const int levelTime = gLevelTime-1;
 71          sprintf(pBuffer, "LEVEL TIME: %d:%02d.%02d",
 72              (levelTime/(kTicsPerSec*60)),
 73              (levelTime/kTicsPerSec)%60,
 74              ((levelTime%kTicsPerSec)*33)/10
 75              );
 76          viewDrawText(3, pBuffer, 160, 121, -128, 0, 1, 1);
 77      }
 78      if (/*dword_28E3D4 != 1 && */((int)totalclock&32))
 79      {
 80          viewDrawText(3, "PRESS A KEY TO CONTINUE", 160, 134, -128, 0, 1, 1);
 81      }
 82  }
 83  
 84  void CEndGameMgr::ProcessKeys(void)
 85  {
 86      //if (dword_28E3D4 == 1)
 87      //{
 88      //    if (gGameOptions.gameType != kGameTypeSinglePlayer || numplayers > 1)
 89      //        netWaitForEveryone(0);
 90      //    Finish();
 91      //}
 92      //else
 93      {
 94          char ch = keyGetScan();
 95          if (CONTROL_JoystickEnabled && !ch)
 96          {
 97              int32_t joy = JOYSTICK_GetControllerButtons();
 98              JOYSTICK_ClearAllButtons();
 99              ch = joy == (1 << CONTROLLER_BUTTON_START);
100          }
101          if (!ch)
102              return;
103          if (gGameOptions.nGameType != kGameTypeSinglePlayer || numplayers > 1)
104              netWaitForEveryone(0);
105          Finish();
106      }
107  }
108  
109  extern void EndLevel(void);
110  
111  void CEndGameMgr::Setup(void)
112  {
113      at1 = gInputMode;
114      gInputMode = INPUT_MODE_3;
115      at0 = 1;
116      EndLevel();
117      sndStartSample(268, 128, -1, 1);
118      keyFlushScans();
119  }
120  
121  //int gNextLevel;
122  
123  void CEndGameMgr::Finish(void)
124  {
125      levelSetupOptions(gGameOptions.nEpisode, gNextLevel);
126      gInitialNetPlayers = numplayers;
127      //if (FXDevice != -1)
128          FX_StopAllSounds();
129      sndKillAllSounds();
130      gStartNewGame = 1;
131      gInputMode = (INPUT_MODE)at1;
132      at0 = 0;
133  }
134  
135  CKillMgr::CKillMgr()
136  {
137      Clear();
138  }
139  
140  bool CKillMgr::AllowedType(spritetype *pSprite)
141  {
142      if (!pSprite)
143          return false;
144      if (pSprite->statnum != kStatDude)
145          return false;
146      if (pSprite->type == kDudeGargoyleStatueFlesh || pSprite->type == kDudeGargoyleStatueStone) // if statue gargoyle, do not count as enemy until they activate
147          return VanillaMode();
148      return pSprite->type != kDudeBat && pSprite->type != kDudeRat && pSprite->type != kDudeInnocent && pSprite->type != kDudeBurningInnocent;
149  }
150  
151  void CKillMgr::SetCount(int nCount)
152  {
153      at0 = nCount;
154  }
155  
156  void CKillMgr::AddCount(int nCount)
157  {
158      at0 += nCount;
159  }
160  
161  void CKillMgr::AddCount(spritetype* pSprite)
162  {
163      dassert(pSprite != NULL);
164      if (VanillaMode() || AllowedType(pSprite))// check type before adding to enemy count
165          at0++;
166  }
167  
168  void CKillMgr::AddKill(spritetype* pSprite)
169  {
170      dassert(pSprite != NULL);
171      if (AllowedType(pSprite)) // check type before adding to enemy kills
172          at4++;
173  }
174  
175  void CKillMgr::RemoveKill(spritetype* pSprite)
176  {
177      if (gKillMgr.at4 <= 0)
178          return;
179      dassert(pSprite != NULL);
180      if (VanillaMode() || AllowedType(pSprite)) // check type before removing from enemy kills
181          at4--;
182  }
183  
184  void CKillMgr::CountTotalKills(void)
185  {
186      at0 = 0;
187      for (int nSprite = headspritestat[kStatDude]; nSprite >= 0; nSprite = nextspritestat[nSprite])
188      {
189          spritetype* pSprite = &sprite[nSprite];
190          if (pSprite->type < kDudeBase || pSprite->type >= kDudeMax)
191              ThrowError("Non-enemy sprite (%d) in the enemy sprite list.", nSprite);
192          if (AllowedType(pSprite))
193              AddCount(1);
194      }
195  }
196  
197  void CKillMgr::Draw(void)
198  {
199      char pBuffer[40];
200      if (gGameOptions.nGameType == kGameTypeSinglePlayer)
201      {
202          viewDrawText(1, "KILLS:", 75, 50, -128, 0, 0, 1);
203          sprintf(pBuffer, "%2d", at4);
204          viewDrawText(1, pBuffer, 160, 50, -128, 0, 0, 1);
205          viewDrawText(1, "OF", 190, 50, -128, 0, 0, 1);
206          sprintf(pBuffer, "%2d", at0);
207          viewDrawText(1, pBuffer, 220, 50, -128, 0, 0, 1);
208      }
209      else
210      {
211          viewDrawText(3, "#", 85, 35, -128, 0, 0, 1);
212          viewDrawText(3, "NAME", 100, 35, -128, 0, 0, 1);
213          viewDrawText(3, "FRAGS", 210, 35, -128, 0, 0, 1);
214          int nStart = 0;
215          int nEnd = gInitialNetPlayers;
216          //if (dword_28E3D4 == 1)
217          //{
218          //    nStart++;
219          //    nEnd++;
220          //}
221          for (int i = nStart; i < nEnd; i++)
222          {
223              sprintf(pBuffer, "%-2d", i);
224              viewDrawText(3, pBuffer, 85, 50+8*i, -128, 0, 0, 1);
225              sprintf(pBuffer, "%s", gProfile[i].name);
226              viewDrawText(3, pBuffer, 100, 50+8*i, -128, 0, 0, 1);
227              sprintf(pBuffer, "%d", gPlayer[i].fragCount);
228              viewDrawText(3, pBuffer, 210, 50+8*i, -128, 0, 0, 1);
229          }
230      }
231  }
232  
233  void CKillMgr::Clear(void)
234  {
235      at0 = at4 = 0;
236  }
237  
238  CSecretMgr::CSecretMgr(void)
239  {
240      Clear();
241  }
242  
243  void CSecretMgr::SetCount(int nCount)
244  {
245      nAllSecrets = nCount;
246  }
247  
248  void CSecretMgr::Found(int nType)
249  {
250      if (nType == 0) nNormalSecretsFound++;
251      else if (nType < 0) {
252          viewSetSystemMessage("Invalid secret type %d triggered.", nType);
253          return;
254      } else nSuperSecretsFound++;
255  
256      if (gGameOptions.nGameType == kGameTypeSinglePlayer) {
257          if (!VanillaMode() && (gSecretStyle >= 2)) {
258              if (gSecretStyle == 2) {
259                  sndStartSample("NOTBLOOD4", 102, -1, 11025);
260                  gSecretStyle = 3;
261              }
262              return;
263          }
264          switch (Random(2)) {
265              case 0:
266                  viewSetMessage("A secret is revealed.", VanillaMode() || !gSecretStyle ? 0 : 8, MESSAGE_PRIORITY_SECRET); // 8: gold
267                  break;
268              case 1:
269                  viewSetMessage("You found a secret.", VanillaMode() || !gSecretStyle ? 0 : 8, MESSAGE_PRIORITY_SECRET); // 8: gold
270                  break;
271          }
272      }
273  }
274  
275  void CSecretMgr::Draw(void)
276  {
277      char pBuffer[40];
278      viewDrawText(1, "SECRETS:", 75, 70, -128, 0, 0, 1);
279      sprintf(pBuffer, "%2d", nNormalSecretsFound);
280      viewDrawText(1, pBuffer, 160, 70, -128, 0, 0, 1);
281      viewDrawText(1, "OF", 190, 70, -128, 0, 0, 1);
282      sprintf(pBuffer, "%2d", VanillaMode() ? gSecretMgr.nAllSecrets : max(gSecretMgr.nNormalSecretsFound, gSecretMgr.nAllSecrets));
283      viewDrawText(1, pBuffer, 220, 70, -128, 0, 0, 1);
284      if (nSuperSecretsFound > 0)
285          viewDrawText(1, "YOU FOUND A SUPER SECRET!", 160, 100, -128, 2, 1, 1);
286  }
287  
288  void CSecretMgr::Clear(void)
289  {
290      nAllSecrets = nNormalSecretsFound = nSuperSecretsFound = 0;
291  }
292  
293  class EndGameLoadSave : public LoadSave {
294  public:
295      virtual void Load(void);
296      virtual void Save(void);
297  };
298  
299  void EndGameLoadSave::Load(void)
300  {
301      Read(&gSecretMgr.nAllSecrets, 4);
302      Read(&gSecretMgr.nNormalSecretsFound, 4);
303      Read(&gSecretMgr.nSuperSecretsFound, 4);
304      Read(&gKillMgr.at0, 4);
305      Read(&gKillMgr.at4, 4);
306  }
307  
308  void EndGameLoadSave::Save(void)
309  {
310      Write(&gSecretMgr.nAllSecrets, 4);
311      Write(&gSecretMgr.nNormalSecretsFound, 4);
312      Write(&gSecretMgr.nSuperSecretsFound, 4);
313      Write(&gKillMgr.at0, 4);
314      Write(&gKillMgr.at4, 4);
315  }
316  
317  CEndGameMgr gEndGameMgr;
318  CSecretMgr gSecretMgr;
319  CKillMgr gKillMgr;
320  static EndGameLoadSave *myLoadSave;
321  
322  void EndGameLoadSaveConstruct(void)
323  {
324      myLoadSave = new EndGameLoadSave();
325  }