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 }