/* ** c_cmds.cpp ** Miscellaneous console commands. ** **--------------------------------------------------------------------------- ** Copyright 1998-2006 Randy Heit ** 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 OF ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. **--------------------------------------------------------------------------- ** */ #include #include #include #ifdef _WIN32 #include #else #include #endif #include "version.h" #include "c_console.h" #include "c_dispatch.h" #include "i_system.h" #include "doomerrors.h" #include "doomstat.h" #include "gstrings.h" #include "s_sound.h" #include "g_game.h" #include "g_level.h" #include "w_wad.h" #include "gi.h" #include "r_defs.h" #include "d_player.h" #include "p_local.h" #include "r_sky.h" #include "p_setup.h" #include "cmdlib.h" #include "d_net.h" #include "v_text.h" #include "p_lnspec.h" #include "r_utility.h" #include "c_functions.h" #include "g_levellocals.h" extern FILE *Logfile; extern bool insave; CVAR (Bool, sv_cheats, false, CVAR_SERVERINFO | CVAR_LATCH) CVAR (Bool, sv_unlimited_pickup, false, CVAR_SERVERINFO) CVAR (Bool, cl_blockcheats, false, 0) CCMD (toggleconsole) { C_ToggleConsole(); } bool CheckCheatmode (bool printmsg) { if ((G_SkillProperty(SKILLP_DisableCheats) || netgame || deathmatch) && (!sv_cheats)) { if (printmsg) Printf ("sv_cheats must be true to enable this command.\n"); return true; } else if (cl_blockcheats) { if (printmsg) Printf ("cl_blockcheats is turned on and disabled this command.\n"); return true; } else { return false; } } CCMD (quit) { if (!insave) exit (0); } CCMD (exit) { if (!insave) exit (0); } /* ================== Cmd_God Sets client to godmode argv(0) god ================== */ CCMD (god) { if (CheckCheatmode ()) return; Net_WriteByte (DEM_GENERICCHEAT); Net_WriteByte (CHT_GOD); } CCMD(god2) { if (CheckCheatmode()) return; Net_WriteByte(DEM_GENERICCHEAT); Net_WriteByte(CHT_GOD2); } CCMD (iddqd) { if (CheckCheatmode ()) return; Net_WriteByte (DEM_GENERICCHEAT); Net_WriteByte (CHT_IDDQD); } CCMD (buddha) { if (CheckCheatmode()) return; Net_WriteByte(DEM_GENERICCHEAT); Net_WriteByte(CHT_BUDDHA); } CCMD(buddha2) { if (CheckCheatmode()) return; Net_WriteByte(DEM_GENERICCHEAT); Net_WriteByte(CHT_BUDDHA2); } CCMD (notarget) { if (CheckCheatmode ()) return; Net_WriteByte (DEM_GENERICCHEAT); Net_WriteByte (CHT_NOTARGET); } CCMD (fly) { if (CheckCheatmode ()) return; Net_WriteByte (DEM_GENERICCHEAT); Net_WriteByte (CHT_FLY); } /* ================== Cmd_Noclip argv(0) noclip ================== */ CCMD (noclip) { if (CheckCheatmode ()) return; Net_WriteByte (DEM_GENERICCHEAT); Net_WriteByte (CHT_NOCLIP); } CCMD (noclip2) { if (CheckCheatmode()) return; Net_WriteByte (DEM_GENERICCHEAT); Net_WriteByte (CHT_NOCLIP2); } CCMD (powerup) { if (CheckCheatmode ()) return; Net_WriteByte (DEM_GENERICCHEAT); Net_WriteByte (CHT_POWER); } CCMD (morphme) { if (CheckCheatmode ()) return; if (argv.argc() == 1) { Net_WriteByte (DEM_GENERICCHEAT); Net_WriteByte (CHT_MORPH); } else { Net_WriteByte (DEM_MORPHEX); Net_WriteString (argv[1]); } } CCMD (anubis) { if (CheckCheatmode ()) return; Net_WriteByte (DEM_GENERICCHEAT); Net_WriteByte (CHT_ANUBIS); } // [GRB] CCMD (resurrect) { if (CheckCheatmode ()) return; Net_WriteByte (DEM_GENERICCHEAT); Net_WriteByte (CHT_RESSURECT); } EXTERN_CVAR (Bool, chasedemo) CCMD (chase) { if (demoplayback) { int i; if (chasedemo) { chasedemo = false; for (i = 0; i < MAXPLAYERS; i++) players[i].cheats &= ~CF_CHASECAM; } else { chasedemo = true; for (i = 0; i < MAXPLAYERS; i++) players[i].cheats |= CF_CHASECAM; } R_ResetViewInterpolation (); } else { // Check if we're allowed to use chasecam. if (gamestate != GS_LEVEL || (!(dmflags2 & DF2_CHASECAM) && deathmatch && CheckCheatmode ())) return; Net_WriteByte (DEM_GENERICCHEAT); Net_WriteByte (CHT_CHASECAM); } } CCMD (idclev) { if (netgame) return; if ((argv.argc() > 1) && (*(argv[1] + 2) == 0) && *(argv[1] + 1) && *argv[1]) { int epsd, map; char buf[2]; FString mapname; buf[0] = argv[1][0] - '0'; buf[1] = argv[1][1] - '0'; if (gameinfo.flags & GI_MAPxx) { epsd = 1; map = buf[0]*10 + buf[1]; } else { epsd = buf[0]; map = buf[1]; } // Catch invalid maps. mapname = CalcMapName (epsd, map); if (!P_CheckMapData(mapname)) return; // So be it. Printf ("%s\n", GStrings("STSTR_CLEV")); G_DeferedInitNew (mapname); //players[0].health = 0; // Force reset } } CCMD (hxvisit) { if (netgame) return; if ((argv.argc() > 1) && (*(argv[1] + 2) == 0) && *(argv[1] + 1) && *argv[1]) { FString mapname("&wt@"); mapname << argv[1][0] << argv[1][1]; if (CheckWarpTransMap (mapname, false)) { // Just because it's in MAPINFO doesn't mean it's in the wad. if (P_CheckMapData(mapname)) { // So be it. Printf ("%s\n", GStrings("STSTR_CLEV")); G_DeferedInitNew (mapname); return; } } Printf ("No such map found\n"); } } CCMD (changemap) { if (who == NULL || !usergame) { Printf ("Use the map command when not in a game.\n"); return; } if (!players[who->player - players].settings_controller && netgame) { Printf ("Only setting controllers can change the map.\n"); return; } if (argv.argc() > 1) { const char *mapname = argv[1]; if (!strcmp(mapname, "*")) mapname = currentUILevel->MapName.GetChars(); try { if (!P_CheckMapData(mapname)) { Printf ("No map %s\n", mapname); } else { if (argv.argc() > 2) { Net_WriteByte (DEM_CHANGEMAP2); Net_WriteByte (atoi(argv[2])); } else { Net_WriteByte (DEM_CHANGEMAP); } Net_WriteString (mapname); } } catch(CRecoverableError &error) { if (error.GetMessage()) Printf("%s", error.GetMessage()); } } else { Printf ("Usage: changemap [position]\n"); } } CCMD (give) { if (CheckCheatmode () || argv.argc() < 2) return; Net_WriteByte (DEM_GIVECHEAT); Net_WriteString (argv[1]); if (argv.argc() > 2) Net_WriteLong(atoi(argv[2])); else Net_WriteLong(0); } CCMD (take) { if (CheckCheatmode () || argv.argc() < 2) return; Net_WriteByte (DEM_TAKECHEAT); Net_WriteString (argv[1]); if (argv.argc() > 2) Net_WriteLong(atoi (argv[2])); else Net_WriteLong (0); } CCMD(setinv) { if (CheckCheatmode() || argv.argc() < 2) return; Net_WriteByte(DEM_SETINV); Net_WriteString(argv[1]); if (argv.argc() > 2) Net_WriteLong(atoi(argv[2])); else Net_WriteLong(0); if (argv.argc() > 3) Net_WriteByte(!!atoi(argv[3])); else Net_WriteByte(0); } CCMD (gameversion) { Printf ("%s @ %s\nCommit %s\n", GetVersionString(), GetGitTime(), GetGitHash()); } CCMD (print) { if (argv.argc() != 2) { Printf ("print : Print a string from the string table\n"); return; } const char *str = GStrings[argv[1]]; if (str == NULL) { Printf ("%s unknown\n", argv[1]); } else { Printf ("%s\n", str); } } UNSAFE_CCMD (exec) { if (argv.argc() < 2) return; for (int i = 1; i < argv.argc(); ++i) { if (!C_ExecFile(argv[i])) { Printf ("Could not exec \"%s\"\n", argv[i]); break; } } } void execLogfile(const char *fn, bool append) { if ((Logfile = fopen(fn, append? "a" : "w"))) { const char *timestr = myasctime(); Printf("Log started: %s\n", timestr); } else { Printf("Could not start log\n"); } } UNSAFE_CCMD (logfile) { if (Logfile) { const char *timestr = myasctime(); Printf("Log stopped: %s\n", timestr); fclose (Logfile); Logfile = NULL; } if (argv.argc() >= 2) { execLogfile(argv[1], argv.argc() >=3? !!argv[2]:false); } } CCMD (puke) { int argc = argv.argc(); if (argc < 2 || argc > 6) { Printf ("Usage: puke