Browse Source

Add debug text commands

pull/2636/head
obligaron 5 years ago committed by Anders Jenbo
parent
commit
36f13b34dc
  1. 18
      Source/control.cpp
  2. 150
      Source/debug.cpp
  3. 3
      Source/debug.h
  4. 3
      Source/interfac.cpp

18
Source/control.cpp

@ -32,6 +32,10 @@
#include "utils/sdl_geometry.h"
#include "options.h"
#ifdef _DEBUG
#include "debug.h"
#endif
namespace devilution {
/**
* @brief Set if the life flask needs to be redrawn during next frame
@ -513,12 +517,18 @@ void ControlSetGoldCurs(PlayerStruct &player)
void ResetTalkMsg()
{
#ifdef _DEBUG
if (CheckDebugTextCommand(TalkMessage))
return;
#endif
uint32_t pmask = 0;
for (int i = 0; i < MAX_PLRS; i++) {
if (WhisperList[i])
pmask |= 1 << i;
}
NetSendCmdString(pmask, TalkMessage);
}
@ -659,7 +669,11 @@ bool GetSpellListSelection(spell_id &pSpell, spell_type &pSplType)
bool IsChatAvailable()
{
#ifdef _DEBUG
return true;
#else
return gbIsMultiplayer;
#endif
}
} // namespace
@ -2074,6 +2088,10 @@ void DiabloHotkeyMsg(uint32_t dwMsg)
assert(dwMsg < QUICK_MESSAGE_OPTIONS);
NetSendCmdString(0xFFFFFF, sgOptions.Chat.szHotKeyMsgs[dwMsg]);
#ifdef _DEBUG
CheckDebugTextCommand(sgOptions.Chat.szHotKeyMsgs[dwMsg]);
#endif
}
} // namespace devilution

150
Source/debug.cpp

@ -4,7 +4,10 @@
* Implementation of debug functions.
*/
#ifdef _DEBUG
#include "cursor.h"
#include "debug.h"
#include "engine/cel_sprite.hpp"
#include "engine/load_cel.hpp"
#include "engine/point.hpp"
@ -16,8 +19,6 @@ namespace devilution {
std::optional<CelSprite> pSquareCel;
#ifdef _DEBUG
namespace {
int DebugPlayerId;
@ -58,6 +59,122 @@ void PrintDebugMonster(int m)
NetSendCmdString(1 << MyPlayerId, dstr);
}
struct DebugCmdItem {
const std::string_view text;
const std::string_view description;
const std::string_view requiredParameter;
std::string (*actionProc)(const std::string_view);
};
extern std::vector<DebugCmdItem> DebugCmdList;
std::string DebugCmdHelp(const std::string_view parameter)
{
if (parameter.empty()) {
std::string ret = "Available Debug Commands: ";
int lenCurrentLine = ret.length();
bool first = true;
for (const auto &dbgCmd : DebugCmdList) {
if ((dbgCmd.text.length() + lenCurrentLine + 2) > MAX_SEND_STR_LEN) {
ret.append("\n");
lenCurrentLine = dbgCmd.text.length();
} else {
if (first)
first = false;
else
ret.append(" - ");
lenCurrentLine += (dbgCmd.text.length() + 2);
}
ret.append(dbgCmd.text);
}
return ret;
} else {
auto debugCmdIterator = std::find_if(DebugCmdList.begin(), DebugCmdList.end(), [&](const DebugCmdItem &elem) { return elem.text == parameter; });
if (debugCmdIterator == DebugCmdList.end())
return fmt::format("Debug command {} wasn't found", parameter);
auto &dbgCmdItem = *debugCmdIterator;
if (dbgCmdItem.requiredParameter.empty())
return fmt::format("Description: {}\nParameters: No additional parameter needed.", dbgCmdItem.description);
return fmt::format("Description: {}\nParameters: {}", dbgCmdItem.description, dbgCmdItem.requiredParameter);
}
}
std::string DebugCmdGiveGoldCheat(const std::string_view parameter)
{
GiveGoldCheat();
return "You are now rich! If only this was as easy in real life...";
}
std::string DebugCmdTakeGoldCheat(const std::string_view parameter)
{
TakeGoldCheat();
return "You are poor...";
}
std::string DebugCmdWarpToLevel(const std::string_view parameter)
{
auto &myPlayer = Players[MyPlayerId];
auto level = atoi(parameter.data());
if (level < 0 || level > (gbIsHellfire ? 24 : 16))
return fmt::format("Level {} is not known. Do you want to write an extension mod?", level);
if (myPlayer.plrlevel == level)
return fmt::format("I did nothing but fulfilled your wish. You are already at level {}.", level);
StartNewLvl(MyPlayerId, (level != 21) ? interface_mode::WM_DIABNEXTLVL : interface_mode::WM_DIABTWARPUP, level);
return fmt::format("Welcome to level {}.", level);
}
std::string DebugCmdResetLevel(const std::string_view parameter)
{
auto &myPlayer = Players[MyPlayerId];
auto level = atoi(parameter.data());
if (level < 0 || level > (gbIsHellfire ? 24 : 16))
return fmt::format("Level {} is not known. Do you want to write an extension mod?", level);
myPlayer._pLvlVisited[level] = false;
if (myPlayer.plrlevel == level)
return fmt::format("Level {} can't be cleaned, cause you still occupy it!", level);
return fmt::format("Level {} was restored and looks fabulous.", level);
}
std::string DebugCmdGodMode(const std::string_view parameter)
{
debug_mode_key_inverted_v = !debug_mode_key_inverted_v;
if (debug_mode_key_inverted_v)
return "A god descended.";
return "You are mortal, beware of the darkness.";
}
std::string DebugCmdLevelUp(const std::string_view parameter)
{
int levels = std::max(1, atoi(parameter.data()));
for (int i = 0; i < levels; i++)
NetSendCmd(true, CMD_CHEAT_EXPERIENCE);
return "New experience leads to new insights.";
}
std::string DebugCmdGetAllSpells(const std::string_view parameter)
{
SetAllSpellsCheat();
return "Magic is no mystery for me.";
}
std::string DebugCmdMaxSpellLevel(const std::string_view parameter)
{
MaxSpellsCheat();
return "Knowledge is power.";
}
std::vector<DebugCmdItem> DebugCmdList = {
{ "help", "Prints help overview or help for a specific command.", "({command})", &DebugCmdHelp },
{ "give gold", "Fills the inventory with gold.", "", &DebugCmdGiveGoldCheat },
{ "give xp", "Levels the player up (min 1 level or {levels}).", "({levels})", &DebugCmdLevelUp },
{ "give spells", "Add all spells to player.", "", &DebugCmdGetAllSpells },
{ "give spells 10", "Set spell level to 10 for all spells.", "", &DebugCmdMaxSpellLevel },
{ "take gold", "Removes all gold from inventory.", "", &DebugCmdTakeGoldCheat },
{ "changelevel", "Moves to specifided {level} (use 0 for town).", "{level}", &DebugCmdWarpToLevel },
{ "restart", "Resets specified {level}.", "{level}", &DebugCmdResetLevel },
{ "god", "Togggles godmode.", "", &DebugCmdGodMode },
};
} // namespace
void LoadDebugGFX()
@ -212,6 +329,33 @@ void NextDebugMonster()
NetSendCmdString(1 << MyPlayerId, dstr);
}
#endif
bool CheckDebugTextCommand(const std::string_view text)
{
auto debugCmdIterator = std::find_if(DebugCmdList.begin(), DebugCmdList.end(), [&](const DebugCmdItem &elem) { return text.find(elem.text) == 0; });
if (debugCmdIterator == DebugCmdList.end())
return false;
auto &dbgCmd = *debugCmdIterator;
std::string_view parameter = "";
if (text.length() > (dbgCmd.text.length() + 1))
parameter = text.substr(dbgCmd.text.length() + 1);
const auto result = dbgCmd.actionProc(parameter);
const std::string delim = "\n";
auto start = 0U;
auto end = result.find(delim);
while (end != std::string::npos) {
const auto line = result.substr(start, end - start);
NetSendCmdString(1 << MyPlayerId, line.c_str());
start = end + delim.length();
end = result.find(delim, start);
}
if (start != result.length())
NetSendCmdString(1 << MyPlayerId, result.substr(start).c_str());
return true;
}
} // namespace devilution
#endif

3
Source/debug.h

@ -5,6 +5,8 @@
*/
#pragma once
#include <string_view>
#include "engine.h"
#include "miniwin/miniwin.h"
#include "utils/stdcompat/optional.hpp"
@ -23,5 +25,6 @@ void PrintDebugPlayer(bool bNextPlayer);
void PrintDebugQuest();
void GetDebugMonster();
void NextDebugMonster();
bool CheckDebugTextCommand(const std::string_view text);
} // namespace devilution

3
Source/interfac.cpp

@ -267,9 +267,8 @@ void ShowProgress(interface_mode uMsg)
}
IncProgress();
FreeGameMem();
currlevel++;
currlevel = myPlayer.plrlevel;
leveltype = gnLevelTypeTbl[currlevel];
assert(myPlayer.plrlevel == currlevel);
IncProgress();
LoadGameLevel(false, ENTRY_MAIN);
IncProgress();

Loading…
Cancel
Save