raze/source/blood/src/messages.cpp

554 lines
17 KiB
C++
Raw Normal View History

2019-09-19 22:42:45 +00:00
//-------------------------------------------------------------------------
/*
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!
2019-09-19 22:42:45 +00:00
#include "build.h"
#include "mmulti.h"
#include "compat.h"
#include "gamecontrol.h"
2019-09-19 22:42:45 +00:00
#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"
2019-09-19 22:42:45 +00:00
BEGIN_BLD_NS
2019-09-19 22:42:45 +00:00
void sub_5A928(void)
{
for (int i = 0; i < buttonMap.NumButtons(); i++)
buttonMap.ClearButton(i);
2019-09-19 22:42:45 +00:00
}
const char *SetGodMode(bool god)
2019-09-19 22:42:45 +00:00
{
playerSetGodMode(gMe, god);
bPlayerCheated = true;
return gMe->godMode? GStrings("TXTB_GODMODE") : GStrings("TXTB_NOTGODMODE");
2019-09-19 22:42:45 +00:00
}
const char *SetClipMode(bool noclip)
2019-09-19 22:42:45 +00:00
{
gNoClip = noclip;
bPlayerCheated = true;
return gNoClip? GStrings("TXTB_NOCLIP") : GStrings("TXTB_NOCLIPOFF");
2019-09-19 22:42:45 +00:00
}
void packStuff(PLAYER *pPlayer)
{
for (int i = 0; i < 5; i++)
packAddItem(pPlayer, i);
}
void packClear(PLAYER *pPlayer)
{
pPlayer->packItemId = 0;
2019-09-19 22:42:45 +00:00
for (int i = 0; i < 5; i++)
{
pPlayer->packSlots[i].isActive = 0;
pPlayer->packSlots[i].curAmount = 0;
2019-09-19 22:42:45 +00:00
}
}
void SetAmmo(bool stat)
{
if (stat)
{
for (int i = 0; i < 12; i++)
gMe->ammoCount[i] = gAmmoInfo[i].max;
viewSetMessage(GStrings("TXTB_FULLAMMO"));
2019-09-19 22:42:45 +00:00
}
else
{
for (int i = 0; i < 12; i++)
gMe->ammoCount[i] = 0;
viewSetMessage(GStrings("TXTB_NOAMMO"));
2019-09-19 22:42:45 +00:00
}
}
void SetWeapons(bool stat)
{
for (int i = 0; i < 14; i++)
{
gMe->hasWeapon[i] = stat;
2019-09-19 22:42:45 +00:00
}
SetAmmo(stat);
if (stat)
viewSetMessage(GStrings("TXTB_ALLWEAP"));
2019-09-19 22:42:45 +00:00
else
{
if (!VanillaMode())
{
// Keep the pitchfork to avoid freeze
gMe->hasWeapon[1] = 1;
gMe->curWeapon = 0;
gMe->nextWeapon = 1;
2019-09-19 22:42:45 +00:00
}
viewSetMessage(GStrings("TXTB_NOWEAP"));
2019-09-19 22:42:45 +00:00
}
}
void SetToys(bool stat)
{
if (stat)
{
packStuff(gMe);
viewSetMessage(GStrings("TXTB_FULLINV"));
2019-09-19 22:42:45 +00:00
}
else
{
packClear(gMe);
viewSetMessage(GStrings("TXTB_NOINV"));
2019-09-19 22:42:45 +00:00
}
}
void SetArmor(bool stat)
{
int nAmount;
if (stat)
{
viewSetMessage(GStrings("TXTB_FULLARM"));
2019-09-19 22:42:45 +00:00
nAmount = 3200;
}
else
{
viewSetMessage(GStrings("TXTB_NOARM"));
2019-09-19 22:42:45 +00:00
nAmount = 0;
}
for (int i = 0; i < 3; i++)
gMe->armor[i] = nAmount;
2019-09-19 22:42:45 +00:00
}
void SetKeys(bool stat)
{
for (int i = 1; i <= 6; i++)
gMe->hasKey[i] = stat;
2019-09-19 22:42:45 +00:00
if (stat)
viewSetMessage(GStrings("TXTB_ALLKEYS"));
2019-09-19 22:42:45 +00:00
else
viewSetMessage(GStrings("TXTB_NOKEYS"));
2019-09-19 22:42:45 +00:00
}
void SetInfiniteAmmo(bool stat)
{
gInfiniteAmmo = stat;
if (gInfiniteAmmo)
viewSetMessage(GStrings("TXTB_INFAMMO"));
2019-09-19 22:42:45 +00:00
else
viewSetMessage(GStrings("TXTB_LIMAMMO"));
2019-09-19 22:42:45 +00:00
}
void SetMap(bool stat)
{
gFullMap = stat;
if (gFullMap)
viewSetMessage(GStrings("TXTB_ALLMAP"));
2019-09-19 22:42:45 +00:00
else
viewSetMessage(GStrings("TXTB_NOALLMAP"));
2019-09-19 22:42:45 +00:00
}
void SetWooMode(bool stat)
{
if (stat)
{
if (!powerupCheck(gMe, kPwUpTwoGuns))
powerupActivate(gMe, kPwUpTwoGuns);
2019-09-19 22:42:45 +00:00
}
else
{
if (powerupCheck(gMe, kPwUpTwoGuns))
2019-09-19 22:42:45 +00:00
{
if (!VanillaMode())
gMe->pwUpTime[kPwUpTwoGuns] = 0;
powerupDeactivate(gMe, kPwUpTwoGuns);
2019-09-19 22:42:45 +00:00
}
}
}
void ToggleWooMode(void)
{
SetWooMode(!(powerupCheck(gMe, kPwUpTwoGuns) != 0));
2019-09-19 22:42:45 +00:00
}
void ToggleBoots(void)
{
if (powerupCheck(gMe, kPwUpJumpBoots))
2019-09-19 22:42:45 +00:00
{
viewSetMessage(GStrings("TXTB_NOJBOOTS"));
2019-09-19 22:42:45 +00:00
if (!VanillaMode())
{
gMe->pwUpTime[kPwUpJumpBoots] = 0;
gMe->packSlots[4].curAmount = 0;
2019-09-19 22:42:45 +00:00
}
powerupDeactivate(gMe, kPwUpJumpBoots);
2019-09-19 22:42:45 +00:00
}
else
{
viewSetMessage(GStrings("TXTB_JBOOTS"));
2019-09-19 22:42:45 +00:00
if (!VanillaMode())
gMe->pwUpTime[kPwUpJumpBoots] = gPowerUpInfo[kPwUpJumpBoots].bonusTime;
powerupActivate(gMe, kPwUpJumpBoots);
2019-09-19 22:42:45 +00:00
}
}
void ToggleInvisibility(void)
{
if (powerupCheck(gMe, kPwUpShadowCloak))
2019-09-19 22:42:45 +00:00
{
viewSetMessage(GStrings("TXTB_VISIBLE"));
2019-09-19 22:42:45 +00:00
if (!VanillaMode())
gMe->pwUpTime[kPwUpShadowCloak] = 0;
powerupDeactivate(gMe, kPwUpShadowCloak);
2019-09-19 22:42:45 +00:00
}
else
{
viewSetMessage(GStrings("TXTB_INVISIBLE"));
powerupActivate(gMe, kPwUpShadowCloak);
2019-09-19 22:42:45 +00:00
}
}
void ToggleInvulnerability(void)
{
if (powerupCheck(gMe, kPwUpDeathMask))
2019-09-19 22:42:45 +00:00
{
viewSetMessage(GStrings("TXTB_VULN"));
2019-09-19 22:42:45 +00:00
if (!VanillaMode())
gMe->pwUpTime[kPwUpDeathMask] = 0;
powerupDeactivate(gMe, kPwUpDeathMask);
2019-09-19 22:42:45 +00:00
}
else
{
viewSetMessage(GStrings("TXTB_INVULN"));
powerupActivate(gMe, kPwUpDeathMask);
2019-09-19 22:42:45 +00:00
}
}
void ToggleDelirium(void)
{
if (powerupCheck(gMe, kPwUpDeliriumShroom))
2019-09-19 22:42:45 +00:00
{
viewSetMessage(GStrings("TXTB_NODELIR"));
2019-09-19 22:42:45 +00:00
if (!VanillaMode())
gMe->pwUpTime[kPwUpDeliriumShroom] = 0;
powerupDeactivate(gMe, kPwUpDeliriumShroom);
2019-09-19 22:42:45 +00:00
}
else
{
viewSetMessage(GStrings("TXTB_DELIR"));
powerupActivate(gMe, kPwUpDeliriumShroom);
2019-09-19 22:42:45 +00:00
}
}
void LevelWarp(int nEpisode, int nLevel)
{
auto map = FindMapByLevelNum(levelnum(nEpisode, nLevel));
if (map) StartLevel(map);
}
bool bPlayerCheated = false;
2019-09-19 22:42:45 +00:00
static int parseArgs(char *pzArgs, int *nArg1, int *nArg2)
2019-09-19 22:42:45 +00:00
{
2020-08-10 18:18:21 +00:00
if (!nArg1 || !nArg2 || strlen(pzArgs) < 3)
2019-09-19 22:42:45 +00:00
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;
2019-09-19 22:42:45 +00:00
}
void ProcessCheat(CHEATCODE nCheatCode, char* pzArgs)
2019-09-19 22:42:45 +00:00
{
dassert(nCheatCode > kCheatNone && nCheatCode < kCheatMax);
if (nCheatCode == kCheatRate)
{
r_showfps = !r_showfps;
2019-09-19 22:42:45 +00:00
return;
}
if (gGameOptions.nGameType != 0)
return;
int nEpisode, nLevel;
switch (nCheatCode)
{
case kCheatSpielberg:
// demo record
2019-09-19 22:42:45 +00:00
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"));
2019-09-19 22:42:45 +00:00
break;
case kCheatMcGee:
{
if (!gMe->pXSprite->burnTime)
evPost(gMe->nSprite, 3, 0, kCallbackFXFlameLick);
actBurnSprite(actSpriteIdToOwnerId(gMe->nSprite), gMe->pXSprite, 2400);
viewSetMessage(GStrings("TXTB_FIRED"));
2019-09-19 22:42:45 +00:00
break;
}
case kCheatEdmark:
actDamageSprite(gMe->nSprite, gMe->pSprite, DAMAGE_TYPE_3, 8000);
viewSetMessage(GStrings("TXTB_THEDAYS"));
2019-09-19 22:42:45 +00:00
break;
case kCheatKrueger:
{
actHealDude(gMe->pXSprite, 200, 200);
gMe->armor[1] = VanillaMode() ? 200 : 3200;
2019-09-19 22:42:45 +00:00
if (!gMe->pXSprite->burnTime)
evPost(gMe->nSprite, 3, 0, kCallbackFXFlameLick);
actBurnSprite(actSpriteIdToOwnerId(gMe->nSprite), gMe->pXSprite, 2400);
viewSetMessage(GStrings("TXTB_RETARD"));
2019-09-19 22:42:45 +00:00
break;
}
case kCheatSterno:
gMe->blindEffect = 250;
2019-09-19 22:42:45 +00:00
break;
case kCheat14: // quakeEffect (causing a little flickerEffect), not used by any cheat code (dead code)
gMe->flickerEffect = 360;
2019-09-19 22:42:45 +00:00
break;
case kCheatSpork:
actHealDude(gMe->pXSprite, 200, 200);
break;
case kCheatGoonies:
SetMap(!gFullMap);
break;
case kCheatClarice:
if (!VanillaMode())
{
viewSetMessage(GStrings("TXTB_HALFARMOR"));
2019-09-19 22:42:45 +00:00
for (int i = 0; i < 3; i++)
gMe->armor[i] = 1600;
2019-09-19 22:42:45 +00:00
}
break;
case kCheatFrankenstein:
gMe->packSlots[0].curAmount = 100;
2019-09-19 22:42:45 +00:00
break;
case kCheatCheeseHead:
gMe->packSlots[1].curAmount = 100;
2019-09-19 22:42:45 +00:00
if (!VanillaMode())
gMe->pwUpTime[kPwUpDivingSuit] = gPowerUpInfo[kPwUpDivingSuit].bonusTime;
2019-09-19 22:42:45 +00:00
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;
2019-09-19 22:42:45 +00:00
if (!VanillaMode())
gMe->pwUpTime[kPwUpDivingSuit] = gPowerUpInfo[kPwUpDivingSuit].bonusTime;
2019-09-19 22:42:45 +00:00
break;
case kCheatForkYou:
SetInfiniteAmmo(false);
SetMap(false);
SetWeapons(false);
SetAmmo(false);
SetArmor(false);
SetToys(false);
SetKeys(false);
SetWooMode(true);
powerupActivate(gMe, kPwUpDeliriumShroom);
2019-09-19 22:42:45 +00:00
gMe->pXSprite->health = 16;
gMe->hasWeapon[1] = 1;
gMe->curWeapon = 0;
gMe->nextWeapon = 1;
2019-09-19 22:42:45 +00:00
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<CHEATCODE code> 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<kCheatIdaho>, 0 }, // IDAHO (All weapons and full ammo)
{"MONTANA", nullptr, doCheat<kCheatMontana>, 0 }, // MONTANA (All weapons, full ammo and all items)
{"GRISWOLD", nullptr, doCheat<kCheatGriswold>, 0 }, // GRISWOLD (Full armor (same effect as getting super armor))
{"EDMARK", nullptr, doCheat<kCheatEdmark>, 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<kCheatTequila>, 0 }, // TEQUILA (Guns akimbo power-up)
{"BUNZ", nullptr, doCheat<kCheatBunz>, 0 }, // BUNZ (All weapons, full ammo, and guns akimbo power-up)
{"FUNKY SHOES", nullptr, doCheat<kCheatFunkyShoes>, 0 }, // FUNKY SHOES (Gives jump boots item and activates it)
{"GATEKEEPER", nullptr, doCheat<kCheatGateKeeper>, 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<kCheatKeyMaster>, 0 }, // KEYMASTER (All keys)
{"JOJO", nullptr, doCheat<kCheatJoJo>, 0 }, // JOJO (Drunk mode (same effect as getting bitten by red spider))
{"SATCHEL", nullptr, doCheat<kCheatSatchel>, 0 }, // SATCHEL (Full inventory)
{"SPORK", nullptr, doCheat<kCheatSpork>, 0 }, // SPORK (200% health (same effect as getting life seed))
{"ONERING", nullptr, doCheat<kCheatOneRing>, 0 }, // ONERING (Cloak of invisibility power-up)
{"MARIO###", nullptr, doCheat<kCheatMario>, 0 }, // MARIO (Warp to level E M, e.g.: MARIO 1 3 will take you to Phantom Express)
{"CALGON", nullptr, doCheat<kCheatCalgon>, 0 }, // CALGON (Jumps to next level or can be used like MARIO with parameters)
{"KEVORKIAN", nullptr, doCheat<kCheatKevorkian>, 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<kCheatMcGee>, 0 }, // MCGEE (Sets you on fire. Displays the message "YOU'RE FIRED".)
{"KRUEGER", nullptr, doCheat<kCheatKrueger>, 0 }, // KRUEGER (200% health, but sets you on fire. Displays the message "FLAME RETARDANT".)
{"CHEESEHEAD", nullptr, doCheat<kCheatCheeseHead>, 0 }, // CHEESEHEAD (100% diving suit)
{"COUSTEAU", nullptr, doCheat<kCheatCousteau>, 0 }, // COUSTEAU (200% health and diving suit)
{"VOORHEES", nullptr, doCheat<kCheatVoorhees>, 0 }, // VOORHEES (Death mask power-up)
{"LARA CROFT", nullptr, doCheat<kCheatLaraCroft>, 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<kCheatHongKong>, 0 }, // HONGKONG (All weapons and infinite ammo)
{"FRANKENSTEIN", nullptr, doCheat<kCheatFrankenstein>, 0 }, // FRANKENSTEIN (100% med-kit)
{"STERNO", nullptr, doCheat<kCheatSterno>, 0 }, // STERNO (Temporary blindness (same effect as getting bitten by green spider))
{"CLARICE", nullptr, doCheat<kCheatClarice>, 0 }, // CLARICE (Gives 100% body armor, 100% fire armor, 100% spirit armor)
{"FORK YOU", nullptr, doCheat<kCheatForkYou>, 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<kCheatLieberMan>, 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<kCheatRate>, 1 }, // RATE (Display frame rate (doesn't count as a cheat))
{"GOONIES", nullptr, doCheat<kCheatGoonies>, 0 }, // GOONIES (Enable full map. Displays the message "YOU HAVE THE MAP".)
//{"SPIELBERG", nullptr, doCheat<kCheatSpielberg, 1 }, // SPIELBERG (Disables all cheats. If number values corresponding to a level and episode number are entered after the cheat word (i.e. "spielberg 1 3" for Phantom Express), you will be spawned to said level and the game will begin recording a demo from your actions.)
};
2019-09-19 22:42:45 +00:00
void cheatReset(void)
2019-09-19 22:42:45 +00:00
{
bPlayerCheated = 0;
2019-09-19 22:42:45 +00:00
playerSetGodMode(gMe, 0);
gNoClip = 0;
packClear(gMe);
gInfiniteAmmo = 0;
gFullMap = 0;
}
class MessagesLoadSave : public LoadSave
{
public:
virtual void Load();
virtual void Save();
};
void MessagesLoadSave::Load()
{
Read(&bPlayerCheated, sizeof(bPlayerCheated));
2019-09-19 22:42:45 +00:00
}
void MessagesLoadSave::Save()
{
Write(&bPlayerCheated, sizeof(bPlayerCheated));
2019-09-19 22:42:45 +00:00
}
static MessagesLoadSave *myLoadSave;
void MessagesLoadSaveConstruct(void)
{
myLoadSave = new MessagesLoadSave();
}
void InitCheats()
{
SetCheats(s_CheatInfo, countof(s_CheatInfo));
}
END_BLD_NS