raze/source/blood/src/messages.cpp

583 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"
#include "gamestate.h"
2020-09-06 10:44:58 +00:00
#include "automap.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
}
}
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
}
const char* GameInterface::GenericCheat(int player, int cheat)
2019-09-19 22:42:45 +00:00
{
// message processing is not perfect because many cheats output multiple messages.
if (gGameOptions.nGameType != 0 || numplayers > 1) // sp only for now.
return nullptr;
if (gamestate != GS_LEVEL || gMe->pXSprite->health == 0) // must be alive and in a level to cheat.
return nullptr;
bPlayerCheated = true;
switch (cheat)
2019-09-19 22:42:45 +00:00
{
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);
2019-09-19 22:42:45 +00:00
case kCheatSpielberg:
// demo record
2019-09-19 22:42:45 +00:00
break;
case kCheatSatchel:
SetToys(true);
break;
case kCheatKevorkian:
actDamageSprite(gMe->nSprite, gMe->pSprite, DAMAGE_TYPE_2, 8000);
return GStrings("TXTB_KEVORKIAN");
2019-09-19 22:42:45 +00:00
case kCheatMcGee:
{
if (!gMe->pXSprite->burnTime)
evPost(gMe->nSprite, 3, 0, kCallbackFXFlameLick);
actBurnSprite(actSpriteIdToOwnerId(gMe->nSprite), gMe->pXSprite, 2400);
return GStrings("TXTB_FIRED");
2019-09-19 22:42:45 +00:00
}
case kCheatEdmark:
actDamageSprite(gMe->nSprite, gMe->pSprite, DAMAGE_TYPE_3, 8000);
return GStrings("TXTB_THEDAYS");
2019-09-19 22:42:45 +00:00
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);
return GStrings("TXTB_RETARD");
2019-09-19 22:42:45 +00:00
}
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 kCheatClarice:
for (int i = 0; i < 3; i++)
gMe->armor[i] = 1600;
return GStrings("TXTB_HALFARMOR");
2019-09-19 22:42:45 +00:00
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 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;
2019-09-19 22:42:45 +00:00
default:
return nullptr;
2019-09-19 22:42:45 +00:00
}
return nullptr;
}
static bool cheatGoonies(cheatseq_t*)
{
SetMap(!gFullMap);
return true;
}
static bool cheatMario(cheatseq_t* c)
{
int nEpisode, nLevel;
if (parseArgs((char*)c->Args, &nEpisode, &nLevel) == 2)
{
auto map = FindMapByLevelNum(levelnum(nEpisode, nLevel));
if (map) DeferedStartGame(map, -1);
}
return true;
}
static bool cheatCalgon(cheatseq_t*)
{
levelEndLevel(0);
return true;
}
static cheatseq_t s_CheatInfo[] = {
{"MPKFA", nullptr, SendGenericCheat, 0, CHT_GOD },
{"CAPINMYASS", nullptr, SendGenericCheat, 0, CHT_GODOFF },
{"NOCAPINMYASS", nullptr, SendGenericCheat, 0, CHT_GODON },
{"I WANNA BE LIKE KEVIN", nullptr, SendGenericCheat, 0, CHT_GODON },
{"IDAHO", "give weapons" },
{"GRISWOLD", "give armor" },
{"MONTANA", nullptr, SendGenericCheat, 0, kCheatMontana }, // MONTANA (All weapons, full ammo and all items)
{"EDMARK", nullptr, SendGenericCheat, 0, kCheatEdmark }, // 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, SendGenericCheat, 0, kCheatTequila }, // TEQUILA (Guns akimbo power-up)
{"BUNZ", nullptr, SendGenericCheat, 0, kCheatBunz }, // BUNZ (All weapons, full ammo, and guns akimbo power-up)
{"FUNKY SHOES", nullptr, SendGenericCheat, 0, kCheatFunkyShoes }, // FUNKY SHOES (Gives jump boots item and activates it)
{"GATEKEEPER", nullptr, SendGenericCheat, 0, kCheatGateKeeper }, // GATEKEEPER (Sets the you cheated flag to true, at the end of the level you will see that you have cheated)
{"KEYMASTER", nullptr, SendGenericCheat, 0, kCheatKeyMaster }, // KEYMASTER (All keys)
{"JOJO", nullptr, SendGenericCheat, 0, kCheatJoJo }, // JOJO (Drunk mode (same effect as getting bitten by red spider))
{"SATCHEL", nullptr, SendGenericCheat, 0, kCheatSatchel }, // SATCHEL (Full inventory)
{"SPORK", nullptr, SendGenericCheat, 0, kCheatSpork }, // SPORK (200% health (same effect as getting life seed))
{"ONERING", nullptr, SendGenericCheat, 0, kCheatOneRing }, // ONERING (Cloak of invisibility power-up)
{"MARIO###", nullptr, cheatMario }, // MARIO (Warp to level E M, e.g.: MARIO 1 3 will take you to Phantom Express)
{"CALGON", nullptr, cheatCalgon }, // CALGON (Jumps to next level)
{"KEVORKIAN", nullptr, SendGenericCheat, 0, kCheatKevorkian }, // 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, SendGenericCheat, 0, kCheatMcGee }, // MCGEE (Sets you on fire. Displays the message "YOU'RE FIRED".)
{"KRUEGER", nullptr, SendGenericCheat, 0, kCheatKrueger }, // KRUEGER (200% health, but sets you on fire. Displays the message "FLAME RETARDANT".)
{"CHEESEHEAD", nullptr, SendGenericCheat, 0, kCheatCheeseHead }, // CHEESEHEAD (100% diving suit)
{"COUSTEAU", nullptr, SendGenericCheat, 0, kCheatCousteau }, // COUSTEAU (200% health and diving suit)
{"VOORHEES", nullptr, SendGenericCheat, 0, kCheatVoorhees }, // VOORHEES (Death mask power-up)
{"LARA CROFT", nullptr, SendGenericCheat, 0, kCheatLaraCroft }, // 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, SendGenericCheat, 0, kCheatHongKong }, // HONGKONG (All weapons and infinite ammo)
{"FRANKENSTEIN", nullptr, SendGenericCheat, 0, kCheatFrankenstein }, // FRANKENSTEIN (100% med-kit)
{"STERNO", nullptr, SendGenericCheat, 0, kCheatSterno }, // STERNO (Temporary blindness (same effect as getting bitten by green spider))
{"CLARICE", nullptr, SendGenericCheat, 0, kCheatClarice }, // CLARICE (Gives 100% body armor, 100% fire armor, 100% spirit armor)
{"FORK YOU", nullptr, SendGenericCheat, 0, kCheatForkYou }, // FORK YOU (Drunk mode, 1HP, no armor, no weapons, no ammo, no items, no keys, no map, guns akimbo power-up)
{"LIEBERMAN", nullptr, SendGenericCheat, 0, kCheatLieberMan }, // LIEBERMAN (Sets the you cheated flag to true, at the end of the level you will see that you have cheated)
{"EVA GALLI", nullptr, SendGenericCheat, 0, CHT_NOCLIP },
{"RATE", "toggle r_showfps", nullptr, 1 }, // RATE (Display frame rate (doesn't count as a cheat))
{"GOONIES", nullptr, cheatGoonies, 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;
}
static void cmd_Give(int player, uint8_t **stream, bool skip)
{
int type = ReadByte(stream);
if (skip) return;
if (numplayers != 1 || gamestate != GS_LEVEL || gMe->pXSprite->health == 0)
{
Printf("give: Cannot give while dead or not in a single-player game.\n");
return;
}
switch (type)
{
case GIVE_ALL:
SetWeapons(true);
SetAmmo(true);
SetToys(true);
SetArmor(true);
SetKeys(true);
bPlayerCheated = true;
break;
case GIVE_HEALTH:
actHealDude(gMe->pXSprite, 200, 200);
bPlayerCheated = true;
break;
case GIVE_WEAPONS:
SetWeapons(true);
bPlayerCheated = true;
break;
case GIVE_AMMO:
SetAmmo(true);
bPlayerCheated = true;
break;
case GIVE_ARMOR:
SetArmor(true);
bPlayerCheated = true;
break;
case GIVE_KEYS:
SetKeys(true);
bPlayerCheated = true;
break;
case GIVE_INVENTORY:
SetToys(true);
bPlayerCheated = true;
break;
default:
break;
}
}
2019-09-19 22:42:45 +00:00
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
}
void MessagesLoadSaveConstruct(void)
{
new MessagesLoadSave();
2019-09-19 22:42:45 +00:00
}
void InitCheats()
{
SetCheats(s_CheatInfo, countof(s_CheatInfo));
Net_SetCommandHandler(DEM_GIVE, cmd_Give);
}
END_BLD_NS