Browse Source

Remove use of tempstr

pull/4177/head
Anders Jenbo 4 years ago
parent
commit
718c46e7fe
  1. 1
      Source/CMakeLists.txt
  2. 61
      Source/control.cpp
  3. 1
      Source/control.h
  4. 9
      Source/cursor.cpp
  5. 10
      Source/diablo.cpp
  6. 6
      Source/error.cpp
  7. 6
      Source/help.cpp
  8. 3
      Source/inv.cpp
  9. 240
      Source/items.cpp
  10. 5
      Source/minitext.cpp
  11. 53
      Source/monster.cpp
  12. 10
      Source/objects.cpp
  13. 17
      Source/panels/spell_list.cpp
  14. 40
      Source/qol/common.cpp
  15. 25
      Source/qol/common.h
  16. 9
      Source/qol/itemlabels.cpp
  17. 1
      Source/qol/monhealthbar.cpp
  18. 13
      Source/qol/stash.cpp
  19. 43
      Source/qol/xpbar.cpp
  20. 148
      Source/stores.cpp

1
Source/CMakeLists.txt

@ -97,7 +97,6 @@ set(libdevilutionx_SRCS
mpq/mpq_writer.cpp
qol/autopickup.cpp
qol/chatlog.cpp
qol/common.cpp
qol/monhealthbar.cpp
qol/stash.cpp
qol/xpbar.cpp

61
Source/control.cpp

@ -67,7 +67,6 @@ bool drawmanaflag;
bool chrbtnactive;
int pnumlines;
UiFlags InfoColor;
char tempstr[256];
int sbooktab;
int8_t initialDropGoldIndex;
bool talkflag;
@ -703,8 +702,7 @@ void CheckPanelInfo()
strcpy(infostr, _("Player attack"));
}
if (PanBtnHotKey[i] != nullptr) {
strcpy(tempstr, fmt::format(_("Hotkey: {:s}"), _(PanBtnHotKey[i])).c_str());
AddPanelString(tempstr);
AddPanelString(fmt::format(_("Hotkey: {:s}"), _(PanBtnHotKey[i])));
}
InfoColor = UiFlags::ColorWhite;
panelflag = true;
@ -714,41 +712,30 @@ void CheckPanelInfo()
strcpy(infostr, _("Select current spell button"));
InfoColor = UiFlags::ColorWhite;
panelflag = true;
strcpy(tempstr, _("Hotkey: 's'"));
AddPanelString(tempstr);
AddPanelString(_("Hotkey: 's'"));
auto &myPlayer = Players[MyPlayerId];
const spell_id spellId = myPlayer._pRSpell;
if (spellId != SPL_INVALID && spellId != SPL_NULL) {
switch (myPlayer._pRSplType) {
case RSPLTYPE_SKILL:
strcpy(tempstr, fmt::format(_("{:s} Skill"), pgettext("spell", spelldata[spellId].sSkillText)).c_str());
AddPanelString(tempstr);
AddPanelString(fmt::format(_("{:s} Skill"), pgettext("spell", spelldata[spellId].sSkillText)));
break;
case RSPLTYPE_SPELL: {
strcpy(tempstr, fmt::format(_("{:s} Spell"), pgettext("spell", spelldata[spellId].sNameText)).c_str());
AddPanelString(tempstr);
AddPanelString(fmt::format(_("{:s} Spell"), pgettext("spell", spelldata[spellId].sNameText)));
int c = std::max(myPlayer._pISplLvlAdd + myPlayer._pSplLvl[spellId], 0);
if (c == 0)
strcpy(tempstr, _("Spell Level 0 - Unusable"));
else
strcpy(tempstr, fmt::format(_("Spell Level {:d}"), c).c_str());
AddPanelString(tempstr);
AddPanelString(c == 0 ? _("Spell Level 0 - Unusable") : fmt::format(_("Spell Level {:d}"), c));
} break;
case RSPLTYPE_SCROLL: {
strcpy(tempstr, fmt::format(_("Scroll of {:s}"), pgettext("spell", spelldata[spellId].sNameText)).c_str());
AddPanelString(tempstr);
AddPanelString(fmt::format(_("Scroll of {:s}"), pgettext("spell", spelldata[spellId].sNameText)));
const InventoryAndBeltPlayerItemsRange items { myPlayer };
const int scrollCount = std::count_if(items.begin(), items.end(), [spellId](const Item &item) {
return item.IsScrollOf(spellId);
});
strcpy(tempstr, fmt::format(ngettext("{:d} Scroll", "{:d} Scrolls", scrollCount), scrollCount).c_str());
AddPanelString(tempstr);
AddPanelString(fmt::format(ngettext("{:d} Scroll", "{:d} Scrolls", scrollCount), scrollCount));
} break;
case RSPLTYPE_CHARGES:
strcpy(tempstr, fmt::format(_("Staff of {:s}"), pgettext("spell", spelldata[spellId].sNameText)).c_str());
AddPanelString(tempstr);
strcpy(tempstr, fmt::format(ngettext("{:d} Charge", "{:d} Charges", myPlayer.InvBody[INVLOC_HAND_LEFT]._iCharges), myPlayer.InvBody[INVLOC_HAND_LEFT]._iCharges).c_str());
AddPanelString(tempstr);
AddPanelString(fmt::format(_("Staff of {:s}"), pgettext("spell", spelldata[spellId].sNameText)));
AddPanelString(fmt::format(ngettext("{:d} Charge", "{:d} Charges", myPlayer.InvBody[INVLOC_HAND_LEFT]._iCharges), myPlayer.InvBody[INVLOC_HAND_LEFT]._iCharges));
break;
case RSPLTYPE_INVALID:
break;
@ -910,10 +897,8 @@ void DrawInfoBox(const Surface &out)
auto &target = Players[pcursplr];
strcpy(infostr, target._pName);
ClearPanel();
strcpy(tempstr, fmt::format(_("{:s}, Level: {:d}"), _(ClassStrTbl[static_cast<std::size_t>(target._pClass)]), target._pLevel).c_str());
AddPanelString(tempstr);
strcpy(tempstr, fmt::format(_("Hit Points {:d} of {:d}"), target._pHitPoints >> 6, target._pMaxHP >> 6).c_str());
AddPanelString(tempstr);
AddPanelString(fmt::format(_("{:s}, Level: {:d}"), _(ClassStrTbl[static_cast<std::size_t>(target._pClass)]), target._pLevel));
AddPanelString(fmt::format(_("Hit Points {:d} of {:d}"), target._pHitPoints >> 6, target._pMaxHP >> 6));
}
}
if (infostr[0] != '\0' || pnumlines != 0)
@ -1051,33 +1036,29 @@ void DrawGoldSplit(const Surface &out, int amount)
CelDrawTo(out, GetPanelPosition(UiPanels::Inventory, { dialogX, 178 }), *pGBoxBuff, 1);
constexpr auto BufferSize = sizeof(tempstr) / sizeof(*tempstr);
CopyUtf8(
tempstr,
fmt::format(ngettext(
/* TRANSLATORS: {:d} is a number. Dialog is shown when splitting a stash of Gold.*/ "You have {:d} gold piece. How many do you want to remove?",
"You have {:d} gold pieces. How many do you want to remove?",
initialDropGoldValue),
const std::string description = fmt::format(
/* TRANSLATORS: {:d} is a number. Dialog is shown when splitting a stash of Gold.*/
ngettext(
"You have {:d} gold piece. How many do you want to remove?",
"You have {:d} gold pieces. How many do you want to remove?",
initialDropGoldValue),
BufferSize);
initialDropGoldValue);
// Pre-wrap the string at spaces, otherwise DrawString would hard wrap in the middle of words
const std::string wrapped = WordWrapString(tempstr, 200);
const std::string wrapped = WordWrapString(description, 200);
// The split gold dialog is roughly 4 lines high, but we need at least one line for the player to input an amount.
// Using a clipping region 50 units high (approx 3 lines with a lineheight of 17) to ensure there is enough room left
// for the text entered by the player.
DrawString(out, wrapped, { GetPanelPosition(UiPanels::Inventory, { dialogX + 31, 75 }), { 200, 50 } }, UiFlags::ColorWhitegold | UiFlags::AlignCenter, 1, 17);
tempstr[0] = '\0';
std::string value = "";
if (amount > 0) {
// snprintf ensures that the destination buffer ends in a null character.
snprintf(tempstr, BufferSize, "%u", amount);
value = fmt::format("{:d}", amount);
}
// Even a ten digit amount of gold only takes up about half a line. There's no need to wrap or clip text here so we
// use the Point form of DrawString.
DrawString(out, tempstr, GetPanelPosition(UiPanels::Inventory, { dialogX + 37, 128 }), UiFlags::ColorWhite | UiFlags::PentaCursor);
DrawString(out, value, GetPanelPosition(UiPanels::Inventory, { dialogX + 37, 128 }), UiFlags::ColorWhite | UiFlags::PentaCursor);
}
void control_drop_gold(char vkey)

