- implemented the 'god' cheat as a network command.

This was mainly chosen as something simple to get the basics set up.
This commit is contained in:
Christoph Oelckers 2020-09-03 00:29:17 +02:00
parent 66d8eae8e1
commit 66bf8113b8
28 changed files with 532 additions and 350 deletions

View file

@ -778,6 +778,7 @@ set (PCH_SOURCES
build/src/voxmodel.cpp
core/movie/playmve.cpp
core/cheats.cpp
core/cheathandler.cpp
core/mathutil.cpp
core/rts.cpp

View file

@ -99,6 +99,7 @@ struct GameInterface : ::GameInterface
void DrawBackground() override;
void Startup() override;
void Render() override;
const char* GenericCheat(int player, int cheat) override;
GameStats getStats() override;
};

View file

@ -37,6 +37,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "view.h"
#include "gstrings.h"
#include "cheathandler.h"
#include "d_protocol.h"
BEGIN_BLD_NS
@ -46,13 +47,10 @@ void sub_5A928(void)
buttonMap.ClearButton(i);
}
void SetGodMode(bool god)
const char *SetGodMode(bool god)
{
playerSetGodMode(gMe, god);
if (gMe->godMode)
viewSetMessage(GStrings("TXTB_GODMODE"));
else
viewSetMessage(GStrings("TXTB_NOTGODMODE"));
return gMe->godMode? GStrings("TXTB_GODMODE") : GStrings("TXTB_NOTGODMODE");
}
void SetClipMode(bool noclip)
@ -318,13 +316,13 @@ void ProcessCheat(CHEATCODE nCheatCode, char* pzArgs)
SetClipMode(!gNoClip);
break;
case kCheatMpkfa:
SetGodMode(!gMe->godMode);
viewSetMessage(SetGodMode(!gMe->godMode));
break;
case kCheatCapInMyAss:
SetGodMode(false);
viewSetMessage(SetGodMode(false));
break;
case kCheatNoCapInMyAss:
SetGodMode(true);
viewSetMessage(SetGodMode(true));
break;
case kCheatIdaho:
SetWeapons(true);
@ -457,6 +455,25 @@ void ProcessCheat(CHEATCODE nCheatCode, char* pzArgs)
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);
default:
return nullptr;
}
}
template<CHEATCODE code> bool doCheat(cheatseq_t *c)
{
ProcessCheat(code, (char*)c->Args);
@ -465,42 +482,42 @@ template<CHEATCODE code> bool doCheat(cheatseq_t *c)
static cheatseq_t s_CheatInfo[] = {
{"MPKFA", doCheat<kCheatMpkfa>, 0 }, // MPKFA (Invincibility)
{"CAPINMYASS", doCheat<kCheatCapInMyAss>, 0 }, // CAPINMYASS (Disable invincibility )
{"NOCAPINMYASS", doCheat<kCheatNoCapInMyAss>, 0 }, // NOCAPINMYASS (Invincibility)
{"I WANNA BE LIKE KEVIN", doCheat<kCheatNoCapInMyAss>, 0 }, // I WANNA BE LIKE KEVIN (Invincibility)
{"IDAHO", doCheat<kCheatIdaho>, 0 }, // IDAHO (All weapons and full ammo)
{"MONTANA", doCheat<kCheatMontana>, 0 }, // MONTANA (All weapons, full ammo and all items)
{"GRISWOLD", doCheat<kCheatGriswold>, 0 }, // GRISWOLD (Full armor (same effect as getting super armor))
{"EDMARK", 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", doCheat<kCheatTequila>, 0 }, // TEQUILA (Guns akimbo power-up)
{"BUNZ", doCheat<kCheatBunz>, 0 }, // BUNZ (All weapons, full ammo, and guns akimbo power-up)
{"FUNKY SHOES", doCheat<kCheatFunkyShoes>, 0 }, // FUNKY SHOES (Gives jump boots item and activates it)
{"GATEKEEPER", 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", doCheat<kCheatKeyMaster>, 0 }, // KEYMASTER (All keys)
{"JOJO", doCheat<kCheatJoJo>, 0 }, // JOJO (Drunk mode (same effect as getting bitten by red spider))
{"SATCHEL", doCheat<kCheatSatchel>, 0 }, // SATCHEL (Full inventory)
{"SPORK", doCheat<kCheatSpork>, 0 }, // SPORK (200% health (same effect as getting life seed))
{"ONERING", doCheat<kCheatOneRing>, 0 }, // ONERING (Cloak of invisibility power-up)
{"MARIO###", doCheat<kCheatMario>, 0 }, // MARIO (Warp to level E M, e.g.: MARIO 1 3 will take you to Phantom Express)
{"CALGON", doCheat<kCheatCalgon>, 0 }, // CALGON (Jumps to next level or can be used like MARIO with parameters)
{"KEVORKIAN", 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", doCheat<kCheatMcGee>, 0 }, // MCGEE (Sets you on fire. Displays the message "YOU'RE FIRED".)
{"KRUEGER", doCheat<kCheatKrueger>, 0 }, // KRUEGER (200% health, but sets you on fire. Displays the message "FLAME RETARDANT".)
{"CHEESEHEAD", doCheat<kCheatCheeseHead>, 0 }, // CHEESEHEAD (100% diving suit)
{"COUSTEAU", doCheat<kCheatCousteau>, 0 }, // COUSTEAU (200% health and diving suit)
{"VOORHEES", doCheat<kCheatVoorhees>, 0 }, // VOORHEES (Death mask power-up)
{"LARA CROFT", 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", doCheat<kCheatHongKong>, 0 }, // HONGKONG (All weapons and infinite ammo)
{"FRANKENSTEIN", doCheat<kCheatFrankenstein>, 0 }, // FRANKENSTEIN (100% med-kit)
{"STERNO", doCheat<kCheatSterno>, 0 }, // STERNO (Temporary blindness (same effect as getting bitten by green spider))
{"CLARICE", doCheat<kCheatClarice>, 0 }, // CLARICE (Gives 100% body armor, 100% fire armor, 100% spirit armor)
{"FORK YOU", 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", 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", doCheat<kCheatEvaGalli>, 0 }, // EVA GALLI (Disable/enable clipping (grant the ability to walk through walls))
{"RATE", doCheat<kCheatRate>, 1 }, // RATE (Display frame rate (doesn't count as a cheat))
{"GOONIES", doCheat<kCheatGoonies>, 0 }, // GOONIES (Enable full map. Displays the message "YOU HAVE THE MAP".)
//{"SPIELBERG", 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.)
{"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", nullptr, doCheat<kCheatEvaGalli>, 0 }, // 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.)
};

View file

@ -42,7 +42,8 @@ enum MESSAGE_PRIORITY {
enum CHEATCODE
{
kCheatNone = 0,
kCheat1, // refills ammo, no cheat code for it
kCheat1 = 1000, // refills ammo, no cheat code for it
kCheatGriswold,
kCheatSatchel,
kCheatEvaGalli,
@ -90,7 +91,6 @@ void SetWeapons(bool stat);
void SetToys(bool stat);
void SetArmor(bool stat);
void SetKeys(bool stat);
void SetGodMode(bool god);
void SetClipMode(bool noclip);
END_BLD_NS

View file

@ -129,19 +129,6 @@ static int osdcmd_give(CCmdFuncPtr parm)
return CCMD_SHOWHELP;
}
static int osdcmd_god(CCmdFuncPtr)
{
if (numplayers == 1 && gamestate == GS_LEVEL)
{
SetGodMode(!gMe->godMode);
bPlayerCheated = true;
}
else
Printf("god: Not in a single-player game.\n");
return CCMD_OK;
}
static int osdcmd_noclip(CCmdFuncPtr)
{
if (numplayers == 1 && gamestate == GS_LEVEL)
@ -249,7 +236,6 @@ int32_t registerosdcommands(void)
{
C_RegisterFunction("map","map <mapname>: loads the given map", osdcmd_map);
C_RegisterFunction("give","give <all|health|weapons|ammo|armor|keys|inventory>: gives requested item", osdcmd_give);
C_RegisterFunction("god","god: toggles god mode", osdcmd_god);
C_RegisterFunction("noclip","noclip: toggles clipping mode", osdcmd_noclip);
C_RegisterFunction("levelwarp","levelwarp <e> <m>: warp to episode 'e' and map 'm'", osdcmd_levelwarp);
C_RegisterFunction("warptocoords","warptocoords [x] [y] [z] [ang] (optional) [horiz] (optional): warps the player to the specified coordinates",osdcmd_warptocoords);

View file

@ -607,8 +607,9 @@ void playerSetRace(PLAYER *pPlayer, int nLifeMode)
pDudeInfo->at70[i] = mulscale8(Handicap[gProfile[pPlayer->nPlayer].skill], pDudeInfo->startDamage[i]);
}
void playerSetGodMode(PLAYER *pPlayer, char bGodMode)
void playerSetGodMode(PLAYER *pPlayer, bool bGodMode)
{
if (pPlayer->godMode == bGodMode) return;
if (bGodMode)
{
for (int i = 0; i < 7; i++)

View file

@ -269,7 +269,7 @@ void packPrevItem(PLAYER *pPlayer);
void packNextItem(PLAYER *pPlayer);
char playerSeqPlaying(PLAYER *pPlayer, int nSeq);
void playerSetRace(PLAYER *pPlayer, int nLifeMode);
void playerSetGodMode(PLAYER *pPlayer, char bGodMode);
void playerSetGodMode(PLAYER *pPlayer, bool bGodMode);
void playerResetInertia(PLAYER *pPlayer);
void playerCorrectInertia(PLAYER *pPlayer, vec3_t const *oldpos);
void playerStart(int nPlayer, int bNewLevel = 0);

View file

@ -59,7 +59,7 @@ extern bool ParsingKeyConf, UnsafeExecutionContext;
extern FString StoredWarp; // [RH] +warp at the command line
extern bool CheckCheatmode (bool printmsg = true);
extern bool CheckCheatmode (bool printmsg = true, bool sponly = false);
FExecList *C_ParseCmdLineParams(FExecList *exec);

View file

@ -1,27 +1,37 @@
//-----------------------------------------------------------------------------
//
/*
** cheathandler.cpp
** Generic Cheat code.
**
**---------------------------------------------------------------------------
// Copyright 1999-2016 Randy Heit
// Copyright 2002-2016 Christoph Oelckers
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// 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, see http://www.gnu.org/licenses/
//
//-----------------------------------------------------------------------------
//
// DESCRIPTION:
// Generic Cheat code.
//
//-----------------------------------------------------------------------------
// Copyright 2002-2020 Christoph Oelckers
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OFf
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
*/
#include "c_cvars.h"
#include "c_dispatch.h"
@ -122,7 +132,7 @@ bool Cheat_Responder (event_t *ev)
void PlaybackCheat(const char *p)
{
if (gi->CheatAllowed(false))
if (!CheckCheatmode(true))
{
event_t ev = { EV_KeyDown, 0, 0, -1 };
Cheat_Responder(&ev); // Reset the parser by passing a non-existent key.
@ -135,9 +145,6 @@ void PlaybackCheat(const char *p)
ev.data2 = -1;
Cheat_Responder(&ev);
}
else
Printf("activatecheat: Cheats not allowed.\n");
}
CCMD(activatecheat)

View file

@ -3,6 +3,7 @@
struct cheatseq_t
{
const char *Sequence;
const char* ccmd;
bool (*Handler)(cheatseq_t *);
uint8_t DontCheck;
// This is working data for processing the cheat

124
source/core/cheats.cpp Normal file
View file

@ -0,0 +1,124 @@
/*
** cheats.cpp
** Common cheat code
**
**---------------------------------------------------------------------------
// Copyright 1999-2016 Randy Heit
// Copyright 2002-2020 Christoph Oelckers
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OFf
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
*/
#include "gamestruct.h"
#include "printf.h"
#include "c_cvars.h"
#include "cheathandler.h"
#include "c_dispatch.h"
#include "d_net.h"
#include "gamestate.h"
#include "mmulti.h"
#include "gstrings.h"
CVAR(Bool, sv_cheats, true, CVAR_ARCHIVE|CVAR_SERVERINFO)
CVAR(Bool, cl_blockcheats, false, 0)
bool CheckCheatmode (bool printmsg, bool sponly)
{
if ((sponly && netgame) || gamestate != GS_LEVEL)
{
if (printmsg) Printf ("Not in a singleplayer game.\n");
return true;
}
else if ((netgame /*|| deathmatch*/) && (!sv_cheats))
{
if (printmsg) Printf ("sv_cheats must be true to enable this command.\n");
return true;
}
else if (cl_blockcheats != 0)
{
if (printmsg && cl_blockcheats == 1) Printf ("cl_blockcheats is turned on and disabled this command.\n");
return true;
}
else
{
const char *gamemsg = gi->CheckCheatMode(); // give the game anopportuity to add its own blocks.
if (printmsg && gamemsg)
{
Printf("%s\n", gamemsg);
return true;
}
return false;
}
}
void genericCheat(int player, uint8_t** stream, bool skip)
{
int cheat = ReadByte(stream);
if (skip) return;
const char *msg = gi->GenericCheat(player, cheat);
if (!msg || !*msg) // Don't print blank lines.
return;
if (player == myconnectindex)
Printf("%s\n", msg);
else
{
FString message = GStrings("TXT_X_CHEATS");
//message.Substitute("%s", player->userinfo.GetName()); // fixme - make globally accessible
Printf("%s: %s\n", message.GetChars(), msg);
}
}
CCMD(god)
{
if (!CheckCheatmode(true, true)) // Right now the god cheat is a global setting in some games and not a player property. This should be changed.
{
Net_WriteByte(DEM_GENERICCHEAT);
Net_WriteByte(CHT_GOD);
}
}
CCMD(godon)
{
if (!CheckCheatmode(true, true))
{
Net_WriteByte(DEM_GENERICCHEAT);
Net_WriteByte(CHT_GODON);
}
}
CCMD(godoff)
{
if (!CheckCheatmode(true, true))
{
Net_WriteByte(DEM_GENERICCHEAT);
Net_WriteByte(CHT_GODOFF);
}
}

10
source/core/cheats.h Normal file
View file

@ -0,0 +1,10 @@
#pragma once
#include <stdint.h>
#include "c_cvars.h"
EXTERN_CVAR(Bool, sv_cheats)
void genericCheat(int player, uint8_t** stream, bool skip);

View file

@ -51,6 +51,7 @@
#include "i_time.h"
#include "d_ticcmd.h"
#include "m_random.h"
#include "cheats.h"
extern bool pauseext;
extern int gametic;
@ -1660,6 +1661,10 @@ bool D_CheckNetGame (void)
const char *v;
int i;
// First install the global net command handlers
Net_SetCommandHandler(DEM_GENERICCHEAT, genericCheat);
for (i = 0; i < MAXNETNODES; i++)
{
nodeingame[i] = false;
@ -1947,7 +1952,7 @@ void Net_DoCommand (int cmd, uint8_t **stream, int player)
assert(cmd >= 0 && cmd < DEM_MAX);
if (cmd >= 0 && cmd < DEM_MAX && nethandlers[cmd])
{
nethandlers[cmd](stream, false);
nethandlers[cmd](player, stream, false);
}
else
I_Error("Unknown net command: %d", cmd);
@ -1958,7 +1963,7 @@ void Net_SkipCommand (int cmd, uint8_t **stream)
{
if (cmd >= 0 && cmd < DEM_MAX && nethandlers[cmd])
{
nethandlers[cmd](stream, true);
nethandlers[cmd](0, stream, true);
}
}

View file

@ -168,9 +168,9 @@ int UnpackUserCmd (InputPacket *ucmd, const InputPacket *basis, uint8_t **stream
if (flags & UCMDF_SIDEMOVE)
ucmd->svel = ReadWord (stream);
if (flags & UCMDF_UPMOVE)
ucmd->q16horiz = ReadWord (stream);
ucmd->q16horiz = ReadLong (stream);
if (flags & UCMDF_ROLL)
ucmd->q16ang = ReadWord (stream);
ucmd->q16ang = ReadLong (stream);
}
return int(*stream - start);

View file

@ -88,12 +88,21 @@ enum EDemoCommand
DEM_BAD, // 0 Bad command
DEM_USERCMD,
DEM_EMPTYUSERCMD,
DEM_CHEAT_GOD,
DEM_GENERICCHEAT,
DEM_MAX
};
typedef void(*NetCommandHandler)(uint8_t **stream, bool skip);
enum ECheat
{
// must contain all cheats from all games
CHT_NONE,
CHT_GOD,
CHT_GODON,
CHT_GODOFF
};
typedef void(*NetCommandHandler)(int player, uint8_t **stream, bool skip);
void Net_SetCommandHandler(EDemoCommand cmd, NetCommandHandler handler) noexcept;
@ -111,8 +120,8 @@ int SkipTicCmd (uint8_t **stream, int count);
void ReadTicCmd (uint8_t **stream, int player, int tic);
void RunNetSpecs (int player, int buf);
int Readuint8_t (uint8_t **stream);
int Reauint32_t (uint8_t **stream);
int ReadByte (uint8_t **stream);
int ReadShort (uint8_t **stream);
int ReadLong (uint8_t **stream);
float ReadFloat (uint8_t **stream);
char *ReadString (uint8_t **stream);

View file

@ -1132,12 +1132,6 @@ CCMD (togglemsg)
}
}
// Just a placeholder for now.
bool CheckCheatmode(bool printmsg)
{
return gi->CheatAllowed(printmsg);
}
bool OkForLocalization(FTextureID texnum, const char* substitute)
{
return false;

View file

@ -8,6 +8,8 @@ bool System_WantGuiCapture(); // During playing this tells us whether the game m
#include "stats.h"
#include "packet.h"
class FSerializer;
struct GameStats
{
int kill, tkill;
@ -89,7 +91,6 @@ struct GameInterface
virtual void QuitToTitle() {}
virtual void SetAmbience(bool on) {}
virtual FString GetCoordString() { return "'stat coord' not implemented"; }
virtual bool CheatAllowed(bool printmsg) { return true; }
virtual void ExitFromMenu() { throw CExitEvent(0); }
virtual ReservedSpace GetReservedScreenSpace(int viewsize) { return { 0, 0 }; }
virtual void ResetFollowPos(bool) {}
@ -101,6 +102,8 @@ struct GameInterface
virtual void Render() {}
virtual void Ticker() {}
virtual int GetPlayerChecksum(int pnum) { return 0x12345678 + pnum; }
virtual const char *CheckCheatMode() { return nullptr; }
virtual const char* GenericCheat(int player, int cheat) = 0;
virtual FString statFPS()
{

View file

@ -46,6 +46,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "c_console.h"
#include "cheathandler.h"
#include "inputstate.h"
#include "d_protocol.h"
#include "core/menu/menu.h"
BEGIN_PS_NS
@ -195,6 +196,39 @@ void ShutDown(void)
//UnInitFX();
}
static const char* GodCheat(int nPlayer, int state)
{
if (state == -1)
{
if (PlayerList[nPlayer].invincibility >= 0)
PlayerList[nPlayer].invincibility = -1;
else
PlayerList[nPlayer].invincibility = 0;
}
else PlayerList[nPlayer].invincibility = -state;
return GStrings(PlayerList[nPlayer].invincibility ? "TXT_EX_DEITYON" : "TXT_EX_DEITYOFF");
}
const char* GameInterface::GenericCheat(int player, int cheat)
{
switch (cheat)
{
case CHT_GOD:
return GodCheat(player, -1);
case CHT_GODOFF:
return GodCheat(player, 0);
case CHT_GODON:
return GodCheat(player, 1);
default:
return nullptr;
}
}
static bool HollyCheat(cheatseq_t* c)
{
// Do the closest thing to this cheat that's available.
@ -214,12 +248,6 @@ static bool CopCheat(cheatseq_t* c)
return true;
}
static bool GodCheat(cheatseq_t* c)
{
lLocalCodes |= kButtonCheatGodMode;
return true;
}
static bool LiteCheat(cheatseq_t* c)
{
Printf(PRINT_NOTIFY, "%s\n", GStrings("TXT_EX_FLASHES"));
@ -289,17 +317,17 @@ static bool CoordCheat(cheatseq_t* c)
static cheatseq_t excheats[] = {
{"holly", HollyCheat, 0},
{"kimberly", KimberlyCheat, 0},
{"lobocop", CopCheat, 0},
{"lobodeity", GodCheat, 0},
{"lobolite", LiteCheat, 0},
{"lobopick", KeyCheat, 0},
{"loboslip", SlipCheat, 0},
{"lobosnake", SnakeCheat, 0},
{"lobosphere", SphereCheat, 0},
{"loboswag", SwagCheat, 0},
{"loboxy", CoordCheat, true},
{"holly", nullptr, HollyCheat, 0},
{"kimberly", nullptr, KimberlyCheat, 0},
{"lobocop", nullptr, CopCheat, 0},
{"lobodeity", "god" },
{"lobolite", nullptr, LiteCheat, 0},
{"lobopick", nullptr, KeyCheat, 0},
{"loboslip", nullptr, SlipCheat, 0},
{"lobosnake", nullptr, SnakeCheat, 0},
{"lobosphere", nullptr, SphereCheat, 0},
{"loboswag", nullptr, SwagCheat, 0},
{"loboxy", nullptr, CoordCheat, true},
};

View file

@ -254,6 +254,7 @@ struct GameInterface : ::GameInterface
void Render() override;
void GetInput(InputPacket* packet) override;
void Startup() override;
const char* GenericCheat(int player, int cheat) override;
::GameStats getStats() override;
};

View file

@ -235,7 +235,7 @@ void UseHeart(short nPlayer)
// invincibility
void UseScarab(short nPlayer)
{
if (PlayerList[nPlayer].invincibility < 900) {
if (PlayerList[nPlayer].invincibility > 0 && PlayerList[nPlayer].invincibility < 900) {
PlayerList[nPlayer].invincibility = 900;
}

View file

@ -34,19 +34,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
BEGIN_PS_NS
static int osdcmd_god(CCmdFuncPtr)
{
if (!nNetPlayerCount && !bInDemo)
{
lLocalCodes |= kButtonCheatGodMode;
}
else
Printf("god: Not in a single-player game.\n");
return CCMD_OK;
}
bool SlipCheat(cheatseq_t* c);
static int osdcmd_noclip(CCmdFuncPtr)
@ -225,7 +212,6 @@ int32_t registerosdcommands(void)
C_RegisterFunction("map","map <mapname>: loads the given map", osdcmd_map);
C_RegisterFunction("exitmap", "exits current map", osdcmd_exitmap);
C_RegisterFunction("doors", "opens/closes doors", osdcmd_doors);
C_RegisterFunction("god","god: toggles god mode", osdcmd_god);
C_RegisterFunction("noclip","noclip: toggles clipping mode", osdcmd_noclip);
C_RegisterFunction("spawn","spawn <creaturetype>: spawns a creature",osdcmd_spawn);
C_RegisterFunction("warptocoords","warptocoords [x] [y] [z] [ang] (optional) [horiz] (optional): warps the player to the specified coordinates",osdcmd_warptocoords);

View file

@ -1281,29 +1281,7 @@ loc_1AB8E:
uint16_t buttons = sPlayerInput[nPlayer].buttons;
auto actions = sPlayerInput[nPlayer].actions;
if (buttons & kButtonCheatGodMode) // LOBODEITY cheat
{
char strDeity[96]; // TODO - reduce in size?
const char *strDMode = NULL;
if (PlayerList[nPlayer].invincibility >= 0)
{
PlayerList[nPlayer].invincibility = -1;
strDMode = "ON";
}
else
{
PlayerList[nPlayer].invincibility = 0;
strDMode = "OFF";
}
sPlayerInput[nPlayer].buttons &= 0xBF;
sprintf(strDeity, "Deity mode %s for player", strDMode);
StatusMessage(150, strDeity);
}
else if (buttons & kButtonCheatGuns) // LOBOCOP cheat
if (buttons & kButtonCheatGuns) // LOBOCOP cheat
{
FillWeapons(nPlayer);
StatusMessage(150, "All weapons loaded for player");

View file

@ -120,16 +120,6 @@ static int ccmd_map(CCmdFuncPtr parm)
return CCMD_OK;
}
static int ccmd_god(CCmdFuncPtr)
{
if (numplayers == 1 && ps[myconnectindex].gm & MODE_GAME)
cheatGod(nullptr);
else
Printf("god: Not in a single-player game.\n");
return CCMD_OK;
}
static int ccmd_noclip(CCmdFuncPtr)
{
if (numplayers == 1 && ps[myconnectindex].gm & MODE_GAME)
@ -333,7 +323,6 @@ int registerosdcommands(void)
C_RegisterFunction("map","map <mapname>: warp to the given map, identified by its name", ccmd_map);
C_RegisterFunction("levelwarp","levelwarp <e> <m>: warp to episode 'e' and map 'm'", ccmd_levelwarp);
C_RegisterFunction("give","give <all|health|weapons|ammo|armor|keys|inventory>: gives requested item", ccmd_give);
C_RegisterFunction("god","god: toggles god mode", ccmd_god);
C_RegisterFunction("noclip","noclip: toggles clipping mode", ccmd_noclip);
C_RegisterFunction("restartmap", "restartmap: restarts the current map", ccmd_restartmap);
C_RegisterFunction("spawn","spawn <picnum> [palnum] [cstat] [ang] [x y z]: spawns a sprite with the given properties",ccmd_spawn);

View file

@ -41,19 +41,78 @@ source as it is released.
#include "c_dispatch.h"
EXTERN_CVAR(Int, developer)
EXTERN_CVAR(Bool, sv_cheats)
BEGIN_DUKE_NS
bool GameInterface::CheatAllowed(bool printmsg)
const char *GameInterface::CheckCheatMode()
{
if (ud.player_skill == 4 || (isRR() && ud.player_skill > 3) || (isRRRA() && ps[myconnectindex].nocheat))
if (sv_cheats && (ud.player_skill == 4 || (isRR() && ud.player_skill > 3) || (isRRRA() && ps[myconnectindex].nocheat)))
{
if (printmsg) FTA(22, &ps[myconnectindex]);
return false;
return quoteMgr.GetQuote(QUOTE_CHEATS_DISABLED);
}
return true;
return nullptr;
}
const char *cheatGod(int myconnectindex, int state)
{
if (state == -1) state = 1 - ud.god;
ud.god = state;
sprite[ps[myconnectindex].i].extra = max_player_health;
hittype[ps[myconnectindex].i].extra = 0;
if (ud.god)
{
if (isRRRA()) S_PlaySound(218, CHAN_AUTO, CHANF_UI);
sprite[ps[myconnectindex].i].cstat = 257;
hittype[ps[myconnectindex].i].temp_data[0] = 0;
hittype[ps[myconnectindex].i].temp_data[1] = 0;
hittype[ps[myconnectindex].i].temp_data[2] = 0;
hittype[ps[myconnectindex].i].temp_data[3] = 0;
hittype[ps[myconnectindex].i].temp_data[4] = 0;
hittype[ps[myconnectindex].i].temp_data[5] = 0;
sprite[ps[myconnectindex].i].hitag = 0;
sprite[ps[myconnectindex].i].lotag = 0;
sprite[ps[myconnectindex].i].pal =
ps[myconnectindex].palookup;
return quoteMgr.GetQuote(QUOTE_CHEAT_GODMODE_ON);
}
else
{
ud.god = 0;
sprite[ps[myconnectindex].i].extra = max_player_health;
hittype[ps[myconnectindex].i].extra = -1;
ps[myconnectindex].last_extra = max_player_health;
return quoteMgr.GetQuote(QUOTE_CHEAT_GODMODE_OFF);
}
}
const char* GameInterface::GenericCheat(int player, int cheat)
{
switch (cheat)
{
case CHT_GOD:
return cheatGod(player, -1);
case CHT_GODOFF:
return cheatGod(player, 0);
case CHT_GODON:
return cheatGod(player, 1);
default:
return nullptr;
}
}
bool cheatWeapons(cheatseq_t *s)
{
int weaponLimit = (VOLUMEONE) ? SHRINKER_WEAPON : MAX_WEAPONS;
@ -124,43 +183,6 @@ static bool cheatAllen(cheatseq_t *)
return true;
}
bool cheatGod(cheatseq_t *)
{
ud.god = 1-ud.god;
if(ud.god)
{
if (isRRRA()) S_PlaySound(218, CHAN_AUTO, CHANF_UI);
sprite[ps[myconnectindex].i].cstat = 257;
hittype[ps[myconnectindex].i].temp_data[0] = 0;
hittype[ps[myconnectindex].i].temp_data[1] = 0;
hittype[ps[myconnectindex].i].temp_data[2] = 0;
hittype[ps[myconnectindex].i].temp_data[3] = 0;
hittype[ps[myconnectindex].i].temp_data[4] = 0;
hittype[ps[myconnectindex].i].temp_data[5] = 0;
sprite[ps[myconnectindex].i].hitag = 0;
sprite[ps[myconnectindex].i].lotag = 0;
sprite[ps[myconnectindex].i].pal =
ps[myconnectindex].palookup;
FTA(17,&ps[myconnectindex]);
}
else
{
ud.god = 0;
sprite[ps[myconnectindex].i].extra = max_player_health;
hittype[ps[myconnectindex].i].extra = -1;
ps[myconnectindex].last_extra = max_player_health;
FTA(18,&ps[myconnectindex]);
}
sprite[ps[myconnectindex].i].extra = max_player_health;
hittype[ps[myconnectindex].i].extra = 0;
return true;
}
bool cheatStuff(cheatseq_t *)
{
cheatWeapons(nullptr);
@ -418,115 +440,115 @@ static bool cheatKfc(cheatseq_t *)
}
static cheatseq_t dukecheats[] = {
{ "dncornholio", cheatGod },
{ "dnstuff", cheatStuff },
{ "dnscotty###", cheatLevel },
{ "dncoords", cheatCoord, 1 },
{ "dnview", cheatView, 1 },
{ "dntime", cheatTime, 1 },
{ "dnunlock", cheatUnlock },
{ "dncashman", cheatCashman },
{ "dnitems", cheatItems },
{ "dnrate", cheatRate, 1 },
{ "dnskill#", cheatSkill },
{ "dnbeta", cheatBeta },
{ "dnhyper", cheatHyper },
{ "dnmonsters", cheatMonsters },
{ "dntodd", cheatTodd },
{ "dnshowmap", cheatMap },
{ "dnkroz", cheatGod },
{ "dnallen", cheatAllen },
{ "dnclip", cheatClip },
{ "dnweapons", cheatWeapons },
{ "dninventory", cheatInventory },
{ "dnkeys", cheatKeys },
{ "dndebug", cheatDebug, 1 },
{ "dncgs", cheatKill },
{ "dncornholio", "god" },
{ "dnstuff", nullptr, cheatStuff },
{ "dnscotty###", nullptr, cheatLevel },
{ "dncoords", nullptr, cheatCoord, 1 },
{ "dnview", nullptr, cheatView, 1 },
{ "dntime", nullptr, cheatTime, 1 },
{ "dnunlock", nullptr, cheatUnlock },
{ "dncashman", nullptr, cheatCashman },
{ "dnitems", nullptr, cheatItems },
{ "dnrate", nullptr, cheatRate, 1 },
{ "dnskill#", nullptr, cheatSkill },
{ "dnbeta", nullptr, cheatBeta },
{ "dnhyper", nullptr, cheatHyper },
{ "dnmonsters", nullptr, cheatMonsters },
{ "dntodd", nullptr, cheatTodd },
{ "dnshowmap", nullptr, cheatMap },
{ "dnkroz", "god" },
{ "dnallen", nullptr, cheatAllen },
{ "dnclip", nullptr, cheatClip },
{ "dnweapons", nullptr, cheatWeapons },
{ "dninventory", nullptr, cheatInventory },
{ "dnkeys", nullptr, cheatKeys },
{ "dndebug", nullptr, cheatDebug, 1 },
{ "dncgs", nullptr, cheatKill },
};
static cheatseq_t ww2cheats[] =
{
// Use the same code prefix as EDuke because 'ww' is not usable here. Since the cheat parser eats input after the second key, this could easily cause interference for WASD users.
{ "gi2god", cheatGod },
{ "gi2blood", cheatStuff },
{ "gi2level###", cheatLevel },
{ "gi2coords", cheatCoord, 1 },
{ "gi2view", cheatView, 1 },
{ "gi2time", cheatTime, 1 },
{ "gi2rate", cheatRate, 1 },
{ "gi2skill", cheatSkill },
{ "gi2enemies", cheatMonsters },
{ "gi2matt", cheatTodd },
{ "gi2showmap", cheatMap },
{ "gi2ryan", cheatGod },
{ "gi2clip", cheatClip },
{ "gi2weapons", cheatWeapons },
{ "gi2inventory", cheatInventory },
{ "gi2debug", cheatDebug, 1 },
{ "gi2cgs", cheatKill },
{ "gi2god", "god" },
{ "gi2blood", nullptr, cheatStuff },
{ "gi2level###", nullptr, cheatLevel },
{ "gi2coords", nullptr, cheatCoord, 1 },
{ "gi2view", nullptr, cheatView, 1 },
{ "gi2time", nullptr, cheatTime, 1 },
{ "gi2rate", nullptr, cheatRate, 1 },
{ "gi2skill", nullptr, cheatSkill },
{ "gi2enemies", nullptr, cheatMonsters },
{ "gi2matt", nullptr, cheatTodd },
{ "gi2showmap", nullptr, cheatMap },
{ "gi2ryan", "god" },
{ "gi2clip", nullptr, cheatClip },
{ "gi2weapons", nullptr, cheatWeapons },
{ "gi2inventory", nullptr, cheatInventory },
{ "gi2debug", nullptr, cheatDebug, 1 },
{ "gi2cgs", nullptr, cheatKill },
};
static cheatseq_t namcheats[] = {
{ "nvacaleb", cheatGod },
{ "nvablood", cheatStuff },
{ "nvalevel###", cheatLevel },
{ "nvacoords", cheatCoord, 1 },
{ "nvaview", cheatView, 1 },
{ "nvatime", cheatTime, 1 },
{ "nvarate", cheatRate, 1 },
{ "nvaskill", cheatSkill },
{ "nvahyper", cheatHyper },
{ "nvaenemies", cheatMonsters },
{ "nvamatt", cheatTodd },
{ "nvashowmap", cheatMap },
{ "nvagod", cheatGod },
{ "nvaclip", cheatClip },
{ "nvaweapons", cheatWeapons },
{ "nvainventory", cheatInventory },
{ "nvadebug", cheatDebug, 1 },
{ "nvacgs", cheatKill },
{ "nvacaleb", "god" },
{ "nvablood", nullptr, cheatStuff },
{ "nvalevel###", nullptr, cheatLevel },
{ "nvacoords", nullptr, cheatCoord, 1 },
{ "nvaview", nullptr, cheatView, 1 },
{ "nvatime", nullptr, cheatTime, 1 },
{ "nvarate", nullptr, cheatRate, 1 },
{ "nvaskill", nullptr, cheatSkill },
{ "nvahyper", nullptr, cheatHyper },
{ "nvaenemies", nullptr, cheatMonsters },
{ "nvamatt", nullptr, cheatTodd },
{ "nvashowmap", nullptr, cheatMap },
{ "nvagod", "god" },
{ "nvaclip", nullptr, cheatClip },
{ "nvaweapons", nullptr, cheatWeapons },
{ "nvainventory",nullptr, cheatInventory },
{ "nvadebug", nullptr, cheatDebug, 1 },
{ "nvacgs", nullptr, cheatKill },
};
static cheatseq_t rrcheats[] = {
{ "rdhounddog", cheatGod },
{ "rdall", cheatStuff },
{ "rdmeadow###", cheatLevel },
{ "rdyerat", cheatCoord, 1 },
{ "rdview", cheatView, 1 },
{ "rdtime", cheatTime, 1 },
{ "rdunlock", cheatUnlock },
{ "rdcluck", cheatCashman },
{ "rditems", cheatItems },
{ "rdrate", cheatRate, 1 },
{ "rdskill#", cheatSkill },
{ "rdteachers", cheatBeta },
{ "rdmoonshine", cheatHyper },
{ "rdcritters", cheatMonsters },
{ "rdrafael", cheatTodd },
{ "rdshowmap", cheatMap },
{ "rdelvis", cheatGod },
{ "rdclip", cheatClip },
{ "rdguns", cheatWeapons },
{ "rdinventory", cheatInventory },
{ "rdkeys", cheatKeys },
{ "rddebug", cheatDebug, 1 },
{ "rdcgs", cheatKill }, // 23 for RR
{ "rdhounddog", "god" },
{ "rdall", nullptr, cheatStuff },
{ "rdmeadow###", nullptr, cheatLevel },
{ "rdyerat", nullptr, cheatCoord, 1 },
{ "rdview", nullptr, cheatView, 1 },
{ "rdtime", nullptr, cheatTime, 1 },
{ "rdunlock", nullptr, cheatUnlock },
{ "rdcluck", nullptr, cheatCashman },
{ "rditems", nullptr, cheatItems },
{ "rdrate", nullptr, cheatRate, 1 },
{ "rdskill#", nullptr, cheatSkill },
{ "rdteachers", nullptr, cheatBeta },
{ "rdmoonshine", nullptr, cheatHyper },
{ "rdcritters", nullptr, cheatMonsters },
{ "rdrafael", nullptr, cheatTodd },
{ "rdshowmap", nullptr, cheatMap },
{ "rdelvis", "god" },
{ "rdclip", nullptr, cheatClip },
{ "rdguns", nullptr, cheatWeapons },
{ "rdinventory", nullptr, cheatInventory },
{ "rdkeys", nullptr, cheatKeys },
{ "rddebug", nullptr, cheatDebug, 1 },
{ "rdcgs", nullptr, cheatKill }, // 23 for RR
// RRRA only!
{ "rdjoseph", cheatMotorcycle },
{ "rdmrbill", cheatKill },
{ "rdtony", cheatTony },
{ "rdgary", cheatGary },
{ "rdrhett", cheatRhett },
{ "rdaaron", cheatAaron },
{ "rdnocheat", cheatNocheat },
{ "rdwoleslagle", cheatDrink },
{ "rdmikael", cheatStuff },
{ "rdgreg", cheatSeasick },
//"rdnoah", // no-op
{ "rdarijit", cheatBoat },
{ "rddonut", cheatBoat },
{ "rdkfc", cheatKfc },
{ "rdvan", cheatVan },
{ "rdjoseph", nullptr, cheatMotorcycle },
{ "rdmrbill", nullptr, cheatKill },
{ "rdtony", nullptr, cheatTony },
{ "rdgary", nullptr, cheatGary },
{ "rdrhett", nullptr, cheatRhett },
{ "rdaaron", nullptr, cheatAaron },
{ "rdnocheat", nullptr, cheatNocheat },
{ "rdwoleslagle",nullptr, cheatDrink },
{ "rdmikael", nullptr, cheatStuff },
{ "rdgreg", nullptr, cheatSeasick },
//"rdnoah", nullptr, // no-op
{ "rdarijit", nullptr, cheatBoat },
{ "rddonut", nullptr, cheatBoat },
{ "rdkfc", nullptr, cheatKfc },
{ "rdvan", nullptr, cheatVan },
};
void InitCheats()

View file

@ -47,7 +47,6 @@ struct GameInterface : public ::GameInterface
void SerializeGameState(FSerializer& arc) override;
void QuitToTitle() override;
FString GetCoordString() override;
bool CheatAllowed(bool printmsg) override;
void ExitFromMenu() override;
ReservedSpace GetReservedScreenSpace(int viewsize) override;
void DrawPlayerSprite(const DVector2& origin, bool onteam) override;
@ -58,6 +57,8 @@ struct GameInterface : public ::GameInterface
void DrawBackground() override;
void Render() override;
void Ticker() override;
const char* GenericCheat(int player, int cheat) override;
const char* CheckCheatMode();
};

View file

@ -37,6 +37,8 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms
#include "gamecontrol.h"
#include "gstrings.h"
#include "cheathandler.h"
#include "d_protocol.h"
#include "cheats.h"
//#include "inv.h"
BEGIN_SW_NS
@ -54,7 +56,7 @@ static PLAYERp checkCheat(cheatseq_t* c)
if (CommEnabled)
return nullptr;
if (Skill >= 3 && !c->DontCheck)
if (Skill >= 3 && !c->DontCheck && !sv_cheats)
{
PutStringInfo(&Player[screenpeek], GStrings("TXTS_TOOSKILLFUL"));
return nullptr;
@ -63,6 +65,38 @@ static PLAYERp checkCheat(cheatseq_t* c)
return &Player[screenpeek];
}
const char *GameInterface::CheckCheatMode()
{
if (Skill >= 3 && !sv_cheats)
{
return GStrings("TXTS_TOOSKILLFUL");
}
return nullptr;
}
const char *GameInterface::GenericCheat(int player, int cheat)
{
switch (cheat)
{
case CHT_GOD:
GodMode ^= 1; // fixme: Make god mode a player property.
return GStrings(GodMode ? "GOD MODE: ON" : "GOD MODE: OFF");
case CHT_GODOFF:
GodMode = 0; // fixme: Make god mode a player property.
return GStrings("GOD MODE: OFF");
case CHT_GODON:
GodMode = 1; // fixme: Make god mode a player property.
return GStrings("GOD MODE: ON");
default:
return nullptr;
}
}
bool RestartCheat(cheatseq_t* c)
{
if (!checkCheat(c)) return false;
@ -180,19 +214,6 @@ bool AmmoCheat(cheatseq_t* c)
return true;
}
bool GodCheat(cheatseq_t* c)
{
PLAYERp pp;
if (!(pp = checkCheat(c))) return false;
//
// GOD mode
//
GodMode ^= 1;
PutStringInfo(pp, GStrings(GodMode? "GOD MODE: ON" : "GOD MODE: OFF"));
return true;
}
bool ClipCheat(cheatseq_t* c)
{
PLAYERp pp;
@ -403,28 +424,29 @@ bool KeysCheat(cheatseq_t* c)
bool EveryCheatToggle(cheatseq_t* c)
{
EveryCheat ^= 1;
return WeaponCheat(c) && GodCheat(c) && ItemCheat(c);
C_DoCommand("god");
return WeaponCheat(c) && ItemCheat(c);
}
// The prefix was changed from 'sw' to 'lw' so that it doesn't contain two keys of the WASD control scheme, which interferes with input control.
static cheatseq_t swcheats[] = {
{"lwgod", GodCheat, 0},
{"lwchan", GodCheat, 0},
{"lwgimme", ItemCheat, 0},
{"lwmedic", HealCheat, 0},
{"lwkey#", KeyCheat, 0},
{"lwkeys", KeysCheat, 0},
{"lwammo", AmmoCheat, 0},
{"lwarmor", ArmorCheat, 0},
{"lwitems", ItemCheat, 0},
{"lwguns", WeaponCheat, 0},
{"lwtrek##", WarpCheat, 0},
{"lwgreed", EveryCheatToggle, 0},
{"lwghost", ClipCheat, 0},
{"lwstart", RestartCheat, 0},
{"lwloc", LocCheat, 0},
{"lwmap", MapCheat, 0},
{"lwroom", RoomCheat, true}, // Room above room dbug
{"lwgod", "god" },
{"lwchan", "god" },
{"lwgimme", nullptr, ItemCheat, 0},
{"lwmedic", nullptr, HealCheat, 0},
{"lwkey#", nullptr, KeyCheat, 0},
{"lwkeys", nullptr, KeysCheat, 0},
{"lwammo", nullptr, AmmoCheat, 0},
{"lwarmor", nullptr, ArmorCheat, 0},
{"lwitems", nullptr, ItemCheat, 0},
{"lwguns", nullptr, WeaponCheat, 0},
{"lwtrek##", nullptr, WarpCheat, 0},
{"lwgreed", nullptr, EveryCheatToggle, 0},
{"lwghost", nullptr, ClipCheat, 0},
{"lwstart", nullptr, RestartCheat, 0},
{"lwloc", nullptr, LocCheat, 0},
{"lwmap", nullptr, MapCheat, 0},
{"lwroom", nullptr, RoomCheat, true}, // Room above room dbug
};

View file

@ -2226,6 +2226,9 @@ struct GameInterface : ::GameInterface
void Ticker(void) override;
void Render() override;
void Startup() override;
const char *CheckCheatMode() override;
const char* GenericCheat(int player, int cheat) override;
GameStats getStats() override;
};

View file

@ -100,12 +100,6 @@ static int osdcmd_map(CCmdFuncPtr parm)
return CCMD_OK;
}
static int osdcmd_god(CCmdFuncPtr)
{
C_DoCommand("activatecheat lwgod");
return CCMD_OK;
}
static int osdcmd_noclip(CCmdFuncPtr)
{
C_DoCommand("activatecheat lwghost");
@ -299,7 +293,6 @@ int32_t registerosdcommands(void)
{
C_RegisterFunction("map","map <mapfile>: loads the given map", osdcmd_map);
C_RegisterFunction("give","give <all|health|weapons|ammo|armor|keys|inventory>: gives requested item", osdcmd_give);
C_RegisterFunction("god","god: toggles god mode", osdcmd_god);
C_RegisterFunction("bunny", "bunny: toggles bunny rocket mode", osdcmd_bunny);
C_RegisterFunction("mirror_debug", "mirror [mirrornum]: print mirror debug info", osdcmd_mirror);
C_RegisterFunction("noclip","noclip: toggles clipping mode", osdcmd_noclip);