From a27ab517dcfae7d641502ad6f5cc2dac8f63197c Mon Sep 17 00:00:00 2001 From: obligaron Date: Mon, 23 Aug 2021 08:35:18 +0200 Subject: [PATCH] Enable multiline DiabloMsg and use it in debug.cpp --- Source/debug.cpp | 30 ++++--------------- Source/error.cpp | 75 ++++++++++++++++++++++++++++++++++++------------ Source/error.h | 2 ++ 3 files changed, 64 insertions(+), 43 deletions(-) diff --git a/Source/debug.cpp b/Source/debug.cpp index d0c676f36..36d2a1a69 100644 --- a/Source/debug.cpp +++ b/Source/debug.cpp @@ -13,6 +13,7 @@ #include "cursor.h" #include "engine/load_cel.hpp" #include "engine/point.hpp" +#include "error.h" #include "inv.h" #include "lighting.h" #include "setmaps.h" @@ -80,19 +81,12 @@ 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 + 3) > MAX_SEND_STR_LEN) { - ret.append("\n"); - lenCurrentLine = dbgCmd.text.length(); - } else { - if (first) - first = false; - else - ret.append(" - "); - lenCurrentLine += (dbgCmd.text.length() + 3); - } + if (first) + first = false; + else + ret.append(" - "); ret.append(dbgCmd.text); } return ret; @@ -509,19 +503,7 @@ bool CheckDebugTextCommand(const std::string_view text) 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()); - + InitDiabloMsg(result); return true; } diff --git a/Source/error.cpp b/Source/error.cpp index a64d6f441..075548cb2 100644 --- a/Source/error.cpp +++ b/Source/error.cpp @@ -19,7 +19,36 @@ namespace devilution { namespace { std::deque DiabloMessages; +std::vector TextLines; uint32_t msgdelay; +int ErrorWindowHeight = 54; +const int LineHeight = 12; +const int LineWidth = 418; + +void InitNextLines() +{ + msgdelay = SDL_GetTicks(); + auto message = DiabloMessages.front(); + + TextLines.clear(); + + char tempstr[1536]; // Longest test is about 768 chars * 2 for unicode + strcpy(tempstr, message.data()); + + WordWrapGameString(tempstr, LineWidth, GameFontSmall, 1); + const string_view paragraphs = tempstr; + + size_t previous = 0; + while (true) { + size_t next = paragraphs.find('\n', previous); + TextLines.emplace_back(paragraphs.substr(previous, next)); + if (next == std::string::npos) + break; + previous = next + 1; + } + + ErrorWindowHeight = std::max(54, static_cast((TextLines.size() * LineHeight) + 42)); +} } // namespace @@ -85,7 +114,11 @@ const char *const MsgStrings[] = { void InitDiabloMsg(diablo_message e) { std::string msg = _(MsgStrings[e]); + InitDiabloMsg(msg); +} +void InitDiabloMsg(std::string msg) +{ if (DiabloMessages.size() >= MAX_SEND_STR_LEN) return; @@ -93,7 +126,8 @@ void InitDiabloMsg(diablo_message e) return; DiabloMessages.push_back(msg); - msgdelay = SDL_GetTicks(); + if (DiabloMessages.size() == 1) + InitNextLines(); } bool IsDiabloMsgAvailable() @@ -111,41 +145,44 @@ void ClrDiabloMsg() DiabloMessages.clear(); } -#define DIALOG_Y ((gnScreenHeight - PANEL_HEIGHT) / 2 - 18) - void DrawDiabloMsg(const Surface &out) { - CelDrawTo(out, { PANEL_X + 101, DIALOG_Y }, *pSTextSlidCels, 1); - CelDrawTo(out, { PANEL_X + 527, DIALOG_Y }, *pSTextSlidCels, 4); - CelDrawTo(out, { PANEL_X + 101, DIALOG_Y + 48 }, *pSTextSlidCels, 2); - CelDrawTo(out, { PANEL_X + 527, DIALOG_Y + 48 }, *pSTextSlidCels, 3); + int dialogStartY = ((gnScreenHeight - PANEL_HEIGHT) / 2) - (ErrorWindowHeight / 2) + 9; + + CelDrawTo(out, { PANEL_X + 101, dialogStartY }, *pSTextSlidCels, 1); + CelDrawTo(out, { PANEL_X + 527, dialogStartY }, *pSTextSlidCels, 4); + CelDrawTo(out, { PANEL_X + 101, dialogStartY + ErrorWindowHeight - 6 }, *pSTextSlidCels, 2); + CelDrawTo(out, { PANEL_X + 527, dialogStartY + ErrorWindowHeight - 6 }, *pSTextSlidCels, 3); int sx = PANEL_X + 109; for (int i = 0; i < 35; i++) { - CelDrawTo(out, { sx, DIALOG_Y }, *pSTextSlidCels, 5); - CelDrawTo(out, { sx, DIALOG_Y + 48 }, *pSTextSlidCels, 7); + CelDrawTo(out, { sx, dialogStartY }, *pSTextSlidCels, 5); + CelDrawTo(out, { sx, dialogStartY + ErrorWindowHeight - 6 }, *pSTextSlidCels, 7); sx += 12; } - int sy = DIALOG_Y + 12; - for (int i = 0; i < 3; i++) { - CelDrawTo(out, { PANEL_X + 101, sy }, *pSTextSlidCels, 6); - CelDrawTo(out, { PANEL_X + 527, sy }, *pSTextSlidCels, 8); - sy += 12; + int drawnYborder = 12; + while ((drawnYborder + 12) < ErrorWindowHeight) { + CelDrawTo(out, { PANEL_X + 101, dialogStartY + drawnYborder }, *pSTextSlidCels, 6); + CelDrawTo(out, { PANEL_X + 527, dialogStartY + drawnYborder }, *pSTextSlidCels, 8); + drawnYborder += 12; } - DrawHalfTransparentRectTo(out, PANEL_X + 104, DIALOG_Y - 8, 432, 54); + DrawHalfTransparentRectTo(out, PANEL_X + 104, dialogStartY - 8, 432, ErrorWindowHeight); auto message = DiabloMessages.front(); - DrawString(out, message, { { PANEL_X + 101, DIALOG_Y + 24 }, { 442, 0 } }, UiFlags::AlignCenter); + int lineNumber = 0; + for (auto &line : TextLines) { + DrawString(out, line.c_str(), { { PANEL_X + 109, dialogStartY + 24 + lineNumber * LineHeight }, { LineWidth, LineHeight } }, UiFlags::AlignCenter, 1, LineHeight); + lineNumber += 1; + } if (msgdelay > 0 && msgdelay <= SDL_GetTicks() - 3500) { msgdelay = 0; } if (msgdelay == 0) { DiabloMessages.pop_front(); - if (!DiabloMessages.empty()) { - msgdelay = SDL_GetTicks(); - } + if (!DiabloMessages.empty()) + InitNextLines(); } } diff --git a/Source/error.h b/Source/error.h index a0382fe66..dac1a69ca 100644 --- a/Source/error.h +++ b/Source/error.h @@ -6,6 +6,7 @@ #pragma once #include +#include #include "engine.h" @@ -70,6 +71,7 @@ enum diablo_message : uint8_t { }; void InitDiabloMsg(diablo_message e); +void InitDiabloMsg(std::string msg); bool IsDiabloMsgAvailable(); void CancelCurrentDiabloMsg(); void ClrDiabloMsg();