1
Source/control.h

@ -41,7 +41,6 @@ extern bool drawmanaflag;
extern bool chrbtnactive;
extern DVL_API_FOR_TEST int pnumlines;
extern UiFlags InfoColor;
extern char tempstr[256];
extern int sbooktab;
extern int8_t initialDropGoldIndex;
extern bool talkflag;

9
Source/cursor.cpp

@ -217,8 +217,7 @@ void CheckTown()
trigflag = true;
ClearPanel();
strcpy(infostr, _("Town Portal"));
strcpy(tempstr, fmt::format(_("from {:s}"), Players[missile._misource]._pName).c_str());
AddPanelString(tempstr);
AddPanelString(fmt::format(_("from {:s}"), Players[missile._misource]._pName));
cursPosition = missile.position.tile;
}
}
@ -233,11 +232,7 @@ void CheckRportal()
trigflag = true;
ClearPanel();
strcpy(infostr, _("Portal to"));
if (!setlevel)
strcpy(tempstr, _("The Unholy Altar"));
else
strcpy(tempstr, _("level 15"));
AddPanelString(tempstr);
AddPanelString(!setlevel ? _("The Unholy Altar") : _("level 15"));
cursPosition = missile.position.tile;
}
}

10
Source/diablo.cpp

@ -12,7 +12,6 @@
#include "DiabloUI/selstart.h"
#include "automap.h"
#include "capture.h"
#include "control.h"
#include "cursor.h"
#include "dead.h"
#ifdef _DEBUG
@ -58,9 +57,10 @@
#include "pfile.h"
#include "plrmsg.h"
#include "qol/chatlog.h"
#include "qol/common.h"
#include "qol/itemlabels.h"
#include "qol/monhealthbar.h"
#include "qol/stash.h"
#include "qol/xpbar.h"
#include "restrict.h"
#include "setmaps.h"
#include "sound.h"
@ -159,7 +159,8 @@ void StartGame(interface_mode uMsg)
#endif
assert(ghMainWnd);
music_stop();
InitQol();
InitMonsterHealthBar();
InitXPBar();
ShowProgress(uMsg);
gmenu_init_menu();
InitLevelCursor();
@ -170,7 +171,8 @@ void StartGame(interface_mode uMsg)
void FreeGame()
{
FreeQol();
FreeMonsterHealthBar();
FreeXPBar();
FreeControlPan();
FreeInvGFX();
FreeStashGFX();

6
Source/error.cpp

@ -9,7 +9,6 @@
#include "error.h"
#include "DiabloUI/ui_flags.hpp"
#include "control.h"
#include "engine/render/cel_render.hpp"
#include "engine/render/text_render.hpp"
#include "panels/info_box.hpp"
@ -34,10 +33,7 @@ void InitNextLines()
TextLines.clear();
char tempstr[1536]; // Longest test is about 768 chars * 2 for unicode
strcpy(tempstr, message.data());
const std::string paragraphs = WordWrapString(tempstr, LineWidth, GameFont12, 1);
const std::string paragraphs = WordWrapString(message, LineWidth, GameFont12, 1);
size_t previous = 0;
while (true) {

6
Source/help.cpp

@ -7,7 +7,6 @@
#include <vector>
#include "DiabloUI/ui_flags.hpp"
#include "control.h"
#include "engine/render/text_render.hpp"
#include "init.h"
#include "minitext.h"
@ -148,12 +147,9 @@ void InitHelp()
return;
HelpFlag = false;
char tempString[1024];
for (const auto *text : HelpText) {
strcpy(tempString, _(text));
const std::string paragraph = WordWrapString(tempString, 577);
const std::string paragraph = WordWrapString(_(text), 577);
size_t previous = 0;
while (true) {

3
Source/inv.cpp

@ -1365,8 +1365,7 @@ void DrawInvBelt(const Surface &out)
if (AllItemsList[myPlayer.SpdList[i].IDidx].iUsable
&& myPlayer.SpdList[i]._itype != ItemType::Gold) {
snprintf(tempstr, sizeof(tempstr) / sizeof(*tempstr), "%i", i + 1);
DrawString(out, tempstr, { position - Displacement { 0, 12 }, InventorySlotSizeInPixels }, UiFlags::ColorWhite | UiFlags::AlignRight);
DrawString(out, fmt::format("{:d}", i + 1), { position - Displacement { 0, 12 }, InventorySlotSizeInPixels }, UiFlags::ColorWhite | UiFlags::AlignRight);
}
}
}

240
Source/items.cpp

@ -1845,140 +1845,102 @@ void PrintItemOil(char iDidx)
{
switch (iDidx) {
case IMISC_OILACC:
strcpy(tempstr, _("increases a weapon's"));
AddPanelString(tempstr);
strcpy(tempstr, _("chance to hit"));
AddPanelString(tempstr);
AddPanelString(_("increases a weapon's"));
AddPanelString(_("chance to hit"));
break;
case IMISC_OILMAST:
strcpy(tempstr, _("greatly increases a"));
AddPanelString(tempstr);
strcpy(tempstr, _("weapon's chance to hit"));
AddPanelString(tempstr);
AddPanelString(_("greatly increases a"));
AddPanelString(_("weapon's chance to hit"));
break;
case IMISC_OILSHARP:
strcpy(tempstr, _("increases a weapon's"));
AddPanelString(tempstr);
strcpy(tempstr, _("damage potential"));
AddPanelString(tempstr);
AddPanelString(_("increases a weapon's"));
AddPanelString(_("damage potential"));
break;
case IMISC_OILDEATH:
strcpy(tempstr, _("greatly increases a weapon's"));
AddPanelString(tempstr);
strcpy(tempstr, _("damage potential - not bows"));
AddPanelString(tempstr);
AddPanelString(_("greatly increases a weapon's"));
AddPanelString(_("damage potential - not bows"));
break;
case IMISC_OILSKILL:
strcpy(tempstr, _("reduces attributes needed"));
AddPanelString(tempstr);
strcpy(tempstr, _("to use armor or weapons"));
AddPanelString(tempstr);
AddPanelString(_("reduces attributes needed"));
AddPanelString(_("to use armor or weapons"));
break;
case IMISC_OILBSMTH:
/*xgettext:no-c-format*/ strcpy(tempstr, _("restores 20% of an"));
AddPanelString(tempstr);
strcpy(tempstr, _("item's durability"));
AddPanelString(tempstr);
AddPanelString(/*xgettext:no-c-format*/ _("restores 20% of an"));
AddPanelString(_("item's durability"));
break;
case IMISC_OILFORT:
strcpy(tempstr, _("increases an item's"));
AddPanelString(tempstr);
strcpy(tempstr, _("current and max durability"));
AddPanelString(tempstr);
AddPanelString(_("increases an item's"));
AddPanelString(_("current and max durability"));
break;
case IMISC_OILPERM:
strcpy(tempstr, _("makes an item indestructible"));
AddPanelString(tempstr);
AddPanelString(_("makes an item indestructible"));
break;
case IMISC_OILHARD:
strcpy(tempstr, _("increases the armor class"));
AddPanelString(tempstr);
strcpy(tempstr, _("of armor and shields"));
AddPanelString(tempstr);
AddPanelString(_("increases the armor class"));
AddPanelString(_("of armor and shields"));
break;
case IMISC_OILIMP:
strcpy(tempstr, _("greatly increases the armor"));
AddPanelString(tempstr);
strcpy(tempstr, _("class of armor and shields"));
AddPanelString(tempstr);
AddPanelString(_("greatly increases the armor"));
AddPanelString(_("class of armor and shields"));
break;
case IMISC_RUNEF:
strcpy(tempstr, _("sets fire trap"));
AddPanelString(tempstr);
AddPanelString(_("sets fire trap"));
break;
case IMISC_RUNEL:
case IMISC_GR_RUNEL:
strcpy(tempstr, _("sets lightning trap"));
AddPanelString(tempstr);
AddPanelString(_("sets lightning trap"));
break;
case IMISC_GR_RUNEF:
strcpy(tempstr, _("sets fire trap"));
AddPanelString(tempstr);
AddPanelString(_("sets fire trap"));
break;
case IMISC_RUNES:
strcpy(tempstr, _("sets petrification trap"));
AddPanelString(tempstr);
AddPanelString(_("sets petrification trap"));
break;
case IMISC_FULLHEAL:
strcpy(tempstr, _("restore all life"));
AddPanelString(tempstr);
AddPanelString(_("restore all life"));
break;
case IMISC_HEAL:
strcpy(tempstr, _("restore some life"));
AddPanelString(tempstr);
AddPanelString(_("restore some life"));
break;
case IMISC_OLDHEAL:
strcpy(tempstr, _("recover life"));
AddPanelString(tempstr);
AddPanelString(_("recover life"));
break;
case IMISC_DEADHEAL:
strcpy(tempstr, _("deadly heal"));
AddPanelString(tempstr);
AddPanelString(_("deadly heal"));
break;
case IMISC_MANA:
strcpy(tempstr, _("restore some mana"));
AddPanelString(tempstr);
AddPanelString(_("restore some mana"));
break;
case IMISC_FULLMANA:
strcpy(tempstr, _("restore all mana"));
AddPanelString(tempstr);
AddPanelString(_("restore all mana"));
break;
case IMISC_ELIXSTR:
strcpy(tempstr, _("increase strength"));
AddPanelString(tempstr);
AddPanelString(_("increase strength"));
break;
case IMISC_ELIXMAG:
strcpy(tempstr, _("increase magic"));
AddPanelString(tempstr);
AddPanelString(_("increase magic"));
break;
case IMISC_ELIXDEX:
strcpy(tempstr, _("increase dexterity"));
AddPanelString(tempstr);
AddPanelString(_("increase dexterity"));
break;
case IMISC_ELIXVIT:
strcpy(tempstr, _("increase vitality"));
AddPanelString(tempstr);
AddPanelString(_("increase vitality"));
break;
case IMISC_ELIXWEAK:
case IMISC_ELIXDIS:
strcpy(tempstr, _("decrease strength"));
AddPanelString(tempstr);
AddPanelString(_("decrease strength"));
break;
case IMISC_ELIXCLUM:
strcpy(tempstr, _("decrease dexterity"));
AddPanelString(tempstr);
AddPanelString(_("decrease dexterity"));
break;
case IMISC_ELIXSICK:
strcpy(tempstr, _("decrease vitality"));
AddPanelString(tempstr);
AddPanelString(_("decrease vitality"));
break;
case IMISC_REJUV:
strcpy(tempstr, _("restore some life and mana"));
AddPanelString(tempstr);
AddPanelString(_("restore some life and mana"));
break;
case IMISC_FULLREJUV:
strcpy(tempstr, _("restore all life and mana"));
AddPanelString(tempstr);
AddPanelString(_("restore all life and mana"));
break;
}
}
@ -1992,49 +1954,38 @@ void DrawUniqueInfoWindow(const Surface &out)
void PrintItemMisc(const Item &item)
{
if (item._iMiscId == IMISC_SCROLL) {
strcpy(tempstr, _("Right-click to read"));
AddPanelString(tempstr);
AddPanelString(_("Right-click to read"));
}
if (item._iMiscId == IMISC_SCROLLT) {
strcpy(tempstr, _("Right-click to read, then"));
AddPanelString(tempstr);
strcpy(tempstr, _("left-click to target"));
AddPanelString(tempstr);
AddPanelString(_("Right-click to read, then"));
AddPanelString(_("left-click to target"));
}
if (item._iMiscId >= IMISC_USEFIRST && item._iMiscId <= IMISC_USELAST) {
PrintItemOil(item._iMiscId);
strcpy(tempstr, _("Right-click to use"));
AddPanelString(tempstr);
AddPanelString(_("Right-click to use"));
}
if (item._iMiscId > IMISC_OILFIRST && item._iMiscId < IMISC_OILLAST) {
PrintItemOil(item._iMiscId);
strcpy(tempstr, _("Right click to use"));
AddPanelString(tempstr);
AddPanelString(_("Right click to use"));
}
if (item._iMiscId > IMISC_RUNEFIRST && item._iMiscId < IMISC_RUNELAST) {
PrintItemOil(item._iMiscId);
strcpy(tempstr, _("Right click to use"));
AddPanelString(tempstr);
AddPanelString(_("Right click to use"));
}
if (item._iMiscId == IMISC_BOOK) {
strcpy(tempstr, _("Right-click to read"));
AddPanelString(tempstr);
AddPanelString(_("Right-click to read"));
}
if (item._iMiscId == IMISC_NOTE) {
strcpy(tempstr, _("Right click to read"));
AddPanelString(tempstr);
AddPanelString(_("Right click to read"));
}
if (item._iMiscId == IMISC_MAPOFDOOM) {
strcpy(tempstr, _("Right-click to view"));
AddPanelString(tempstr);
AddPanelString(_("Right-click to view"));
}
if (item._iMiscId == IMISC_EAR) {
strcpy(tempstr, fmt::format(_("Level: {:d}"), item._ivalue).c_str());
AddPanelString(tempstr);
AddPanelString(fmt::format(_("Level: {:d}"), item._ivalue));
}
if (item._iMiscId == IMISC_AURIC) {
strcpy(tempstr, _("Doubles gold capacity"));
AddPanelString(tempstr);
AddPanelString(_("Doubles gold capacity"));
}
}
@ -2045,14 +1996,14 @@ void PrintItemInfo(const Item &item)
uint8_t dex = item._iMinDex;
uint8_t mag = item._iMinMag;
if (str != 0 || mag != 0 || dex != 0) {
strcpy(tempstr, _("Required:"));
std::string text = _("Required:");
if (str != 0)
strcpy(tempstr + strlen(tempstr), fmt::format(_(" {:d} Str"), str).c_str());
text.append(fmt::format(_(" {:d} Str"), str));
if (mag != 0)
strcpy(tempstr + strlen(tempstr), fmt::format(_(" {:d} Mag"), mag).c_str());
text.append(fmt::format(_(" {:d} Mag"), mag));
if (dex != 0)
strcpy(tempstr + strlen(tempstr), fmt::format(_(" {:d} Dex"), dex).c_str());
AddPanelString(tempstr);
text.append(fmt::format(_(" {:d} Dex"), dex));
AddPanelString(text);
}
}
@ -3414,24 +3365,30 @@ void RecreateItem(Item &item, int idx, uint16_t icreateinfo, int iseed, int ival
void RecreateEar(Item &item, uint16_t ic, int iseed, int id, int dur, int mdur, int ch, int mch, int ivalue, int ibuff)
{
InitializeItem(item, IDI_EAR);
tempstr[0] = static_cast<char>((ic >> 8) & 0x7F);
tempstr[1] = static_cast<char>(ic & 0x7F);
tempstr[2] = static_cast<char>((iseed >> 24) & 0x7F);
tempstr[3] = static_cast<char>((iseed >> 16) & 0x7F);
tempstr[4] = static_cast<char>((iseed >> 8) & 0x7F);
tempstr[5] = static_cast<char>(iseed & 0x7F);
tempstr[6] = static_cast<char>(id & 0x7F);
tempstr[7] = static_cast<char>(dur & 0x7F);
tempstr[8] = static_cast<char>(mdur & 0x7F);
tempstr[9] = static_cast<char>(ch & 0x7F);
tempstr[10] = static_cast<char>(mch & 0x7F);
tempstr[11] = static_cast<char>((ivalue >> 8) & 0x7F);
tempstr[12] = static_cast<char>((ibuff >> 24) & 0x7F);
tempstr[13] = static_cast<char>((ibuff >> 16) & 0x7F);
tempstr[14] = static_cast<char>((ibuff >> 8) & 0x7F);
tempstr[15] = static_cast<char>(ibuff & 0x7F);
tempstr[16] = '\0';
strcpy(item._iName, fmt::format(_(/* TRANSLATORS: {:s} will be a Character Name */ "Ear of {:s}"), tempstr).c_str());
char heroName[17];
heroName[0] = static_cast<char>((ic >> 8) & 0x7F);
heroName[1] = static_cast<char>(ic & 0x7F);
heroName[2] = static_cast<char>((iseed >> 24) & 0x7F);
heroName[3] = static_cast<char>((iseed >> 16) & 0x7F);
heroName[4] = static_cast<char>((iseed >> 8) & 0x7F);
heroName[5] = static_cast<char>(iseed & 0x7F);
heroName[6] = static_cast<char>(id & 0x7F);
heroName[7] = static_cast<char>(dur & 0x7F);
heroName[8] = static_cast<char>(mdur & 0x7F);
heroName[9] = static_cast<char>(ch & 0x7F);
heroName[10] = static_cast<char>(mch & 0x7F);
heroName[11] = static_cast<char>((ivalue >> 8) & 0x7F);
heroName[12] = static_cast<char>((ibuff >> 24) & 0x7F);
heroName[13] = static_cast<char>((ibuff >> 16) & 0x7F);
heroName[14] = static_cast<char>((ibuff >> 8) & 0x7F);
heroName[15] = static_cast<char>(ibuff & 0x7F);
heroName[16] = '\0';
std::string itemName = fmt::format(_(/* TRANSLATORS: {:s} will be a Character Name */ "Ear of {:s}"), heroName);
CopyUtf8(item._iName, itemName, sizeof(item._iName));
item._iCurs = ((ivalue >> 6) & 3) + ICURS_EAR_SORCERER;
item._ivalue = ivalue & 0x3F;
item._iCreateInfo = ic;
@ -3985,31 +3942,24 @@ void PrintItemDetails(const Item &item)
if (item._iClass == ICLASS_WEAPON) {
if (item._iMinDam == item._iMaxDam) {
if (item._iMaxDur == DUR_INDESTRUCTIBLE)
strcpy(tempstr, fmt::format(_("damage: {:d} Indestructible"), item._iMinDam).c_str());
AddPanelString(fmt::format(_("damage: {:d} Indestructible"), item._iMinDam));
else
strcpy(tempstr, fmt::format(_(/* TRANSLATORS: Dur: is durability */ "damage: {:d} Dur: {:d}/{:d}"), item._iMinDam, item._iDurability, item._iMaxDur).c_str());
AddPanelString(fmt::format(_(/* TRANSLATORS: Dur: is durability */ "damage: {:d} Dur: {:d}/{:d}"), item._iMinDam, item._iDurability, item._iMaxDur));
} else {
if (item._iMaxDur == DUR_INDESTRUCTIBLE)
strcpy(tempstr, fmt::format(_("damage: {:d}-{:d} Indestructible"), item._iMinDam, item._iMaxDam).c_str());
AddPanelString(fmt::format(_("damage: {:d}-{:d} Indestructible"), item._iMinDam, item._iMaxDam));
else
strcpy(tempstr, fmt::format(_(/* TRANSLATORS: Dur: is durability */ "damage: {:d}-{:d} Dur: {:d}/{:d}"), item._iMinDam, item._iMaxDam, item._iDurability, item._iMaxDur).c_str());
AddPanelString(fmt::format(_(/* TRANSLATORS: Dur: is durability */ "damage: {:d}-{:d} Dur: {:d}/{:d}"), item._iMinDam, item._iMaxDam, item._iDurability, item._iMaxDur));
}
AddPanelString(tempstr);
}
if (item._iClass == ICLASS_ARMOR) {
if (item._iMaxDur == DUR_INDESTRUCTIBLE)
strcpy(tempstr, fmt::format(_("armor: {:d} Indestructible"), item._iAC).c_str());
AddPanelString(fmt::format(_("armor: {:d} Indestructible"), item._iAC));
else
strcpy(tempstr, fmt::format(_(/* TRANSLATORS: Dur: is durability */ "armor: {:d} Dur: {:d}/{:d}"), item._iAC, item._iDurability, item._iMaxDur).c_str());
AddPanelString(tempstr);
AddPanelString(fmt::format(_(/* TRANSLATORS: Dur: is durability */ "armor: {:d} Dur: {:d}/{:d}"), item._iAC, item._iDurability, item._iMaxDur));
}
if (item._iMiscId == IMISC_STAFF && item._iMaxCharges != 0) {
if (item._iMinDam == item._iMaxDam)
strcpy(tempstr, fmt::format(_(/* TRANSLATORS: dam: is damage Dur: is durability */ "dam: {:d} Dur: {:d}/{:d}"), item._iMinDam, item._iDurability, item._iMaxDur).c_str());
else
strcpy(tempstr, fmt::format(_(/* TRANSLATORS: dam: is damage Dur: is durability */ "dam: {:d}-{:d} Dur: {:d}/{:d}"), item._iMinDam, item._iMaxDam, item._iDurability, item._iMaxDur).c_str());
strcpy(tempstr, fmt::format(_("Charges: {:d}/{:d}"), item._iCharges, item._iMaxCharges).c_str());
AddPanelString(tempstr);
AddPanelString(fmt::format(_("Charges: {:d}/{:d}"), item._iCharges, item._iMaxCharges));
}
if (item._iPrePower != -1) {
AddPanelString(PrintItemPower(item._iPrePower, item));
@ -4030,34 +3980,30 @@ void PrintItemDur(const Item &item)
if (item._iClass == ICLASS_WEAPON) {
if (item._iMinDam == item._iMaxDam) {
if (item._iMaxDur == DUR_INDESTRUCTIBLE)
strcpy(tempstr, fmt::format(_("damage: {:d} Indestructible"), item._iMinDam).c_str());
AddPanelString(fmt::format(_("damage: {:d} Indestructible"), item._iMinDam));
else
strcpy(tempstr, fmt::format(_("damage: {:d} Dur: {:d}/{:d}"), item._iMinDam, item._iDurability, item._iMaxDur).c_str());
AddPanelString(fmt::format(_("damage: {:d} Dur: {:d}/{:d}"), item._iMinDam, item._iDurability, item._iMaxDur));
} else {
if (item._iMaxDur == DUR_INDESTRUCTIBLE)
strcpy(tempstr, fmt::format(_("damage: {:d}-{:d} Indestructible"), item._iMinDam, item._iMaxDam).c_str());
AddPanelString(fmt::format(_("damage: {:d}-{:d} Indestructible"), item._iMinDam, item._iMaxDam));
else
strcpy(tempstr, fmt::format(_("damage: {:d}-{:d} Dur: {:d}/{:d}"), item._iMinDam, item._iMaxDam, item._iDurability, item._iMaxDur).c_str());
AddPanelString(fmt::format(_("damage: {:d}-{:d} Dur: {:d}/{:d}"), item._iMinDam, item._iMaxDam, item._iDurability, item._iMaxDur));
}
AddPanelString(tempstr);
if (item._iMiscId == IMISC_STAFF && item._iMaxCharges > 0) {
strcpy(tempstr, fmt::format(_("Charges: {:d}/{:d}"), item._iCharges, item._iMaxCharges).c_str());
AddPanelString(tempstr);
AddPanelString(fmt::format(_("Charges: {:d}/{:d}"), item._iCharges, item._iMaxCharges));
}
if (item._iMagical != ITEM_QUALITY_NORMAL)
AddPanelString(_("Not Identified"));
}
if (item._iClass == ICLASS_ARMOR) {
if (item._iMaxDur == DUR_INDESTRUCTIBLE)
strcpy(tempstr, fmt::format(_("armor: {:d} Indestructible"), item._iAC).c_str());
AddPanelString(fmt::format(_("armor: {:d} Indestructible"), item._iAC));
else
strcpy(tempstr, fmt::format(_("armor: {:d} Dur: {:d}/{:d}"), item._iAC, item._iDurability, item._iMaxDur).c_str());
AddPanelString(tempstr);
AddPanelString(fmt::format(_("armor: {:d} Dur: {:d}/{:d}"), item._iAC, item._iDurability, item._iMaxDur));
if (item._iMagical != ITEM_QUALITY_NORMAL)
AddPanelString(_("Not Identified"));
if (item._iMiscId == IMISC_STAFF && item._iMaxCharges > 0) {
strcpy(tempstr, fmt::format(_("Charges: {:d}/{:d}"), item._iCharges, item._iMaxCharges).c_str());
AddPanelString(tempstr);
AddPanelString(fmt::format(_("Charges: {:d}/{:d}"), item._iCharges, item._iMaxCharges));
}
}
if (IsAnyOf(item._itype, ItemType::Ring, ItemType::Amulet))

5
Source/minitext.cpp

@ -42,10 +42,7 @@ void LoadText(const char *text)
{
TextLines.clear();
char tempstr[2560];
strcpy(tempstr, text);
const std::string paragraphs = WordWrapString(tempstr, 543, GameFont30);
const std::string paragraphs = WordWrapString(text, 543, GameFont30);
size_t previous = 0;
while (true) {

53
Source/monster.cpp

@ -4644,12 +4644,11 @@ void M_FallenFear(Point position)
void PrintMonstHistory(int mt)
{
if (*sgOptions.Gameplay.showMonsterType) {
strcpy(tempstr, fmt::format(_("Type: {:s} Kills: {:d}"), GetMonsterTypeText(MonstersData[mt]), MonsterKillCounts[mt]).c_str());
AddPanelString(fmt::format(_("Type: {:s} Kills: {:d}"), GetMonsterTypeText(MonstersData[mt]), MonsterKillCounts[mt]));
} else {
strcpy(tempstr, fmt::format(_("Total kills: {:d}"), MonsterKillCounts[mt]).c_str());
AddPanelString(fmt::format(_("Total kills: {:d}"), MonsterKillCounts[mt]));
}
AddPanelString(tempstr);
if (MonsterKillCounts[mt] >= 30) {
int minHP = MonstersData[mt].mMinHP;
int maxHP = MonstersData[mt].mMaxHP;
@ -4679,38 +4678,32 @@ void PrintMonstHistory(int mt)
minHP = 4 * minHP + hpBonusHell;
maxHP = 4 * maxHP + hpBonusHell;
}
strcpy(tempstr, fmt::format(_("Hit Points: {:d}-{:d}"), minHP, maxHP).c_str());
AddPanelString(tempstr);
AddPanelString(fmt::format(_("Hit Points: {:d}-{:d}"), minHP, maxHP));
}
if (MonsterKillCounts[mt] >= 15) {
int res = (sgGameInitInfo.nDifficulty != DIFF_HELL) ? MonstersData[mt].mMagicRes : MonstersData[mt].mMagicRes2;
if ((res & (RESIST_MAGIC | RESIST_FIRE | RESIST_LIGHTNING | IMMUNE_MAGIC | IMMUNE_FIRE | IMMUNE_LIGHTNING)) == 0) {
strcpy(tempstr, _("No magic resistance"));
AddPanelString(tempstr);
AddPanelString(_("No magic resistance"));
} else {
if ((res & (RESIST_MAGIC | RESIST_FIRE | RESIST_LIGHTNING)) != 0) {
strcpy(tempstr, _("Resists: "));
std::string resists = _("Resists:");
if ((res & RESIST_MAGIC) != 0)
strcat(tempstr, _("Magic "));
resists.append(_(" Magic"));
if ((res & RESIST_FIRE) != 0)
strcat(tempstr, _("Fire "));
resists.append(_(" Fire"));
if ((res & RESIST_LIGHTNING) != 0)
strcat(tempstr, _("Lightning "));
string_view str { tempstr };
str.remove_suffix(str.size() - FindLastUtf8Symbols(str));
AddPanelString(str);
resists.append(_(" Lightning"));
AddPanelString(resists);
}
if ((res & (IMMUNE_MAGIC | IMMUNE_FIRE | IMMUNE_LIGHTNING)) != 0) {
strcpy(tempstr, _("Immune: "));
std::string immune = _("Immune:");
if ((res & IMMUNE_MAGIC) != 0)
strcat(tempstr, _("Magic "));
immune.append(_(" Magic"));
if ((res & IMMUNE_FIRE) != 0)
strcat(tempstr, _("Fire "));
immune.append(_(" Fire"));
if ((res & IMMUNE_LIGHTNING) != 0)
strcat(tempstr, _("Lightning "));
string_view str { tempstr };
str.remove_suffix(str.size() - FindLastUtf8Symbols(str));
AddPanelString(str);
immune.append(_(" Lightning"));
AddPanelString(immune);
}
}
}
@ -4720,28 +4713,24 @@ void PrintUniqueHistory()
{
auto &monster = Monsters[pcursmonst];
if (*sgOptions.Gameplay.showMonsterType) {
strcpy(tempstr, fmt::format(_("Type: {:s}"), GetMonsterTypeText(*monster.MData)).c_str());
AddPanelString(tempstr);
AddPanelString(fmt::format(_("Type: {:s}"), GetMonsterTypeText(*monster.MData)));
}
int res = monster.mMagicRes & (RESIST_MAGIC | RESIST_FIRE | RESIST_LIGHTNING | IMMUNE_MAGIC | IMMUNE_FIRE | IMMUNE_LIGHTNING);
if (res == 0) {
strcpy(tempstr, _("No resistances"));
AddPanelString(tempstr);
strcpy(tempstr, _("No Immunities"));
AddPanelString(_("No resistances"));
AddPanelString(_("No Immunities"));
} else {
if ((res & (RESIST_MAGIC | RESIST_FIRE | RESIST_LIGHTNING)) != 0)
strcpy(tempstr, _("Some Magic Resistances"));
AddPanelString(_("Some Magic Resistances"));
else
strcpy(tempstr, _("No resistances"));
AddPanelString(tempstr);
AddPanelString(_("No resistances"));
if ((res & (IMMUNE_MAGIC | IMMUNE_FIRE | IMMUNE_LIGHTNING)) != 0) {
strcpy(tempstr, _("Some Magic Immunities"));
AddPanelString(_("Some Magic Immunities"));
} else {
strcpy(tempstr, _("No Immunities"));
AddPanelString(_("No Immunities"));
}
}
AddPanelString(tempstr);
}
void PlayEffect(Monster &monster, int mode)

10
Source/objects.cpp

@ -9,7 +9,6 @@
#include "DiabloUI/ui_flags.hpp"
#include "automap.h"
#include "control.h"
#include "cursor.h"
#ifdef _DEBUG
#include "debug.h"
@ -5457,8 +5456,7 @@ void GetObjectStr(const Object &object)
break;
case OBJ_SHRINEL:
case OBJ_SHRINER:
strcpy(tempstr, fmt::format(_(/* TRANSLATORS: {:s} will be a name from the Shrine block above */ "{:s} Shrine"), _(ShrineNames[object._oVar1])).c_str());
strcpy(infostr, tempstr);
strcpy(infostr, fmt::format(_(/* TRANSLATORS: {:s} will be a name from the Shrine block above */ "{:s} Shrine"), _(ShrineNames[object._oVar1])).c_str());
break;
case OBJ_SKELBOOK:
strcpy(infostr, _("Skeleton Tome"));
@ -5526,14 +5524,12 @@ void GetObjectStr(const Object &object)
}
if (Players[MyPlayerId]._pClass == HeroClass::Rogue) {
if (object._oTrapFlag) {
strcpy(tempstr, fmt::format(_(/* TRANSLATORS: {:s} will either be a chest or a door */ "Trapped {:s}"), infostr).c_str());
strcpy(infostr, tempstr);
strcpy(infostr, fmt::format(_(/* TRANSLATORS: {:s} will either be a chest or a door */ "Trapped {:s}"), infostr).c_str());
InfoColor = UiFlags::ColorRed;
}
}
if (object.IsDisabled()) {
strcpy(tempstr, fmt::format(_(/* TRANSLATORS: If user enabled diablo.ini setting "Disable Crippling Shrines" is set to 1; also used for Na-Kruls leaver */ "{:s} (disabled)"), infostr).c_str());
strcpy(infostr, tempstr);
strcpy(infostr, fmt::format(_(/* TRANSLATORS: If user enabled diablo.ini setting "Disable Crippling Shrines" is set to 1; also used for Na-Kruls leaver */ "{:s} (disabled)"), infostr).c_str());
InfoColor = UiFlags::ColorRed;
}
}

17
Source/panels/spell_list.cpp

@ -168,14 +168,12 @@ void DrawSpellList(const Surface &out)
PrintSBookSpellType(out, spellListItem.location, _("Spell"), spellColor);
strcpy(infostr, fmt::format(_("{:s} Spell"), pgettext("spell", spellDataItem.sNameText)).c_str());
if (spellId == SPL_HBOLT) {
strcpy(tempstr, _("Damages undead only"));
AddPanelString(tempstr);
AddPanelString(_("Damages undead only"));
}
if (spellLevel == 0)
strcpy(tempstr, _("Spell Level 0 - Unusable"));
AddPanelString(_("Spell Level 0 - Unusable"));
else
strcpy(tempstr, fmt::format(_("Spell Level {:d}"), spellLevel).c_str());
AddPanelString(tempstr);
AddPanelString(fmt::format(_("Spell Level {:d}"), spellLevel));
break;
case RSPLTYPE_SCROLL: {
if (myPlayer.plrlevel != 0) {
@ -187,8 +185,7 @@ void DrawSpellList(const Surface &out)
const int scrollCount = std::count_if(items.begin(), items.end(), [spellId](const Item &item) {
return item.IsScrollOf(spellId);
});
strcpy(tempstr, fmt::format(ngettext("{:d} Scroll", "{:d} Scrolls", scrollCount), scrollCount).c_str());
AddPanelString(tempstr);
AddPanelString(fmt::format(ngettext("{:d} Scroll", "{:d} Scrolls", scrollCount), scrollCount));
} break;
case RSPLTYPE_CHARGES: {
if (myPlayer.plrlevel != 0) {
@ -197,15 +194,13 @@ void DrawSpellList(const Surface &out)
PrintSBookSpellType(out, spellListItem.location, _("Staff"), spellColor);
strcpy(infostr, fmt::format(_("Staff of {:s}"), pgettext("spell", spellDataItem.sNameText)).c_str());
int charges = myPlayer.InvBody[INVLOC_HAND_LEFT]._iCharges;
strcpy(tempstr, fmt::format(ngettext("{:d} Charge", "{:d} Charges", charges), charges).c_str());
AddPanelString(tempstr);
AddPanelString(fmt::format(ngettext("{:d} Charge", "{:d} Charges", charges), charges));
} break;
case RSPLTYPE_INVALID:
break;
}
if (hotkeyName) {
strcpy(tempstr, fmt::format(_("Spell Hotkey {:s}"), *hotkeyName).c_str());
AddPanelString(tempstr);
AddPanelString(fmt::format(_("Spell Hotkey {:s}"), *hotkeyName));
}
}
}

40
Source/qol/common.cpp

@ -1,40 +0,0 @@
/**
* @file common.h
*
* Common functions for QoL features
*/
#include <SDL.h>
#include "common.h"
#include "engine.h"
#include "engine/render/text_render.hpp"
#include "qol/monhealthbar.h"
#include "qol/xpbar.h"
#include "utils/language.h"
namespace devilution {
char *PrintWithSeparator(char *out, int n)
{
if (n < 1000) {
return out + sprintf(out, "%d", n);
}
char *append = PrintWithSeparator(out, n / 1000);
return append + sprintf(append, _(/* TRANSLATORS: Decimal separator */ ",%03d"), n % 1000);
}
void FreeQol()
{
FreeMonsterHealthBar();
FreeXPBar();
}
void InitQol()
{
InitMonsterHealthBar();
InitXPBar();
}
} // namespace devilution

25
Source/qol/common.h

@ -1,25 +0,0 @@
/**
* @file common.h
*
* Common functions for QoL features
*/
#pragma once
#include <SDL.h>
namespace devilution {
struct Surface;
/**
* @brief Prints integer into buffer, using ',' as thousands separator.
* @param out Destination buffer
* @param n Number to print
* @return Address of first character after printed number
*/
char *PrintWithSeparator(char *out, int n);
void FreeQol();
void InitQol();
} // namespace devilution

9
Source/qol/itemlabels.cpp

@ -4,7 +4,8 @@
#include <unordered_set>
#include <vector>
#include "common.h"
#include <fmt/format.h>
#include "control.h"
#include "cursor.h"
#include "engine/point.hpp"
@ -13,6 +14,7 @@
#include "inv.h"
#include "itemlabels.h"
#include "utils/language.h"
#include "utils/stdcompat/string_view.hpp"
namespace devilution {
@ -65,10 +67,9 @@ void AddItemToLabelQueue(int id, int x, int y)
return;
Item &item = Items[id];
const char *textOnGround;
std::string textOnGround;
if (item._itype == ItemType::Gold) {
std::sprintf(tempstr, _("%i gold"), item._ivalue);
textOnGround = tempstr;
textOnGround = fmt::format(_("{:d} gold"), item._ivalue);
} else {
textOnGround = item._iIdentified ? item._iIName : item._iName;
}

1
Source/qol/monhealthbar.cpp

@ -8,7 +8,6 @@
#include "control.h"
#include "cursor.h"
#include "options.h"
#include "qol/common.h"
#include "utils/language.h"
namespace devilution {

13
Source/qol/stash.cpp

@ -564,26 +564,21 @@ void DrawGoldWithdraw(const Surface &out, int amount)
CelDrawTo(out, GetPanelPosition(UiPanels::Stash, { dialogX, 178 }), *pGBoxBuff, 1);
constexpr auto BufferSize = sizeof(tempstr) / sizeof(*tempstr);
CopyUtf8(tempstr, _("How many gold pieces do you want to withdraw? (MAX 5000)"), BufferSize);
// Pre-wrap the string at spaces, otherwise DrawString would hard wrap in the middle of words
const std::string wrapped = WordWrapString(tempstr, 200);
const std::string wrapped = WordWrapString(_("How many gold pieces do you want to withdraw? (MAX 5000)"), 200);
// The split gold dialog is roughly 4 lines high, but we need at least one line for the player to input an amount.
// Using a clipping region 50 units high (approx 3 lines with a lineheight of 17) to ensure there is enough room left
// for the text entered by the player.
DrawString(out, wrapped, { GetPanelPosition(UiPanels::Stash, { dialogX + 31, 75 }), { 200, 50 } }, UiFlags::ColorWhitegold | UiFlags::AlignCenter, 1, 17);
tempstr[0] = '\0';
std::string value = "";
if (amount > 0) {
// snprintf ensures that the destination buffer ends in a null character.
snprintf(tempstr, BufferSize, "%u", amount);
value = fmt::format("{:d}", amount);
}
// Even a ten digit amount of gold only takes up about half a line. There's no need to wrap or clip text here so we
// use the Point form of DrawString.
DrawString(out, tempstr, GetPanelPosition(UiPanels::Stash, { dialogX + 37, 128 }), UiFlags::ColorWhite | UiFlags::PentaCursor);
DrawString(out, value, GetPanelPosition(UiPanels::Stash, { dialogX + 37, 128 }), UiFlags::ColorWhite | UiFlags::PentaCursor);
}
void CloseGoldWithdraw()

43
Source/qol/xpbar.cpp

@ -10,7 +10,6 @@
#include <fmt/format.h>
#include "DiabloUI/art_draw.h"
#include "common.h"
#include "control.h"
#include "engine/point.hpp"
#include "options.h"
@ -45,6 +44,27 @@ void DrawEndCap(const Surface &out, Point point, int idx, const ColorGradient &g
out.SetPixel({ point.x, point.y + 3 }, gradient[idx / 2]);
}
/**
* @brief Prints integer with thousands separator.
*/
std::string PrintWithSeparator(int n)
{
std::string number = fmt::format("{:d}", n);
std::string out = "";
int length = number.length();
int mlength = length % 3;
if (mlength == 0)
mlength = 3;
out.append(number.substr(0, mlength));
for (int i = mlength; i < length; i += 3) {
out.append(_(/* TRANSLATORS: Thousands separator */ ","));
out.append(number.substr(i, 3));
}
return out;
}
} // namespace
void InitXPBar()
@ -122,17 +142,13 @@ bool CheckXPBarInfo()
const int8_t charLevel = player._pLevel;
strcpy(tempstr, fmt::format(_("Level {:d}"), charLevel).c_str());
AddPanelString(tempstr);
AddPanelString(fmt::format(_("Level {:d}"), charLevel));
if (charLevel == MAXCHARLEVEL) {
// Show a maximum level indicator for max level players.
InfoColor = UiFlags::ColorWhitegold;
strcpy(tempstr, _("Experience: "));
PrintWithSeparator(tempstr + strlen(tempstr), ExpLvlsTbl[charLevel - 1]);
AddPanelString(tempstr);
AddPanelString(fmt::format("Experience: {:s}", PrintWithSeparator(ExpLvlsTbl[charLevel - 1])));
AddPanelString(_("Maximum Level"));
return true;
@ -140,16 +156,9 @@ bool CheckXPBarInfo()
InfoColor = UiFlags::ColorWhite;
strcpy(tempstr, _("Experience: "));
PrintWithSeparator(tempstr + strlen(tempstr), player._pExperience);
AddPanelString(tempstr);
strcpy(tempstr, _("Next Level: "));
PrintWithSeparator(tempstr + strlen(tempstr), ExpLvlsTbl[charLevel]);
AddPanelString(tempstr);
strcpy(PrintWithSeparator(tempstr, ExpLvlsTbl[charLevel] - player._pExperience), fmt::format(_(" to Level {:d}"), charLevel + 1).c_str());
AddPanelString(tempstr);
AddPanelString(fmt::format("Experience: {:s}", PrintWithSeparator(player._pExperience)));
AddPanelString(fmt::format("Next Level: {:s}", PrintWithSeparator(ExpLvlsTbl[charLevel])));
AddPanelString(fmt::format(_("{:s} to Level {:d}"), PrintWithSeparator(ExpLvlsTbl[charLevel] - player._pExperience), charLevel + 1));
return true;
}

148
Source/stores.cpp

@ -22,6 +22,8 @@
#include "qol/stash.h"
#include "towners.h"
#include "utils/language.h"
#include "utils/stdcompat/string_view.hpp"
#include "utils/utf8.hpp"
namespace devilution {
@ -201,11 +203,11 @@ void AddSTextVal(int y, int val)
stext[y]._sval = val;
}
void AddSText(int x, int y, const char *str, UiFlags flags, bool sel)
void AddSText(int x, int y, string_view text, UiFlags flags, bool sel)
{
stext[y]._sx = x;
stext[y]._syoff = 0;
strcpy(stext[y]._sstr, str);
CopyUtf8(stext[y]._sstr, text, sizeof(stext[y]._sstr));
stext[y].flags = flags;
stext[y]._sline = 0;
stext[y]._ssel = sel;
@ -233,60 +235,58 @@ void AddItemListBackButton(bool selectable = false)
void PrintStoreItem(const Item &item, int l, UiFlags flags)
{
char sstr[128];
std::string productLine = "";
sstr[0] = '\0';
if (item._iIdentified) {
if (item._iMagical != ITEM_QUALITY_UNIQUE) {
if (item._iPrePower != -1) {
strcat(sstr, PrintItemPower(item._iPrePower, item).c_str());
productLine.append(PrintItemPower(item._iPrePower, item));
}
}
if (item._iSufPower != -1) {
if (sstr[0] != '\0')
strcat(sstr, _(", "));
strcat(sstr, PrintItemPower(item._iSufPower, item).c_str());
if (!productLine.empty())
productLine.append(_(", "));
productLine.append(PrintItemPower(item._iSufPower, item));
}
}
if (item._iMiscId == IMISC_STAFF && item._iMaxCharges != 0) {
strcpy(tempstr, fmt::format(_("Charges: {:d}/{:d}"), item._iCharges, item._iMaxCharges).c_str());
if (sstr[0] != '\0')
strcat(sstr, _(", "));
strcat(sstr, tempstr);
if (!productLine.empty())
productLine.append(_(", "));
productLine.append(fmt::format(_("Charges: {:d}/{:d}"), item._iCharges, item._iMaxCharges));
}
if (sstr[0] != '\0') {
AddSText(40, l, sstr, flags, false);
if (!productLine.empty()) {
AddSText(40, l, productLine, flags, false);
l++;
productLine = "";
}
sstr[0] = '\0';
if (item._iClass == ICLASS_WEAPON)
strcpy(sstr, fmt::format(_("Damage: {:d}-{:d} "), item._iMinDam, item._iMaxDam).c_str());
if (item._iClass == ICLASS_ARMOR)
strcpy(sstr, fmt::format(_("Armor: {:d} "), item._iAC).c_str());
if (item._iMaxDur != DUR_INDESTRUCTIBLE && item._iMaxDur != 0) {
strcpy(tempstr, fmt::format(_("Dur: {:d}/{:d}, "), item._iDurability, item._iMaxDur).c_str());
strcat(sstr, tempstr);
} else {
strcat(sstr, _("Indestructible, "));
if (item._itype != ItemType::Misc) {
if (item._iClass == ICLASS_WEAPON)
productLine = fmt::format(_("Damage: {:d}-{:d} "), item._iMinDam, item._iMaxDam);
else if (item._iClass == ICLASS_ARMOR)
productLine = fmt::format(_("Armor: {:d} "), item._iAC);
else if (item._iMaxDur != DUR_INDESTRUCTIBLE && item._iMaxDur != 0)
productLine = fmt::format(_("Dur: {:d}/{:d}, "), item._iDurability, item._iMaxDur);
else
productLine = _("Indestructible, ");
}
if (item._itype == ItemType::Misc)
sstr[0] = '\0';
int8_t str = item._iMinStr;
uint8_t mag = item._iMinMag;
int8_t dex = item._iMinDex;
if (str == 0 && mag == 0 && dex == 0) {
strcat(sstr, _("No required attributes"));
productLine.append(_("No required attributes"));
} else {
strcpy(tempstr, _("Required:"));
productLine.append(_("Required:"));
if (str != 0)
strcpy(tempstr + strlen(tempstr), fmt::format(_(" {:d} Str"), str).c_str());
productLine.append(fmt::format(_(" {:d} Str"), str));
if (mag != 0)
strcpy(tempstr + strlen(tempstr), fmt::format(_(" {:d} Mag"), mag).c_str());
productLine.append(fmt::format(_(" {:d} Mag"), mag));
if (dex != 0)
strcpy(tempstr + strlen(tempstr), fmt::format(_(" {:d} Dex"), dex).c_str());
strcat(sstr, tempstr);
productLine.append(fmt::format(_(" {:d} Dex"), dex));
}
AddSText(40, l++, sstr, flags, false);
AddSText(40, l++, productLine, flags, false);
}
void StoreAutoPlace()
@ -354,9 +354,7 @@ void StartSmithBuy()
stextsval = 0;
/* TRANSLATORS: This text is white space sensitive. Check for correct alignment! */
strcpy(tempstr, fmt::format(_("I have these items for sale: Your gold: {:d}"), Players[MyPlayerId]._pGold).c_str());
AddSText(0, 1, tempstr, UiFlags::ColorWhitegold | UiFlags::AlignCenter, false);
AddSText(0, 1, fmt::format(_("I have these items for sale: Your gold: {:d}"), Players[MyPlayerId]._pGold).c_str(), UiFlags::ColorWhitegold | UiFlags::AlignCenter, false);
AddSLine(3);
ScrollSmithBuy(stextsval);
AddItemListBackButton();
@ -421,9 +419,7 @@ bool StartSmithPremiumBuy()
stextsval = 0;
/* TRANSLATORS: This text is white space sensitive. Check for correct alignment! */
strcpy(tempstr, fmt::format(_("I have these premium items for sale: Your gold: {:d}"), Players[MyPlayerId]._pGold).c_str());
AddSText(0, 1, tempstr, UiFlags::ColorWhitegold | UiFlags::AlignCenter, false);
AddSText(0, 1, fmt::format(_("I have these premium items for sale: Your gold: {:d}"), Players[MyPlayerId]._pGold).c_str(), UiFlags::ColorWhitegold | UiFlags::AlignCenter, false);
AddSLine(3);
AddItemListBackButton();
@ -542,9 +538,7 @@ void StartSmithSell()
stextscrl = false;
/* TRANSLATORS: This text is white space sensitive. Check for correct alignment! */
strcpy(tempstr, fmt::format(_("You have nothing I want. Your gold: {:d}"), myPlayer._pGold).c_str());
AddSText(0, 1, tempstr, UiFlags::ColorWhitegold | UiFlags::AlignCenter, false);
AddSText(0, 1, fmt::format(_("You have nothing I want. Your gold: {:d}"), myPlayer._pGold).c_str(), UiFlags::ColorWhitegold | UiFlags::AlignCenter, false);
AddSLine(3);
AddItemListBackButton(/*selectable=*/true);
return;
@ -555,9 +549,7 @@ void StartSmithSell()
stextsmax = myPlayer._pNumInv;
/* TRANSLATORS: This text is white space sensitive. Check for correct alignment! */
strcpy(tempstr, fmt::format(_("Which item is for sale? Your gold: {:d}"), myPlayer._pGold).c_str());
AddSText(0, 1, tempstr, UiFlags::ColorWhitegold | UiFlags::AlignCenter, false);
AddSText(0, 1, fmt::format(_("Which item is for sale? Your gold: {:d}"), myPlayer._pGold).c_str(), UiFlags::ColorWhitegold | UiFlags::AlignCenter, false);
AddSLine(3);
ScrollSmithSell(stextsval);
AddItemListBackButton();
@ -628,9 +620,7 @@ void StartSmithRepair()
stextscrl = false;
/* TRANSLATORS: This text is white space sensitive. Check for correct alignment! */
strcpy(tempstr, fmt::format(_("You have nothing to repair. Your gold: {:d}"), myPlayer._pGold).c_str());
AddSText(0, 1, tempstr, UiFlags::ColorWhitegold | UiFlags::AlignCenter, false);
AddSText(0, 1, fmt::format(_("You have nothing to repair. Your gold: {:d}"), myPlayer._pGold).c_str(), UiFlags::ColorWhitegold | UiFlags::AlignCenter, false);
AddSLine(3);
AddItemListBackButton(/*selectable=*/true);
return;
@ -641,9 +631,7 @@ void StartSmithRepair()
stextsmax = myPlayer._pNumInv;
/* TRANSLATORS: This text is white space sensitive. Check for correct alignment! */
strcpy(tempstr, fmt::format(_("Repair which item? Your gold: {:d}"), myPlayer._pGold).c_str());
AddSText(0, 1, tempstr, UiFlags::ColorWhitegold | UiFlags::AlignCenter, false);
AddSText(0, 1, fmt::format(_("Repair which item? Your gold: {:d}"), myPlayer._pGold).c_str(), UiFlags::ColorWhitegold | UiFlags::AlignCenter, false);
AddSLine(3);
ScrollSmithSell(stextsval);
@ -731,9 +719,7 @@ void StartWitchBuy()
stextsmax = 20;
/* TRANSLATORS: This text is white space sensitive. Check for correct alignment! */
strcpy(tempstr, fmt::format(_("I have these items for sale: Your gold: {:d}"), Players[MyPlayerId]._pGold).c_str());
AddSText(0, 1, tempstr, UiFlags::ColorWhitegold | UiFlags::AlignCenter, false);
AddSText(0, 1, fmt::format(_("I have these items for sale: Your gold: {:d}"), Players[MyPlayerId]._pGold).c_str(), UiFlags::ColorWhitegold | UiFlags::AlignCenter, false);
AddSLine(3);
ScrollWitchBuy(stextsval);
AddItemListBackButton();
@ -826,9 +812,7 @@ void StartWitchSell()
stextscrl = false;
/* TRANSLATORS: This text is white space sensitive. Check for correct alignment! */
strcpy(tempstr, fmt::format(_("You have nothing I want. Your gold: {:d}"), myPlayer._pGold).c_str());
AddSText(0, 1, tempstr, UiFlags::ColorWhitegold | UiFlags::AlignCenter, false);
AddSText(0, 1, fmt::format(_("You have nothing I want. Your gold: {:d}"), myPlayer._pGold).c_str(), UiFlags::ColorWhitegold | UiFlags::AlignCenter, false);
AddSLine(3);
AddItemListBackButton(/*selectable=*/true);
return;
@ -839,9 +823,7 @@ void StartWitchSell()
stextsmax = myPlayer._pNumInv;
/* TRANSLATORS: This text is white space sensitive. Check for correct alignment! */
strcpy(tempstr, fmt::format(_("Which item is for sale? Your gold: {:d}"), myPlayer._pGold).c_str());
AddSText(0, 1, tempstr, UiFlags::ColorWhitegold | UiFlags::AlignCenter, false);
AddSText(0, 1, fmt::format(_("Which item is for sale? Your gold: {:d}"), myPlayer._pGold).c_str(), UiFlags::ColorWhitegold | UiFlags::AlignCenter, false);
AddSLine(3);
ScrollSmithSell(stextsval);
AddItemListBackButton();
@ -903,9 +885,7 @@ void StartWitchRecharge()
stextscrl = false;
/* TRANSLATORS: This text is white space sensitive. Check for correct alignment! */
strcpy(tempstr, fmt::format(_("You have nothing to recharge. Your gold: {:d}"), myPlayer._pGold).c_str());
AddSText(0, 1, tempstr, UiFlags::ColorWhitegold | UiFlags::AlignCenter, false);
AddSText(0, 1, fmt::format(_("You have nothing to recharge. Your gold: {:d}"), myPlayer._pGold).c_str(), UiFlags::ColorWhitegold | UiFlags::AlignCenter, false);
AddSLine(3);
AddItemListBackButton(/*selectable=*/true);
return;
@ -916,9 +896,7 @@ void StartWitchRecharge()
stextsmax = myPlayer._pNumInv;
/* TRANSLATORS: This text is white space sensitive. Check for correct alignment! */
strcpy(tempstr, fmt::format(_("Recharge which item? Your gold: {:d}"), myPlayer._pGold).c_str());
AddSText(0, 1, tempstr, UiFlags::ColorWhitegold | UiFlags::AlignCenter, false);
AddSText(0, 1, fmt::format(_("Recharge which item? Your gold: {:d}"), myPlayer._pGold).c_str(), UiFlags::ColorWhitegold | UiFlags::AlignCenter, false);
AddSLine(3);
ScrollSmithSell(stextsval);
AddItemListBackButton();
@ -973,33 +951,35 @@ void StoreConfirm()
AddSTextVal(8, item._iIvalue);
PrintStoreItem(item, 9, itemColor);
string_view prompt;
switch (stextshold) {
case STORE_BBOY:
strcpy(tempstr, _("Do we have a deal?"));
prompt = _("Do we have a deal?");
break;
case STORE_SIDENTIFY:
strcpy(tempstr, _("Are you sure you want to identify this item?"));
prompt = _("Are you sure you want to identify this item?");
break;
case STORE_HBUY:
case STORE_SPBUY:
case STORE_WBUY:
case STORE_SBUY:
strcpy(tempstr, _("Are you sure you want to buy this item?"));
prompt = _("Are you sure you want to buy this item?");
break;
case STORE_WRECHARGE:
strcpy(tempstr, _("Are you sure you want to recharge this item?"));
prompt = _("Are you sure you want to recharge this item?");
break;
case STORE_SSELL:
case STORE_WSELL:
strcpy(tempstr, _("Are you sure you want to sell this item?"));
prompt = _("Are you sure you want to sell this item?");
break;
case STORE_SREPAIR:
strcpy(tempstr, _("Are you sure you want to repair this item?"));
prompt = _("Are you sure you want to repair this item?");
break;
default:
app_fatal("Unknown store dialog %i", stextshold);
}
AddSText(0, 15, tempstr, UiFlags::ColorWhite | UiFlags::AlignCenter, false);
AddSText(0, 15, prompt, UiFlags::ColorWhite | UiFlags::AlignCenter, false);
AddSText(0, 18, _("Yes"), UiFlags::ColorWhite | UiFlags::AlignCenter, true);
AddSText(0, 20, _("No"), UiFlags::ColorWhite | UiFlags::AlignCenter, true);
}
@ -1029,9 +1009,7 @@ void SStartBoyBuy()
stextscrl = false;
/* TRANSLATORS: This text is white space sensitive. Check for correct alignment! */
strcpy(tempstr, fmt::format(_("I have this item for sale: Your gold: {:d}"), MyPlayer->_pGold).c_str());
AddSText(0, 1, tempstr, UiFlags::ColorWhitegold | UiFlags::AlignCenter, false);
AddSText(0, 1, fmt::format(_("I have this item for sale: Your gold: {:d}"), MyPlayer->_pGold), UiFlags::ColorWhitegold | UiFlags::AlignCenter, false);
AddSLine(3);
UiFlags itemColor = boyitem.getTextColorWithStatCheck();
@ -1112,9 +1090,7 @@ void StartHealerBuy()
stextsval = 0;
/* TRANSLATORS: This text is white space sensitive. Check for correct alignment! */
strcpy(tempstr, fmt::format(_("I have these items for sale: Your gold: {:d}"), Players[MyPlayerId]._pGold).c_str());
AddSText(0, 1, tempstr, UiFlags::ColorWhitegold | UiFlags::AlignCenter, false);
AddSText(0, 1, fmt::format(_("I have these items for sale: Your gold: {:d}"), Players[MyPlayerId]._pGold), UiFlags::ColorWhitegold | UiFlags::AlignCenter, false);
AddSLine(3);
ScrollHealerBuy(stextsval);
@ -1232,9 +1208,7 @@ void StartStorytellerIdentify()
stextscrl = false;
/* TRANSLATORS: This text is white space sensitive. Check for correct alignment! */
strcpy(tempstr, fmt::format(_("You have nothing to identify. Your gold: {:d}"), myPlayer._pGold).c_str());
AddSText(0, 1, tempstr, UiFlags::ColorWhitegold | UiFlags::AlignCenter, false);
AddSText(0, 1, fmt::format(_("You have nothing to identify. Your gold: {:d}"), myPlayer._pGold), UiFlags::ColorWhitegold | UiFlags::AlignCenter, false);
AddSLine(3);
AddItemListBackButton(/*selectable=*/true);
return;
@ -1245,9 +1219,7 @@ void StartStorytellerIdentify()
stextsmax = myPlayer._pNumInv;
/* TRANSLATORS: This text is white space sensitive. Check for correct alignment! */
strcpy(tempstr, fmt::format(_("Identify which item? Your gold: {:d}"), myPlayer._pGold).c_str());
AddSText(0, 1, tempstr, UiFlags::ColorWhitegold | UiFlags::AlignCenter, false);
AddSText(0, 1, fmt::format(_("Identify which item? Your gold: {:d}"), myPlayer._pGold), UiFlags::ColorWhitegold | UiFlags::AlignCenter, false);
AddSLine(3);
ScrollSmithSell(stextsval);
@ -1276,12 +1248,10 @@ void StartTalk()
stextsize = false;
stextscrl = false;
strcpy(tempstr, fmt::format(_("Talk to {:s}"), _(TownerNames[talker])).c_str());
AddSText(0, 2, tempstr, UiFlags::ColorWhitegold | UiFlags::AlignCenter, false);
AddSText(0, 2, fmt::format(_("Talk to {:s}"), _(TownerNames[talker])), UiFlags::ColorWhitegold | UiFlags::AlignCenter, false);
AddSLine(5);
if (gbIsSpawn) {
strcpy(tempstr, fmt::format(_("Talking to {:s}"), _(TownerNames[talker])).c_str());
AddSText(0, 10, tempstr, UiFlags::ColorWhite | UiFlags::AlignCenter, false);
AddSText(0, 10, fmt::format(_("Talking to {:s}"), _(TownerNames[talker])), UiFlags::ColorWhite | UiFlags::AlignCenter, false);
AddSText(0, 12, _("is not available"), UiFlags::ColorWhite | UiFlags::AlignCenter, false);
AddSText(0, 14, _("in the shareware"), UiFlags::ColorWhite | UiFlags::AlignCenter, false);
AddSText(0, 16, _("version"), UiFlags::ColorWhite | UiFlags::AlignCenter, false);

Loading…
Cancel
Save