//------------------------------------------------------------------------- /* Copyright (C) 2010-2019 EDuke32 developers and contributors Copyright (C) 2019 Nuke.YKT This file is part of NBlood. NBlood is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. 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. */ //------------------------------------------------------------------------- #include "ns.h" // Must come before everything else! #include "build.h" #include "mmulti.h" #include "compat.h" #include "gamecontrol.h" #include "common_game.h" #include "blood.h" #include "eventq.h" #include "globals.h" #include "levels.h" #include "loadsave.h" #include "messages.h" #include "player.h" #include "view.h" #include "gstrings.h" #include "cheathandler.h" #include "d_protocol.h" BEGIN_BLD_NS void sub_5A928(void) { for (int i = 0; i < buttonMap.NumButtons(); i++) buttonMap.ClearButton(i); } const char *SetGodMode(bool god) { playerSetGodMode(gMe, god); bPlayerCheated = true; return gMe->godMode? GStrings("TXTB_GODMODE") : GStrings("TXTB_NOTGODMODE"); } const char *SetClipMode(bool noclip) { gNoClip = noclip; bPlayerCheated = true; return gNoClip? GStrings("TXTB_NOCLIP") : GStrings("TXTB_NOCLIPOFF"); } void packStuff(PLAYER *pPlayer) { for (int i = 0; i < 5; i++) packAddItem(pPlayer, i); } void packClear(PLAYER *pPlayer) { pPlayer->packItemId = 0; for (int i = 0; i < 5; i++) { pPlayer->packSlots[i].isActive = 0; pPlayer->packSlots[i].curAmount = 0; } } void SetAmmo(bool stat) { if (stat) { for (int i = 0; i < 12; i++) gMe->ammoCount[i] = gAmmoInfo[i].max; viewSetMessage(GStrings("TXTB_FULLAMMO")); } else { for (int i = 0; i < 12; i++) gMe->ammoCount[i] = 0; viewSetMessage(GStrings("TXTB_NOAMMO")); } } void SetWeapons(bool stat) { for (int i = 0; i < 14; i++) { gMe->hasWeapon[i] = stat; } SetAmmo(stat); if (stat) viewSetMessage(GStrings("TXTB_ALLWEAP")); else { if (!VanillaMode()) { // Keep the pitchfork to avoid freeze gMe->hasWeapon[1] = 1; gMe->curWeapon = 0; gMe->nextWeapon = 1; } viewSetMessage(GStrings("TXTB_NOWEAP")); } } void SetToys(bool stat) { if (stat) { packStuff(gMe); viewSetMessage(GStrings("TXTB_FULLINV")); } else { packClear(gMe); viewSetMessage(GStrings("TXTB_NOINV")); } } void SetArmor(bool stat) { int nAmount; if (stat) { viewSetMessage(GStrings("TXTB_FULLARM")); nAmount = 3200; } else { viewSetMessage(GStrings("TXTB_NOARM")); nAmount = 0; } for (int i = 0; i < 3; i++) gMe->armor[i] = nAmount; } void SetKeys(bool stat) { for (int i = 1; i <= 6; i++) gMe->hasKey[i] = stat; if (stat) viewSetMessage(GStrings("TXTB_ALLKEYS")); else viewSetMessage(GStrings("TXTB_NOKEYS")); } void SetInfiniteAmmo(bool stat) { gInfiniteAmmo = stat; if (gInfiniteAmmo) viewSetMessage(GStrings("TXTB_INFAMMO")); else viewSetMessage(GStrings("TXTB_LIMAMMO")); } void SetMap(bool stat) { gFullMap = stat; if (gFullMap) viewSetMessage(GStrings("TXTB_ALLMAP")); else viewSetMessage(GStrings("TXTB_NOALLMAP")); } void SetWooMode(bool stat) { if (stat) { if (!powerupCheck(gMe, kPwUpTwoGuns)) powerupActivate(gMe, kPwUpTwoGuns); } else { if (powerupCheck(gMe, kPwUpTwoGuns)) { if (!VanillaMode()) gMe->pwUpTime[kPwUpTwoGuns] = 0; powerupDeactivate(gMe, kPwUpTwoGuns); } } } void ToggleWooMode(void) { SetWooMode(!(powerupCheck(gMe, kPwUpTwoGuns) != 0)); } void ToggleBoots(void) { if (powerupCheck(gMe, kPwUpJumpBoots)) { viewSetMessage(GStrings("TXTB_NOJBOOTS")); if (!VanillaMode()) { gMe->pwUpTime[kPwUpJumpBoots] = 0; gMe->packSlots[4].curAmount = 0; } powerupDeactivate(gMe, kPwUpJumpBoots); } else { viewSetMessage(GStrings("TXTB_JBOOTS")); if (!VanillaMode()) gMe->pwUpTime[kPwUpJumpBoots] = gPowerUpInfo[kPwUpJumpBoots].bonusTime; powerupActivate(gMe, kPwUpJumpBoots); } } void ToggleInvisibility(void) { if (powerupCheck(gMe, kPwUpShadowCloak)) { viewSetMessage(GStrings("TXTB_VISIBLE")); if (!VanillaMode()) gMe->pwUpTime[kPwUpShadowCloak] = 0; powerupDeactivate(gMe, kPwUpShadowCloak); } else { viewSetMessage(GStrings("TXTB_INVISIBLE")); powerupActivate(gMe, kPwUpShadowCloak); } } void ToggleInvulnerability(void) { if (powerupCheck(gMe, kPwUpDeathMask)) { viewSetMessage(GStrings("TXTB_VULN")); if (!VanillaMode()) gMe->pwUpTime[kPwUpDeathMask] = 0; powerupDeactivate(gMe, kPwUpDeathMask); } else { viewSetMessage(GStrings("TXTB_INVULN")); powerupActivate(gMe, kPwUpDeathMask); } } void ToggleDelirium(void) { if (powerupCheck(gMe, kPwUpDeliriumShroom)) { viewSetMessage(GStrings("TXTB_NODELIR")); if (!VanillaMode()) gMe->pwUpTime[kPwUpDeliriumShroom] = 0; powerupDeactivate(gMe, kPwUpDeliriumShroom); } else { viewSetMessage(GStrings("TXTB_DELIR")); powerupActivate(gMe, kPwUpDeliriumShroom); } } void LevelWarp(int nEpisode, int nLevel) { auto map = FindMapByLevelNum(levelnum(nEpisode, nLevel)); if (map) StartLevel(map); } bool bPlayerCheated = false; static int parseArgs(char *pzArgs, int *nArg1, int *nArg2) { if (!nArg1 || !nArg2 || strlen(pzArgs) < 3) return -1; *nArg1 = pzArgs[0] - '0' - 1; *nArg2 = (pzArgs[1] - '0')*10+(pzArgs[2]-'0') - 1; *nArg1 = ClipRange(*nArg1, 0, gEpisodeCount-1); *nArg2 = ClipRange(*nArg2, 0, gEpisodeInfo[*nArg1].nLevels-1); return 2; } void ProcessCheat(CHEATCODE nCheatCode, char* pzArgs) { dassert(nCheatCode > kCheatNone && nCheatCode < kCheatMax); if (nCheatCode == kCheatRate) { r_showfps = !r_showfps; return; } if (gGameOptions.nGameType != 0) return; int nEpisode, nLevel; switch (nCheatCode) { case kCheatSpielberg: // demo record break; case kCheat1: SetAmmo(true); break; case kCheatGriswold: SetArmor(true); break; case kCheatSatchel: SetToys(true); break; case kCheatIdaho: SetWeapons(true); break; case kCheatKevorkian: actDamageSprite(gMe->nSprite, gMe->pSprite, DAMAGE_TYPE_2, 8000); viewSetMessage(GStrings("TXTB_KEVORKIAN")); break; case kCheatMcGee: { if (!gMe->pXSprite->burnTime) evPost(gMe->nSprite, 3, 0, kCallbackFXFlameLick); actBurnSprite(actSpriteIdToOwnerId(gMe->nSprite), gMe->pXSprite, 2400); viewSetMessage(GStrings("TXTB_FIRED")); break; } case kCheatEdmark: actDamageSprite(gMe->nSprite, gMe->pSprite, DAMAGE_TYPE_3, 8000); viewSetMessage(GStrings("TXTB_THEDAYS")); break; case kCheatKrueger: { actHealDude(gMe->pXSprite, 200, 200); gMe->armor[1] = VanillaMode() ? 200 : 3200; if (!gMe->pXSprite->burnTime) evPost(gMe->nSprite, 3, 0, kCallbackFXFlameLick); actBurnSprite(actSpriteIdToOwnerId(gMe->nSprite), gMe->pXSprite, 2400); viewSetMessage(GStrings("TXTB_RETARD")); break; } case kCheatSterno: gMe->blindEffect = 250; break; case kCheat14: // quakeEffect (causing a little flickerEffect), not used by any cheat code (dead code) gMe->flickerEffect = 360; break; case kCheatSpork: actHealDude(gMe->pXSprite, 200, 200); break; case kCheatGoonies: SetMap(!gFullMap); break; case kCheatClarice: if (!VanillaMode()) { viewSetMessage(GStrings("TXTB_HALFARMOR")); for (int i = 0; i < 3; i++) gMe->armor[i] = 1600; } break; case kCheatFrankenstein: gMe->packSlots[0].curAmount = 100; break; case kCheatCheeseHead: gMe->packSlots[1].curAmount = 100; if (!VanillaMode()) gMe->pwUpTime[kPwUpDivingSuit] = gPowerUpInfo[kPwUpDivingSuit].bonusTime; break; case kCheatTequila: ToggleWooMode(); break; case kCheatFunkyShoes: ToggleBoots(); break; case kCheatKeyMaster: SetKeys(true); break; case kCheatOneRing: ToggleInvisibility(); break; case kCheatVoorhees: ToggleInvulnerability(); break; case kCheatJoJo: ToggleDelirium(); break; case kCheatRate: // show FPS, handled before (dead code), leave here for safety return; case kCheatMario: if (parseArgs(pzArgs, &nEpisode, &nLevel) == 2) LevelWarp(nEpisode, nLevel); break; case kCheatCalgon: if (parseArgs(pzArgs, &nEpisode, &nLevel) == 2) LevelWarp(nEpisode, nLevel); else if (!VanillaMode()) levelEndLevel(0); break; case kCheatLaraCroft: SetInfiniteAmmo(!gInfiniteAmmo); SetWeapons(gInfiniteAmmo); break; case kCheatHongKong: SetWeapons(true); SetInfiniteAmmo(true); break; case kCheatMontana: SetWeapons(true); SetToys(true); break; case kCheatBunz: SetWeapons(true); SetWooMode(true); break; case kCheatCousteau: actHealDude(gMe->pXSprite,200,200); gMe->packSlots[1].curAmount = 100; if (!VanillaMode()) gMe->pwUpTime[kPwUpDivingSuit] = gPowerUpInfo[kPwUpDivingSuit].bonusTime; break; case kCheatForkYou: SetInfiniteAmmo(false); SetMap(false); SetWeapons(false); SetAmmo(false); SetArmor(false); SetToys(false); SetKeys(false); SetWooMode(true); powerupActivate(gMe, kPwUpDeliriumShroom); gMe->pXSprite->health = 16; gMe->hasWeapon[1] = 1; gMe->curWeapon = 0; gMe->nextWeapon = 1; break; default: break; } bPlayerCheated = true; } const char* GameInterface::GenericCheat(int player, int cheat) { switch (cheat) { case CHT_GOD: return SetGodMode(!gMe->godMode); case CHT_GODOFF: return SetGodMode(false); case CHT_GODON: return SetGodMode(true); case CHT_NOCLIP: return SetClipMode(!gNoClip); default: return nullptr; } } template bool doCheat(cheatseq_t *c) { ProcessCheat(code, (char*)c->Args); return true; } static cheatseq_t s_CheatInfo[] = { {"MPKFA", "god" }, // MPKFA (Invincibility) {"CAPINMYASS", "godoff" }, // CAPINMYASS (Disable invincibility ) {"NOCAPINMYASS", "godon" }, // NOCAPINMYASS (Invincibility) {"I WANNA BE LIKE KEVIN", "godon" }, // I WANNA BE LIKE KEVIN (Invincibility) {"IDAHO", nullptr, doCheat, 0 }, // IDAHO (All weapons and full ammo) {"MONTANA", nullptr, doCheat, 0 }, // MONTANA (All weapons, full ammo and all items) {"GRISWOLD", nullptr, doCheat, 0 }, // GRISWOLD (Full armor (same effect as getting super armor)) {"EDMARK", nullptr, doCheat, 0 }, // EDMARK (Does a lot of fire damage to you (if you have 200HP and 200 fire armor then you can survive). Displays the message "THOSE WERE THE DAYS".) {"TEQUILA", nullptr, doCheat, 0 }, // TEQUILA (Guns akimbo power-up) {"BUNZ", nullptr, doCheat, 0 }, // BUNZ (All weapons, full ammo, and guns akimbo power-up) {"FUNKY SHOES", nullptr, doCheat, 0 }, // FUNKY SHOES (Gives jump boots item and activates it) {"GATEKEEPER", nullptr, doCheat, 0 }, // GATEKEEPER (Sets the you cheated flag to true, at the end of the level you will see that you have cheated) {"KEYMASTER", nullptr, doCheat, 0 }, // KEYMASTER (All keys) {"JOJO", nullptr, doCheat, 0 }, // JOJO (Drunk mode (same effect as getting bitten by red spider)) {"SATCHEL", nullptr, doCheat, 0 }, // SATCHEL (Full inventory) {"SPORK", nullptr, doCheat, 0 }, // SPORK (200% health (same effect as getting life seed)) {"ONERING", nullptr, doCheat, 0 }, // ONERING (Cloak of invisibility power-up) {"MARIO###", nullptr, doCheat, 0 }, // MARIO (Warp to level E M, e.g.: MARIO 1 3 will take you to Phantom Express) {"CALGON", nullptr, doCheat, 0 }, // CALGON (Jumps to next level or can be used like MARIO with parameters) {"KEVORKIAN", nullptr, doCheat, 0 }, // KEVORKIAN (Does a lot of physical damage to you (if you have 200HP and 200 fire armor then you can survive). Displays the message "KEVORKIAN APPROVES".) {"MCGEE", nullptr, doCheat, 0 }, // MCGEE (Sets you on fire. Displays the message "YOU'RE FIRED".) {"KRUEGER", nullptr, doCheat, 0 }, // KRUEGER (200% health, but sets you on fire. Displays the message "FLAME RETARDANT".) {"CHEESEHEAD", nullptr, doCheat, 0 }, // CHEESEHEAD (100% diving suit) {"COUSTEAU", nullptr, doCheat, 0 }, // COUSTEAU (200% health and diving suit) {"VOORHEES", nullptr, doCheat, 0 }, // VOORHEES (Death mask power-up) {"LARA CROFT", nullptr, doCheat, 0 }, // LARA CROFT (All weapons and infinite ammo. Displays the message "LARA RULES". Typing it the second time will lose all weapons and ammo.) {"HONGKONG", nullptr, doCheat, 0 }, // HONGKONG (All weapons and infinite ammo) {"FRANKENSTEIN", nullptr, doCheat, 0 }, // FRANKENSTEIN (100% med-kit) {"STERNO", nullptr, doCheat, 0 }, // STERNO (Temporary blindness (same effect as getting bitten by green spider)) {"CLARICE", nullptr, doCheat, 0 }, // CLARICE (Gives 100% body armor, 100% fire armor, 100% spirit armor) {"FORK YOU", nullptr, doCheat, 0 }, // FORK YOU (Drunk mode, 1HP, no armor, no weapons, no ammo, no items, no keys, no map, guns akimbo power-up) {"LIEBERMAN", nullptr, doCheat, 0 }, // LIEBERMAN (Sets the you cheated flag to true, at the end of the level you will see that you have cheated) {"EVA GALLI", "noclip" }, // EVA GALLI (Disable/enable clipping (grant the ability to walk through walls)) {"RATE", nullptr, doCheat, 1 }, // RATE (Display frame rate (doesn't count as a cheat)) {"GOONIES", nullptr, doCheat, 0 }, // GOONIES (Enable full map. Displays the message "YOU HAVE THE MAP".) //{"SPIELBERG", nullptr, doCheat