From 64263583775b98bb6dea2c34e4ccfc2fbf29edb7 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 29 Sep 2022 02:24:55 -0700 Subject: [PATCH] Let some cheat commands work online noclip god scale gravflip hurtme --- src/command.c | 1 + src/d_netcmd.c | 134 ++++++++++++++++++++++++++++++++++++++++++++++++- src/d_netcmd.h | 3 ++ src/m_cheat.c | 33 ++---------- src/m_cheat.h | 10 ++++ 5 files changed, 152 insertions(+), 29 deletions(-) diff --git a/src/command.c b/src/command.c index d1355a923..6358858cb 100644 --- a/src/command.c +++ b/src/command.c @@ -37,6 +37,7 @@ #include "r_data.h" // Color_cons_t #include "r_skins.h" #include "m_random.h" +#include "p_local.h" // P_ResetPlayerCheats //======== // protos. diff --git a/src/d_netcmd.c b/src/d_netcmd.c index dcc351fb9..652a41290 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -96,6 +96,7 @@ static void Got_DiscordInfo(UINT8 **cp, INT32 playernum); static void Got_ScheduleTaskcmd(UINT8 **cp, INT32 playernum); static void Got_ScheduleClearcmd(UINT8 **cp, INT32 playernum); static void Got_Automatecmd(UINT8 **cp, INT32 playernum); +static void Got_Cheat(UINT8 **cp, INT32 playernum); static void PointLimit_OnChange(void); static void TimeLimit_OnChange(void); @@ -625,7 +626,8 @@ const char *netxcmdnames[MAXNETXCMD - 1] = "PLAYSOUND", // XD_PLAYSOUND "SCHEDULETASK", // XD_SCHEDULETASK "SCHEDULECLEAR", // XD_SCHEDULECLEAR - "AUTOMATE" // XD_AUTOMATE + "AUTOMATE", // XD_AUTOMATE + "CHEAT", // XD_CHEAT }; // ========================================================================= @@ -678,6 +680,8 @@ void D_RegisterServerCommands(void) RegisterNetXCmd(XD_SCHEDULECLEAR, Got_ScheduleClearcmd); RegisterNetXCmd(XD_AUTOMATE, Got_Automatecmd); + RegisterNetXCmd(XD_CHEAT, Got_Cheat); + // Remote Administration COM_AddCommand("password", Command_Changepassword_f); COM_AddCommand("login", Command_Login_f); // useful in dedicated to kick off remote admin @@ -1970,6 +1974,42 @@ void D_SendPlayerConfig(UINT8 n) SendNetXCmdForPlayer(n, XD_POWERLEVEL, buf, p-buf); } +void D_Cheat(INT32 playernum, INT32 cheat, ...) +{ + va_list ap; + + UINT8 buf[64]; + UINT8 *p = buf; + + if (!CV_CheatsEnabled()) + { + CONS_Printf("This cannot be used without cheats enabled.\n"); + return; + } + + WRITEUINT8(p, playernum); + WRITEUINT8(p, cheat); + + va_start(ap, cheat); +#define COPY(writemacro, type) writemacro (p, va_arg(ap, type)) + + switch (cheat) + { + case CHEAT_SCALE: + COPY(WRITEFIXED, fixed_t); + break; + + case CHEAT_HURT: + COPY(WRITEINT32, INT32); + break; + } + +#undef COPY + va_end(ap); + + SendNetXCmd(XD_CHEAT, buf, p - buf); +} + // Only works for displayplayer, sorry! static void Command_ResetCamera_f(void) { @@ -5409,6 +5449,98 @@ static void Got_Automatecmd(UINT8 **cp, INT32 playernum) } } +static void Got_Cheat(UINT8 **cp, INT32 playernum) +{ + UINT8 targetPlayer = READUINT8(*cp); + cheat_t cheat = READUINT8(*cp); + + player_t *player; + + if (cheat >= NUMBER_OF_CHEATS || !CV_CheatsEnabled() || targetPlayer >= MAXPLAYERS || + playernode[targetPlayer] != playernode[playernum]) + { + CONS_Alert(CONS_WARNING, + M_GetText ("Illegal cheat command received from %s\n"), + player_names[playernum]); + return; + } + + player = &players[targetPlayer]; + + switch (cheat) + { + case CHEAT_NOCLIP: { + const char *status = "on"; + + if (!P_MobjWasRemoved(player->mo)) + { + player->mo->flags ^= MF_NOCLIP; + + if (!(player->mo->flags & MF_NOCLIP)) + { + status = "off"; + } + } + + CV_CheaterWarning(targetPlayer, va("noclip %s", status)); + break; + } + + case CHEAT_GOD: { + const char *status = (player->pflags & PF_GODMODE) ? "off" : "on"; + + player->pflags ^= PF_GODMODE; + + CV_CheaterWarning(targetPlayer, va("GOD MODE %s", status)); + break; + } + + case CHEAT_SCALE: { + const fixed_t smin = FRACUNIT/100; + const fixed_t smax = 100*FRACUNIT; + + fixed_t s = READFIXED(*cp); + float f; + + s = min(max(smin, s), smax); + f = FIXED_TO_FLOAT(s); + + if (!P_MobjWasRemoved(player->mo)) + { + player->mo->destscale = s; + } + + CV_CheaterWarning(targetPlayer, va("scale = %d%s", (int)f, M_Ftrim(FIXED_TO_FLOAT(s)))); + break; + } + + case CHEAT_FLIP: { + if (!P_MobjWasRemoved(player->mo)) + { + player->mo->flags2 ^= MF2_OBJECTFLIP; + } + + CV_CheaterWarning(targetPlayer, "invert gravity"); + break; + } + + case CHEAT_HURT: { + INT32 damage = READINT32(*cp); + + if (!P_MobjWasRemoved(player->mo)) + { + P_DamageMobj(player->mo, NULL, NULL, damage, DMG_NORMAL); + } + + CV_CheaterWarning(targetPlayer, va("%d damage to me", damage)); + break; + } + + case NUMBER_OF_CHEATS: + break; + } +} + /** Prints the number of displayplayers[0]. * * \todo Possibly remove this; it was useful for debugging at one point. diff --git a/src/d_netcmd.h b/src/d_netcmd.h index 0114c726f..48c658ae3 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -179,6 +179,7 @@ typedef enum XD_SCHEDULETASK, // 36 XD_SCHEDULECLEAR, // 37 XD_AUTOMATE, // 38 + XD_CHEAT, // 39 MAXNETXCMD } netxcmd_t; @@ -278,6 +279,8 @@ void Automate_Clear(void); extern UINT32 livestudioaudience_timer; void LiveStudioAudience(void); +void D_Cheat(INT32 playernum, INT32 cheat, ...); + // used for the player setup menu UINT8 CanChangeSkin(INT32 playernum); diff --git a/src/m_cheat.c b/src/m_cheat.c index 5c9c0015e..a7c183b98 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -251,32 +251,18 @@ boolean cht_Responder(event_t *ev) // command that can be typed at the console! void Command_CheatNoClip_f(void) { - player_t *plyr; - REQUIRE_CHEATS; REQUIRE_INLEVEL; - REQUIRE_SINGLEPLAYER; // TODO: make netplay compatible - plyr = &players[consoleplayer]; - - if (!plyr->mo || P_MobjWasRemoved(plyr->mo)) - return; - - plyr->mo->flags ^= MF_NOCLIP; - CONS_Printf(M_GetText("No Clipping %s\n"), plyr->mo->flags & MF_NOCLIP ? M_GetText("On") : M_GetText("Off")); + D_Cheat(consoleplayer, CHEAT_NOCLIP); } void Command_CheatGod_f(void) { - player_t *plyr; - REQUIRE_CHEATS; REQUIRE_INLEVEL; - REQUIRE_SINGLEPLAYER; // TODO: make multiplayer compatible - plyr = &players[consoleplayer]; - plyr->pflags ^= PF_GODMODE; - CONS_Printf(M_GetText("Cheese Mode %s\n"), plyr->pflags & PF_GODMODE ? M_GetText("On") : M_GetText("Off")); + D_Cheat(consoleplayer, CHEAT_GOD); } void Command_Scale_f(void) @@ -286,7 +272,6 @@ void Command_Scale_f(void) REQUIRE_CHEATS; REQUIRE_INLEVEL; - REQUIRE_SINGLEPLAYER; // TODO: make multiplayer compatible if (scale < FRACUNIT/100 || scale > 100*FRACUNIT) //COM_Argv(1) will return a null string if they did not give a paramater, so... { @@ -294,29 +279,21 @@ void Command_Scale_f(void) return; } - if (!players[consoleplayer].mo) - return; - - players[consoleplayer].mo->destscale = scale; - - CONS_Printf(M_GetText("Scale set to %s\n"), COM_Argv(1)); + D_Cheat(consoleplayer, CHEAT_SCALE, scale); } void Command_Gravflip_f(void) { REQUIRE_CHEATS; REQUIRE_INLEVEL; - REQUIRE_SINGLEPLAYER; // TODO: make multiplayer compatible - if (players[consoleplayer].mo) - players[consoleplayer].mo->flags2 ^= MF2_OBJECTFLIP; + D_Cheat(consoleplayer, CHEAT_FLIP); } void Command_Hurtme_f(void) { REQUIRE_CHEATS; REQUIRE_INLEVEL; - REQUIRE_SINGLEPLAYER; // TODO: make multiplayer compatible if (COM_Argc() < 2) { @@ -324,7 +301,7 @@ void Command_Hurtme_f(void) return; } - P_DamageMobj(players[consoleplayer].mo, NULL, NULL, atoi(COM_Argv(1)), DMG_NORMAL); + D_Cheat(consoleplayer, CHEAT_HURT, atoi(COM_Argv(1))); } void Command_RTeleport_f(void) diff --git a/src/m_cheat.h b/src/m_cheat.h index ec1a129cf..080fe9997 100644 --- a/src/m_cheat.h +++ b/src/m_cheat.h @@ -19,6 +19,16 @@ #include "p_mobj.h" #include "command.h" +typedef enum { + CHEAT_NOCLIP, + CHEAT_GOD, + CHEAT_SCALE, + CHEAT_FLIP, + CHEAT_HURT, + + NUMBER_OF_CHEATS +} cheat_t; + boolean cht_Responder(event_t *ev); void cht_Init(void);