diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index c29fc2fa0..15fcfe881 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -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 diff --git a/source/blood/src/blood.h b/source/blood/src/blood.h index 2e08291a5..98f5152c0 100644 --- a/source/blood/src/blood.h +++ b/source/blood/src/blood.h @@ -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; }; diff --git a/source/blood/src/messages.cpp b/source/blood/src/messages.cpp index fb4ee0ead..0e3a5fcf6 100644 --- a/source/blood/src/messages.cpp +++ b/source/blood/src/messages.cpp @@ -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 bool doCheat(cheatseq_t *c) { ProcessCheat(code, (char*)c->Args); @@ -465,42 +482,42 @@ template bool doCheat(cheatseq_t *c) static cheatseq_t s_CheatInfo[] = { - {"MPKFA", doCheat, 0 }, // MPKFA (Invincibility) - {"CAPINMYASS", doCheat, 0 }, // CAPINMYASS (Disable invincibility ) - {"NOCAPINMYASS", doCheat, 0 }, // NOCAPINMYASS (Invincibility) - {"I WANNA BE LIKE KEVIN", doCheat, 0 }, // I WANNA BE LIKE KEVIN (Invincibility) - {"IDAHO", doCheat, 0 }, // IDAHO (All weapons and full ammo) - {"MONTANA", doCheat, 0 }, // MONTANA (All weapons, full ammo and all items) - {"GRISWOLD", doCheat, 0 }, // GRISWOLD (Full armor (same effect as getting super armor)) - {"EDMARK", 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", doCheat, 0 }, // TEQUILA (Guns akimbo power-up) - {"BUNZ", doCheat, 0 }, // BUNZ (All weapons, full ammo, and guns akimbo power-up) - {"FUNKY SHOES", doCheat, 0 }, // FUNKY SHOES (Gives jump boots item and activates it) - {"GATEKEEPER", doCheat, 0 }, // GATEKEEPER (Sets the you cheated flag to true, at the end of the level you will see that you have cheated) - {"KEYMASTER", doCheat, 0 }, // KEYMASTER (All keys) - {"JOJO", doCheat, 0 }, // JOJO (Drunk mode (same effect as getting bitten by red spider)) - {"SATCHEL", doCheat, 0 }, // SATCHEL (Full inventory) - {"SPORK", doCheat, 0 }, // SPORK (200% health (same effect as getting life seed)) - {"ONERING", doCheat, 0 }, // ONERING (Cloak of invisibility power-up) - {"MARIO###", doCheat, 0 }, // MARIO (Warp to level E M, e.g.: MARIO 1 3 will take you to Phantom Express) - {"CALGON", doCheat, 0 }, // CALGON (Jumps to next level or can be used like MARIO with parameters) - {"KEVORKIAN", 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", doCheat, 0 }, // MCGEE (Sets you on fire. Displays the message "YOU'RE FIRED".) - {"KRUEGER", doCheat, 0 }, // KRUEGER (200% health, but sets you on fire. Displays the message "FLAME RETARDANT".) - {"CHEESEHEAD", doCheat, 0 }, // CHEESEHEAD (100% diving suit) - {"COUSTEAU", doCheat, 0 }, // COUSTEAU (200% health and diving suit) - {"VOORHEES", doCheat, 0 }, // VOORHEES (Death mask power-up) - {"LARA CROFT", 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", doCheat, 0 }, // HONGKONG (All weapons and infinite ammo) - {"FRANKENSTEIN", doCheat, 0 }, // FRANKENSTEIN (100% med-kit) - {"STERNO", doCheat, 0 }, // STERNO (Temporary blindness (same effect as getting bitten by green spider)) - {"CLARICE", doCheat, 0 }, // CLARICE (Gives 100% body armor, 100% fire armor, 100% spirit armor) - {"FORK YOU", doCheat, 0 }, // FORK YOU (Drunk mode, 1HP, no armor, no weapons, no ammo, no items, no keys, no map, guns akimbo power-up) - {"LIEBERMAN", 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", doCheat, 0 }, // EVA GALLI (Disable/enable clipping (grant the ability to walk through walls)) - {"RATE", doCheat, 1 }, // RATE (Display frame rate (doesn't count as a cheat)) - {"GOONIES", doCheat, 0 }, // GOONIES (Enable full map. Displays the message "YOU HAVE THE MAP".) - //{"SPIELBERG", 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", nullptr, doCheat, 0 }, // 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, doCheatgodMode); - 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 : loads the given map", osdcmd_map); C_RegisterFunction("give","give : 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 : 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); diff --git a/source/blood/src/player.cpp b/source/blood/src/player.cpp index 14bd39cff..016cf1097 100644 --- a/source/blood/src/player.cpp +++ b/source/blood/src/player.cpp @@ -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++) diff --git a/source/blood/src/player.h b/source/blood/src/player.h index fe06055dd..908766a40 100644 --- a/source/blood/src/player.h +++ b/source/blood/src/player.h @@ -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); diff --git a/source/common/console/c_dispatch.h b/source/common/console/c_dispatch.h index b381b6884..57d681c49 100644 --- a/source/common/console/c_dispatch.h +++ b/source/common/console/c_dispatch.h @@ -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); diff --git a/source/core/cheathandler.cpp b/source/core/cheathandler.cpp index 3e710ae7f..c9cd26f52 100644 --- a/source/core/cheathandler.cpp +++ b/source/core/cheathandler.cpp @@ -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) diff --git a/source/core/cheathandler.h b/source/core/cheathandler.h index 9c4ef070d..7641b4482 100644 --- a/source/core/cheathandler.h +++ b/source/core/cheathandler.h @@ -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 diff --git a/source/core/cheats.cpp b/source/core/cheats.cpp new file mode 100644 index 000000000..ece52227b --- /dev/null +++ b/source/core/cheats.cpp @@ -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); + } +} + + diff --git a/source/core/cheats.h b/source/core/cheats.h new file mode 100644 index 000000000..468ae3224 --- /dev/null +++ b/source/core/cheats.h @@ -0,0 +1,10 @@ +#pragma once + +#include +#include "c_cvars.h" + +EXTERN_CVAR(Bool, sv_cheats) + +void genericCheat(int player, uint8_t** stream, bool skip); + + diff --git a/source/core/d_net.cpp b/source/core/d_net.cpp index 608c571c7..44b47900b 100644 --- a/source/core/d_net.cpp +++ b/source/core/d_net.cpp @@ -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); } } diff --git a/source/core/d_protocol.cpp b/source/core/d_protocol.cpp index a11eba662..063a72cf4 100644 --- a/source/core/d_protocol.cpp +++ b/source/core/d_protocol.cpp @@ -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); diff --git a/source/core/d_protocol.h b/source/core/d_protocol.h index 8305f8e98..e3cf62b79 100644 --- a/source/core/d_protocol.h +++ b/source/core/d_protocol.h @@ -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); diff --git a/source/core/gamecontrol.cpp b/source/core/gamecontrol.cpp index b700c3afc..bd648a470 100644 --- a/source/core/gamecontrol.cpp +++ b/source/core/gamecontrol.cpp @@ -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; diff --git a/source/core/gamestruct.h b/source/core/gamestruct.h index 472ae7e64..6c01d2cfd 100644 --- a/source/core/gamestruct.h +++ b/source/core/gamestruct.h @@ -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() { diff --git a/source/exhumed/src/exhumed.cpp b/source/exhumed/src/exhumed.cpp index 7b1f954ae..5d9eef9fc 100644 --- a/source/exhumed/src/exhumed.cpp +++ b/source/exhumed/src/exhumed.cpp @@ -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}, }; diff --git a/source/exhumed/src/exhumed.h b/source/exhumed/src/exhumed.h index bf8be1e0c..22b9abc4c 100644 --- a/source/exhumed/src/exhumed.h +++ b/source/exhumed/src/exhumed.h @@ -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; }; diff --git a/source/exhumed/src/items.cpp b/source/exhumed/src/items.cpp index 4956ab5aa..512e7c630 100644 --- a/source/exhumed/src/items.cpp +++ b/source/exhumed/src/items.cpp @@ -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; } diff --git a/source/exhumed/src/osdcmds.cpp b/source/exhumed/src/osdcmds.cpp index 595e4fdc9..aa27a1f1f 100644 --- a/source/exhumed/src/osdcmds.cpp +++ b/source/exhumed/src/osdcmds.cpp @@ -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 : 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 : 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); diff --git a/source/exhumed/src/player.cpp b/source/exhumed/src/player.cpp index b34877513..bb257821f 100644 --- a/source/exhumed/src/player.cpp +++ b/source/exhumed/src/player.cpp @@ -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"); diff --git a/source/games/duke/src/ccmds.cpp b/source/games/duke/src/ccmds.cpp index 537cfc934..0fcf58875 100644 --- a/source/games/duke/src/ccmds.cpp +++ b/source/games/duke/src/ccmds.cpp @@ -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 : warp to the given map, identified by its name", ccmd_map); C_RegisterFunction("levelwarp","levelwarp : warp to episode 'e' and map 'm'", ccmd_levelwarp); C_RegisterFunction("give","give : 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 [palnum] [cstat] [ang] [x y z]: spawns a sprite with the given properties",ccmd_spawn); diff --git a/source/games/duke/src/cheats.cpp b/source/games/duke/src/cheats.cpp index 8c69288b1..47960dbf5 100644 --- a/source/games/duke/src/cheats.cpp +++ b/source/games/duke/src/cheats.cpp @@ -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() diff --git a/source/games/duke/src/duke3d.h b/source/games/duke/src/duke3d.h index 01dfbf453..87061c2ba 100644 --- a/source/games/duke/src/duke3d.h +++ b/source/games/duke/src/duke3d.h @@ -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(); }; diff --git a/source/sw/src/cheats.cpp b/source/sw/src/cheats.cpp index 2599020de..f669976c8 100644 --- a/source/sw/src/cheats.cpp +++ b/source/sw/src/cheats.cpp @@ -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 }; diff --git a/source/sw/src/game.h b/source/sw/src/game.h index 431512452..732c82286 100644 --- a/source/sw/src/game.h +++ b/source/sw/src/game.h @@ -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; }; diff --git a/source/sw/src/osdcmds.cpp b/source/sw/src/osdcmds.cpp index 2db3c23d2..5f32c248a 100644 --- a/source/sw/src/osdcmds.cpp +++ b/source/sw/src/osdcmds.cpp @@ -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 : loads the given map", osdcmd_map); C_RegisterFunction("give","give : 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);