diff --git a/Source/spell_book.cpp b/Source/spell_book.cpp deleted file mode 100644 index a47003ecd..000000000 --- a/Source/spell_book.cpp +++ /dev/null @@ -1,212 +0,0 @@ -#include "panels/spell_book.hpp" - -#include "control.h" -#include "engine/cel_sprite.hpp" -#include "engine/load_cel.hpp" -#include "engine/rectangle.hpp" -#include "engine/render/cel_render.hpp" -#include "engine/render/text_render.hpp" -#include "init.h" -#include "missiles.h" -#include "panels/spell_icons.hpp" -#include "player.h" -#include "spelldat.h" -#include "utils/language.h" -#include "utils/stdcompat/optional.hpp" - -#define SPLICONLAST (gbIsHellfire ? 52 : 43) - -namespace devilution { -namespace { - -std::optional pSBkBtnCel; -std::optional pSBkIconCels; -std::optional pSpellBkCel; - -/** Maps from spellbook page number and position to spell_id. */ -spell_id SpellPages[6][7] = { - { SPL_NULL, SPL_FIREBOLT, SPL_CBOLT, SPL_HBOLT, SPL_HEAL, SPL_HEALOTHER, SPL_FLAME }, - { SPL_RESURRECT, SPL_FIREWALL, SPL_TELEKINESIS, SPL_LIGHTNING, SPL_TOWN, SPL_FLASH, SPL_STONE }, - { SPL_RNDTELEPORT, SPL_MANASHIELD, SPL_ELEMENT, SPL_FIREBALL, SPL_WAVE, SPL_CHAIN, SPL_GUARDIAN }, - { SPL_NOVA, SPL_GOLEM, SPL_TELEPORT, SPL_APOCA, SPL_BONESPIRIT, SPL_FLARE, SPL_ETHEREALIZE }, - { SPL_LIGHTWALL, SPL_IMMOLAT, SPL_WARP, SPL_REFLECT, SPL_BERSERK, SPL_FIRERING, SPL_SEARCH }, - { SPL_INVALID, SPL_INVALID, SPL_INVALID, SPL_INVALID, SPL_INVALID, SPL_INVALID, SPL_INVALID } -}; - -constexpr int SpellBookDescriptionWidth = 250; -constexpr int SpellBookDescriptionHeight = 43; -constexpr int SpellBookDescriptionPaddingLeft = 2; -constexpr int SpellBookDescriptionPaddingRight = 2; - -void PrintSBookStr(const Surface &out, Point position, string_view text, UiFlags flags = UiFlags::None) -{ - DrawString(out, text, - { GetPanelPosition(UiPanels::Spell, { SPLICONLENGTH + SpellBookDescriptionPaddingLeft + position.x, position.y }), - { SpellBookDescriptionWidth - SpellBookDescriptionPaddingLeft - SpellBookDescriptionPaddingRight, 0 } }, - UiFlags::ColorWhite | flags); -} - -spell_type GetSBookTrans(spell_id ii, bool townok) -{ - auto &player = Players[MyPlayerId]; - if ((player._pClass == HeroClass::Monk) && (ii == SPL_SEARCH)) - return RSPLTYPE_SKILL; - spell_type st = RSPLTYPE_SPELL; - if ((player._pISpells & GetSpellBitmask(ii)) != 0) { - st = RSPLTYPE_CHARGES; - } - if ((player._pAblSpells & GetSpellBitmask(ii)) != 0) { - st = RSPLTYPE_SKILL; - } - if (st == RSPLTYPE_SPELL) { - if (CheckSpell(MyPlayerId, ii, st, true) != SpellCheckResult::Success) { - st = RSPLTYPE_INVALID; - } - if ((char)(player._pSplLvl[ii] + player._pISplLvlAdd) <= 0) { - st = RSPLTYPE_INVALID; - } - } - if (townok && currlevel == 0 && st != RSPLTYPE_INVALID && !spelldata[ii].sTownSpell) { - st = RSPLTYPE_INVALID; - } - - return st; -} - -} // namespace - -void InitSpellBook() -{ - pSpellBkCel = LoadCel("Data\\SpellBk.CEL", SPANEL_WIDTH); - - if (gbIsHellfire) { - static const int SBkBtnHellfireWidths[] = { 0, 61, 61, 61, 61, 61, 76 }; - pSBkBtnCel = LoadCel("Data\\SpellBkB.CEL", SBkBtnHellfireWidths); - } else { - pSBkBtnCel = LoadCel("Data\\SpellBkB.CEL", 76); - } - pSBkIconCels = LoadCel("Data\\SpellI2.CEL", 37); - - Player &player = Players[MyPlayerId]; - if (player._pClass == HeroClass::Warrior) { - SpellPages[0][0] = SPL_REPAIR; - } else if (player._pClass == HeroClass::Rogue) { - SpellPages[0][0] = SPL_DISARM; - } else if (player._pClass == HeroClass::Sorcerer) { - SpellPages[0][0] = SPL_RECHARGE; - } else if (player._pClass == HeroClass::Monk) { - SpellPages[0][0] = SPL_SEARCH; - } else if (player._pClass == HeroClass::Bard) { - SpellPages[0][0] = SPL_IDENTIFY; - } else if (player._pClass == HeroClass::Barbarian) { - SpellPages[0][0] = SPL_BLODBOIL; - } -} - -void FreeSpellBook() -{ - pSpellBkCel = std::nullopt; - pSBkBtnCel = std::nullopt; - pSBkIconCels = std::nullopt; -} - -void DrawSpellBook(const Surface &out) -{ - CelDrawTo(out, GetPanelPosition(UiPanels::Spell, { 0, 351 }), *pSpellBkCel, 1); - if (gbIsHellfire && sbooktab < 5) { - CelDrawTo(out, GetPanelPosition(UiPanels::Spell, { 61 * sbooktab + 7, 348 }), *pSBkBtnCel, sbooktab + 1); - } else { - // BUGFIX: rendering of page 3 and page 4 buttons are both off-by-one pixel (fixed). - int sx = 76 * sbooktab + 7; - if (sbooktab == 2 || sbooktab == 3) { - sx++; - } - CelDrawTo(out, GetPanelPosition(UiPanels::Spell, { sx, 348 }), *pSBkBtnCel, sbooktab + 1); - } - auto &player = Players[MyPlayerId]; - uint64_t spl = player._pMemSpells | player._pISpells | player._pAblSpells; - - const int lineHeight = 18; - - int yp = 12; - const int textPaddingTop = 7; - for (int i = 1; i < 8; i++) { - spell_id sn = SpellPages[sbooktab][i - 1]; - if (sn != SPL_INVALID && (spl & GetSpellBitmask(sn)) != 0) { - spell_type st = GetSBookTrans(sn, true); - SetSpellTrans(st); - const Point spellCellPosition = GetPanelPosition(UiPanels::Spell, { 11, yp + SpellBookDescriptionHeight }); - DrawSpellCel(out, spellCellPosition, *pSBkIconCels, SpellITbl[sn]); - if (sn == player._pRSpell && st == player._pRSplType) { - SetSpellTrans(RSPLTYPE_SKILL); - DrawSpellCel(out, spellCellPosition, *pSBkIconCels, SPLICONLAST); - } - - const Point line0 { 0, yp + textPaddingTop }; - const Point line1 { 0, yp + textPaddingTop + lineHeight }; - PrintSBookStr(out, line0, pgettext("spell", spelldata[sn].sNameText)); - switch (GetSBookTrans(sn, false)) { - case RSPLTYPE_SKILL: - PrintSBookStr(out, line1, _("Skill")); - break; - case RSPLTYPE_CHARGES: { - int charges = player.InvBody[INVLOC_HAND_LEFT]._iCharges; - PrintSBookStr(out, line1, fmt::format(ngettext("Staff ({:d} charge)", "Staff ({:d} charges)", charges), charges)); - } break; - default: { - int mana = GetManaAmount(player, sn) >> 6; - if (sn != SPL_BONESPIRIT) { - int min; - int max; - GetDamageAmt(sn, &min, &max); - if (min != -1) { - if (sn == SPL_HEAL || sn == SPL_HEALOTHER) { - PrintSBookStr(out, line1, fmt::format(_(/* TRANSLATORS: UI constrains, keep short please.*/ "Heals: {:d} - {:d}"), min, max), UiFlags::AlignRight); - } else { - PrintSBookStr(out, line1, fmt::format(_(/* TRANSLATORS: UI constrains, keep short please.*/ "Damage: {:d} - {:d}"), min, max), UiFlags::AlignRight); - } - } - } else { - PrintSBookStr(out, line1, _(/* TRANSLATORS: UI constrains, keep short please.*/ "Dmg: 1/3 target hp"), UiFlags::AlignRight); - } - PrintSBookStr(out, line1, fmt::format(pgettext(/* TRANSLATORS: UI constrains, keep short please.*/ "spellbook", "Mana: {:d}"), mana)); - int lvl = std::max(player._pSplLvl[sn] + player._pISplLvlAdd, 0); - if (lvl == 0) { - PrintSBookStr(out, line0, _("Level 0 - Unusable"), UiFlags::AlignRight); - } else { - PrintSBookStr(out, line0, fmt::format(pgettext(/* TRANSLATORS: UI constrains, keep short please.*/ "spellbook", "Level {:d}"), lvl), UiFlags::AlignRight); - } - } break; - } - } - yp += SpellBookDescriptionHeight; - } -} - -void CheckSBook() -{ - Rectangle iconArea = { GetPanelPosition(UiPanels::Spell, { 11, 18 }), { 48 - 11, 314 - 18 } }; - Rectangle tabArea = { GetPanelPosition(UiPanels::Spell, { 7, 320 }), { 311 - 7, 349 - 320 } }; - if (iconArea.Contains(MousePosition)) { - spell_id sn = SpellPages[sbooktab][(MousePosition.y - GetRightPanel().position.y - 18) / 43]; - auto &player = Players[MyPlayerId]; - uint64_t spl = player._pMemSpells | player._pISpells | player._pAblSpells; - if (sn != SPL_INVALID && (spl & GetSpellBitmask(sn)) != 0) { - spell_type st = RSPLTYPE_SPELL; - if ((player._pISpells & GetSpellBitmask(sn)) != 0) { - st = RSPLTYPE_CHARGES; - } - if ((player._pAblSpells & GetSpellBitmask(sn)) != 0) { - st = RSPLTYPE_SKILL; - } - player._pRSpell = sn; - player._pRSplType = st; - force_redraw = 255; - } - } - if (tabArea.Contains(MousePosition)) { - sbooktab = (MousePosition.x - (GetRightPanel().position.x + 7)) / (gbIsHellfire ? 61 : 76); - } -} - -} // namespace devilution diff --git a/Source/spell_icons.cpp b/Source/spell_icons.cpp deleted file mode 100644 index b5eb20ebf..000000000 --- a/Source/spell_icons.cpp +++ /dev/null @@ -1,152 +0,0 @@ -#include "panels/spell_icons.hpp" - -#include "engine/load_cel.hpp" -#include "engine/render/cel_render.hpp" -#include "init.h" -#include "palette.h" -#include "utils/stdcompat/optional.hpp" - -namespace devilution { - -namespace { -std::optional pSpellCels; -uint8_t SplTransTbl[256]; -} // namespace - -const char SpellITbl[] = { - 27, - 1, - 2, - 3, - 4, - 5, - 6, - 7, - 8, - 9, - 28, - 13, - 12, - 18, - 16, - 14, - 18, - 19, - 11, - 20, - 15, - 21, - 23, - 24, - 25, - 22, - 26, - 29, - 37, - 38, - 39, - 42, - 41, - 40, - 10, - 36, - 30, - 51, - 51, - 50, - 46, - 47, - 43, - 45, - 48, - 49, - 44, - 35, - 35, - 35, - 35, - 35, -}; - -void LoadSpellIcons() -{ - if (!gbIsHellfire) - pSpellCels = LoadCel("CtrlPan\\SpelIcon.CEL", SPLICONLENGTH); - else - pSpellCels = LoadCel("Data\\SpelIcon.CEL", SPLICONLENGTH); - SetSpellTrans(RSPLTYPE_SKILL); -} - -void FreeSpellIcons() -{ - pSpellCels = std::nullopt; -} - -void DrawSpellCel(const Surface &out, Point position, int nCel) -{ - DrawSpellCel(out, position, *pSpellCels, nCel); -} - -void DrawSpellCel(const Surface &out, Point position, const CelSprite &sprite, int nCel) -{ - CelDrawLightTo(out, position, sprite, nCel, SplTransTbl); -} - -void SetSpellTrans(spell_type t) -{ - if (t == RSPLTYPE_SKILL) { - for (int i = 0; i < 128; i++) - SplTransTbl[i] = i; - } - for (int i = 128; i < 256; i++) - SplTransTbl[i] = i; - SplTransTbl[255] = 0; - - switch (t) { - case RSPLTYPE_SPELL: - SplTransTbl[PAL8_YELLOW] = PAL16_BLUE + 1; - SplTransTbl[PAL8_YELLOW + 1] = PAL16_BLUE + 3; - SplTransTbl[PAL8_YELLOW + 2] = PAL16_BLUE + 5; - for (int i = PAL16_BLUE; i < PAL16_BLUE + 16; i++) { - SplTransTbl[PAL16_BEIGE - PAL16_BLUE + i] = i; - SplTransTbl[PAL16_YELLOW - PAL16_BLUE + i] = i; - SplTransTbl[PAL16_ORANGE - PAL16_BLUE + i] = i; - } - break; - case RSPLTYPE_SCROLL: - SplTransTbl[PAL8_YELLOW] = PAL16_BEIGE + 1; - SplTransTbl[PAL8_YELLOW + 1] = PAL16_BEIGE + 3; - SplTransTbl[PAL8_YELLOW + 2] = PAL16_BEIGE + 5; - for (int i = PAL16_BEIGE; i < PAL16_BEIGE + 16; i++) { - SplTransTbl[PAL16_YELLOW - PAL16_BEIGE + i] = i; - SplTransTbl[PAL16_ORANGE - PAL16_BEIGE + i] = i; - } - break; - case RSPLTYPE_CHARGES: - SplTransTbl[PAL8_YELLOW] = PAL16_ORANGE + 1; - SplTransTbl[PAL8_YELLOW + 1] = PAL16_ORANGE + 3; - SplTransTbl[PAL8_YELLOW + 2] = PAL16_ORANGE + 5; - for (int i = PAL16_ORANGE; i < PAL16_ORANGE + 16; i++) { - SplTransTbl[PAL16_BEIGE - PAL16_ORANGE + i] = i; - SplTransTbl[PAL16_YELLOW - PAL16_ORANGE + i] = i; - } - break; - case RSPLTYPE_INVALID: - SplTransTbl[PAL8_YELLOW] = PAL16_GRAY + 1; - SplTransTbl[PAL8_YELLOW + 1] = PAL16_GRAY + 3; - SplTransTbl[PAL8_YELLOW + 2] = PAL16_GRAY + 5; - for (int i = PAL16_GRAY; i < PAL16_GRAY + 15; i++) { - SplTransTbl[PAL16_BEIGE - PAL16_GRAY + i] = i; - SplTransTbl[PAL16_YELLOW - PAL16_GRAY + i] = i; - SplTransTbl[PAL16_ORANGE - PAL16_GRAY + i] = i; - } - SplTransTbl[PAL16_BEIGE + 15] = 0; - SplTransTbl[PAL16_YELLOW + 15] = 0; - SplTransTbl[PAL16_ORANGE + 15] = 0; - break; - case RSPLTYPE_SKILL: - break; - } -} - -} // namespace devilution diff --git a/Source/spell_list.cpp b/Source/spell_list.cpp deleted file mode 100644 index 222776286..000000000 --- a/Source/spell_list.cpp +++ /dev/null @@ -1,372 +0,0 @@ -#include "panels/spell_list.hpp" - -#include "control.h" -#include "controls/keymapper.hpp" -#include "engine.h" -#include "engine/render/text_render.hpp" -#include "inv_iterators.hpp" -#include "palette.h" -#include "panels/spell_icons.hpp" -#include "player.h" -#include "spells.h" -#include "utils/language.h" - -#define SPLROWICONLS 10 - -namespace devilution { - -extern std::array quickSpellActionIndexes; - -namespace { - -void PrintSBookSpellType(const Surface &out, Point position, const std::string &text, uint8_t rectColorIndex) -{ - Point rect { position }; - rect += Displacement { 0, -SPLICONLENGTH + 1 }; - - // Top - DrawHorizontalLine(out, rect, SPLICONLENGTH, rectColorIndex); - DrawHorizontalLine(out, rect + Displacement { 0, 1 }, SPLICONLENGTH, rectColorIndex); - - // Bottom - DrawHorizontalLine(out, rect + Displacement { 0, SPLICONLENGTH - 2 }, SPLICONLENGTH, rectColorIndex); - DrawHorizontalLine(out, rect + Displacement { 0, SPLICONLENGTH - 1 }, SPLICONLENGTH, rectColorIndex); - - // Left Side - DrawVerticalLine(out, rect, SPLICONLENGTH, rectColorIndex); - DrawVerticalLine(out, rect + Displacement { 1, 0 }, SPLICONLENGTH, rectColorIndex); - - // Right Side - DrawVerticalLine(out, rect + Displacement { SPLICONLENGTH - 2, 0 }, SPLICONLENGTH, rectColorIndex); - DrawVerticalLine(out, rect + Displacement { SPLICONLENGTH - 1, 0 }, SPLICONLENGTH, rectColorIndex); - - // Align the spell type text with bottom of spell icon - position += Displacement { SPLICONLENGTH / 2 - GetLineWidth(text.c_str()) / 2, (IsSmallFontTall() ? -19 : -15) }; - - // Draw a drop shadow below and to the left of the text - DrawString(out, text, position + Displacement { -1, 1 }, UiFlags::ColorBlack); - DrawString(out, text, position + Displacement { -1, -1 }, UiFlags::ColorBlack); - DrawString(out, text, position + Displacement { 1, -1 }, UiFlags::ColorBlack); - // Then draw the text over the top - DrawString(out, text, position, UiFlags::ColorWhite); -} - -void PrintSBookHotkey(const Surface &out, Point position, const std::string &text) -{ - // Align the hot key text with the top-right corner of the spell icon - position += Displacement { SPLICONLENGTH - (GetLineWidth(text.c_str()) + 5), 5 - SPLICONLENGTH }; - - // Draw a drop shadow below and to the left of the text - DrawString(out, text, position + Displacement { -1, 1 }, UiFlags::ColorBlack); - // Then draw the text over the top - DrawString(out, text, position, UiFlags::ColorWhite); -} - -bool GetSpellListSelection(spell_id &pSpell, spell_type &pSplType) -{ - pSpell = spell_id::SPL_INVALID; - pSplType = spell_type::RSPLTYPE_INVALID; - auto &myPlayer = Players[MyPlayerId]; - - for (auto &spellListItem : GetSpellListItems()) { - if (spellListItem.isSelected) { - pSpell = spellListItem.id; - pSplType = spellListItem.type; - if (myPlayer._pClass == HeroClass::Monk && spellListItem.id == SPL_SEARCH) - pSplType = RSPLTYPE_SKILL; - return true; - } - } - - return false; -} - -} // namespace - -void DrawSpell(const Surface &out) -{ - auto &myPlayer = Players[MyPlayerId]; - spell_id spl = myPlayer._pRSpell; - spell_type st = myPlayer._pRSplType; - - // BUGFIX: Move the next line into the if statement to avoid OOB (SPL_INVALID is -1) (fixed) - if (st == RSPLTYPE_SPELL && spl != SPL_INVALID) { - int tlvl = myPlayer._pISplLvlAdd + myPlayer._pSplLvl[spl]; - if (CheckSpell(MyPlayerId, spl, st, true) != SpellCheckResult::Success) - st = RSPLTYPE_INVALID; - if (tlvl <= 0) - st = RSPLTYPE_INVALID; - } - if (currlevel == 0 && st != RSPLTYPE_INVALID && !spelldata[spl].sTownSpell) - st = RSPLTYPE_INVALID; - SetSpellTrans(st); - const int nCel = (spl != SPL_INVALID) ? SpellITbl[spl] : 27; - const Point position { PANEL_X + 565, PANEL_Y + 119 }; - DrawSpellCel(out, position, nCel); -} - -void DrawSpellList(const Surface &out) -{ - infostr[0] = '\0'; - ClearPanel(); - - auto &myPlayer = Players[MyPlayerId]; - - for (auto &spellListItem : GetSpellListItems()) { - const spell_id spellId = spellListItem.id; - spell_type transType = spellListItem.type; - int spellLevel = 0; - const SpellData &spellDataItem = spelldata[static_cast(spellListItem.id)]; - if (currlevel == 0 && !spellDataItem.sTownSpell) { - transType = RSPLTYPE_INVALID; - } - if (spellListItem.type == RSPLTYPE_SPELL) { - spellLevel = std::max(myPlayer._pISplLvlAdd + myPlayer._pSplLvl[spellListItem.id], 0); - if (spellLevel == 0) - transType = RSPLTYPE_INVALID; - } - - SetSpellTrans(transType); - DrawSpellCel(out, spellListItem.location, SpellITbl[static_cast(spellId)]); - - if (!spellListItem.isSelected) - continue; - - uint8_t spellColor = PAL16_GRAY + 5; - - switch (spellListItem.type) { - case RSPLTYPE_SKILL: - spellColor = PAL16_YELLOW - 46; - PrintSBookSpellType(out, spellListItem.location, _("Skill"), spellColor); - strcpy(infostr, fmt::format(_("{:s} Skill"), pgettext("spell", spellDataItem.sSkillText)).c_str()); - break; - case RSPLTYPE_SPELL: - if (myPlayer.plrlevel != 0) { - spellColor = PAL16_BLUE + 5; - } - 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); - } - if (spellLevel == 0) - strcpy(tempstr, _("Spell Level 0 - Unusable")); - else - strcpy(tempstr, fmt::format(_("Spell Level {:d}"), spellLevel).c_str()); - AddPanelString(tempstr); - break; - case RSPLTYPE_SCROLL: { - if (myPlayer.plrlevel != 0) { - spellColor = PAL16_RED - 59; - } - PrintSBookSpellType(out, spellListItem.location, _("Scroll"), spellColor); - strcpy(infostr, fmt::format(_("Scroll of {:s}"), pgettext("spell", spellDataItem.sNameText)).c_str()); - 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); - } break; - case RSPLTYPE_CHARGES: { - if (myPlayer.plrlevel != 0) { - spellColor = PAL16_ORANGE + 5; - } - 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); - } break; - case RSPLTYPE_INVALID: - break; - } - for (int t = 0; t < 4; t++) { - if (myPlayer._pSplHotKey[t] == spellId && myPlayer._pSplTHotKey[t] == spellListItem.type) { - auto hotkeyName = keymapper.KeyNameForAction(quickSpellActionIndexes[t]); - PrintSBookHotkey(out, spellListItem.location, hotkeyName); - strcpy(tempstr, fmt::format(_("Spell Hotkey {:s}"), hotkeyName.c_str()).c_str()); - AddPanelString(tempstr); - } - } - } -} - -std::vector GetSpellListItems() -{ - std::vector spellListItems; - - uint64_t mask; - - int x = PANEL_X + 12 + SPLICONLENGTH * SPLROWICONLS; - int y = PANEL_Y - 17; - - for (int i = RSPLTYPE_SKILL; i < RSPLTYPE_INVALID; i++) { - auto &myPlayer = Players[MyPlayerId]; - switch ((spell_type)i) { - case RSPLTYPE_SKILL: - mask = myPlayer._pAblSpells; - break; - case RSPLTYPE_SPELL: - mask = myPlayer._pMemSpells; - break; - case RSPLTYPE_SCROLL: - mask = myPlayer._pScrlSpells; - break; - case RSPLTYPE_CHARGES: - mask = myPlayer._pISpells; - break; - case RSPLTYPE_INVALID: - break; - } - int8_t j = SPL_FIREBOLT; - for (uint64_t spl = 1; j < MAX_SPELLS; spl <<= 1, j++) { - if ((mask & spl) == 0) - continue; - int lx = x; - int ly = y - SPLICONLENGTH; - bool isSelected = (MousePosition.x >= lx && MousePosition.x < lx + SPLICONLENGTH && MousePosition.y >= ly && MousePosition.y < ly + SPLICONLENGTH); - spellListItems.emplace_back(SpellListItem { { x, y }, (spell_type)i, (spell_id)j, isSelected }); - x -= SPLICONLENGTH; - if (x == PANEL_X + 12 - SPLICONLENGTH) { - x = PANEL_X + 12 + SPLICONLENGTH * SPLROWICONLS; - y -= SPLICONLENGTH; - } - } - if (mask != 0 && x != PANEL_X + 12 + SPLICONLENGTH * SPLROWICONLS) - x -= SPLICONLENGTH; - if (x == PANEL_X + 12 - SPLICONLENGTH) { - x = PANEL_X + 12 + SPLICONLENGTH * SPLROWICONLS; - y -= SPLICONLENGTH; - } - } - - return spellListItems; -} - -void SetSpell() -{ - spell_id pSpell; - spell_type pSplType; - - spselflag = false; - if (!GetSpellListSelection(pSpell, pSplType)) { - return; - } - - ClearPanel(); - - auto &myPlayer = Players[MyPlayerId]; - myPlayer._pRSpell = pSpell; - myPlayer._pRSplType = pSplType; - - force_redraw = 255; -} - -void SetSpeedSpell(int slot) -{ - spell_id pSpell; - spell_type pSplType; - - if (!GetSpellListSelection(pSpell, pSplType)) { - return; - } - auto &myPlayer = Players[MyPlayerId]; - for (int i = 0; i < 4; ++i) { - if (myPlayer._pSplHotKey[i] == pSpell && myPlayer._pSplTHotKey[i] == pSplType) - myPlayer._pSplHotKey[i] = SPL_INVALID; - } - myPlayer._pSplHotKey[slot] = pSpell; - myPlayer._pSplTHotKey[slot] = pSplType; -} - -void ToggleSpell(int slot) -{ - uint64_t spells; - - auto &myPlayer = Players[MyPlayerId]; - - if (myPlayer._pSplHotKey[slot] == SPL_INVALID) { - return; - } - - switch (myPlayer._pSplTHotKey[slot]) { - case RSPLTYPE_SKILL: - spells = myPlayer._pAblSpells; - break; - case RSPLTYPE_SPELL: - spells = myPlayer._pMemSpells; - break; - case RSPLTYPE_SCROLL: - spells = myPlayer._pScrlSpells; - break; - case RSPLTYPE_CHARGES: - spells = myPlayer._pISpells; - break; - case RSPLTYPE_INVALID: - return; - } - - if ((spells & GetSpellBitmask(myPlayer._pSplHotKey[slot])) != 0) { - myPlayer._pRSpell = myPlayer._pSplHotKey[slot]; - myPlayer._pRSplType = myPlayer._pSplTHotKey[slot]; - force_redraw = 255; - } -} - -void DoSpeedBook() -{ - spselflag = true; - int xo = PANEL_X + 12 + SPLICONLENGTH * 10; - int yo = PANEL_Y - 17; - int x = xo + SPLICONLENGTH / 2; - int y = yo - SPLICONLENGTH / 2; - - auto &myPlayer = Players[MyPlayerId]; - - if (myPlayer._pRSpell != SPL_INVALID) { - for (int i = RSPLTYPE_SKILL; i <= RSPLTYPE_CHARGES; i++) { - uint64_t spells; - switch (i) { - case RSPLTYPE_SKILL: - spells = myPlayer._pAblSpells; - break; - case RSPLTYPE_SPELL: - spells = myPlayer._pMemSpells; - break; - case RSPLTYPE_SCROLL: - spells = myPlayer._pScrlSpells; - break; - case RSPLTYPE_CHARGES: - spells = myPlayer._pISpells; - break; - } - uint64_t spell = 1; - for (int j = 1; j < MAX_SPELLS; j++) { - if ((spell & spells) != 0) { - if (j == myPlayer._pRSpell && i == myPlayer._pRSplType) { - x = xo + SPLICONLENGTH / 2; - y = yo - SPLICONLENGTH / 2; - } - xo -= SPLICONLENGTH; - if (xo == PANEL_X + 12 - SPLICONLENGTH) { - xo = PANEL_X + 12 + SPLICONLENGTH * SPLROWICONLS; - yo -= SPLICONLENGTH; - } - } - spell <<= 1ULL; - } - if (spells != 0 && xo != PANEL_X + 12 + SPLICONLENGTH * SPLROWICONLS) - xo -= SPLICONLENGTH; - if (xo == PANEL_X + 12 - SPLICONLENGTH) { - xo = PANEL_X + 12 + SPLICONLENGTH * SPLROWICONLS; - yo -= SPLICONLENGTH; - } - } - } - - SetCursorPos({ x, y }); -} - -} // namespace devilution