aboutsummaryrefslogtreecommitdiff
path: root/engines/kyra/gui_eob.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/kyra/gui_eob.cpp')
-rw-r--r--engines/kyra/gui_eob.cpp4093
1 files changed, 4093 insertions, 0 deletions
diff --git a/engines/kyra/gui_eob.cpp b/engines/kyra/gui_eob.cpp
new file mode 100644
index 0000000000..e3c0743e5c
--- /dev/null
+++ b/engines/kyra/gui_eob.cpp
@@ -0,0 +1,4093 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifdef ENABLE_EOB
+
+#include "kyra/eobcommon.h"
+#include "kyra/gui_eob.h"
+#include "kyra/script_eob.h"
+#include "kyra/text_rpg.h"
+#include "kyra/timer.h"
+#include "kyra/util.h"
+
+#include "backends/keymapper/keymapper.h"
+#include "common/system.h"
+#include "common/savefile.h"
+#include "graphics/scaler.h"
+
+namespace Kyra {
+
+Button *EoBCoreEngine::gui_getButton(Button *buttonList, int index) {
+ while (buttonList) {
+ if (buttonList->index == index)
+ return buttonList;
+ buttonList = buttonList->nextButton;
+ }
+
+ return 0;
+}
+
+void EoBCoreEngine::gui_drawPlayField(bool refresh) {
+ _screen->loadEoBBitmap("PLAYFLD", _cgaMappingDeco, 5, 3, 2);
+ int cp = _screen->setCurPage(2);
+ gui_drawCompass(true);
+
+ if (refresh && !_sceneDrawPage2)
+ drawScene(0);
+
+ _screen->setCurPage(cp);
+ _screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0, Screen::CR_NO_P_CHECK);
+
+ if (!_loading)
+ _screen->updateScreen();
+
+ _screen->loadEoBBitmap("INVENT", _cgaMappingInv, 5, 3, 2);
+}
+
+void EoBCoreEngine::gui_restorePlayField() {
+ loadVcnData(0, (_flags.gameID == GI_EOB1) ? _cgaMappingLevel[_cgaLevelMappingIndex[_currentLevel - 1]] : 0);
+ _screen->_curPage = 0;
+ gui_drawPlayField(true);
+ gui_drawAllCharPortraitsWithStats();
+}
+
+void EoBCoreEngine::gui_drawAllCharPortraitsWithStats() {
+ for (int i = 0; i < 6; i++)
+ gui_drawCharPortraitWithStats(i);
+}
+
+void EoBCoreEngine::gui_drawCharPortraitWithStats(int index) {
+ if (!testCharacter(index, 1))
+ return;
+
+ static const uint16 charPortraitPosX[] = { 8, 80, 184, 256 };
+ static const uint16 charPortraitPosY[] = { 2, 54, 106 };
+
+ EoBCharacter *c = &_characters[index];
+ int txtCol1 = 12;
+ int txtCol2 = 15;
+
+ if ((_flags.gameID == GI_EOB1 && c->flags & 6) || (_flags.gameID == GI_EOB2 && c->flags & 0x0e)) {
+ txtCol1 = 8;
+ txtCol2 = 6;
+ }
+
+ if (_currentControlMode == 0) {
+ int x2 = charPortraitPosX[index & 1];
+ int y2 = charPortraitPosY[index >> 1];
+ Screen::FontId cf = _screen->setFont(Screen::FID_6_FNT);
+
+ _screen->copyRegion(176, 168, x2 , y2, 64, 24, 2, 2, Screen::CR_NO_P_CHECK);
+ _screen->copyRegion(240, 168, x2, y2 + 24, 64, 26, 2, 2, Screen::CR_NO_P_CHECK);
+ int cp = _screen->setCurPage(2);
+
+ if (index == _exchangeCharacterId)
+ _screen->printText(_characterGuiStringsSt[0], x2 + 2, y2 + 2, 8, guiSettings()->colors.fill);
+ else
+ _screen->printText(c->name, x2 + 2, y2 + 2, txtCol1, guiSettings()->colors.fill);
+
+ gui_drawFaceShape(index);
+ gui_drawWeaponSlot(index, 0);
+ gui_drawWeaponSlot(index, 1);
+ gui_drawHitpoints(index);
+
+ if (testCharacter(index, 2))
+ gui_drawCharPortraitStatusFrame(index);
+
+ if (c->damageTaken > 0) {
+ _screen->drawShape(2, _redSplatShape, x2 + 13, y2 + 30, 0);
+ Common::String tmpStr = Common::String::format("%d", c->damageTaken);
+ _screen->printText(tmpStr.c_str(), x2 + 34 - tmpStr.size() * 3, y2 + 42, (_configRenderMode == Common::kRenderCGA) ? 12 : 15, 0);
+ }
+
+ _screen->setCurPage(cp);
+ _screen->setFont(cf);
+
+ if (!cp) {
+ _screen->copyRegion(x2, y2, charPortraitPosX[2 + (index & 1)], y2, 64, 50, 2, 0, Screen::CR_NO_P_CHECK);
+ _screen->updateScreen();
+ }
+ } else if ((_currentControlMode == 1 || _currentControlMode == 2) && index == _updateCharNum) {
+ _screen->copyRegion(176, 0, 0, 0, 144, 168, 2, 2, Screen::CR_NO_P_CHECK);
+ _screen->_curPage = 2;
+ gui_drawFaceShape(index);
+ _screen->printShadedText(c->name, 219, 6, txtCol2, guiSettings()->colors.fill);
+ gui_drawHitpoints(index);
+ gui_drawFoodStatusGraph(index);
+
+ if (_currentControlMode == 1) {
+ if (c->hitPointsCur == -10)
+ _screen->printShadedText(_characterGuiStringsSt[1], 247, 158, 6, guiSettings()->colors.extraFill);
+ else if (c->hitPointsCur < 1)
+ _screen->printShadedText(_characterGuiStringsSt[2], 226, 158, 6, guiSettings()->colors.extraFill);
+ else if (c->effectFlags & (_flags.gameID == GI_EOB1 ? 0x80 : 0x2000))
+ _screen->printShadedText(_characterGuiStringsSt[3], 220, 158, 6, guiSettings()->colors.extraFill);
+ else if (c->flags & 2)
+ _screen->printShadedText(_characterGuiStringsSt[4], 235, 158, 6, guiSettings()->colors.extraFill);
+ else if (c->flags & 4)
+ _screen->printShadedText(_characterGuiStringsSt[5], 232, 158, 6, guiSettings()->colors.extraFill);
+ else if (c->flags & 8)
+ _screen->printShadedText(_characterGuiStringsSt[6], 232, 158, 6, guiSettings()->colors.extraFill);
+
+ for (int i = 0; i < 27; i++)
+ gui_drawInventoryItem(i, 0, 2);
+ gui_drawInventoryItem(16, 1, 2);
+
+ } else {
+ static const uint16 cm2X1[] = { 179, 272, 301 };
+ static const uint16 cm2Y1[] = { 36, 51, 51 };
+ static const uint16 cm2X2[] = { 271, 300, 318 };
+ static const uint16 cm2Y2[] = { 165, 165, 147 };
+
+ for (int i = 0; i < 3; i++)
+ _screen->fillRect(cm2X1[i], cm2Y1[i], cm2X2[i], cm2Y2[i], guiSettings()->colors.extraFill);
+
+ _screen->printShadedText(_characterGuiStringsIn[0], 183, 42, 15, guiSettings()->colors.extraFill);
+ _screen->printText(_chargenClassStrings[c->cClass], 183, 55, 12, guiSettings()->colors.extraFill);
+ _screen->printText(_chargenAlignmentStrings[c->alignment], 183, 62, 12, guiSettings()->colors.extraFill);
+ _screen->printText(_chargenRaceSexStrings[c->raceSex], 183, 69, 12, guiSettings()->colors.extraFill);
+
+ for (int i = 0; i < 6; i++)
+ _screen->printText(_chargenStatStrings[6 + i], 183, 82 + i * 7, 12, guiSettings()->colors.extraFill);
+
+ _screen->printText(_characterGuiStringsIn[1], 183, 124, 12, guiSettings()->colors.extraFill);
+ _screen->printText(_characterGuiStringsIn[2], 239, 138, 12, guiSettings()->colors.extraFill);
+ _screen->printText(_characterGuiStringsIn[3], 278, 138, 12, guiSettings()->colors.extraFill);
+
+ _screen->printText(getCharStrength(c->strengthCur, c->strengthExtCur).c_str(), 275, 82, 15, guiSettings()->colors.extraFill);
+ _screen->printText(Common::String::format("%d", c->intelligenceCur).c_str(), 275, 89, 15, guiSettings()->colors.extraFill);
+ _screen->printText(Common::String::format("%d", c->wisdomCur).c_str(), 275, 96, 15, guiSettings()->colors.extraFill);
+ _screen->printText(Common::String::format("%d", c->dexterityCur).c_str(), 275, 103, 15, guiSettings()->colors.extraFill);
+ _screen->printText(Common::String::format("%d", c->constitutionCur).c_str(), 275, 110, 15, guiSettings()->colors.extraFill);
+ _screen->printText(Common::String::format("%d", c->charismaCur).c_str(), 275, 117, 15, guiSettings()->colors.extraFill);
+ _screen->printText(Common::String::format("%d", c->armorClass).c_str(), 275, 124, 15, guiSettings()->colors.extraFill);
+
+ for (int i = 0; i < 3; i++) {
+ int t = getCharacterClassType(c->cClass, i);
+ if (t == -1)
+ continue;
+
+ _screen->printText(_chargenClassStrings[t + 15], 180, 145 + 7 * i, 12, guiSettings()->colors.extraFill);
+ Common::String tmpStr = Common::String::format("%d", c->experience[i]);
+ _screen->printText(tmpStr.c_str(), 251 - tmpStr.size() * 3, 145 + 7 * i, 15, guiSettings()->colors.extraFill);
+ tmpStr = Common::String::format("%d", c->level[i]);
+ _screen->printText(tmpStr.c_str(), 286 - tmpStr.size() * 3, 145 + 7 * i, 15, guiSettings()->colors.extraFill);
+ }
+ }
+
+ _screen->_curPage = 0;
+ _screen->copyRegion(176, 0, 176, 0, 144, 168, 2, 0, Screen::CR_NO_P_CHECK);
+ _screen->copyRegion(0, 0, 176, 0, 144, 168, 2, 2, Screen::CR_NO_P_CHECK);
+ _screen->updateScreen();
+ }
+}
+
+void EoBCoreEngine::gui_drawFaceShape(int index) {
+ if (!testCharacter(index, 1))
+ return;
+
+ static const uint8 xCoords[] = { 8, 80 };
+ static const uint8 yCoords[] = { 11, 63, 115 };
+
+ int x = xCoords[index & 1];
+ int y = yCoords[index >> 1];
+
+ if (!_screen->_curPage)
+ x += 176;
+
+ if (_currentControlMode) {
+ if (_updateCharNum != index)
+ return;
+
+ x = 181;
+ y = 3;
+ }
+
+ EoBCharacter *c = &_characters[index];
+
+ if (c->hitPointsCur == -10) {
+ _screen->drawShape(_screen->_curPage, _deadCharShape, x, y, 0);
+ return;
+ }
+
+ if (_flags.gameID == GI_EOB1) {
+ if (c->effectFlags & 4) {
+ _screen->fillRect(x, y, x + 31, y + 31, 12);
+ return;
+ }
+ } else {
+ if (c->effectFlags & 0x140) {
+ _screen->setFadeTableIndex(1);
+ _screen->setShapeFadeMode(1, true);
+ }
+
+ if (c->flags & 2) {
+ _screen->setFadeTableIndex(0);
+ _screen->setShapeFadeMode(1, true);
+ }
+
+ if (c->flags & 8) {
+ _screen->setFadeTableIndex(2);
+ _screen->setShapeFadeMode(1, true);
+ }
+ }
+
+ _screen->drawShape(_screen->_curPage, c->faceShape, x, y, 0);
+
+ if (c->hitPointsCur < 1)
+ _screen->drawShape(_screen->_curPage, _disabledCharGrid, x, y, 0);
+
+ _screen->setFadeTableIndex(4);
+ _screen->setShapeFadeMode(1, false);
+}
+
+void EoBCoreEngine::gui_drawWeaponSlot(int charIndex, int slot) {
+ static const uint8 xCoords[] = { 40, 112 };
+ static const uint8 yCoords[] = { 11, 27, 63, 79, 115, 131 };
+
+ int x = xCoords[charIndex & 1];
+ int y = yCoords[(charIndex & 6) + slot];
+
+ if (!_screen->_curPage)
+ x += 176;
+
+ int itm = _characters[charIndex].inventory[slot];
+ gui_drawBox(x, y, 31, 16, guiSettings()->colors.frame1, guiSettings()->colors.frame2, guiSettings()->colors.fill);
+
+ if (_characters[charIndex].slotStatus[slot]) {
+ gui_drawWeaponSlotStatus(x, y, _characters[charIndex].slotStatus[slot]);
+ return;
+ }
+
+ if (itm)
+ drawItemIconShape(_screen->_curPage, itm, x + 8, y);
+ else if (!slot && _flags.gameID == GI_EOB2 && checkScriptFlags(0x80000000))
+ _screen->drawShape(_screen->_curPage, _itemIconShapes[103], x + 8, y, 0);
+ else
+ _screen->drawShape(_screen->_curPage, _itemIconShapes[85 + slot], x + 8, y, 0);
+
+ if ((_characters[charIndex].disabledSlots & (1 << slot)) || !validateWeaponSlotItem(charIndex, slot) || (_characters[charIndex].hitPointsCur <= 0) || (_characters[charIndex].flags & 0x0c))
+ _screen->drawShape(_screen->_curPage, _weaponSlotGrid, x, y, 0);
+}
+
+void EoBCoreEngine::gui_drawWeaponSlotStatus(int x, int y, int status) {
+ Common::String tmpStr;
+ Common::String tmpStr2;
+
+ if (status > -3 || status == -5)
+ _screen->drawShape(_screen->_curPage, _greenSplatShape, x - 1, y, 0);
+ else
+ gui_drawBox(x, y, 31, 16, guiSettings()->colors.warningFrame1, guiSettings()->colors.warningFrame2, guiSettings()->colors.warningFill);
+
+ switch (status + 5) {
+ case 0:
+ tmpStr = _characterGuiStringsWp[2];
+ break;
+ case 1:
+ tmpStr = _characterGuiStringsWr[2];
+ tmpStr2 = _characterGuiStringsWr[3];
+ break;
+ case 2:
+ tmpStr = _characterGuiStringsWr[0];
+ tmpStr2 = _characterGuiStringsWr[1];
+ break;
+ case 3:
+ tmpStr = _characterGuiStringsWp[1];
+ break;
+ case 4:
+ tmpStr = _characterGuiStringsWp[0];
+ break;
+ default:
+ tmpStr = Common::String::format("%d", status);
+ break;
+ }
+
+ int textColor= (_configRenderMode == Common::kRenderCGA) ? 2 : 15;
+
+ if (!tmpStr2.empty()) {
+ _screen->printText(tmpStr.c_str(), x + (16 - tmpStr.size() * 3), y + 2, textColor, 0);
+ _screen->printText(tmpStr2.c_str(), x + (16 - tmpStr.size() * 3), y + 9, textColor, 0);
+ } else {
+ _screen->printText(tmpStr.c_str(), x + (16 - tmpStr.size() * 3), y + 5, textColor, 0);
+ }
+}
+
+void EoBCoreEngine::gui_drawHitpoints(int index) {
+ if (!testCharacter(index, 1))
+ return;
+
+ if (_currentControlMode && (index != _updateCharNum))
+ return;
+
+ static const uint8 xCoords[] = { 23, 95 };
+ static const uint8 yCoords[] = { 46, 98, 150 };
+ static const uint8 barColor[] = { 3, 5, 8 };
+
+ int x = xCoords[index & 1];
+ int y = yCoords[index >> 1];
+ int w = 38;
+ int h = 3;
+
+ if (!_screen->_curPage)
+ x += 176;
+
+ if (_currentControlMode) {
+ x = 250;
+ y = 16;
+ w = 51;
+ h = 5;
+ }
+
+ EoBCharacter *c = &_characters[index];
+
+ if (_configHpBarGraphs) {
+ int bgCur = c->hitPointsCur + 10;
+ int bgMax = c->hitPointsMax + 10;
+ int col = ((bgMax / 3) > bgCur) ? 1 : 0;
+ if (bgCur <= 10)
+ col = 2;
+
+ if (!_currentControlMode)
+ _screen->printText(_characterGuiStringsHp[0], x - 13, y - 1, 12, 0);
+
+
+ gui_drawHorizontalBarGraph(x, y, w, h, bgCur, bgMax, barColor[col], guiSettings()->colors.barGraph);
+
+ } else {
+ Common::String tmpString = Common::String::format(_characterGuiStringsHp[1], c->hitPointsCur, c->hitPointsMax);
+
+ if (!_currentControlMode) {
+ x -= 13;
+ y -= 1;
+ }
+
+ _screen->printText(tmpString.c_str(), x, y, 12, guiSettings()->colors.fill);
+ }
+}
+
+void EoBCoreEngine::gui_drawFoodStatusGraph(int index) {
+ if (!_currentControlMode)
+ return;
+
+ if (!testCharacter(index, 1))
+ return;
+
+ EoBCharacter *c = &_characters[index];
+ if (!(c->flags & 1))
+ return;
+
+ if (index != _updateCharNum)
+ return;
+
+ uint8 col = c->food < 20 ? 8 : (c->food < 33 ? 5 : 3);
+ gui_drawHorizontalBarGraph(250, 25, 51, 5, c->food, 100, col, guiSettings()->colors.barGraph);
+}
+
+void EoBCoreEngine::gui_drawHorizontalBarGraph(int x, int y, int w, int h, int32 curVal, int32 maxVal, int col1, int col2) {
+ gui_drawBox(x - 1, y - 1, w + 3, h + 2, guiSettings()->colors.frame2, guiSettings()->colors.frame1, -1);
+ KyraRpgEngine::gui_drawHorizontalBarGraph(x, y, w + 2, h, curVal, maxVal, col1, col2);
+}
+
+void EoBCoreEngine::gui_drawCharPortraitStatusFrame(int index) {
+ uint8 redGreenColor = (_partyEffectFlags & 0x20000) ? 4 : ((_configRenderMode == Common::kRenderCGA) ? 3 : 6);
+
+ static const uint8 xCoords[] = { 8, 80 };
+ static const uint8 yCoords[] = { 2, 54, 106 };
+ int x = xCoords[index & 1];
+ int y = yCoords[index >> 1];
+ int xOffset = (_configRenderMode == Common::kRenderCGA) ? 0 : 1;
+
+ if (!_screen->_curPage)
+ x += 176;
+
+ EoBCharacter *c = &_characters[index];
+
+ bool redGreen = ((c->effectFlags & 0x4818) || (_partyEffectFlags & 0x20000) || c->effectsRemainder[0] || c->effectsRemainder[1]) ? true : false;
+ bool yellow = ((c->effectFlags & 0x13000) || (_partyEffectFlags & 0x8420)) ? true : false;
+
+ if (redGreen || yellow) {
+ if (redGreen && !yellow) {
+ _screen->drawBox(x, y, x + 63, y + 49, redGreenColor);
+ return;
+ }
+
+ if (yellow && !redGreen) {
+ _screen->drawBox(x, y, x + 63, y + 49, 5);
+ return;
+ }
+
+ int iX = x;
+ int iY = y;
+
+ for (int i = 0; i < 64; i += 16) {
+ x = iX + i;
+ if (redGreen) {
+ _screen->drawClippedLine(x, y, x + 7, y, redGreenColor);
+ _screen->drawClippedLine(x + 8, y + 49, x + 15, y + 49, redGreenColor);
+ }
+ if (yellow) {
+ _screen->drawClippedLine(x + 8, y, x + 15, y, 5);
+ _screen->drawClippedLine(x, y + 49, x + 7, y + 49, 5);
+ }
+ }
+
+ x = iX;
+
+ for (int i = 1; i < 48; i += 12) {
+ y = iY + i - 1;
+
+ if (yellow) {
+ _screen->drawClippedLine(x, y + 1, x, y + 6, 5);
+ _screen->drawClippedLine(x + 63, y + 7, x + 63, y + 12, 5);
+ }
+ if (redGreen) {
+ _screen->drawClippedLine(x, y + 7, x, y + 12, redGreenColor);
+ _screen->drawClippedLine(x + 63, y + 1, x + 63, y + 6, redGreenColor);
+ }
+ }
+
+ } else {
+ _screen->drawClippedLine(x, y, x + 62, y, guiSettings()->colors.frame2);
+ _screen->drawClippedLine(x, y + 49, x + 62, y + 49, guiSettings()->colors.frame1);
+ _screen->drawClippedLine(x - xOffset, y, x - xOffset, y + 50, 12);
+ _screen->drawClippedLine(x + 63, y, x + 63, y + 50, 12);
+ }
+}
+
+void EoBCoreEngine::gui_drawInventoryItem(int slot, int special, int pageNum) {
+ int x = _inventorySlotsX[slot];
+ int y = _inventorySlotsY[slot];
+
+ int item = _characters[_updateCharNum].inventory[slot];
+ int cp = _screen->setCurPage(pageNum);
+
+ if (special) {
+ int wh = (slot == 25 || slot == 26) ? 10 : 18;
+
+ uint8 col1 = guiSettings()->colors.frame1;
+ uint8 col2 = guiSettings()->colors.frame2;
+ if (_configRenderMode == Common::kRenderCGA ) {
+ col1 = 1;
+ col2 = 3;
+ }
+
+ gui_drawBox(x - 1, y - 1, wh, wh, col1, col2, slot == 16 ? -1 : guiSettings()->colors.fill);
+
+ if (slot == 16) {
+ _screen->fillRect(227, 65, 238, 69, 12);
+ int cnt = countQueuedItems(_characters[_updateCharNum].inventory[slot], -1, -1, 1, 1);
+ x = cnt >= 10 ? 227 : 233;
+ Common::String str = Common::String::format("%d", cnt);
+ _screen->printText(str.c_str(), x, 65, 15, 0);
+ }
+ }
+
+ if (slot != 16 && item) {
+ if (slot == 25 || slot == 26) {
+ x -= 4;
+ y -= 4;
+ }
+ drawItemIconShape(pageNum, item, x, y);
+ }
+ _screen->_curPage = cp;
+ _screen->updateScreen();
+}
+
+void EoBCoreEngine::gui_drawCompass(bool force) {
+ if (_currentDirection == _compassDirection && !force)
+ return;
+
+ static const uint8 shpX[2][3] = { { 0x70, 0x4D, 0x95 }, { 0x72, 0x4F, 0x97 } };
+ static const uint8 shpY[2][3] = { { 0x7F, 0x9A, 0x9A }, { 0x83, 0x9E, 0x9E } };
+ int g = _flags.gameID == GI_EOB1 ? 0 : 1;
+
+ for (int i = 0; i < 3; i++)
+ _screen->drawShape(_screen->_curPage, _compassShapes[(i << 2) + _currentDirection], shpX[g][i], shpY[g][i], 0);
+
+ _compassDirection = _currentDirection;
+}
+
+void EoBCoreEngine::gui_drawDialogueBox() {
+ gui_drawBox(0, 121, 320, 79, guiSettings()->colors.frame1, guiSettings()->colors.frame2, guiSettings()->colors.fill);
+ txt()->clearCurDim();
+}
+
+void EoBCoreEngine::gui_drawSpellbook() {
+ _screen->setCurPage(2);
+ int numTab = (_flags.gameID == GI_EOB1) ? 5 : 6;
+ _screen->copyRegion(64, 121, 64, 121, 112, 56, 0, 2, Screen::CR_NO_P_CHECK);
+
+ for (int i = 0; i < numTab; i++) {
+ int col1 = 0;
+ int col2 = 1;
+ int col3 = 2;
+
+ if (_configRenderMode == Common::kRenderCGA) {
+ if (i == _openBookSpellLevel) {
+ col1 = 1;
+ col2 = 2;
+ col3 = 3;
+ }
+ } else {
+ col1 = guiSettings()->colors.inactiveTabFrame1;
+ col2 = guiSettings()->colors.inactiveTabFrame2;
+ col3 = guiSettings()->colors.inactiveTabFill;
+
+ if (i == _openBookSpellLevel) {
+ col1 = guiSettings()->colors.frame1;
+ col2 = guiSettings()->colors.frame2;
+ col3 = guiSettings()->colors.fill;
+ }
+ }
+
+ if (_flags.gameID == GI_EOB1) {
+ gui_drawBox(i * 21 + 71, 122, 21, 9, col1, col2, col3);
+ _screen->printText(_magicStrings7[i], i * 21 + 73, 123, 12, 0);
+ } else {
+ gui_drawBox(i * 18 + 68, 121, 18, 9, col1, col2, col3);
+ _screen->printText(Common::String::format("%d", i + 1).c_str(), i * 18 + 75, 123, 12, 0);
+ }
+ }
+
+ if (_flags.gameID == GI_EOB1)
+ gui_drawBox(71, 131, 105, 44, guiSettings()->colors.frame1, guiSettings()->colors.frame2, guiSettings()->colors.fill);
+ else {
+ gui_drawBox(68, 130, 108, 47, guiSettings()->colors.frame1, guiSettings()->colors.frame2, guiSettings()->colors.fill);
+ gui_drawBox(68, 168, 78, 9, guiSettings()->colors.extraFrame1, guiSettings()->colors.extraFrame2, guiSettings()->colors.extraFill);
+ gui_drawBox(146, 168, 14, 9, guiSettings()->colors.extraFrame1, guiSettings()->colors.extraFrame2, guiSettings()->colors.extraFill);
+ gui_drawBox(160, 168, 16, 9, guiSettings()->colors.extraFrame1, guiSettings()->colors.extraFrame2, guiSettings()->colors.extraFill);
+ gui_drawSpellbookScrollArrow(150, 169, 0);
+ gui_drawSpellbookScrollArrow(165, 169, 1);
+ }
+
+ int textCol1 = (_configRenderMode == Common::kRenderCGA) ? 3 : 15;
+ int textCol2 = 8;
+ int textXa = 74;
+ int textXs = 71;
+ int textY = 170;
+ int col3 = (_configRenderMode == Common::kRenderCGA) ? 2 : guiSettings()->colors.fill;
+ int col4 = guiSettings()->colors.extraFill;
+ int col5 = 12;
+
+ if (_flags.gameID == GI_EOB1) {
+ textCol2 = (_configRenderMode == Common::kRenderCGA) ? 12 : 11;
+ textXa = textXs = 73;
+ textY = 168;
+ col4 = col3;
+ col5 = textCol1;
+ }
+
+ for (int i = 0; i < 7; i++) {
+ int d = _openBookAvailableSpells[_openBookSpellLevel * 10 + _openBookSpellListOffset + i];
+ if (_openBookSpellSelectedItem == i) {
+ if (d >= 0 && i < 6 && (i + _openBookSpellListOffset) < 9) {
+ _screen->printText(_openBookSpellList[d], textXs, 132 + 6 * i, textCol1, textCol2);
+ } else if (i == 6) {
+ if (_flags.gameID == GI_EOB2)
+ _screen->fillRect(69, 169, 144, 175, textCol2);
+ _screen->printText(_magicStrings1[0], textXa, textY, textCol1, textCol2);
+ }
+ } else {
+ if (d >= 0 && i < 6 && (i + _openBookSpellListOffset) < 9)
+ _screen->printText(_openBookSpellList[d], textXs, 132 + 6 * i, textCol1, col3);
+ else
+ _screen->printText(_magicStrings1[0], textXa, textY, col5, col4);
+ }
+ }
+
+ if (_characters[_openBookChar].disabledSlots & 4) {
+ static const uint8 xpos[] = { 0x44, 0x62, 0x80, 0x90 };
+ static const uint8 ypos[] = { 0x82, 0x92, 0x98 };
+ for (int yc = 0; yc < 3; yc++) {
+ for (int xc = 0; xc < 4; xc++)
+ _screen->drawShape(_screen->_curPage, _weaponSlotGrid, xpos[xc], ypos[yc], 0);
+ }
+ }
+
+ if (_openBookAvailableSpells[_openBookSpellLevel * 10 + 6] <= 0)
+ _screen->drawShape(2, _blackBoxWideGrid, 146, 168, 0);
+
+ _screen->setCurPage(0);
+ _screen->copyRegion(64, 121, 64, 121, 112, 56, 2, 0, Screen::CR_NO_P_CHECK);
+ if (!_loading)
+ _screen->updateScreen();
+}
+
+void EoBCoreEngine::gui_drawSpellbookScrollArrow(int x, int y, int direction) {
+ static const uint8 x1[] = { 0, 2, 1, 0, 2, 2 };
+ static const uint8 x2[] = { 2, 4, 5, 6, 4, 4 };
+ if (direction) {
+ _screen->setPagePixel(_screen->_curPage, x + 3, y + 5, 12);
+ for (int i = 1; i < 6; i++)
+ _screen->drawClippedLine(x + x1[i], (5 - i) + y, x + x2[i], (5 - i) + y, 12);
+ } else {
+ _screen->setPagePixel(_screen->_curPage, x + 3, y, 12);
+ for (int i = 1; i < 6; i++)
+ _screen->drawClippedLine(x + x1[i], y + i, x + x2[i], y + i, 12);
+ }
+}
+
+void EoBCoreEngine::gui_updateSlotAfterScrollUse() {
+ _characters[_openBookChar].disabledSlots ^= (1 << (--_castScrollSlot));
+ setCharEventTimer(_openBookChar, 18, _castScrollSlot + 2, 1);
+ gui_drawCharPortraitWithStats(_openBookChar);
+ _openBookChar = _openBookCharBackup;
+ _openBookType = _openBookTypeBackup;
+ _castScrollSlot = 0;
+ gui_toggleButtons();
+}
+
+void EoBCoreEngine::gui_updateControls() {
+ Button b;
+ if (_currentControlMode)
+ clickedPortraitRestore(&b);
+ if (_updateFlags)
+ clickedSpellbookAbort(&b);
+}
+
+void EoBCoreEngine::gui_toggleButtons() {
+ if (_currentControlMode == 0)
+ gui_setPlayFieldButtons();
+ else if (_currentControlMode == 1)
+ gui_setInventoryButtons();
+ else if (_currentControlMode == 2)
+ gui_setStatsListButtons();
+}
+
+void EoBCoreEngine::gui_setPlayFieldButtons() {
+ gui_resetButtonList();
+ gui_initButtonsFromList(_updateFlags ? _buttonList2 : _buttonList1);
+}
+
+void EoBCoreEngine::gui_setInventoryButtons() {
+ gui_resetButtonList();
+ gui_initButtonsFromList(_updateFlags ? _buttonList5 : _buttonList3);
+}
+
+void EoBCoreEngine::gui_setStatsListButtons() {
+ gui_resetButtonList();
+ gui_initButtonsFromList(_updateFlags ? _buttonList6 : _buttonList4);
+}
+
+void EoBCoreEngine::gui_setSwapCharacterButtons() {
+ gui_resetButtonList();
+ gui_initButtonsFromList(_buttonList7);
+}
+
+void EoBCoreEngine::gui_setCastOnWhomButtons() {
+ gui_resetButtonList();
+ gui_initButtonsFromList(_buttonList8);
+}
+
+void EoBCoreEngine::gui_initButton(int index, int, int, int) {
+ Button *b = 0;
+ int cnt = 1;
+
+ if (_flags.gameID == GI_EOB1 && index > 92)
+ return;
+
+ if (_activeButtons) {
+ Button *n = _activeButtons;
+ while (n->nextButton) {
+ ++cnt;
+ n = n->nextButton;
+ }
+
+ ++cnt;
+ b = n->nextButton = &_activeButtonData[cnt];
+ } else {
+ b = &_activeButtonData[0];
+ _activeButtons = b;
+ }
+
+ *b = Button();
+ b->data0Val2 = 12;
+ b->data1Val2 = b->data2Val2 = 15;
+ b->data3Val2 = 8;
+
+ b->index = index + 1;
+
+ const EoBGuiButtonDef *d = &_buttonDefs[index];
+ b->buttonCallback = _buttonCallbacks[index];
+
+ if (_flags.gameID == GI_EOB1) {
+ // EOB1 spellbook modifications
+ if (index > 60 && index < 66) {
+ d = &_buttonDefs[index + 34];
+ b->buttonCallback = _buttonCallbacks[index + 34];
+ } else if (index == 88) {
+ d = &_buttonDefs[index + 12];
+ b->buttonCallback = _buttonCallbacks[index + 12];
+ }
+ }
+
+ b->x = d->x;
+ b->y = d->y;
+ b->width = d->w;
+ b->height = d->h;
+
+ // EOB1 spellbook modifications
+ if (_flags.gameID == GI_EOB1 && ((index > 66 && index < 73) || (index > 76 && index < 79)))
+ b->y++;
+
+ b->flags = d->flags;
+ b->keyCode = d->keyCode;
+ b->keyCode2 = d->keyCode2;
+ b->arg = d->arg;
+}
+
+int EoBCoreEngine::clickedCharPortraitDefault(Button *button) {
+ if (!testCharacter(button->arg, 1))
+ return 1;
+
+ gui_processCharPortraitClick(button->arg);
+ return 0;
+}
+
+int EoBCoreEngine::clickedCamp(Button *button) {
+ gui_updateControls();
+ disableSysTimer(2);
+ int cd = _screen->curDimIndex();
+
+ for (int i = 0; i < 6; i++) {
+ if (!testCharacter(i, 1))
+ continue;
+ _characters[i].damageTaken = 0;
+ _characters[i].slotStatus[0] = _characters[i].slotStatus[1] = 0;
+ gui_drawCharPortraitWithStats(i);
+ }
+
+ _screen->copyPage(0, 7);
+ _screen->copyRegion(0, 120, 0, 0, 176, 24, 0, _useHiResDithering ? 1 : 12, Screen::CR_NO_P_CHECK);
+
+ _gui->runCampMenu();
+
+ _screen->copyRegion(0, 0, 0, 120, 176, 24, _useHiResDithering ? 1 : 12, 2, Screen::CR_NO_P_CHECK);
+ _screen->setScreenDim(cd);
+ drawScene(0);
+
+ for (int i = 0; i < 6; i++)
+ sortCharacterSpellList(i);
+
+ _screen->setCurPage(0);
+ const ScreenDim *dm = _screen->getScreenDim(10);
+ _screen->copyRegion(dm->sx << 3, dm->sy, dm->sx << 3, dm->sy, dm->w << 3, dm->h, 2, 0, Screen::CR_NO_P_CHECK);
+
+ _screen->updateScreen();
+
+ enableSysTimer(2);
+ advanceTimers(_restPartyElapsedTime);
+ _restPartyElapsedTime = 0;
+
+ checkPartyStatus(true);
+
+ return button->arg;
+}
+
+int EoBCoreEngine::clickedSceneDropPickupItem(Button *button) {
+ uint16 block = _currentBlock;
+ if (button->arg > 1) {
+ block = calcNewBlockPosition(_currentBlock, _currentDirection);
+ int f = _wllWallFlags[_levelBlockProperties[block].walls[_sceneDrawVarDown]];
+ if (!(f & 0x0b))
+ return 1;
+ }
+ int d = _dropItemDirIndex[(_currentDirection << 2) + button->arg];
+
+ if (_itemInHand) {
+ setItemPosition((Item *)&_levelBlockProperties[block & 0x3ff].drawObjects, block, _itemInHand, d);
+ setHandItem(0);
+ runLevelScript(block, 4);
+ } else {
+ d = getQueuedItem((Item *)&_levelBlockProperties[block].drawObjects, d, -1);
+ if (!d)
+ return 1;
+ setHandItem(d);
+ runLevelScript(block, 8);
+ }
+
+ _sceneUpdateRequired = true;
+ return 1;
+}
+
+int EoBCoreEngine::clickedCharPortrait2(Button *button) {
+ if (!_gui->_progress) {
+ if (!testCharacter(button->arg, 1))
+ return button->index;
+ }
+
+ _currentControlMode = 1;
+ if (!_gui->_progress)
+ _updateCharNum = button->arg;
+
+ _screen->copyRegion(176, 0, 0, 0, 144, 168, 0, 5, Screen::CR_NO_P_CHECK);
+ gui_drawCharPortraitWithStats(_updateCharNum);
+ gui_setInventoryButtons();
+
+ return button->index;
+}
+
+int EoBCoreEngine::clickedWeaponSlot(Button *button) {
+ if (!testCharacter(button->arg, 1))
+ return 1;
+
+ // Fix this using the coordinates from gui_drawWeaponSlot().
+ // The coordinates used in the original are slightly wrong
+ // (most noticeable for characters 5 and 6).
+ static const uint8 sY[] = { 27, 27, 79, 79, 131, 131 };
+ int slot = sY[button->arg] > _mouseY ? 0 : 1;
+
+ if ((_gui->_flagsMouseLeft & 0x7f) == 1)
+ gui_processWeaponSlotClickLeft(button->arg, slot);
+ else
+ gui_processWeaponSlotClickRight(button->arg, slot);
+
+ return 1;
+}
+
+int EoBCoreEngine::clickedCharNameLabelRight(Button *button) {
+ if (!testCharacter(button->arg, 1))
+ return button->index;
+
+ if (_updateFlags) {
+ Button b;
+ clickedSpellbookAbort(&b);
+ }
+
+ if (_exchangeCharacterId == -1) {
+ _exchangeCharacterId = button->arg;
+ gui_setSwapCharacterButtons();
+ gui_drawCharPortraitWithStats(_exchangeCharacterId);
+ enableTimer(0);
+ } else {
+ int d = _exchangeCharacterId;
+ _exchangeCharacterId = -1;
+ exchangeCharacters(d, button->arg);
+
+ _timer->disable(0);
+ gui_drawCharPortraitWithStats(d);
+ gui_processCharPortraitClick(button->arg);
+ gui_drawCharPortraitWithStats(button->arg);
+ gui_setPlayFieldButtons();
+ setupCharacterTimers();
+ }
+
+ return button->index;
+}
+
+int EoBCoreEngine::clickedInventorySlot(Button *button) {
+ gui_processInventorySlotClick(button->arg);
+ return button->index;
+}
+
+int EoBCoreEngine::clickedEatItem(Button *button) {
+ eatItemInHand(_updateCharNum);
+ return button->index;
+}
+
+int EoBCoreEngine::clickedInventoryPrevChar(Button *button) {
+ if (_gui->_progress == 1)
+ _updateCharNum = 0;
+ else if (_gui->_progress == 2)
+ _updateCharNum = 1;
+ else
+ _updateCharNum = getNextValidCharIndex(_updateCharNum, -1);
+
+ gui_drawCharPortraitWithStats(_updateCharNum);
+ return button->index;
+}
+
+int EoBCoreEngine::clickedInventoryNextChar(Button *button) {
+ int oldVal = _updateCharNum;
+ int v = button->arg == 2 ? 2 : 0;
+
+ if (_gui->_progress == 1)
+ _updateCharNum = v + 2;
+ else if (_gui->_progress == 2)
+ _updateCharNum = v + 3;
+ else
+ _updateCharNum = getNextValidCharIndex(_updateCharNum, 1);
+
+ if (!testCharacter(_updateCharNum, 1)) {
+ _updateCharNum = oldVal;
+ return 1;
+ }
+
+ gui_drawCharPortraitWithStats(_updateCharNum);
+ return button->index;
+}
+
+int EoBCoreEngine::clickedSpellbookTab(Button *button) {
+ _openBookSpellLevel = button->arg;
+ _openBookSpellListOffset = 0;
+
+ for (_openBookSpellSelectedItem = 0; _openBookSpellSelectedItem < 6; _openBookSpellSelectedItem++) {
+ if (_openBookAvailableSpells[_openBookSpellLevel * 10 + _openBookSpellSelectedItem] > 0)
+ break;
+ }
+
+ gui_drawSpellbook();
+
+ _characters[_openBookChar].slotStatus[3] = _openBookSpellLevel;
+ _characters[_openBookChar].slotStatus[2] = _openBookSpellSelectedItem;
+ _characters[_openBookChar].slotStatus[4] = _openBookSpellListOffset;
+
+ return button->index;
+}
+
+int EoBCoreEngine::clickedSpellbookList(Button *button) {
+ int listIndex = button->arg;
+ bool spellLevelAvailable = false;
+
+ if (listIndex == 6) {
+ for (int i = 0; i < 10; i++) {
+ if (_openBookAvailableSpells[_openBookSpellLevel * 10 + i] > 0) {
+ spellLevelAvailable = true;
+ break;
+ }
+ }
+ if (!spellLevelAvailable)
+ return button->index;
+
+ int v = (_gui->_progress == 1) ? -1 : ((_gui->_progress == 2) ? 1 : 0);
+
+ _openBookSpellSelectedItem += _openBookSpellListOffset;
+ if (_openBookSpellSelectedItem == 12 || (_openBookSpellSelectedItem == 6 && _openBookSpellListOffset == 0))
+ _openBookSpellSelectedItem = 9;
+
+ do {
+ _openBookSpellSelectedItem += v;
+ int s = (_openBookSpellSelectedItem >= 0) ? _openBookSpellSelectedItem : 9;
+ _openBookSpellSelectedItem = (s <= 9) ? s : 0;
+ } while (_openBookAvailableSpells[_openBookSpellLevel * 10 + _openBookSpellSelectedItem] <= 0 && _openBookSpellSelectedItem != 9);
+
+ if (_openBookSpellSelectedItem >= 6) {
+ _openBookSpellListOffset = 6;
+ if (_openBookSpellSelectedItem == 9)
+ _openBookSpellSelectedItem = 6;
+ else
+ _openBookSpellSelectedItem -= 6;
+ } else {
+ _openBookSpellListOffset = 0;
+ }
+
+ if (_openBookSpellListOffset == 6 && _openBookAvailableSpells[_openBookSpellLevel * 10 + 6] <= 0)
+ _openBookSpellListOffset = 0;
+
+ gui_drawSpellbook();
+
+ } else {
+ if (listIndex == 7 || _openBookAvailableSpells[_openBookSpellLevel * 10 + _openBookSpellListOffset + listIndex] > 0) {
+ if (listIndex < 6) {
+ if (_openBookSpellListOffset + listIndex < 9)
+ _openBookSpellSelectedItem = listIndex;
+ else if (listIndex != 7)
+ return button->index;
+ } else if (listIndex != 7) {
+ return button->index;
+ }
+
+ if (_openBookSpellSelectedItem < 6 && ((_openBookSpellSelectedItem + _openBookSpellListOffset) < 9)) {
+ if (_characters[_openBookChar].disabledSlots & 4)
+ return button->index;
+
+ gui_drawSpellbook();
+
+ int s = _openBookAvailableSpells[_openBookSpellLevel * 10 + _openBookSpellListOffset + _openBookSpellSelectedItem];
+ if (_openBookType == 1)
+ s += _clericSpellOffset;
+
+ castSpell(s, 0);
+
+ } else if ((_openBookSpellSelectedItem == 6 && listIndex == 7) || (_openBookSpellSelectedItem != 6 && listIndex == 6)) {
+ Button b;
+ clickedSpellbookAbort(&b);
+ }
+ }
+ }
+
+ _characters[_openBookChar].slotStatus[2] = _openBookSpellSelectedItem;
+ _characters[_openBookChar].slotStatus[4] = _openBookSpellListOffset;
+ return button->index;
+}
+
+int EoBCoreEngine::clickedCastSpellOnCharacter(Button *button) {
+ _activeSpellCharId = button->arg & 0xff;
+
+ if (_activeSpellCharId == 0xff) {
+ printWarning(_magicStrings3[_flags.gameID == GI_EOB1 ? 2 : 1]);
+ if (_castScrollSlot) {
+ gui_updateSlotAfterScrollUse();
+ } else {
+ gui_toggleButtons();
+ gui_drawSpellbook();
+ }
+ } else {
+ if (_characters[_activeSpellCharId].flags & 1)
+ startSpell(_activeSpell);
+ }
+
+ return button->index;
+}
+
+int EoBCoreEngine::clickedInventoryNextPage(Button *button) {
+ if (_currentControlMode == 2) {
+ gui_setInventoryButtons();
+ _currentControlMode = 1;
+ } else {
+ gui_setStatsListButtons();
+ _currentControlMode = 2;
+ }
+
+ gui_drawCharPortraitWithStats(_updateCharNum);
+ return button->index;
+}
+
+int EoBCoreEngine::clickedPortraitRestore(Button *button) {
+ _currentControlMode = 0;
+ _screen->_curPage = 2;
+ _screen->copyRegion(0, 0, 0, 0, 144, 168, 5, _screen->_curPage, Screen::CR_NO_P_CHECK);
+ gui_drawAllCharPortraitsWithStats();
+ _screen->_curPage = 0;
+ _screen->copyRegion(0, 0, 176, 0, 144, 168, 2, 0, Screen::CR_NO_P_CHECK);
+ _screen->updateScreen();
+ gui_setPlayFieldButtons();
+ return button->index;
+}
+
+int EoBCoreEngine::clickedUpArrow(Button *button) {
+ int b = calcNewBlockPositionAndTestPassability(_currentBlock, _currentDirection);
+
+ if (b == -1) {
+ notifyBlockNotPassable();
+ } else {
+ moveParty(b);
+ _sceneDefaultUpdate = 1;
+ }
+
+ return button->index;
+}
+
+int EoBCoreEngine::clickedDownArrow(Button *button) {
+ int b = calcNewBlockPositionAndTestPassability(_currentBlock, (_currentDirection + 2) & 3);
+
+ if (b == -1) {
+ notifyBlockNotPassable();
+ } else {
+ moveParty(b);
+ _sceneDefaultUpdate = 1;
+ }
+
+ return button->index;
+}
+
+int EoBCoreEngine::clickedLeftArrow(Button *button) {
+ int b = calcNewBlockPositionAndTestPassability(_currentBlock, (_currentDirection - 1) & 3);
+
+ if (b == -1) {
+ notifyBlockNotPassable();
+ } else {
+ moveParty(b);
+ _sceneDefaultUpdate = 1;
+ }
+
+ return button->index;
+}
+
+int EoBCoreEngine::clickedRightArrow(Button *button) {
+ int b = calcNewBlockPositionAndTestPassability(_currentBlock, (_currentDirection + 1) & 3);
+
+ if (b == -1) {
+ notifyBlockNotPassable();
+ } else {
+ moveParty(b);
+ _sceneDefaultUpdate = 1;
+ }
+
+ return button->index;
+}
+
+int EoBCoreEngine::clickedTurnLeftArrow(Button *button) {
+ _currentDirection = (_currentDirection - 1) & 3;
+ //_keybControlUnk = -1;
+ _sceneDefaultUpdate = 1;
+ _sceneUpdateRequired = true;
+ return button->index;
+}
+
+int EoBCoreEngine::clickedTurnRightArrow(Button *button) {
+ _currentDirection = (_currentDirection + 1) & 3;
+ //_keybControlUnk = -1;
+ _sceneDefaultUpdate = 1;
+ _sceneUpdateRequired = true;
+ return button->index;
+}
+
+int EoBCoreEngine::clickedAbortCharSwitch(Button *button) {
+ _timer->disable(0);
+ int c = _exchangeCharacterId;
+ _exchangeCharacterId = -1;
+ gui_drawCharPortraitWithStats(c);
+ gui_setPlayFieldButtons();
+ return button->index;
+}
+
+int EoBCoreEngine::clickedSceneThrowItem(Button *button) {
+ if (!_itemInHand)
+ return button->index;
+
+ if (launchObject(_updateCharNum, _itemInHand, _currentBlock, _dropItemDirIndex[(_currentDirection << 2) + button->arg], _currentDirection, _items[_itemInHand].type)) {
+ setHandItem(0);
+ _sceneUpdateRequired = true;
+ }
+
+ return button->index;
+}
+
+int EoBCoreEngine::clickedSceneSpecial(Button *button) {
+ _clickedSpecialFlag = 0x40;
+ return specialWallAction(calcNewBlockPosition(_currentBlock, _currentDirection), _currentDirection);
+}
+
+int EoBCoreEngine::clickedSpellbookAbort(Button *button) {
+ _updateFlags = 0;
+ _screen->copyRegion(0, 0, 64, 121, 112, 56, _useHiResDithering ? 4 : 10, 0, Screen::CR_NO_P_CHECK);
+ _screen->updateScreen();
+ gui_drawCompass(true);
+ gui_toggleButtons();
+ return button->index;
+}
+
+int EoBCoreEngine::clickedSpellbookScroll(Button *button) {
+ if (_openBookAvailableSpells[_openBookSpellLevel * 10] > 0) {
+ _openBookSpellListOffset ^= 6;
+ _openBookSpellSelectedItem = 0;
+ } else {
+ _openBookSpellListOffset = 6;
+ }
+
+ _characters[_openBookChar].slotStatus[2] = _openBookSpellSelectedItem;
+ _characters[_openBookChar].slotStatus[4] = _openBookSpellListOffset;
+
+ gui_drawSpellbook();
+
+ return button->index;
+}
+
+int EoBCoreEngine::clickedUnk(Button *button) {
+ return button->index;
+}
+
+void EoBCoreEngine::gui_processCharPortraitClick(int index) {
+ if (index == _updateCharNum)
+ return;
+
+ int a = _updateCharNum;
+ _updateCharNum = index;
+
+ gui_drawCharPortraitWithStats(a);
+ gui_drawCharPortraitWithStats(index);
+}
+
+void EoBCoreEngine::gui_processWeaponSlotClickLeft(int charIndex, int slotIndex) {
+ int itm = _characters[charIndex].inventory[slotIndex];
+ if (_items[itm].flags & 0x20)
+ return;
+
+ int ih = _itemInHand;
+ int t = _items[ih].type;
+ uint16 v = (ih) ? _itemTypes[t].invFlags : 0xffff;
+
+ if (v & _slotValidationFlags[slotIndex]) {
+ setHandItem(itm);
+ _characters[charIndex].inventory[slotIndex] = ih;
+ gui_drawCharPortraitWithStats(charIndex);
+ }
+
+ recalcArmorClass(charIndex);
+}
+
+void EoBCoreEngine::gui_processWeaponSlotClickRight(int charIndex, int slotIndex) {
+ if (!testCharacter(charIndex, 0x0d))
+ return;
+
+ Item itm = _characters[charIndex].inventory[slotIndex];
+ int wslot = slotIndex < 2 ? slotIndex : -1;
+
+ if (slotIndex < 2 && (!validateWeaponSlotItem(charIndex, slotIndex) || (!_currentControlMode && (_characters[charIndex].disabledSlots & (1 << slotIndex)))))
+ return;
+
+ if (!itemUsableByCharacter(charIndex, itm))
+ _txt->printMessage(_itemMisuseStrings[0], -1, _characters[charIndex].name);
+
+ if (!itm && slotIndex > 1)
+ return;
+
+ int8 tp = _items[itm].type;
+ int8 vl = _items[itm].value;
+ uint8 ep = _itemTypes[tp].extraProperties & 0x7f;
+
+ switch (ep) {
+ case 0:
+ case 16:
+ // Item automatically used when worn
+ _txt->printMessage(_itemMisuseStrings[1]);
+ break;
+
+ case 1:
+ case 2:
+ case 3:
+ // Weapons
+ if (!_currentControlMode)
+ useSlotWeapon(charIndex, slotIndex, itm);
+ break;
+
+ case 4:
+ case 8:
+ case 12:
+ case 13:
+ case 15:
+ // Item not used that way
+ _txt->printMessage(_itemMisuseStrings[2]);
+ break;
+
+ case 5:
+ case 6:
+ // Cleric holy symbol / mage spell book
+ if (!_currentControlMode)
+ useMagicBookOrSymbol(charIndex, ep == 6 ? 1 : 0);
+ break;
+
+ case 7:
+ // Food ration
+ // Don't do anything if mouse control is enabled (we don't support anything else)
+ // eatItemInHand(charIndex);
+ break;
+
+ case 10:
+ if (_flags.gameID == GI_EOB1)
+ vl += _clericSpellOffset;
+ // drop through
+ case 9:
+ // Mage/Cleric Scroll
+ if (!_currentControlMode)
+ useMagicScroll(charIndex, vl, wslot);
+ break;
+
+ case 11:
+ // Letters, Notes, Maps
+ displayParchment(vl);
+ break;
+
+ case 14:
+ // Potion
+ usePotion(charIndex, wslot);
+ break;
+
+ case 18:
+ useWand(charIndex, wslot);
+ break;
+
+ case 19:
+ // eob2 horn
+ useHorn(charIndex, wslot);
+ break;
+
+ case 20:
+ if (vl == 1)
+ inflictCharacterDamage(charIndex, 200);
+ else
+ useMagicScroll(charIndex, 55, wslot);
+ deleteInventoryItem(charIndex, wslot);
+ break;
+
+ default:
+ break;
+ }
+
+ if (_flags.gameID == GI_EOB1 || (ep == 1 && charIndex >= 2))
+ return;
+
+ _lastUsedItem = itm;
+ runLevelScript(calcNewBlockPosition(_currentBlock, _currentDirection), 0x100);
+ _lastUsedItem = 0;
+}
+
+void EoBCoreEngine::gui_processInventorySlotClick(int slot) {
+ int itm = _characters[_updateCharNum].inventory[slot];
+ int ih = _itemInHand;
+ if (!validateInventorySlotForItem(ih, _updateCharNum, slot))
+ return;
+
+ if (slot == 16) {
+ if (ih) {
+ setItemPosition(&_characters[_updateCharNum].inventory[16], -2, ih, 0);
+ gui_drawInventoryItem(slot, 1, 0);
+ setHandItem(0);
+
+ } else {
+ itm = getQueuedItem(&_characters[_updateCharNum].inventory[16], 0, -1);
+ gui_drawInventoryItem(slot, 1, 0);
+ setHandItem(itm);
+ }
+
+ } else {
+ setHandItem(itm);
+ _characters[_updateCharNum].inventory[slot] = ih;
+ gui_drawInventoryItem(slot, 1, 0);
+ recalcArmorClass(_updateCharNum);
+ }
+}
+
+GUI_EoB::GUI_EoB(EoBCoreEngine *vm) : GUI(vm), _vm(vm), _screen(vm->_screen) {
+ _menuStringsPrefsTemp = new char*[4];
+ memset(_menuStringsPrefsTemp, 0, 4 * sizeof(char *));
+
+ _saveSlotStringsTemp = new char*[6];
+ for (int i = 0; i < 6; i++) {
+ _saveSlotStringsTemp[i] = new char[20];
+ memset(_saveSlotStringsTemp[i], 0, 20);
+ }
+ _saveSlotIdTemp = new int16[6];
+ _savegameOffset = 0;
+ _saveSlotX = _saveSlotY = 0;
+
+ _specialProcessButton = _backupButtonList = 0;
+ _flagsMouseLeft = _flagsMouseRight = _flagsModifier = 0;
+ _backupButtonList = 0;
+ _progress = 0;
+ _prcButtonUnk3 = 1;
+ _cflag = 0xffff;
+
+ _menuLineSpacing = 0;
+ _menuLastInFlags = 0;
+ _menuCur = 0;
+ _menuNumItems = 0;
+
+ _numPages = (_vm->game() == GI_EOB2) ? 8 : 5;
+ _numVisPages = (_vm->game() == GI_EOB2) ? 6 : 5;
+ _clericSpellAvltyFlags = (_vm->game() == GI_EOB2) ? 0xf7ffffff : 0x7bffff;
+ _paladinSpellAvltyFlags = (_vm->game() == GI_EOB2) ? 0xa9bbd1d : 0x800ff2;
+ _numAssignedSpellsOfType = new int8[72];
+ memset(_numAssignedSpellsOfType, 0, 72);
+
+ _charSelectRedraw = false;
+
+ _highLightColorTable = (_vm->game() == GI_EOB1 && (_vm->_configRenderMode == Common::kRenderCGA || _vm->_configRenderMode == Common::kRenderEGA)) ? _highlightColorTableEGA : _highlightColorTableVGA;
+ _updateBoxIndex = -1;
+ _highLightBoxTimer = 0;
+ _updateBoxColorIndex = 0;
+
+ _needRest = false;
+}
+
+GUI_EoB::~GUI_EoB() {
+ if (_menuStringsPrefsTemp) {
+ for (int i = 0; i < 4; i++)
+ delete[] _menuStringsPrefsTemp[i];
+ delete[] _menuStringsPrefsTemp;
+ }
+
+ if (_saveSlotStringsTemp) {
+ for (int i = 0; i < 6; i++)
+ delete[] _saveSlotStringsTemp[i];
+ delete[] _saveSlotStringsTemp;
+ }
+
+ delete[] _saveSlotIdTemp;
+
+ delete[] _numAssignedSpellsOfType;
+}
+
+void GUI_EoB::processButton(Button *button) {
+ if (!button->data0Val1 && !button->data2Val1 && !button->data1Val1)
+ return;
+
+ if ((button->flags & 0x18) == 0x18)
+ return;
+
+ int sd = button->dimTableIndex;
+ const ScreenDim *dm = _screen->getScreenDim(sd);
+
+ int fx = button->x;
+ if (fx < 0)
+ fx += (dm->w << 3);
+
+ int sx = fx + (dm->sx << 3);
+
+ int fy = button->y;
+ if (fy < 0)
+ fy += dm->h;
+
+ int sy = fy + dm->sy;
+
+ uint16 fw = button->width;
+ uint16 fh = button->height;
+
+ uint8 col1 = button->data1Val1;
+ uint8 col2 = button->data1Val3;
+
+ int fx2 = sx + fw - 1;
+ int fy2 = sy + fh - 1;
+
+ if (button->flags2 & 1) {
+ if (button->data1Val1 == 1) {
+ if (button->data0Val1 == 1) {
+ _screen->drawShape(_screen->_curPage, button->data1ShapePtr, fx, fy, sd);
+ } else if (button->data0Val1 == 2) {
+ if (!(button->flags2 & 4))
+ _screen->printText((const char *)button->data1ShapePtr, sx, sy, col1, col2);
+ } else if (button->data0Val1 == 3) {
+ // nullsub (at least EOBII)
+ } else if (button->data0Val1 == 4) {
+ if (button->data1Callback)
+ (*button->data1Callback)(button);
+ }
+ } else if (button->data1Val1 == 2) {
+ if (!(button->flags2 & 4))
+ _screen->drawBox(sx, sy, fx2, fy2, col1);
+ } else if (button->data1Val1 == 3) {
+ // nullsub (at least EOBII)
+ } else if (button->data1Val1 == 4) {
+ if (button->data1Callback)
+ (*button->data1Callback)(button);
+ }
+ }
+
+ if (button->flags2 & 4) {
+ if (button->data2Val1 == 1) {
+ if (button->data0Val1 == 1) {
+ _screen->drawShape(_screen->_curPage, button->data2ShapePtr, fx, fy, sd);
+ } else if (button->data0Val1 == 2) {
+ if (button->flags2 & 1)
+ _screen->printText((const char *)button->data2ShapePtr, sx, sy, button->data3Val2, button->data3Val3);
+ else
+ _screen->printText((const char *)button->data2ShapePtr, sx, sy, button->data2Val2, button->data2Val3);
+ } else if (button->data0Val1 == 3) {
+ // nullsub (at least EOBII)
+ } else if (button->data0Val1 == 4) {
+ if (button->data2Callback)
+ (*button->data2Callback)(button);
+ }
+ } else if (button->data2Val1 == 2) {
+ _screen->drawBox(sx, sy, fx2, fy2, (button->flags2 & 1) ? button->data3Val2 : button->data2Val2);
+ } else if (button->data2Val1 == 3) {
+ // nullsub (at least EOBII)
+ } else if (button->data2Val1 == 4) {
+ if (button->data2Callback)
+ (*button->data2Callback)(button);
+ }
+ }
+
+ if (!(button->flags2 & 5)) {
+ if (button->data0Val1 == 1) {
+ _screen->drawShape(_screen->_curPage, button->data0ShapePtr, fx, fy, sd);
+ } else if (button->data0Val1 == 2) {
+ _screen->printText((const char *)button->data0ShapePtr, sx, sy, button->data0Val2, button->data0Val3);
+ } else if (button->data0Val1 == 3) {
+ // nullsub (at least EOBII)
+ } else if (button->data0Val1 == 4) {
+ if (button->data0Callback)
+ (*button->data0Callback)(button);
+ } else if (button->data0Val1 == 5) {
+ _screen->drawBox(sx, sy, fx2, fy2, button->data0Val2);
+ } else {
+ if (!button->data0Val1) {
+ if (button->data1Val1 == 2 || button->data2Val1 == 2) {
+ _screen->drawBox(sx, sy, fx2, fy2, button->data0Val2);
+ } else {
+ // nullsub (at least EOBII)
+ }
+ }
+ }
+ }
+}
+
+int GUI_EoB::processButtonList(Kyra::Button *buttonList, uint16 inputFlags, int8 mouseWheel) {
+ _progress = 0;
+ uint16 in = inputFlags & 0xff;
+ uint16 buttonReleaseFlag = 0;
+ bool clickEvt = false;
+ //_vm->_processingButtons = true;
+ _flagsMouseLeft = (_vm->_mouseClick == 1) ? 2 : 4;
+ _flagsMouseRight = (_vm->_mouseClick == 2) ? 2 : 4;
+ _vm->_mouseClick = 0;
+
+ if (mouseWheel) {
+ return 204 + mouseWheel;
+ } else if (in >= 199 && in <= 202) {
+ buttonReleaseFlag = (inputFlags & 0x800) ? 3 : 1;
+ if (in < 201)
+ _flagsMouseLeft = buttonReleaseFlag;
+ else
+ _flagsMouseRight = buttonReleaseFlag;
+
+ ////////////////////////////
+ if (!buttonList && !(inputFlags & 0x800))
+ return inputFlags & 0xff;
+ ////////////////////////////
+
+ inputFlags = 0;
+ clickEvt = true;
+ } else if (inputFlags & 0x8000) {
+ inputFlags &= 0xff;
+ }
+
+ uint16 result = 0;
+ bool runLoop = true;
+
+ if (!buttonList)
+ return inputFlags;
+
+ if (_vm->_buttonListChanged || (buttonList != _backupButtonList)) {
+ _backupButtonList = buttonList;
+ _flagsModifier = 0;
+
+ while (runLoop) {
+ processButton(buttonList);
+ _flagsModifier |= (buttonList->flags & 0xAA04);
+
+ // UNUSED
+ //if (buttonList->flags2 & 0x20) {
+ //if (_processButtonListExtraCallback)
+ // this->*_processButtonListExtraCallback(buttonList);
+ //}
+
+ if (buttonList->nextButton)
+ buttonList = buttonList->nextButton;
+ else
+ runLoop = false;
+ }
+
+ _vm->_buttonListChanged = false;
+
+ _specialProcessButton = 0;
+ _prcButtonUnk3 = 1;
+ _cflag = 0xffff;
+ }
+
+ int sd = 0;
+ const ScreenDim *dm = _screen->getScreenDim(sd);
+
+ int x1 = dm->sx << 3;
+ int y1 = dm->sy;
+ int w1 = dm->w << 3;
+ int h1 = dm->h;
+
+ uint16 v8 = 0;
+ uint16 v18 = 0;
+ uint16 v16 = 0;
+
+ if (_specialProcessButton)
+ buttonList = _specialProcessButton;
+
+ while (runLoop) {
+ if (buttonList->flags & 8) {
+ buttonList = buttonList->nextButton;
+ runLoop = buttonList ? true : false;
+ continue;
+ }
+
+ int vc = 0;
+ int v6 = 0;
+ uint16 iFlag = buttonList->index | 0x8000;
+ uint16 flgs2 = buttonList->flags2;
+ uint16 flgs = buttonList->flags;
+
+ if (flgs2 & 1)
+ flgs2 |= 8;
+ else
+ flgs2 &= 0xfff7;
+
+ if (flgs2 & 4)
+ flgs2 |= 0x10;
+ else
+ flgs2 &= 0xffef;
+
+ uint16 vL = 0;
+ uint16 vR = 0;
+
+ if (inputFlags) {
+ if (buttonList->keyCode == inputFlags) {
+ _progress = 1;
+ _flagsMouseLeft = 1;
+ flgs2 ^= 1;
+ result = iFlag;
+ v6 = 1;
+ } else if (buttonList->keyCode2 == inputFlags) {
+ _progress = 2;
+ _flagsMouseRight = 1;
+ result = iFlag;
+ v6 = 1;
+ }
+ } else if (_flagsModifier || clickEvt) {
+ vL = flgs & 0xf00;
+ vR = flgs & 0xf000;
+
+ if (_prcButtonUnk3) {
+ if (sd != buttonList->dimTableIndex) {
+ sd = buttonList->dimTableIndex;
+ dm = _screen->getScreenDim(sd);
+ x1 = dm->sx << 3;
+ y1 = dm->sy;
+ w1 = dm->w << 3;
+ h1 = dm->h;
+ }
+
+ int x2 = x1;
+ if (buttonList->x < 0)
+ x2 += w1;
+ x2 += buttonList->x;
+
+ int y2 = y1;
+ if (buttonList->y < 0)
+ y2 += h1;
+ y2 += buttonList->y;
+
+ if (_vm->_mouseX >= x2 && _vm->_mouseX <= (x2 + buttonList->width) && _vm->_mouseY >= y2 && _vm->_mouseY <= (y2 + buttonList->height)) {
+ flgs2 |= 2;
+
+ if (vL) {
+ switch (_flagsMouseLeft - 1) {
+ case 0:
+ v18 = 1;
+
+ if ((flgs & 4) && buttonList->data2Val1) {
+ flgs2 |= 4;
+ vc = 1;
+ } else {
+ flgs2 &= 0xfffb;
+ }
+
+ if (flgs & 0x100) {
+ v6 = 1;
+ if (!(flgs & 1)) {
+ flgs2 ^= 1;
+ result = iFlag;
+ }
+ }
+
+ if (flgs & 0x40) {
+ _specialProcessButton = buttonList;
+ v8 = 1;
+ }
+
+ _cflag = flgs;
+ break;
+
+ case 1:
+ if (flgs != _cflag)
+ break;
+
+ if ((flgs & 4) && buttonList->data2Val1) {
+ flgs2 |= 4;
+ vc = 1;
+ } else {
+ flgs2 &= 0xfffb;
+ }
+
+ if (!(flgs & 0x200))
+ break;
+
+ v6 = 1;
+
+ if (flgs & 1)
+ break;
+
+ flgs2 |= 1;
+ result = iFlag;
+ break;
+
+ case 2:
+ if (_cflag != flgs)
+ break;
+
+ if (flgs & 0x400) {
+ v6 = 1;
+ if (flgs & 1) {
+ flgs2 ^= 1;
+ result = iFlag;
+ }
+ }
+
+ if ((flgs & 2) && (flgs2 & 1))
+ flgs2 &= 0xfffe;
+ break;
+
+ case 3:
+ if ((flgs & 4) || (!buttonList->data2Val1))
+ flgs2 &= 0xfffb;
+ else
+ flgs2 |= 4;
+
+ if (flgs & 0x800) {
+ v6 = 1;
+ break;
+ }
+
+ if ((flgs & 2) && (flgs2 & 1))
+ flgs2 &= 0xfffe;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (vR && !v6 && !vc) {
+ switch (_flagsMouseRight - 1) {
+ case 0:
+ v18 = 1;
+
+ if ((flgs & 4) && buttonList->data2Val1)
+ flgs2 |= 4;
+ else
+ flgs2 &= 0xfffb;
+
+ if (flgs & 0x1000) {
+ v6 = 1;
+ if (!(flgs & 1)) {
+ flgs2 ^= 1;
+ result = iFlag;
+ }
+ }
+
+ if (flgs & 0x40) {
+ _specialProcessButton = buttonList;
+ v8 = 1;
+ }
+
+ _cflag = flgs;
+ break;
+
+ case 1:
+ if (flgs != _cflag)
+ break;
+
+ if ((flgs & 4) && buttonList->data2Val1)
+ flgs2 |= 4;
+ else
+ flgs2 &= 0xfffb;
+
+ if (!(flgs & 0x2000))
+ break;
+
+ v6 = 1;
+
+ if (flgs & 1)
+ break;
+
+ flgs2 |= 1;
+ result = iFlag;
+ break;
+ case 2:
+ if (_cflag != flgs)
+ break;
+
+ if (flgs & 0x4000) {
+ v6 = 1;
+ if (flgs & 1) {
+ flgs2 ^= 1;
+ result = iFlag;
+ }
+ }
+
+ if ((flgs & 2) && (flgs2 & 1))
+ flgs2 &= 0xfffe;
+ break;
+
+ case 3:
+ if ((flgs & 4) || (!buttonList->data2Val1))
+ flgs2 &= 0xfffb;
+ else
+ flgs2 |= 4;
+
+ if (flgs & 0x8000) {
+ v6 = 1;
+ break;
+ }
+
+ if ((flgs & 2) && (flgs2 & 1))
+ flgs2 &= 0xfffe;
+ break;
+
+ default:
+ break;
+ }
+ }
+ } else { // if (_vm->_mouseX >= x2 && _vm->_mouseX <= (x2 + buttonList->width)....)
+ flgs2 &= 0xfff9;
+
+ if ((flgs & 0x40) && (!(flgs & 0x80)) && _specialProcessButton && !v8) {
+ static const uint16 flagsTable[] = { 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000, 0x8000 };
+
+ if (vL) {
+ v16 = flagsTable[_flagsMouseLeft - 1];
+ if (v16 & flgs)
+ v6 = 1;
+ }
+
+ if (vR && !v6) {
+ v16 = flagsTable[_flagsMouseRight + 3];
+ if (v16 & flgs)
+ v6 = 1;
+ }
+
+ if (!v6) {
+ _specialProcessButton = 0;
+ _prcButtonUnk3 = 1;
+ }
+ }
+
+ if ((flgs & 2) && (flgs2 & 1))
+ flgs2 &= 0xfffe;
+ } // end if (_vm->_mouseX >= x2 && _vm->_mouseX <= (x2 + buttonList->width)....)
+ } // end if (_prcButtonUnk3)
+ } // end if (_flagsModifier || clickEvt)
+
+ buttonList->flags = flgs;
+ buttonList->flags2 = flgs2;
+
+ bool f21 = (flgs2 & 8) ? true : false;
+ bool f22 = (flgs2 & 1) ? true : false;
+ bool f23 = (flgs2 & 0x10) ? true : false;
+ bool f24 = (flgs2 & 4) ? true : false;
+
+ if (f21 != f22 || f23 != f24)
+ processButton(buttonList);
+
+ if (v6 && buttonList->buttonCallback)
+ runLoop = !(*buttonList->buttonCallback)(buttonList);
+
+ if ((flgs2 & 2) && (flgs & 0x20))
+ runLoop = false;
+
+ if (_specialProcessButton && ((vL && _flagsMouseLeft == 3) || (vR && _flagsMouseRight == 3))) {
+ _specialProcessButton = 0;
+ _prcButtonUnk3 = 1;
+ runLoop = false;
+ }
+
+ if (_specialProcessButton && !v8)
+ runLoop = false;
+
+ buttonList = buttonList->nextButton;
+ if (!buttonList)
+ runLoop = false;
+ };
+
+ if ((_flagsMouseLeft == 1 || _flagsMouseRight == 1) && !v18)
+ _cflag = 0xffff;
+
+ if (!result)
+ result = inputFlags;
+
+ return result;
+}
+
+void GUI_EoB::simpleMenu_setup(int sd, int maxItem, const char *const *strings, int32 menuItemsMask, int itemOffset, int lineSpacing) {
+ simpleMenu_initMenuItemsMask(sd, maxItem, menuItemsMask, itemOffset);
+
+ const ScreenDim *dm = _screen->getScreenDim(19 + sd);
+ int x = (_screen->_curDim->sx + dm->sx) << 3;
+ int y = _screen->_curDim->sy + dm->sy;
+
+ int v = simpleMenu_getMenuItem(_menuCur, menuItemsMask, itemOffset);
+
+ for (int i = 0; i < _menuNumItems; i++) {
+ int item = simpleMenu_getMenuItem(i, menuItemsMask, itemOffset);
+ int ty = y + i * (lineSpacing + _screen->getFontHeight());
+ _screen->printShadedText(strings[item], x, ty, (_vm->_configRenderMode == Common::kRenderCGA) ? 1 : dm->unkA, 0);
+ if (item == v)
+ _screen->printText(strings[item], x, ty, dm->unkC, 0);
+ }
+
+ _screen->updateScreen();
+ _menuLineSpacing = lineSpacing;
+ _menuLastInFlags = 0;
+ _vm->removeInputTop();
+}
+
+int GUI_EoB::simpleMenu_process(int sd, const char *const *strings, void *b, int32 menuItemsMask, int itemOffset) {
+ const ScreenDim *dm = _screen->getScreenDim(19 + sd);
+ int h = _menuNumItems - 1;
+ int currentItem = _menuCur % _menuNumItems;
+ int newItem = currentItem;
+ int result = -1;
+ int lineH = (_menuLineSpacing + _screen->getFontHeight());
+ int lineS1 = _menuLineSpacing >> 1;
+ int x = (_screen->_curDim->sx + dm->sx) << 3;
+ int y = _screen->_curDim->sy + dm->sy;
+
+ int inFlag = _vm->checkInput(0, false, 0) & 0x8ff;
+ _vm->removeInputTop();
+ Common::Point mousePos = _vm->getMousePos();
+
+ int x1 = (_screen->_curDim->sx << 3) + (dm->sx * _screen->getFontWidth());
+ int y1 = _screen->_curDim->sy + dm->sy - lineS1;
+ int x2 = x1 + (dm->w * _screen->getFontWidth()) - 1;
+ int y2 = y1 + _menuNumItems * lineH - 1;
+ if (_vm->posWithinRect(mousePos.x, mousePos.y, x1, y1, x2, y2))
+ newItem = (mousePos.y - y1) / lineH;
+
+ if (inFlag == 199 || inFlag == 201) {
+ if (_vm->posWithinRect(_vm->_mouseX, _vm->_mouseY, x1, y1, x2, y2))
+ result = newItem = (_vm->_mouseY - y1) / lineH;
+ } else if (inFlag == _vm->_keyMap[Common::KEYCODE_RETURN] || inFlag == _vm->_keyMap[Common::KEYCODE_SPACE] || inFlag == _vm->_keyMap[Common::KEYCODE_KP5]) {
+ result = newItem;
+ } else if (inFlag == _vm->_keyMap[Common::KEYCODE_HOME] || inFlag == _vm->_keyMap[Common::KEYCODE_KP7] || inFlag == _vm->_keyMap[Common::KEYCODE_PAGEUP] || inFlag == _vm->_keyMap[Common::KEYCODE_KP9]) {
+ newItem = 0;
+ } else if (inFlag == _vm->_keyMap[Common::KEYCODE_END] || inFlag == _vm->_keyMap[Common::KEYCODE_KP1] || inFlag == _vm->_keyMap[Common::KEYCODE_PAGEDOWN] || inFlag == _vm->_keyMap[Common::KEYCODE_KP3]) {
+ newItem = h;
+ } else if (inFlag == _vm->_keyMap[Common::KEYCODE_UP] || inFlag == _vm->_keyMap[Common::KEYCODE_KP8]) {
+ if (--newItem < 0)
+ newItem = h;
+ } else if (inFlag == _vm->_keyMap[Common::KEYCODE_DOWN] || inFlag == _vm->_keyMap[Common::KEYCODE_KP2]) {
+ if (++newItem > h)
+ newItem = 0;
+ } else {
+ _menuLastInFlags = inFlag;
+ }
+
+ if (newItem != currentItem) {
+ _screen->printText(strings[simpleMenu_getMenuItem(currentItem, menuItemsMask, itemOffset)], x, y + currentItem * lineH, (_vm->_configRenderMode == Common::kRenderCGA) ? 1 : dm->unkA, 0);
+ _screen->printText(strings[simpleMenu_getMenuItem(newItem, menuItemsMask, itemOffset)], x, y + newItem * lineH , dm->unkC, 0);
+ _screen->updateScreen();
+ }
+
+ if (result != -1) {
+ result = simpleMenu_getMenuItem(result, menuItemsMask, itemOffset);
+ simpleMenu_flashSelection(strings[result], x, y + newItem * lineH, dm->unkA, dm->unkC, 0);
+ }
+
+ _menuCur = newItem;
+
+ return result;
+}
+
+int GUI_EoB::simpleMenu_getMenuItem(int index, int32 menuItemsMask, int itemOffset) {
+ if (menuItemsMask == -1)
+ return index;
+
+ int res = 0;
+ int i = index;
+
+ for (; i; res++) {
+ if (menuItemsMask & (1 << (res + itemOffset)))
+ i--;
+ }
+
+ while (!(menuItemsMask & (1 << (res + itemOffset))))
+ res++;
+
+ return res;
+}
+
+void GUI_EoB::simpleMenu_flashSelection(const char *str, int x, int y, int color1, int color2, int color3) {
+ for (int i = 0; i < 3; i++) {
+ _screen->printText(str, x, y, color2, color3);
+ _screen->updateScreen();
+ _vm->_system->delayMillis(32);
+ _screen->printText(str, x, y, color1, color3);
+ _screen->updateScreen();
+ _vm->_system->delayMillis(32);
+ }
+}
+
+void GUI_EoB::runCampMenu() {
+ Screen::FontId of = _screen->setFont(Screen::FID_8_FNT);
+
+ Button *highlightButton = 0;
+ Button *prevHighlightButton = 0;
+
+ int newMenu = 0;
+ int lastMenu = -1;
+ bool redrawPortraits = false;
+
+ _charSelectRedraw = false;
+ _needRest = false;
+ Button *buttonList = 0;
+
+ for (bool runLoop = true; runLoop && !_vm->shouldQuit();) {
+ if (newMenu == 2)
+ updateOptionsStrings();
+
+ if (newMenu != -1) {
+ releaseButtons(buttonList);
+
+ _vm->_menuDefs[0].titleStrId = newMenu ? 1 : 56;
+ if (newMenu == 2)
+ _vm->_menuDefs[2].titleStrId = 57;
+ else if (newMenu == 1)
+ _vm->_menuDefs[1].titleStrId = 58;
+
+ buttonList = initMenu(newMenu);
+
+ if (newMenu != lastMenu) {
+ highlightButton = buttonList;
+ prevHighlightButton = 0;
+ }
+
+ lastMenu = newMenu;
+ newMenu = -1;
+ }
+
+ int inputFlag = _vm->checkInput(buttonList, false, 0) & 0x80ff;
+ _vm->removeInputTop();
+
+ if (inputFlag == _vm->_keyMap[Common::KEYCODE_ESCAPE])
+ inputFlag = 0x8007;
+ else if (inputFlag == _vm->_keyMap[Common::KEYCODE_KP5] || inputFlag == _vm->_keyMap[Common::KEYCODE_SPACE] || inputFlag == _vm->_keyMap[Common::KEYCODE_RETURN]) {
+ inputFlag = 0x8000 + prevHighlightButton->index;
+ }
+
+ Button *clickedButton = _vm->gui_getButton(buttonList, inputFlag & 0x7fff);
+
+ if (clickedButton) {
+ drawMenuButton(prevHighlightButton, false, false, true);
+ drawMenuButton(clickedButton, true, true, true);
+ _screen->updateScreen();
+ _vm->_system->delayMillis(80);
+ drawMenuButton(clickedButton, false, true, true);
+ _screen->updateScreen();
+ highlightButton = clickedButton;
+ prevHighlightButton = 0;
+ }
+
+ if (inputFlag == _vm->_keyMap[Common::KEYCODE_KP3] || inputFlag == _vm->_keyMap[Common::KEYCODE_PAGEDOWN] || inputFlag == _vm->_keyMap[Common::KEYCODE_KP1] || inputFlag == _vm->_keyMap[Common::KEYCODE_END]) {
+ highlightButton = _vm->gui_getButton(buttonList, _vm->_menuDefs[lastMenu].firstButtonStrId + _vm->_menuDefs[lastMenu].numButtons);
+ inputFlag = _vm->_keyMap[Common::KEYCODE_UP];
+ } else if (inputFlag == _vm->_keyMap[Common::KEYCODE_KP7] || inputFlag == _vm->_keyMap[Common::KEYCODE_HOME] || inputFlag == _vm->_keyMap[Common::KEYCODE_KP9] || inputFlag == _vm->_keyMap[Common::KEYCODE_PAGEUP]) {
+ highlightButton = _vm->gui_getButton(buttonList, _vm->_menuDefs[lastMenu].firstButtonStrId + 1);
+ } else if (inputFlag == _vm->_keyMap[Common::KEYCODE_KP8] || inputFlag == _vm->_keyMap[Common::KEYCODE_UP] || inputFlag == _vm->_keyMap[Common::KEYCODE_KP2] || inputFlag == _vm->_keyMap[Common::KEYCODE_DOWN]) {
+ if (prevHighlightButton) {
+ int dir = (inputFlag == _vm->_keyMap[Common::KEYCODE_UP]) ? -1 : 1;
+ int s = prevHighlightButton->index + dir;
+ int a = _vm->_menuDefs[lastMenu].firstButtonStrId + 1;
+ int b = a + _vm->_menuDefs[lastMenu].numButtons - 1;
+
+ do {
+ if (s < a)
+ s = b;
+ if (s > b)
+ s = a;
+ if (_vm->_menuButtonDefs[s - 1].flags & 2)
+ break;
+ s += dir;
+ } while (!_vm->shouldQuit());
+
+ highlightButton = _vm->gui_getButton(buttonList, s);
+ }
+
+ } else if (inputFlag > 0x8000 && inputFlag < 0x8010) {
+ int i = 0;
+ int cnt = 0;
+
+ switch (inputFlag) {
+ case 0x8001:
+ if (restParty())
+ runLoop = false;
+ else
+ _needRest = false;
+ redrawPortraits = true;
+ newMenu = 0;
+ break;
+
+ case 0x8002:
+ runMemorizePrayMenu(selectCharacterDialogue(23), 0);
+ newMenu = 0;
+ break;
+
+ case 0x8003:
+ runMemorizePrayMenu(selectCharacterDialogue(26), 1);
+ newMenu = 0;
+ break;
+
+ case 0x8004:
+ scribeScrollDialogue();
+ newMenu = 0;
+ break;
+
+ case 0x8005:
+ newMenu = 2;
+ break;
+
+ case 0x8006:
+ newMenu = 1;
+ break;
+
+ case 0x8007:
+ if (_needRest)
+ displayTextBox(44);
+ // fall through
+
+ case 0x800c:
+ case 0x800f:
+ if (lastMenu == 1 || lastMenu == 2)
+ newMenu = 0;
+ else if (inputFlag == _vm->_keyMap[Common::KEYCODE_ESCAPE])
+ newMenu = 0;
+ else
+ runLoop = false;
+ break;
+
+ case 0x8008:
+ if (runLoadMenu(0, 0))
+ runLoop = false;
+ else
+ newMenu = 1;
+ break;
+
+ case 0x8009:
+ if (runSaveMenu(0, 0))
+ displayTextBox(14);
+ newMenu = 1;
+ break;
+
+ case 0x800a:
+ for (; i < 6; i++) {
+ if (_vm->testCharacter(i, 1))
+ cnt++;
+ }
+
+ if (cnt > 4) {
+ _vm->dropCharacter(selectCharacterDialogue(53));
+ _vm->gui_drawPlayField(false);
+ _screen->copyRegion(0, 120, 0, 0, 176, 24, 0, _vm->_useHiResDithering ? 1 : 12, Screen::CR_NO_P_CHECK);
+ _screen->setFont(Screen::FID_6_FNT);
+ _vm->gui_drawAllCharPortraitsWithStats();
+ _screen->setFont(Screen::FID_8_FNT);
+ } else {
+ displayTextBox(45);
+ }
+
+ newMenu = 0;
+ break;
+
+ case 0x800b:
+ if (confirmDialogue(46))
+ _vm->quitGame();
+ newMenu = 0;
+ break;
+
+ case 0x800d:
+ _vm->_configSounds ^= true;
+ _vm->_configMusic = _vm->_configSounds ? 1 : 0;
+ newMenu = 2;
+ break;
+
+ case 0x800e:
+ _vm->_configHpBarGraphs ^= true;
+ newMenu = 2;
+ redrawPortraits = true;
+ break;
+
+ default:
+ break;
+ }
+
+ lastMenu = -1;
+
+ } else {
+ Common::Point p = _vm->getMousePos();
+ for (Button *b = buttonList; b; b = b->nextButton) {
+ if ((b->arg & 2) && _vm->posWithinRect(p.x, p.y, b->x, b->y, b->x + b->width, b->y + b->height))
+ highlightButton = b;
+ }
+ }
+
+ if (_charSelectRedraw || redrawPortraits) {
+ for (int i = 0; i < 6; i++) {
+ _vm->gui_drawCharPortraitWithStats(i);
+ _vm->sortCharacterSpellList(i);
+ }
+ }
+
+ _charSelectRedraw = redrawPortraits = false;
+
+ if (prevHighlightButton != highlightButton && newMenu == -1 && runLoop) {
+ drawMenuButton(prevHighlightButton, false, false, true);
+ drawMenuButton(highlightButton, false, true, true);
+ _screen->updateScreen();
+ prevHighlightButton = highlightButton;
+ }
+ }
+
+ _screen->setFont(of);
+ releaseButtons(buttonList);
+ _vm->writeSettings();
+}
+
+bool GUI_EoB::runLoadMenu(int x, int y) {
+ const ScreenDim *dm = _screen->getScreenDim(11);
+ int xo = dm->sx;
+ int yo = dm->sy;
+ bool result = false;
+
+ _screen->modifyScreenDim(11, dm->sx + (x >> 3), dm->sy + y, dm->w, dm->h);
+
+ for (bool runLoop = true; runLoop && !_vm->shouldQuit();) {
+ updateSaveSlotsList(_vm->_targetName);
+ int slot = selectSaveSlotDialogue(x, y, 1);
+ if (slot > 5) {
+ runLoop = result = false;
+ } else if (slot >= 0) {
+ if (_saveSlotIdTemp[slot] == -1) {
+ messageDialogue(11, 65, 6);
+ } else {
+ if (_vm->loadGameState(_saveSlotIdTemp[slot]).getCode() != Common::kNoError)
+ messageDialogue(11, 16, 6);
+ runLoop = false;
+ result = true;
+ }
+ }
+ }
+
+ _screen->modifyScreenDim(11, xo, yo, dm->w, dm->h);
+ return result;
+}
+
+bool GUI_EoB::confirmDialogue2(int dim, int id, int deflt) {
+ int od = _screen->curDimIndex();
+ Screen::FontId of = _screen->setFont(Screen::FID_8_FNT);
+ _screen->setScreenDim(dim);
+
+ drawTextBox(dim, id);
+
+ int16 x[2];
+ x[0] = (_screen->_curDim->sx << 3) + 8;
+ x[1] = (_screen->_curDim->sx + _screen->_curDim->w - 5) << 3;
+ int16 y = _screen->_curDim->sy + _screen->_curDim->h - 21;
+ int newHighlight = deflt ^ 1;
+ int lastHighlight = -1;
+
+ for (int i = 0; i < 2; i++)
+ drawMenuButtonBox(x[i], y, 32, 14, false, false);
+
+ for (bool runLoop = true; runLoop && !_vm->shouldQuit();) {
+ Common::Point p = _vm->getMousePos();
+ if (_vm->posWithinRect(p.x, p.y, x[0], y, x[0] + 32, y + 14))
+ newHighlight = 0;
+ else if (_vm->posWithinRect(p.x, p.y, x[1], y, x[1] + 32, y + 14))
+ newHighlight = 1;
+
+ int inputFlag = _vm->checkInput(0, false, 0) & 0x8ff;
+ _vm->removeInputTop();
+
+ if (inputFlag == _vm->_keyMap[Common::KEYCODE_SPACE] || inputFlag == _vm->_keyMap[Common::KEYCODE_RETURN]) {
+ runLoop = false;
+ } else if (inputFlag == _vm->_keyMap[Common::KEYCODE_LEFT] || inputFlag == _vm->_keyMap[Common::KEYCODE_KP4] || inputFlag == _vm->_keyMap[Common::KEYCODE_RIGHT] || inputFlag == _vm->_keyMap[Common::KEYCODE_KP6]) {
+ newHighlight ^= 1;
+ } else if (inputFlag == _vm->_keyMap[Common::KEYCODE_n]) {
+ newHighlight = 1;
+ runLoop = false;
+ } else if (inputFlag == _vm->_keyMap[Common::KEYCODE_y]) {
+ newHighlight = 0;
+ runLoop = false;
+ } else if (inputFlag == 199 || inputFlag == 201) {
+ if (_vm->posWithinRect(p.x, p.y, x[0], y, x[0] + 32, y + 14)) {
+ newHighlight = 0;
+ runLoop = false;
+ } else if (_vm->posWithinRect(p.x, p.y, x[1], y, x[1] + 32, y + 14)) {
+ newHighlight = 1;
+ runLoop = false;
+ }
+ }
+
+ if (newHighlight != lastHighlight) {
+ for (int i = 0; i < 2; i++)
+ _screen->printShadedText(_vm->_menuYesNoStrings[i], x[i] + 16 - (strlen(_vm->_menuYesNoStrings[i]) << 2) + 1, y + 3, i == newHighlight ? 6 : 15, 0);
+ _screen->updateScreen();
+ lastHighlight = newHighlight;
+ }
+ }
+
+ drawMenuButtonBox(x[newHighlight], y, 32, 14, true, true);
+ _screen->updateScreen();
+ _vm->_system->delayMillis(80);
+ drawMenuButtonBox(x[newHighlight], y, 32, 14, false, true);
+ _screen->updateScreen();
+
+ _screen->copyRegion(0, _screen->_curDim->h, _screen->_curDim->sx << 3, _screen->_curDim->sy, _screen->_curDim->w << 3, _screen->_curDim->h, 2, 0, Screen::CR_NO_P_CHECK);
+ _screen->setFont(of);
+ _screen->setScreenDim(od);
+
+ return newHighlight == 0;
+}
+
+void GUI_EoB::messageDialogue(int dim, int id, int buttonTextCol) {
+ int od = _screen->curDimIndex();
+ _screen->setScreenDim(dim);
+ Screen::FontId of = _screen->setFont(Screen::FID_8_FNT);
+
+ drawTextBox(dim, id);
+ const ScreenDim *dm = _screen->getScreenDim(dim);
+
+ int bx = ((dm->sx + dm->w) << 3) - ((strlen(_vm->_menuOkString) << 3) + 16);
+ int by = dm->sy + dm->h - 19;
+ int bw = (strlen(_vm->_menuOkString) << 3) + 7;
+
+ drawMenuButtonBox(bx, by, bw, 14, false, false);
+ _screen->printShadedText(_vm->_menuOkString, bx + 4, by + 3, buttonTextCol, 0);
+ _screen->updateScreen();
+
+ for (bool runLoop = true; runLoop && !_vm->shouldQuit();) {
+ int inputFlag = _vm->checkInput(0, false, 0) & 0x8ff;
+ _vm->removeInputTop();
+
+ if (inputFlag == 199 || inputFlag == 201) {
+ if (_vm->posWithinRect(_vm->_mouseX, _vm->_mouseY, bx, by, bx + bw, by + 14))
+ runLoop = false;
+ } else if (inputFlag == _vm->_keyMap[Common::KEYCODE_SPACE] || inputFlag == _vm->_keyMap[Common::KEYCODE_RETURN] || inputFlag == _vm->_keyMap[Common::KEYCODE_o]) {
+ runLoop = false;
+ }
+ }
+
+ drawMenuButtonBox(bx, by, bw, 14, true, true);
+ _screen->updateScreen();
+ _vm->_system->delayMillis(80);
+ drawMenuButtonBox(bx, by, bw, 14, false, true);
+ _screen->updateScreen();
+
+ _screen->copyRegion(0, dm->h, dm->sx << 3, dm->sy, dm->w << 3, dm->h, 2, 0, Screen::CR_NO_P_CHECK);
+ _screen->setScreenDim(od);
+ _screen->setFont(of);
+ dm = _screen->getScreenDim(dim);
+}
+
+void GUI_EoB::messageDialogue2(int dim, int id, int buttonTextCol) {
+ drawMenuButtonBox(_screen->_curDim->sx << 3, _screen->_curDim->sy, _screen->_curDim->w << 3, _screen->_curDim->h, false, false);
+
+ _screen->_curPage = 2;
+ _screen->setClearScreenDim(dim);
+ drawMenuButtonBox(_screen->_curDim->sx << 3, _screen->_curDim->sy, _screen->_curDim->w << 3, _screen->_curDim->h, false, false);
+ _screen->printShadedText(getMenuString(id), (_screen->_curDim->sx << 3) + 5, _screen->_curDim->sy + 5, 15, 0);
+ _screen->_curPage = 0;
+ _screen->copyRegion(_screen->_curDim->sx << 3, _screen->_curDim->sy, _screen->_curDim->sx << 3, _screen->_curDim->sy, _screen->_curDim->w << 3, _screen->_curDim->h, 2, 0, Screen::CR_NO_P_CHECK);
+
+ int x = (_screen->_curDim->sx << 3) + (_screen->_curDim->w << 2) - (strlen(_vm->_menuOkString) << 2);
+ int y = _screen->_curDim->sy + _screen->_curDim->h - 21;
+ int w = (strlen(_vm->_menuOkString) << 3) + 8;
+ drawMenuButtonBox(x, y, w, 14, false, false);
+ _screen->printShadedText(_vm->_menuOkString, x + 4, y + 3, buttonTextCol, 0);
+ _screen->updateScreen();
+
+ for (bool runLoop = true; runLoop && !_vm->shouldQuit();) {
+ int inputFlag = _vm->checkInput(0, false, 0) & 0x8ff;
+ _vm->removeInputTop();
+
+ if (inputFlag == 199 || inputFlag == 201) {
+ if (_vm->posWithinRect(_vm->_mouseX, _vm->_mouseY, x, y, x + w, y + 14))
+ runLoop = false;
+ } else if (inputFlag == _vm->_keyMap[Common::KEYCODE_SPACE] || inputFlag == _vm->_keyMap[Common::KEYCODE_RETURN] || inputFlag == _vm->_keyMap[Common::KEYCODE_o]) {
+ runLoop = false;
+ }
+ }
+
+ _vm->gui_drawBox(x, y, w, 14, _vm->guiSettings()->colors.frame2, _vm->guiSettings()->colors.fill, -1);
+ _screen->updateScreen();
+ _vm->_system->delayMillis(80);
+ drawMenuButtonBox(x, y, w, 14, false, false);
+ _screen->printShadedText(_vm->_menuOkString, x + 4, y + 3, buttonTextCol, 0);
+ _screen->updateScreen();
+
+}
+
+void GUI_EoB::updateBoxFrameHighLight(int box) {
+ if (_updateBoxIndex == box) {
+ if (_updateBoxIndex == -1)
+ return;
+
+ if (_vm->_system->getMillis() <= _highLightBoxTimer)
+ return;
+
+ if (!_highLightColorTable[_updateBoxColorIndex])
+ _updateBoxColorIndex = 0;
+
+ const EoBRect16 *r = &_highlightFrames[_updateBoxIndex];
+ _screen->drawBox(r->x1, r->y1, r->x2, r->y2, _highLightColorTable[_updateBoxColorIndex++]);
+ _screen->updateScreen();
+
+ _highLightBoxTimer = _vm->_system->getMillis() + _vm->_tickLength;
+
+ } else {
+ if (_updateBoxIndex != -1) {
+ const EoBRect16 *r = &_highlightFrames[_updateBoxIndex];
+ _screen->drawBox(r->x1, r->y1, r->x2, r->y2, 12);
+ _screen->updateScreen();
+ }
+
+ _updateBoxColorIndex = 0;
+ _updateBoxIndex = box;
+ _highLightBoxTimer = _vm->_system->getMillis();
+ }
+}
+
+int GUI_EoB::getTextInput(char *dest, int x, int y, int destMaxLen, int textColor1, int textColor2, int cursorColor) {
+#ifdef ENABLE_KEYMAPPER
+ Common::Keymapper *const keymapper = _vm->getEventManager()->getKeymapper();
+ keymapper->pushKeymap(Common::kGlobalKeymapName);
+#endif
+
+ uint8 cursorState = 1;
+ char sufx[] = " ";
+
+ int len = strlen(dest);
+ if (len > destMaxLen) {
+ len = destMaxLen;
+ dest[destMaxLen] = 0;
+ }
+
+ int pos = len;
+ if (len >= destMaxLen)
+ pos--;
+
+ _screen->copyRegion((x - 1) << 3, y, 0, 191, (destMaxLen + 2) << 3, 9, 0, 2, Screen::CR_NO_P_CHECK);
+ _screen->printShadedText(dest, x << 3, y, textColor1, textColor2);
+
+ uint32 next = _vm->_system->getMillis() + 2 * _vm->_tickLength;
+ sufx[0] = (pos < len) ? dest[pos] : 32;
+ _screen->printText(sufx, (x + pos) << 3, y, textColor1, cursorColor);
+
+ int in = 0;
+
+ do {
+ in = 0;
+ _keyPressed.reset();
+
+ while (!in && !_vm->shouldQuit()) {
+ if (next <= _vm->_system->getMillis()) {
+ if (cursorState) {
+ _screen->copyRegion((pos + 1) << 3, 191, (x + pos) << 3, y, 8, 9, 2, 0, Screen::CR_NO_P_CHECK);
+ _screen->printShadedText(sufx, (x + pos) << 3, y, textColor1, textColor2);
+ } else {
+ _screen->printText(sufx, (x + pos) << 3, y, textColor1, cursorColor);
+ }
+
+ _screen->updateScreen();
+ cursorState ^= 1;
+ next = _vm->_system->getMillis() + 2 * _vm->_tickLength;
+ }
+
+ _vm->updateInput();
+ for (Common::List<KyraEngine_v1::Event>::const_iterator evt = _vm->_eventList.begin(); evt != _vm->_eventList.end(); ++evt) {
+ if (evt->event.type == Common::EVENT_KEYDOWN) {
+ _keyPressed = evt->event.kbd;
+ in = _keyPressed.ascii;
+ }
+ }
+ _vm->removeInputTop();
+ }
+
+ if (_keyPressed.keycode == Common::KEYCODE_BACKSPACE) {
+ if (pos >= len && len > 0) {
+ dest[--len] = 0;
+ pos--;
+
+ } else if (pos > 0) {
+ for (int i = pos; i < destMaxLen; i++)
+ dest[i - 1] = dest[i];
+ dest[--len] = 0;
+ pos--;
+ }
+
+ } else if (_keyPressed.keycode == Common::KEYCODE_LEFT || _keyPressed.keycode == Common::KEYCODE_KP4) {
+ if (pos > 0)
+ pos--;
+
+ } else if (_keyPressed.keycode == Common::KEYCODE_RIGHT || _keyPressed.keycode == Common::KEYCODE_KP6) {
+ if (pos < len && pos < (destMaxLen - 1))
+ pos++;
+
+ } else if (in > 31 && in < 126) {
+ if (!(in == 32 && pos == 0)) {
+ if (in >= 97 && in <= 122)
+ in -= 32;
+
+ if (pos < len) {
+ for (int i = destMaxLen - 1; i >= pos; i--)
+ dest[i + 1] = dest[i];
+
+ dest[pos++] = in;
+
+ if (len == destMaxLen)
+ dest[len] = 0;
+
+ } else {
+ if (pos == destMaxLen) {
+ pos--;
+ len--;
+ }
+
+ dest[pos++] = in;
+ dest[pos] = 0;
+ }
+
+ if (++len > destMaxLen)
+ len = destMaxLen;
+
+ if (pos > (destMaxLen - 1))
+ pos = (destMaxLen - 1);
+ }
+ }
+
+ _screen->copyRegion(0, 191, (x - 1) << 3, y, (destMaxLen + 2) << 3, 9, 2, 0, Screen::CR_NO_P_CHECK);
+ _screen->printShadedText(dest, x << 3, y, textColor1, textColor2);
+ sufx[0] = (pos < len) ? dest[pos] : 32;
+
+ if (cursorState)
+ _screen->printText(sufx, (x + pos) << 3, y, textColor1, cursorColor);
+ else
+ _screen->printShadedText(sufx, (x + pos) << 3, y, textColor1, textColor2);
+ _screen->updateScreen();
+
+ } while (_keyPressed.keycode != Common::KEYCODE_RETURN && _keyPressed.keycode != Common::KEYCODE_ESCAPE && !_vm->shouldQuit());
+
+#ifdef ENABLE_KEYMAPPER
+ keymapper->popKeymap(Common::kGlobalKeymapName);
+#endif
+
+ return _keyPressed.keycode == Common::KEYCODE_ESCAPE ? -1 : len;
+}
+
+void GUI_EoB::transferWaitBox() {
+ const ScreenDim *dm = _screen->getScreenDim(11);
+ int xo = dm->sx;
+ int yo = dm->sy;
+ _screen->modifyScreenDim(11, dm->sx + 9, dm->sy + 24, dm->w, dm->h);
+ displayTextBox(-4);
+ _screen->modifyScreenDim(11, xo, yo, dm->w, dm->h);
+}
+
+Common::String GUI_EoB::transferTargetMenu(Common::Array<Common::String> &targets) {
+ if (_savegameList) {
+ for (int i = 0; i < _savegameListSize; i++)
+ delete[] _savegameList[i];
+ delete[] _savegameList;
+ }
+
+ _savegameListSize = targets.size();
+ _savegameList = new char*[_savegameListSize];
+ memset(_savegameList, 0, _savegameListSize * sizeof(char *));
+
+ Common::StringArray::iterator ii = targets.begin();
+ for (int i = 0; i < _savegameListSize; ++i) {
+ _savegameList[i] = new char[(*ii).size() + 1];
+ strcpy(_savegameList[i], (*ii++).c_str());
+ }
+
+ const ScreenDim *dm = _screen->getScreenDim(11);
+ int xo = dm->sx;
+ int yo = dm->sy;
+ _screen->modifyScreenDim(11, dm->sx + 9, dm->sy + 14, dm->w, dm->h);
+
+ int slot = 0;
+ do {
+ slot = selectSaveSlotDialogue(72, 14, 2);
+ if (slot == 6)
+ break;
+ } while (_saveSlotIdTemp[slot] == -1);
+
+ _screen->copyRegion(72, 14, 72, 14, 176, 144, _vm->_useHiResDithering ? 7 : 12, 0, Screen::CR_NO_P_CHECK);
+ _screen->modifyScreenDim(11, xo, yo, dm->w, dm->h);
+
+ return (slot < 6) ? _savegameList[_savegameOffset + slot] : Common::String();
+}
+
+bool GUI_EoB::transferFileMenu(Common::String &targetName, Common::String &selection) {
+ updateSaveSlotsList(targetName, true);
+ _saveSlotsListUpdateNeeded = true;
+ selection.clear();
+
+ if (!_savegameListSize)
+ return false;
+
+ const ScreenDim *dm = _screen->getScreenDim(11);
+ int xo = dm->sx;
+ int yo = dm->sy;
+ _screen->modifyScreenDim(11, dm->sx + 9, dm->sy + 14, dm->w, dm->h);
+
+ int slot = 0;
+ do {
+ slot = selectSaveSlotDialogue(72, 14, 4);
+ if (slot == 6)
+ break;
+
+ if (_saveSlotIdTemp[slot] == -1)
+ messageDialogue(11, 65, 6);
+ else {
+ _screen->modifyScreenDim(11, xo, yo, dm->w, dm->h);
+ selection = _vm->getSavegameFilename(targetName, _saveSlotIdTemp[slot]);
+ return true;
+ }
+ } while (_saveSlotIdTemp[slot] == -1);
+
+ _screen->modifyScreenDim(11, xo, yo, dm->w, dm->h);
+ return true;
+}
+
+void GUI_EoB::createScreenThumbnail(Graphics::Surface &dst) {
+ uint8 *screenPal = new uint8[768];
+ _screen->getRealPalette(0, screenPal);
+ uint16 width = Screen::SCREEN_W;
+ uint16 height = Screen::SCREEN_H;
+ if (_vm->_useHiResDithering) {
+ width <<= 1;
+ height <<= 1;
+ }
+
+ ::createThumbnail(&dst, _screen->getCPagePtr(7), width, height, screenPal);
+ delete[] screenPal;
+}
+
+void GUI_EoB::simpleMenu_initMenuItemsMask(int menuId, int maxItem, int32 menuItemsMask, int itemOffset) {
+ if (menuItemsMask == -1) {
+ _menuNumItems = _screen->getScreenDim(19 + menuId)->h;
+ _menuCur = _screen->getScreenDim(19 + menuId)->unk8;
+ return;
+ }
+
+ _menuNumItems = 0;
+
+ for (int i = 0; i < maxItem; i++) {
+ if (menuItemsMask & (1 << (i + itemOffset)))
+ _menuNumItems++;
+ }
+
+ _menuCur = 0;
+}
+
+bool GUI_EoB::runSaveMenu(int x, int y) {
+ const ScreenDim *dm = _screen->getScreenDim(11);
+ int xo = dm->sx;
+ int yo = dm->sy;
+ bool result = false;
+
+ _screen->modifyScreenDim(11, dm->sx + (x >> 3), dm->sy + y, dm->w, dm->h);
+
+ for (bool runLoop = true; runLoop && !_vm->shouldQuit();) {
+ updateSaveSlotsList(_vm->_targetName);
+ int slot = selectSaveSlotDialogue(x, y, 0);
+ if (slot > 5) {
+ runLoop = result = false;
+ } else if (slot >= 0) {
+ bool useSlot = (_saveSlotIdTemp[slot] == -1);
+ if (useSlot)
+ _saveSlotStringsTemp[slot][0] = 0;
+ else
+ useSlot = confirmDialogue2(11, 55, 1);
+
+ if (!useSlot)
+ continue;
+
+ int fx = (x + 1) << 3;
+ int fy = y + slot * 17 + 23;
+
+ for (int in = -1; in == -1 && !_vm->shouldQuit();) {
+ _screen->fillRect(fx - 2, fy, fx + 160, fy + 8, _vm->guiSettings()->colors.fill);
+ in = getTextInput(_saveSlotStringsTemp[slot], x + 1, fy, 19, 2, 0, 8);
+ if (!strlen(_saveSlotStringsTemp[slot])) {
+ messageDialogue(11, 54, 6);
+ in = -1;
+ }
+ };
+
+ _screen->fillRect(fx - 2, fy, fx + 160, fy + 8, _vm->guiSettings()->colors.fill);
+ _screen->printShadedText(_saveSlotStringsTemp[slot], (x + 1) << 3, fy, 15, 0);
+
+ Graphics::Surface thumb;
+ createScreenThumbnail(thumb);
+ Common::Error err = _vm->saveGameStateIntern(_savegameOffset + slot, _saveSlotStringsTemp[slot], &thumb);
+ thumb.free();
+
+ if (err.getCode() == Common::kNoError)
+ result = true;
+ else
+ messageDialogue(11, 15, 6);
+
+ runLoop = false;
+ }
+ }
+
+ _screen->modifyScreenDim(11, xo, yo, dm->w, dm->h);
+ return result;
+}
+
+int GUI_EoB::selectSaveSlotDialogue(int x, int y, int id) {
+ _saveSlotX = _saveSlotY = 0;
+ int col1 = (_vm->_configRenderMode == Common::kRenderCGA) ? 1 : 15;
+ _screen->setCurPage(2);
+
+ _savegameOffset = 0;
+
+ drawMenuButtonBox(0, 0, 176, 144, false, false);
+ const char *title = (id < 2) ? _vm->_saveLoadStrings[2 + id] : _vm->_transferStringsScummVM[id - 1];
+ _screen->printShadedText(title, 52, 5, col1, 0);
+
+ _screen->copyRegion(0, 0, x, y, 176, 144, 2, 0, Screen::CR_NO_P_CHECK);
+ _screen->setCurPage(0);
+ _screen->updateScreen();
+
+ _saveSlotX = x;
+ _saveSlotY = y;
+ int lastHighlight = -1;
+ int lastOffset = -1;
+ int newHighlight = 0;
+ int slot = -1;
+
+ for (bool runLoop = true; runLoop && !_vm->shouldQuit();) {
+ int inputFlag = _vm->checkInput(0, false, 0) & 0x8ff;
+ _vm->removeInputTop();
+
+ if (inputFlag == _vm->_keyMap[Common::KEYCODE_SPACE] || inputFlag == _vm->_keyMap[Common::KEYCODE_RETURN]) {
+ runLoop = false;
+ } else if (inputFlag == _vm->_keyMap[Common::KEYCODE_ESCAPE]) {
+ newHighlight = 6;
+ runLoop = false;
+ } else if (inputFlag == _vm->_keyMap[Common::KEYCODE_DOWN] || inputFlag == _vm->_keyMap[Common::KEYCODE_KP2]) {
+ if (++newHighlight > 5) {
+ newHighlight = 5;
+ if (++_savegameOffset > 984)
+ _savegameOffset = 984;
+ else
+ lastOffset = -1;
+ }
+ } else if (inputFlag == _vm->_keyMap[Common::KEYCODE_UP] || inputFlag == _vm->_keyMap[Common::KEYCODE_KP8]) {
+ if (--newHighlight < 0) {
+ newHighlight = 0;
+ if (--_savegameOffset < 0)
+ _savegameOffset = 0;
+ else
+ lastOffset = -1;
+ }
+ } else if (inputFlag == _vm->_keyMap[Common::KEYCODE_PAGEDOWN] || inputFlag == _vm->_keyMap[Common::KEYCODE_KP1]) {
+ _savegameOffset += 6;
+ if (_savegameOffset > 984)
+ _savegameOffset = 984;
+ else
+ lastOffset = -1;
+ } else if (inputFlag == _vm->_keyMap[Common::KEYCODE_PAGEUP] || inputFlag == _vm->_keyMap[Common::KEYCODE_KP7]) {
+ _savegameOffset -= 6;
+ if (_savegameOffset < 0)
+ _savegameOffset = 0;
+ else
+ lastOffset = -1;
+ } else if (inputFlag == 205) {
+ if (++_savegameOffset > 984)
+ _savegameOffset = 984;
+ else
+ lastOffset = -1;
+ } else if (inputFlag == 203) {
+ if (--_savegameOffset < 0)
+ _savegameOffset = 0;
+ else
+ lastOffset = -1;
+ } else {
+ slot = getHighlightSlot();
+ if (slot != -1) {
+ newHighlight = slot;
+ if (inputFlag == 199)
+ runLoop = false;
+ }
+ }
+
+ if (lastOffset != _savegameOffset) {
+ lastHighlight = -1;
+ setupSaveMenuSlots();
+ for (int i = 0; i < 7; i++)
+ drawSaveSlotButton(i, 1, col1);
+ lastOffset = _savegameOffset;
+ }
+
+ if (lastHighlight != newHighlight) {
+ drawSaveSlotButton(lastHighlight, 0, col1);
+ drawSaveSlotButton(newHighlight, 0, 6);
+
+ // Display highlighted slot index in the bottom left corner to avoid people getting lost with the 990 save slots
+ _screen->setFont(Screen::FID_6_FNT);
+ int sli = (newHighlight == 6) ? _savegameOffset : (_savegameOffset + newHighlight);
+ _screen->printText(Common::String::format("%03d/989", sli).c_str(), _saveSlotX + 5, _saveSlotY + 135, _vm->guiSettings()->colors.frame2, _vm->guiSettings()->colors.fill);
+ _screen->setFont(Screen::FID_8_FNT);
+
+ _screen->updateScreen();
+ lastHighlight = newHighlight;
+ }
+ }
+
+ drawSaveSlotButton(newHighlight, 2, 6);
+ _screen->updateScreen();
+ _vm->_system->delayMillis(80);
+ drawSaveSlotButton(newHighlight, 1, 6);
+ _screen->updateScreen();
+
+ return newHighlight;
+}
+
+void GUI_EoB::runMemorizePrayMenu(int charIndex, int spellType) {
+ if (charIndex == -1)
+ return;
+
+ uint8 np[8];
+ memset(np, 0, sizeof(np));
+ uint32 avltyFlags = 0;
+ int li = 0;
+ int lv = 0;
+
+ EoBCharacter *c = &_vm->_characters[charIndex];
+ int8 wm = c->wisdomCur - 12;
+ if (wm < 0)
+ wm = 0;
+
+ if (spellType) {
+ li = _vm->getCharacterLevelIndex(2, c->cClass);
+
+ if (li == -1) {
+ li = _vm->getCharacterLevelIndex(4, c->cClass);
+
+ if (li != -1) {
+ lv = c->level[li] - 1;
+ if (lv < 0)
+ lv = 0;
+
+ for (int i = 0; i < _numPages; i++)
+ np[i] = _vm->_numSpellsPal[lv * _numPages + i];
+
+ avltyFlags = _paladinSpellAvltyFlags;
+ }
+
+ } else {
+ lv = c->level[li] - 1;
+ for (int i = 0; i < _numPages; i++) {
+ np[i] = _vm->_numSpellsCleric[lv * _numPages + i];
+ if (np[i])
+ np[i] += _vm->_numSpellsWisAdj[wm * _numPages + i];
+ }
+ avltyFlags = _clericSpellAvltyFlags;
+ }
+
+ } else {
+ li = _vm->getCharacterLevelIndex(1, c->cClass);
+
+ if (li == -1) {
+ if (_vm->checkInventoryForRings(charIndex, 1)) {
+ np[3] <<= 1;
+ np[4] <<= 1;
+ }
+
+ } else {
+ lv = c->level[li] - 1;
+ for (int i = 0; i < _numPages; i++)
+ np[i] = _vm->_numSpellsMage[lv * _numPages + i];
+
+ avltyFlags = c->mageSpellsAvailableFlags;
+ }
+ }
+
+ int8 *menuSpellMap = new int8[88];
+ memset(menuSpellMap, 0, 88);
+ int8 *numAssignedSpellsPerBookPage = new int8[8];
+ memset(numAssignedSpellsPerBookPage, 0, 8);
+ memset(_numAssignedSpellsOfType, 0, 72);
+ int8 *lh = new int8[40];
+ memset(lh, 0, 40);
+
+ memcpy(lh, spellType ? _vm->_spellLevelsCleric : _vm->_spellLevelsMage, spellType ? _vm->_spellLevelsClericSize : _vm->_spellLevelsMageSize);
+ int8 *charSpellList = spellType ? c->clericSpells : c->mageSpells;
+
+ for (int i = 0; i < 80; i++) {
+ int8 s = charSpellList[i];
+ if (s == 0 || (_vm->game() == GI_EOB2 && s == 29))
+ continue;
+
+ if (s < 0)
+ s = -s;
+ else
+ _numAssignedSpellsOfType[s * 2 - 1]++;
+
+ s--;
+ _numAssignedSpellsOfType[s * 2]++;
+ numAssignedSpellsPerBookPage[lh[s] - 1]++;
+ }
+
+ for (int i = 0; i < 32; i++) {
+ if (!(avltyFlags & (1 << i)))
+ continue;
+
+ int d = lh[i] - 1;
+ if (d < 0)
+ continue;
+
+ if (!spellType || (spellType && np[d])) {
+ menuSpellMap[d * 11]++;
+ menuSpellMap[d * 11 + menuSpellMap[d * 11]] = i + 1;
+ }
+ }
+
+ Button *buttonList = initMenu(4);
+
+ int lastHighLightText = -1;
+ int lastHighLightButton = -1;
+ int newHighLightButton = 0;
+ int newHighLightText = 0;
+ bool updateDesc = true;
+ bool updateList = true;
+
+ for (bool runLoop = true; runLoop && !_vm->shouldQuit();) {
+ updateBoxFrameHighLight(charIndex);
+
+ if (newHighLightButton < 0)
+ newHighLightButton = 7;
+ if (newHighLightButton > 7)
+ newHighLightButton = 0;
+
+ Button *b = 0;
+
+ if (lastHighLightButton != newHighLightButton) {
+ if (lastHighLightButton >= 0)
+ drawMenuButton(_vm->gui_getButton(buttonList, lastHighLightButton + 26), false, false, true);
+ drawMenuButton(_vm->gui_getButton(buttonList, newHighLightButton + 26), false, true, true);
+ newHighLightText = 0;
+ lastHighLightText = -1;
+ lastHighLightButton = newHighLightButton;
+ updateDesc = updateList = true;
+ }
+
+ if (updateList) {
+ updateList = false;
+ _screen->setCurPage(2);
+ for (int ii = 1; ii < 9; ii++)
+ memorizePrayMenuPrintString(menuSpellMap[lastHighLightButton * 11 + ii], ii - 1, spellType, false, false);
+
+ _screen->setCurPage(0);
+ _screen->copyRegion(0, 50, 0, 50, 176, 72, 2, 0, Screen::CR_NO_P_CHECK);
+ lastHighLightText = -1;
+ }
+
+ if (updateDesc) {
+ updateDesc = false;
+ _screen->printShadedText(Common::String::format(_vm->_menuStringsMgc[1], np[lastHighLightButton] - numAssignedSpellsPerBookPage[lastHighLightButton], np[lastHighLightButton]).c_str(), 8, 38, 9, _vm->guiSettings()->colors.fill);
+ }
+
+ if (newHighLightText < 0)
+ newHighLightText = menuSpellMap[lastHighLightButton * 11] - 1;
+
+ if (menuSpellMap[lastHighLightButton * 11] <= newHighLightText)
+ newHighLightText = 0;
+
+ if (newHighLightText != lastHighLightText) {
+ memorizePrayMenuPrintString(menuSpellMap[lastHighLightButton * 11 + lastHighLightText + 1], lastHighLightText, spellType, true, false);
+ memorizePrayMenuPrintString(menuSpellMap[lastHighLightButton * 11 + newHighLightText + 1], newHighLightText, spellType, true, true);
+ lastHighLightText = newHighLightText;
+ }
+
+ int inputFlag = _vm->checkInput(buttonList, false, 0) & 0x80ff;
+ _vm->removeInputTop();
+
+ if (inputFlag == _vm->_keyMap[Common::KEYCODE_KP6] || inputFlag == _vm->_keyMap[Common::KEYCODE_RIGHT]) {
+ inputFlag = 0x801a + ((lastHighLightButton + 1) % _numVisPages);
+ } else if (inputFlag == _vm->_keyMap[Common::KEYCODE_KP4] || inputFlag == _vm->_keyMap[Common::KEYCODE_LEFT]) {
+ inputFlag = lastHighLightButton ? 0x8019 + lastHighLightButton : 0x8019 + _numVisPages;
+ } else if (inputFlag == _vm->_keyMap[Common::KEYCODE_ESCAPE]) {
+ inputFlag = 0x8018;
+ } else {
+ Common::Point p = _vm->getMousePos();
+ if (_vm->posWithinRect(p.x, p.y, 8, 50, 168, 122)) {
+ newHighLightText = (p.y - 50) / 9;
+ if (menuSpellMap[lastHighLightButton * 11] - 1 < newHighLightText)
+ newHighLightText = menuSpellMap[lastHighLightButton * 11] - 1;
+ }
+ }
+
+ if (inputFlag & 0x8000) {
+ b = _vm->gui_getButton(buttonList, inputFlag & 0x7fff);
+ drawMenuButton(b, true, true, true);
+ _screen->updateScreen();
+ _vm->_system->delayMillis(80);
+ drawMenuButton(b, false, false, true);
+ _screen->updateScreen();
+ }
+
+ if (inputFlag == 0x8019 || inputFlag == _vm->_keyMap[Common::KEYCODE_KP_PLUS] || inputFlag == _vm->_keyMap[Common::KEYCODE_PLUS] || inputFlag == _vm->_keyMap[Common::KEYCODE_KP5] || inputFlag == _vm->_keyMap[Common::KEYCODE_SPACE] || inputFlag == _vm->_keyMap[Common::KEYCODE_RETURN]) {
+ if (np[lastHighLightButton] > numAssignedSpellsPerBookPage[lastHighLightButton] && lastHighLightText != -1) {
+ _numAssignedSpellsOfType[menuSpellMap[lastHighLightButton * 11 + lastHighLightText + 1] * 2 - 2]++;
+ numAssignedSpellsPerBookPage[lastHighLightButton]++;
+ memorizePrayMenuPrintString(menuSpellMap[lastHighLightButton * 11 + lastHighLightText + 1], lastHighLightText, spellType, false, true);
+ updateDesc = true;
+ }
+
+ } else if (inputFlag == _vm->_keyMap[Common::KEYCODE_KP_MINUS] || inputFlag == _vm->_keyMap[Common::KEYCODE_MINUS]) {
+ if (np[lastHighLightButton] && _numAssignedSpellsOfType[menuSpellMap[lastHighLightButton * 11 + lastHighLightText + 1] * 2 - 2]) {
+ _numAssignedSpellsOfType[menuSpellMap[lastHighLightButton * 11 + lastHighLightText + 1] * 2 - 2]--;
+ numAssignedSpellsPerBookPage[lastHighLightButton]--;
+ memorizePrayMenuPrintString(menuSpellMap[lastHighLightButton * 11 + lastHighLightText + 1], lastHighLightText, spellType, false, true);
+ updateDesc = true;
+ }
+
+ } else if (inputFlag == _vm->_keyMap[Common::KEYCODE_UP] || inputFlag == _vm->_keyMap[Common::KEYCODE_KP8]) {
+ newHighLightText = lastHighLightText - 1;
+ } else if (inputFlag == _vm->_keyMap[Common::KEYCODE_DOWN] || inputFlag == _vm->_keyMap[Common::KEYCODE_KP2]) {
+ newHighLightText = lastHighLightText + 1;
+ } else if (inputFlag == _vm->_keyMap[Common::KEYCODE_END] || inputFlag == _vm->_keyMap[Common::KEYCODE_KP1]) {
+ newHighLightText = menuSpellMap[lastHighLightButton * 11] - 1;
+ } else if (inputFlag == _vm->_keyMap[Common::KEYCODE_HOME] || inputFlag == _vm->_keyMap[Common::KEYCODE_KP7]) {
+ newHighLightText = 0;
+ } else if (inputFlag == 0x8017) {
+ if (numAssignedSpellsPerBookPage[lastHighLightButton]) {
+ for (int i = 1; i <= menuSpellMap[lastHighLightButton * 11]; i++) {
+ numAssignedSpellsPerBookPage[lastHighLightButton] -= _numAssignedSpellsOfType[menuSpellMap[lastHighLightButton * 11 + i] * 2 - 2];
+ _numAssignedSpellsOfType[menuSpellMap[lastHighLightButton * 11 + i] * 2 - 2] = 0;
+ }
+
+ updateDesc = updateList = true;
+ }
+
+ } else if (inputFlag == 0x8018) {
+ _vm->gui_drawAllCharPortraitsWithStats();
+ runLoop = false;
+
+ } else if (inputFlag & 0x8000) {
+ newHighLightButton = inputFlag - 0x801a;
+ if (newHighLightButton == lastHighLightButton)
+ drawMenuButton(_vm->gui_getButton(buttonList, inputFlag & 0x7fff), false, true, true);
+ }
+ }
+
+ releaseButtons(buttonList);
+ updateBoxFrameHighLight(-1);
+
+ _screen->setFont(Screen::FID_6_FNT);
+ _vm->gui_drawCharPortraitWithStats(charIndex);
+ _screen->setFont(Screen::FID_8_FNT);
+
+ memset(charSpellList, 0, 80);
+ if (spellType && _vm->game() == GI_EOB2)
+ charSpellList[0] = 29;
+
+ for (int i = 0; i < 32; i++) {
+ if (_numAssignedSpellsOfType[i * 2] < _numAssignedSpellsOfType[i * 2 + 1])
+ _numAssignedSpellsOfType[i * 2 + 1] = _numAssignedSpellsOfType[i * 2];
+
+ if (_numAssignedSpellsOfType[i * 2 + 1]) {
+ _numAssignedSpellsOfType[i * 2]--;
+ _numAssignedSpellsOfType[i * 2 + 1]--;
+
+ int pg = lh[i] - 1;
+ for (int ii = 0; ii < 10; ii++) {
+ if (!charSpellList[pg * 10 + ii]) {
+ charSpellList[pg * 10 + ii] = i + 1;
+ break;
+ }
+ }
+ i--;
+
+ } else if (_numAssignedSpellsOfType[i * 2]) {
+ _numAssignedSpellsOfType[i * 2]--;
+
+ _needRest = true;
+ int pg = lh[i] - 1;
+ for (int ii = 0; ii < 10; ii++) {
+ if (!charSpellList[pg * 10 + ii]) {
+ charSpellList[pg * 10 + ii] = -(i + 1);
+ break;
+ }
+ }
+ i--;
+ }
+ }
+
+ delete[] menuSpellMap;
+ delete[] numAssignedSpellsPerBookPage;
+ delete[] lh;
+}
+
+
+void GUI_EoB::scribeScrollDialogue() {
+ int16 *scrollInvSlot = new int16[32];
+ int16 *scrollCharacter = new int16[32];
+ int16 *menuItems = new int16[6];
+ int numScrolls = 0;
+
+ for (int i = 0; i < 32; i++) {
+ for (int ii = 0; ii < 6; ii++) {
+ scrollInvSlot[i] = _vm->checkInventoryForItem(ii, 34, i + 1) + 1;
+ if (scrollInvSlot[i] > 0) {
+ numScrolls++;
+ scrollCharacter[i] = ii;
+ break;
+ }
+ }
+ }
+
+ if (numScrolls) {
+ int csel = selectCharacterDialogue(49);
+ if (csel != -1) {
+
+ EoBCharacter *c = &_vm->_characters[csel];
+ int s = 0;
+
+ for (int i = 0; i < 32 && s < 6; i++) {
+ if (!scrollInvSlot[i])
+ continue;
+
+ if (c->mageSpellsAvailableFlags & (1 << i))
+ scrollInvSlot[i] = 0;
+ else
+ menuItems[s++] = i + 1;
+ }
+
+ if (s) {
+ Button *buttonList = 0;
+ bool redraw = true;
+ int lastHighLight = -1;
+ int newHighLight = 0;
+
+ while (s && !_vm->shouldQuit()) {
+ if (redraw) {
+ s = 0;
+ for (int i = 0; i < 32 && s < 6; i++) {
+ if (!scrollInvSlot[i])
+ continue;
+ menuItems[s++] = i + 1;
+ }
+
+ if (!s)
+ break;
+
+ releaseButtons(buttonList);
+ buttonList = initMenu(6);
+
+ for (int i = 0; i < s; i++)
+ _screen->printShadedText(_vm->_mageSpellList[menuItems[i]], 8, 9 * i + 50, 15, 0);
+
+ redraw = false;
+ lastHighLight = -1;
+ newHighLight = 0;
+ }
+
+ if (lastHighLight != newHighLight) {
+ if (lastHighLight >= 0)
+ _screen->printText(_vm->_mageSpellList[menuItems[lastHighLight]], 8, 9 * lastHighLight + 50, 15, 0);
+ lastHighLight = newHighLight;
+ _screen->printText(_vm->_mageSpellList[menuItems[lastHighLight]], 8, 9 * lastHighLight + 50, 6, 0);
+ _screen->updateScreen();
+ }
+
+ int inputFlag = _vm->checkInput(buttonList, false, 0);
+ _vm->removeInputTop();
+
+ if (inputFlag == 0) {
+ Common::Point p = _vm->getMousePos();
+ if (_vm->posWithinRect(p.x, p.y, 8, 50, 176, s * 9 + 49))
+ newHighLight = (p.y - 50) / 9;
+ } else if (inputFlag == _vm->_keyMap[Common::KEYCODE_KP2] || inputFlag == _vm->_keyMap[Common::KEYCODE_DOWN]) {
+ newHighLight = (newHighLight + 1) % s;
+ } else if (inputFlag == _vm->_keyMap[Common::KEYCODE_KP8] || inputFlag == _vm->_keyMap[Common::KEYCODE_UP]) {
+ newHighLight = (newHighLight + s - 1) % s;
+ } else if (inputFlag == 0x8023 || inputFlag == _vm->_keyMap[Common::KEYCODE_ESCAPE]) {
+ s = 0;
+ } else if (inputFlag == 0x8024) {
+ newHighLight = (_vm->_mouseY - 50) / 9;
+ if (newHighLight >= 0 && newHighLight < s) {
+ inputFlag = _vm->_keyMap[Common::KEYCODE_SPACE];
+ } else {
+ inputFlag = 0;
+ newHighLight = lastHighLight;
+ }
+ }
+
+ if (inputFlag == _vm->_keyMap[Common::KEYCODE_SPACE] || inputFlag == _vm->_keyMap[Common::KEYCODE_RETURN] || inputFlag == _vm->_keyMap[Common::KEYCODE_KP5]) {
+ int t = menuItems[newHighLight] - 1;
+ Item scItem = _vm->_characters[scrollCharacter[t]].inventory[scrollInvSlot[t] - 1];
+ c->mageSpellsAvailableFlags |= (1 << t);
+ _vm->_characters[scrollCharacter[t]].inventory[scrollInvSlot[t] - 1] = 0;
+ _vm->gui_drawCharPortraitWithStats(_vm->_characters[scrollCharacter[t]].id);
+ scrollInvSlot[t] = 0;
+ _vm->_items[scItem].block = -1;
+ redraw = true;
+ s--;
+ }
+ }
+
+ releaseButtons(buttonList);
+
+ } else {
+ displayTextBox(51);
+ }
+ }
+ } else {
+ displayTextBox(50);
+ }
+
+ delete[] menuItems;
+ delete[] scrollCharacter;
+ delete[] scrollInvSlot;
+}
+
+bool GUI_EoB::restParty() {
+ static const int8 eob1healSpells[] = { 2, 15, 20, 24 };
+ static const int8 eob2healSpells[] = { 3, 16, 20, 28 };
+ const int8 *spells = _vm->game() == GI_EOB1 ? eob1healSpells : eob2healSpells;
+
+ uint8 crs[6];
+ memset(crs, 0, 6);
+ int hours = 0;
+
+ if (_vm->_inf->preventRest()) {
+ assert(_vm->_menuStringsRest3[0]);
+ _vm->restParty_displayWarning(_vm->_menuStringsRest3[0]);
+ return true;
+ }
+
+ if (_vm->restParty_updateMonsters())
+ return true;
+
+ if (_vm->restParty_extraAbortCondition())
+ return true;
+
+ drawMenuButtonBox(_screen->_curDim->sx << 3, _screen->_curDim->sy, _screen->_curDim->w << 3, _screen->_curDim->h, false, false);
+
+ int nonPoisoned = 0;
+ for (int i = 0; i < 6; i++) {
+ if (!_vm->testCharacter(i, 1))
+ continue;
+ nonPoisoned |= _vm->testCharacter(i, 0x10);
+ }
+
+ if (!nonPoisoned) {
+ if (!confirmDialogue(59))
+ return false;
+ }
+
+ int8 *list = 0;
+ bool useHealers = false;
+ bool res = false;
+ bool restLoop = true;
+ bool restContinue = false;
+ int injured = _vm->restParty_getCharacterWithLowestHp();
+
+ if (injured > 0) {
+ for (int i = 0; i < 6; i++) {
+ if (!_vm->testCharacter(i, 13))
+ continue;
+ if (_vm->getCharacterLevelIndex(2, _vm->_characters[i].cClass) == -1 && _vm->getCharacterLevelIndex(4, _vm->_characters[i].cClass) == -1)
+ continue;
+ if (_vm->checkInventoryForItem(i, 30, -1) == -1)
+ continue;
+ if (_vm->restParty_checkHealSpells(i)) {
+ useHealers = confirmDialogue(40);
+ break;
+ }
+ }
+ }
+
+ _screen->setClearScreenDim(7);
+ _screen->setFont(Screen::FID_6_FNT);
+
+ restParty_updateRestTime(hours, true);
+
+ for (int l = 0; !res && restLoop && !_vm->shouldQuit();) {
+ l++;
+
+ // Regenerate spells
+ for (int i = 0; i < 6; i++) {
+ crs[i]++;
+
+ if (!_vm->_characters[i].food)
+ continue;
+ if (!_vm->testCharacter(i, 5))
+ continue;
+
+ if (_vm->checkInventoryForItem(i, 30, -1) != -1) {
+ list = _vm->_characters[i].clericSpells;
+
+ for (int ii = 0; ii < 80; ii++) {
+ if ((ii / 10 + 48) >= crs[i])
+ break;
+
+ if (*list >= 0) {
+ list++;
+ continue;
+ }
+
+ *list *= -1;
+ crs[i] = 48;
+ _vm->_txt->printMessage(Common::String::format(_vm->_menuStringsRest2[0], _vm->_characters[i].name, _vm->_spells[_vm->_clericSpellOffset + *list].name).c_str());
+ _vm->delay(80);
+ break;
+ }
+ }
+
+ if (_vm->checkInventoryForItem(i, 29, -1) != -1) {
+ list = _vm->_characters[i].mageSpells;
+
+ for (int ii = 0; ii < 80; ii++) {
+ if ((ii / 6 + 48) >= crs[i])
+ break;
+
+ if (*list >= 0) {
+ list++;
+ continue;
+ }
+
+ *list *= -1;
+ crs[i] = 48;
+ _vm->_txt->printMessage(Common::String::format(_vm->_menuStringsRest2[1], _vm->_characters[i].name, _vm->_spells[*list].name).c_str());
+ _vm->delay(80);
+ break;
+ }
+ }
+ }
+
+ // Heal party members
+ if (useHealers) {
+ for (int i = 0; i < 6 && injured; i++) {
+ if (_vm->getCharacterLevelIndex(2, _vm->_characters[i].cClass) == -1 && _vm->getCharacterLevelIndex(4, _vm->_characters[i].cClass) == -1)
+ continue;
+ if (_vm->checkInventoryForItem(i, 30, -1) == -1)
+ continue;
+
+ list = 0;
+ if (crs[i] >= 48) {
+ for (int ii = 0; !list && ii < 3; ii++)
+ list = (int8 *)memchr(_vm->_characters[i].clericSpells, -spells[ii], 80);
+ }
+
+ if (list)
+ break;
+
+ list = _vm->_characters[i].clericSpells;
+ for (int ii = 0; ii < 80 && injured; ii++) {
+ int healHp = 0;
+ if (*list == spells[0])
+ healHp = _vm->rollDice(1, 8, 0);
+ else if (*list == spells[1])
+ healHp = _vm->rollDice(2, 8, 1);
+ else if (*list == spells[2])
+ healHp = _vm->rollDice(3, 8, 3);
+
+ if (!healHp) {
+ list++;
+ continue;
+ }
+
+ *list *= -1;
+ list++;
+
+ crs[i] = 0;
+ injured--;
+
+ _vm->_txt->printMessage(Common::String::format(_vm->_menuStringsRest2[2], _vm->_characters[i].name, _vm->_characters[injured].name).c_str());
+ _vm->delay(80);
+
+ _vm->_characters[injured].hitPointsCur += healHp;
+ if (_vm->_characters[injured].hitPointsCur > _vm->_characters[injured].hitPointsMax)
+ _vm->_characters[injured].hitPointsCur = _vm->_characters[injured].hitPointsMax;
+
+ _vm->gui_drawCharPortraitWithStats(injured++);
+ }
+ }
+ }
+
+ if (l == 6) {
+ l = 0;
+ restParty_updateRestTime(++hours, false);
+ _vm->_restPartyElapsedTime += (32760 * _vm->_tickLength);
+
+ // Update poisoning
+ for (int i = 0; i < 6; i++) {
+ if (!_vm->testCharacter(i, 1))
+ continue;
+ if (_vm->testCharacter(i, 16))
+ continue;
+ _vm->inflictCharacterDamage(i, 10);
+ _vm->delayWithTicks(5);
+ }
+
+ if (!(hours % 8)) {
+ bool starving = false;
+ for (int i = 0; i < 6; i++) {
+ // Add Lay On Hands spell
+ if (_vm->_characters[i].cClass == 2) {
+ list = (int8 *)memchr(_vm->_characters[i].clericSpells, spells[3], 10);
+ if (list) {
+ *list = spells[3];
+ } else {
+ list = (int8 *)memchr(_vm->_characters[i].clericSpells, -spells[3], 10);
+ if (list) {
+ *list = spells[3];
+ } else if (!memchr(_vm->_characters[i].clericSpells, spells[3], 10)) {
+ list = (int8 *)memchr(_vm->_characters[i].clericSpells, 0, 10);
+ *list = spells[3];
+ }
+ }
+ }
+
+ if (!_vm->testCharacter(i, 3))
+ continue;
+
+ // Update hitpoints and food status
+ if (_vm->_characters[i].food) {
+ if (_vm->_characters[i].hitPointsCur < _vm->_characters[i].hitPointsMax) {
+ _vm->_characters[i].hitPointsCur++;
+ _screen->setFont(Screen::FID_6_FNT);
+ _vm->gui_drawCharPortraitWithStats(i);
+ }
+
+ if (!_vm->checkInventoryForRings(i, 2)) {
+ if (_vm->_characters[i].food <= 5) {
+ _vm->_characters[i].food = 0;
+ starving = true;
+ } else {
+ _vm->_characters[i].food -= 5;
+ }
+ }
+ } else {
+ if ((hours % 24) || (_vm->_characters[i].hitPointsCur <= -10))
+ continue;
+ _vm->inflictCharacterDamage(i, 1);
+ starving = true;
+ _screen->setFont(Screen::FID_6_FNT);
+ _vm->gui_drawCharPortraitWithStats(i);
+ }
+ }
+
+ if (starving) {
+ if (!confirmDialogue(47)) {
+ restContinue = false;
+ restLoop = false;
+ }
+ restParty_updateRestTime(hours, true);
+ }
+ injured = restLoop ? _vm->restParty_getCharacterWithLowestHp() : 0;
+ }
+ }
+
+ if (!_vm->restParty_checkSpellsToLearn() && restLoop && !restContinue && injured) {
+ restContinue = confirmDialogue(41);
+ restParty_updateRestTime(hours, true);
+ if (!restContinue)
+ restLoop = false;
+ }
+
+ int in = _vm->checkInput(0, false, 0);
+ _vm->removeInputTop();
+ if (in)
+ restLoop = false;
+
+ if (restLoop) {
+ res = _vm->restParty_updateMonsters();
+ if (!res)
+ res = _vm->checkPartyStatus(false);
+ }
+
+ if (!_vm->restParty_checkSpellsToLearn()) {
+ if (!restContinue) {
+ if (!useHealers)
+ restLoop = false;
+ }
+ if (!injured)
+ restLoop = false;
+ }
+ }
+
+ _vm->removeInputTop();
+ _screen->setScreenDim(4);
+ _screen->setFont(Screen::FID_8_FNT);
+
+ if (!res) {
+ if (!injured)
+ displayTextBox(43);
+ if (hours > 4)
+ _vm->restParty_npc();
+ }
+
+ return res;
+}
+
+bool GUI_EoB::confirmDialogue(int id) {
+ int od = _screen->curDimIndex();
+ Screen::FontId of = _screen->setFont(Screen::FID_8_FNT);
+
+ Button *buttonList = initMenu(5);
+
+ _screen->printShadedText(getMenuString(id), (_screen->_curDim->sx + 1) << 3, _screen->_curDim->sy + 4, 15, 0);
+
+ int newHighlight = 0;
+ int lastHighlight = -1;
+ bool result = false;
+
+ for (bool runLoop = true; runLoop && !_vm->shouldQuit();) {
+ if (newHighlight != lastHighlight) {
+ if (lastHighlight != -1)
+ drawMenuButton(_vm->gui_getButton(buttonList, lastHighlight + 33), false, false, true);
+ drawMenuButton(_vm->gui_getButton(buttonList, newHighlight + 33), false, true, true);
+ _screen->updateScreen();
+ lastHighlight = newHighlight;
+ }
+
+ int inputFlag = _vm->checkInput(buttonList, false, 0) & 0x80ff;
+ _vm->removeInputTop();
+
+ if (inputFlag == _vm->_keyMap[Common::KEYCODE_KP5] || inputFlag == _vm->_keyMap[Common::KEYCODE_SPACE] || inputFlag == _vm->_keyMap[Common::KEYCODE_RETURN]) {
+ result = lastHighlight == 0;
+ inputFlag = 0x8021 + lastHighlight;
+ runLoop = false;
+ } else if (inputFlag == _vm->_keyMap[Common::KEYCODE_KP4] || inputFlag == _vm->_keyMap[Common::KEYCODE_LEFT] || inputFlag == _vm->_keyMap[Common::KEYCODE_KP6] || inputFlag == _vm->_keyMap[Common::KEYCODE_RIGHT]) {
+ newHighlight ^= 1;
+ } else if (inputFlag == 0x8021) {
+ result = true;
+ runLoop = false;
+ } else if (inputFlag == 0x8022) {
+ result = false;
+ runLoop = false;
+ } else {
+ Common::Point p = _vm->getMousePos();
+ for (Button *b = buttonList; b; b = b->nextButton) {
+ if ((b->arg & 2) && _vm->posWithinRect(p.x, p.y, b->x, b->y, b->x + b->width, b->y + b->height))
+ newHighlight = b->index - 33;
+ }
+ }
+
+ if (!runLoop) {
+ Button *b = _vm->gui_getButton(buttonList, lastHighlight + 33);
+ drawMenuButton(b, true, true, true);
+ _screen->updateScreen();
+ _vm->_system->delayMillis(80);
+ drawMenuButton(b, false, true, true);
+ _screen->updateScreen();
+ }
+ }
+
+ releaseButtons(buttonList);
+
+ _screen->setFont(of);
+ _screen->setScreenDim(od);
+
+ return result;
+}
+
+int GUI_EoB::selectCharacterDialogue(int id) {
+ uint8 flags = (id == 26) ? (_vm->game() == GI_EOB1 ? 0x04 : 0x14) : 0x02;
+ _vm->removeInputTop();
+
+ _charSelectRedraw = false;
+ bool starvedUnconscious = false;
+ int count = 0;
+ int result = -1;
+ int found[6];
+
+ for (int i = 0; i < 6; i++) {
+ found[i] = -1;
+
+ if (!_vm->testCharacter(i, 1))
+ continue;
+
+ if (!(_vm->_classModifierFlags[_vm->_characters[i].cClass] & flags) && (id != 53))
+ continue;
+
+ if (id != 53 && (!_vm->_characters[i].food || !_vm->testCharacter(i, 4))) {
+ starvedUnconscious = true;
+ } else {
+ found[i] = 0;
+ result = i;
+ count++;
+ }
+ }
+
+ if (!count) {
+ int eid = 0;
+ if (id == 23)
+ eid = (starvedUnconscious || _vm->game() == GI_EOB1) ? 28 : 72;
+ else if (id == 26)
+ eid = (starvedUnconscious || _vm->game() == GI_EOB1) ? 27 : 73;
+ else if (id == 49)
+ eid = 52;
+
+ displayTextBox(eid);
+ return -1;
+ }
+
+ static const uint16 selX[] = { 184, 256, 184, 256, 184, 256 };
+ static const uint8 selY[] = { 2, 2, 54, 54, 106, 106};
+
+ for (int i = 0; i < 6; i++) {
+ if (found[i] != -1 || !_vm->testCharacter(i, 1))
+ continue;
+
+ _screen->drawShape(0, _vm->_blackBoxSmallGrid, selX[i], selY[i], 0);
+ _screen->drawShape(0, _vm->_blackBoxSmallGrid, selX[i] + 16, selY[i], 0);
+ _screen->drawShape(0, _vm->_blackBoxSmallGrid, selX[i] + 32, selY[i], 0);
+ _screen->drawShape(0, _vm->_blackBoxSmallGrid, selX[i] + 48, selY[i], 0);
+ _charSelectRedraw = true;
+ }
+
+ if (count == 1) {
+ int l = _vm->getCharacterLevelIndex(4, _vm->_characters[result].cClass);
+
+ if (l == -1)
+ return result;
+
+ if (_vm->_characters[result].level[l] > 8)
+ return result;
+
+ displayTextBox(24);
+ return -1;
+ }
+
+ _vm->_menuDefs[3].titleStrId = id;
+ Button *buttonList = initMenu(3);
+
+ result = -2;
+ int hlCur = -1;
+ Screen::FontId of = _screen->setFont(Screen::FID_6_FNT);
+
+ while (result == -2 && !_vm->shouldQuit()) {
+ int inputFlag = _vm->checkInput(buttonList, false, 0);
+ _vm->removeInputTop();
+
+ updateBoxFrameHighLight(hlCur);
+
+ if (inputFlag == _vm->_keyMap[Common::KEYCODE_KP4] || inputFlag == _vm->_keyMap[Common::KEYCODE_LEFT] || inputFlag == _vm->_keyMap[Common::KEYCODE_KP8] || inputFlag == _vm->_keyMap[Common::KEYCODE_UP] || inputFlag == _vm->_keyMap[Common::KEYCODE_a] || inputFlag == _vm->_keyMap[Common::KEYCODE_w]) {
+ updateBoxFrameHighLight(-1);
+ _vm->gui_drawCharPortraitWithStats(hlCur--);
+ if (hlCur < 0)
+ hlCur = 5;
+ while (found[hlCur]) {
+ if (--hlCur < 0)
+ hlCur = 5;
+ }
+
+ } else if (inputFlag == _vm->_keyMap[Common::KEYCODE_KP6] || inputFlag == _vm->_keyMap[Common::KEYCODE_RIGHT] || inputFlag == _vm->_keyMap[Common::KEYCODE_KP2] || inputFlag == _vm->_keyMap[Common::KEYCODE_DOWN] || inputFlag == _vm->_keyMap[Common::KEYCODE_z] || inputFlag == _vm->_keyMap[Common::KEYCODE_s]) {
+ updateBoxFrameHighLight(-1);
+ _vm->gui_drawCharPortraitWithStats(hlCur++);
+ if (hlCur == 6)
+ hlCur = 0;
+ while (found[hlCur]) {
+ if (++hlCur == 6)
+ hlCur = 0;
+ }
+
+ } else if (inputFlag == _vm->_keyMap[Common::KEYCODE_KP5] || inputFlag == _vm->_keyMap[Common::KEYCODE_RETURN]) {
+ if (hlCur >= 0)
+ result = hlCur;
+
+ } else if (inputFlag == _vm->_keyMap[Common::KEYCODE_ESCAPE] || inputFlag == 0x8010) {
+ _screen->setFont(Screen::FID_8_FNT);
+ drawMenuButton(buttonList, true, true, true);
+ _screen->updateScreen();
+ _vm->_system->delayMillis(80);
+ drawMenuButton(buttonList, false, false, true);
+ _screen->updateScreen();
+ _screen->setFont(Screen::FID_6_FNT);
+ result = -1;
+
+ } else if (inputFlag > 0x8010 && inputFlag < 0x8017) {
+ result = inputFlag - 0x8011;
+ if (found[result])
+ result = -2;
+ }
+ }
+
+ updateBoxFrameHighLight(-1);
+ if (hlCur >= 0)
+ _vm->gui_drawCharPortraitWithStats(hlCur);
+
+ _screen->setFont(Screen::FID_8_FNT);
+
+ if (result != -1 && id != 53) {
+ if (flags & 4) {
+ int lv = _vm->getCharacterLevelIndex(4, _vm->_characters[result].cClass);
+ if (lv != -1) {
+ if (_vm->_characters[result].level[lv] < 9) {
+ displayTextBox(24);
+ result = -1;
+ }
+ }
+ } else {
+ if (_vm->checkInventoryForItem(result, 29, -1) == -1) {
+ displayTextBox(25);
+ result = -1;
+ }
+ }
+ }
+
+ releaseButtons(buttonList);
+ _screen->setFont(of);
+
+ return result;
+}
+
+void GUI_EoB::displayTextBox(int id) {
+ int op = _screen->setCurPage(2);
+ int od = _screen->curDimIndex();
+ Screen::FontId of = _screen->setFont(Screen::FID_8_FNT);
+ _screen->setClearScreenDim(11);
+ const ScreenDim *dm = _screen->getScreenDim(11);
+
+ drawMenuButtonBox(dm->sx << 3, dm->sy, dm->w << 3, dm->h, false, false);
+ _screen->printShadedText(getMenuString(id), (dm->sx << 3) + 5, dm->sy + 5, 15, 0);
+ _screen->copyRegion(dm->sx << 3, dm->sy, dm->sx << 3, dm->sy, dm->w << 3, dm->h, 2, 0, Screen::CR_NO_P_CHECK);
+ _screen->updateScreen();
+
+ for (uint32 timeOut = _vm->_system->getMillis() + 1440; _vm->_system->getMillis() < timeOut && !_vm->shouldQuit();) {
+ int in = _vm->checkInput(0, false, 0);
+ _vm->removeInputTop();
+ if (in && !(in & 0x800))
+ break;
+ _vm->_system->delayMillis(4);
+ }
+
+ _screen->setCurPage(op);
+ _screen->setFont(of);
+ _screen->setScreenDim(od);
+}
+
+Button *GUI_EoB::initMenu(int id) {
+ _screen->setCurPage(2);
+
+ EoBMenuDef *m = &_vm->_menuDefs[id];
+
+ if (m->dim) {
+ const ScreenDim *dm = _screen->getScreenDim(m->dim);
+ _screen->fillRect(dm->sx << 3, dm->sy, ((dm->sx + dm->w) << 3) - 1, (dm->sy + dm->h) - 1, _vm->guiSettings()->colors.fill);
+ _screen->setScreenDim(m->dim);
+ drawMenuButtonBox(dm->sx << 3, dm->sy, dm->w << 3, dm->h, false, false);
+ }
+
+ _screen->printShadedText(getMenuString(m->titleStrId), 5, 5, m->titleCol, 0);
+
+ Button *buttons = 0;
+ for (int i = 0; i < m->numButtons; i++) {
+ const EoBMenuButtonDef *df = &_vm->_menuButtonDefs[m->firstButtonStrId + i];
+ Button *b = new Button;
+ b->index = m->firstButtonStrId + i + 1;
+ if (id == 4 && _vm->game() == GI_EOB1)
+ b->index -= 14;
+
+ b->data0Val2 = 12;
+ b->data1Val2 = b->data2Val2 = 15;
+ b->data3Val2 = 8;
+ b->flags = 0x1100;
+ b->keyCode = df->keyCode;
+ b->keyCode2 = df->keyCode | 0x100;
+ b->x = df->x;
+ b->y = df->y;
+ b->width = df->width;
+ b->height = df->height;
+ b->extButtonDef = df;
+ b->arg = df->flags;
+
+ drawMenuButton(b, false, false, false);
+ buttons = linkButton(buttons, b);
+ }
+
+ _screen->copyRegion(_screen->_curDim->sx << 3, _screen->_curDim->sy, _screen->_curDim->sx << 3, _screen->_curDim->sy, _screen->_curDim->w << 3, _screen->_curDim->h, 2, 0, Screen::CR_NO_P_CHECK);
+ _vm->gui_notifyButtonListChanged();
+ _screen->setCurPage(0);
+ _screen->updateScreen();
+
+ return buttons;
+}
+
+void GUI_EoB::drawMenuButton(Button *b, bool clicked, bool highlight, bool noFill) {
+ if (!b)
+ return;
+
+ const EoBMenuButtonDef *d = (const EoBMenuButtonDef *)b->extButtonDef;
+
+ if (d->flags & 1)
+ drawMenuButtonBox(b->x, b->y, b->width, b->height, clicked, noFill);
+
+ if (d->labelId) {
+ const char *s = getMenuString(d->labelId);
+
+ int xOffs = 4;
+ int yOffs = 3;
+
+ if (d->flags & 4) {
+ xOffs = ((b->width - (strlen(s) << 3)) >> 1) + 1;
+ yOffs = (b->height - 7) >> 1;
+ }
+
+ int col1 = (_vm->_configRenderMode == Common::kRenderCGA) ? 1 : 15;
+
+ if (noFill || clicked)
+ _screen->printText(s, b->x + xOffs, b->y + yOffs, highlight ? 6 : col1, 0);
+ else
+ _screen->printShadedText(s, b->x + xOffs, b->y + yOffs, highlight ? 6 : col1, 0);
+ }
+}
+
+void GUI_EoB::drawMenuButtonBox(int x, int y, int w, int h, bool clicked, bool noFill) {
+ uint8 col1 = _vm->guiSettings()->colors.frame1;
+ uint8 col2 = _vm->guiSettings()->colors.frame2;
+
+ if (clicked)
+ col1 = col2 = _vm->guiSettings()->colors.fill;
+
+ _vm->gui_drawBox(x, y, w, h, col1, col2, -1);
+ _vm->gui_drawBox(x + 1, y + 1, w - 2, h - 2, _vm->guiSettings()->colors.frame1, _vm->guiSettings()->colors.frame2, noFill ? -1 : _vm->guiSettings()->colors.fill);
+}
+
+void GUI_EoB::drawTextBox(int dim, int id) {
+ int od = _screen->curDimIndex();
+ _screen->setScreenDim(dim);
+ const ScreenDim *dm = _screen->getScreenDim(dim);
+ Screen::FontId of = _screen->setFont(Screen::FID_8_FNT);
+
+ if (dm->w <= 22 && dm->h <= 84)
+ _screen->copyRegion(dm->sx << 3, dm->sy, 0, dm->h, dm->w << 3, dm->h, 0, 2, Screen::CR_NO_P_CHECK);
+
+ _screen->setCurPage(2);
+
+ drawMenuButtonBox(0, 0, dm->w << 3, dm->h, false, false);
+ _screen->printShadedText(getMenuString(id), 5, 5, 15, 0);
+
+ _screen->setCurPage(0);
+ _screen->copyRegion(0, 0, dm->sx << 3, dm->sy, dm->w << 3, dm->h, 2, 0, Screen::CR_NO_P_CHECK);
+ _screen->updateScreen();
+ _screen->setScreenDim(od);
+ _screen->setFont(of);
+}
+
+void GUI_EoB::drawSaveSlotButton(int slot, int redrawBox, int textCol) {
+ if (slot < 0)
+ return;
+
+ int x = _saveSlotX + 4;
+ int y = _saveSlotY + slot * 17 + 20;
+ int w = 167;
+ const char *s = (slot < 6) ? _saveSlotStringsTemp[slot] : _vm->_saveLoadStrings[0];
+
+ if (slot >= 6) {
+ x = _saveSlotX + 118;
+ y = _saveSlotY + 126;
+ w = 53;
+ }
+
+ if (redrawBox)
+ drawMenuButtonBox(x, y, w, 14, (redrawBox - 1) ? true : false, false);
+
+ _screen->printShadedText(s, x + 4, y + 3, textCol, 0);
+}
+
+void GUI_EoB::memorizePrayMenuPrintString(int spellId, int bookPageIndex, int spellType, bool noFill, bool highLight) {
+ if (bookPageIndex < 0)
+ return;
+
+ int y = bookPageIndex * 9 + 50;
+ int col1 = (_vm->_configRenderMode == Common::kRenderCGA) ? 1 : 15;
+
+ if (spellId) {
+ Common::String s(Common::String::format(_vm->_menuStringsMgc[0], spellType ? _vm->_clericSpellList[spellId] : _vm->_mageSpellList[spellId], _numAssignedSpellsOfType[spellId * 2 - 2]));
+ if (noFill)
+ _screen->printText(s.c_str(), 8, y, highLight ? 6 : col1, 0);
+ else
+ _screen->printShadedText(s.c_str(), 8, y, highLight ? 6 : col1, _vm->guiSettings()->colors.fill);
+
+ } else {
+ _screen->fillRect(6, y, 168, y + 8, _vm->guiSettings()->colors.fill);
+ }
+}
+
+void GUI_EoB::updateOptionsStrings() {
+ for (int i = 0; i < 4; i++) {
+ delete[] _menuStringsPrefsTemp[i];
+ _menuStringsPrefsTemp[i] = new char[strlen(_vm->_menuStringsPrefs[i]) + 8];
+ }
+
+ Common::strlcpy(_menuStringsPrefsTemp[0], Common::String::format(_vm->_menuStringsPrefs[0], _vm->_menuStringsOnOff[_vm->_configMusic ? 0 : 1]).c_str(), strlen(_vm->_menuStringsPrefs[0]) + 8);
+ Common::strlcpy(_menuStringsPrefsTemp[1], Common::String::format(_vm->_menuStringsPrefs[1], _vm->_menuStringsOnOff[_vm->_configSounds ? 0 : 1]).c_str(), strlen(_vm->_menuStringsPrefs[1]) + 8);
+ Common::strlcpy(_menuStringsPrefsTemp[2], Common::String::format(_vm->_menuStringsPrefs[2], _vm->_menuStringsOnOff[_vm->_configHpBarGraphs ? 0 : 1]).c_str(), strlen(_vm->_menuStringsPrefs[2]) + 8);
+ Common::strlcpy(_menuStringsPrefsTemp[3], Common::String::format(_vm->_menuStringsPrefs[3], _vm->_menuStringsOnOff[_vm->_configMouse ? 0 : 1]).c_str(), strlen(_vm->_menuStringsPrefs[3]) + 8);
+}
+
+const char *GUI_EoB::getMenuString(int id) {
+ static const char empty[] = "";
+
+ if (id >= 69)
+ return _vm->_menuStringsTransfer[id - 69];
+ else if (id == 68)
+ return _vm->_transferStringsScummVM[0];
+ else if (id == 67)
+ return _vm->_menuStringsDefeat[0];
+ else if (id == 66)
+ return _vm->_errorSlotEmptyString;
+ else if (id == 65)
+ return _vm->_errorSlotEmptyString;
+ else if (id >= 63)
+ return _vm->_menuStringsSpec[id - 63];
+ else if (id >= 60)
+ return _vm->_menuStringsSpellNo[id - 60];
+ else if (id == 59)
+ return _vm->_menuStringsPoison[0];
+ else if (id >= 56)
+ return _vm->_menuStringsHead[id - 56];
+ else if (id == 55)
+ return _vm->_menuStringsDrop2[_vm->game() == GI_EOB1 ? 1 : 2];
+ else if (id == 54)
+ return _vm->_errorSlotNoNameString;
+ else if (id == 53)
+ return _vm->_menuStringsDrop2[0];
+ else if (id >= 48)
+ return _vm->_menuStringsScribe[id - 48];
+ else if (id == 47)
+ return _vm->_menuStringsStarve[0];
+ else if (id == 46)
+ return _vm->_menuStringsExit[0];
+ else if (id == 45)
+ return _vm->_menuStringsDrop[0];
+ else if (id >= 40)
+ return _vm->_menuStringsRest[id - 40];
+ else if (id >= 23)
+ return _vm->_menuStringsSpells[id - 23];
+ else if (id >= 21)
+ return _vm->_menuStringsOnOff[id - 21];
+ else if (id >= 17)
+ return _menuStringsPrefsTemp[id - 17];
+ else if (id >= 9)
+ return _vm->_menuStringsSaveLoad[id - 9];
+ else if (id >= 1)
+ return _vm->_menuStringsMain[id - 1];
+ else if (id < 0)
+ return _vm->_transferStringsScummVM[-id];
+ return empty;
+}
+
+Button *GUI_EoB::linkButton(Button *list, Button *newbt) {
+ if (!list) {
+ list = newbt;
+ return list;
+ }
+
+ if (!newbt)
+ return list;
+
+ Button *resList = list;
+ while (list->nextButton)
+ list = list->nextButton;
+ list->nextButton = newbt;
+ newbt->nextButton = 0;
+
+ return resList;
+}
+
+void GUI_EoB::releaseButtons(Button *list) {
+ while (list) {
+ Button *n = list->nextButton;
+ delete list;
+ list = n;
+ }
+ _vm->gui_notifyButtonListChanged();
+}
+
+void GUI_EoB::setupSaveMenuSlots() {
+ for (int i = 0; i < 6; ++i) {
+ if (_savegameOffset + i < _savegameListSize) {
+ if (_savegameList[i + _savegameOffset]) {
+ Common::strlcpy(_saveSlotStringsTemp[i], _savegameList[i + _savegameOffset], 20);
+ _saveSlotIdTemp[i] = i + _savegameOffset;
+ continue;
+ }
+ }
+ Common::strlcpy(_saveSlotStringsTemp[i], _vm->_saveLoadStrings[1], 20);
+ _saveSlotIdTemp[i] = -1;
+ }
+}
+
+int GUI_EoB::getHighlightSlot() {
+ int res = -1;
+ Common::Point p = _vm->getMousePos();
+
+ for (int i = 0; i < 6; i++) {
+ int y = _saveSlotY + i * 17 + 20;
+ if (_vm->posWithinRect(p.x, p.y, _saveSlotX + 4, y, _saveSlotX + 167, y + 14)) {
+ res = i;
+ break;
+ }
+ }
+
+ if (_vm->posWithinRect(p.x, p.y, _saveSlotX + 118, _saveSlotY + 126, _saveSlotX + 171, _saveSlotY + 140))
+ res = 6;
+
+ return res;
+}
+
+void GUI_EoB::sortSaveSlots() {
+ Common::sort(_saveSlots.begin(), _saveSlots.end(), Common::Less<int>());
+}
+
+void GUI_EoB::restParty_updateRestTime(int hours, bool init) {
+ Screen::FontId of = _screen->setFont(Screen::FID_8_FNT);
+ int od = _screen->curDimIndex();
+ _screen->setScreenDim(10);
+
+ if (init) {
+ _screen->setCurPage(0);
+ _vm->_txt->clearCurDim();
+ drawMenuButtonBox(_screen->_curDim->sx << 3, _screen->_curDim->sy, _screen->_curDim->w << 3, _screen->_curDim->h, false, false);
+ _screen->copyRegion(_screen->_curDim->sx << 3, _screen->_curDim->sy, _screen->_curDim->sx << 3, _screen->_curDim->sy, _screen->_curDim->w << 3, _screen->_curDim->h, 0, 2, Screen::CR_NO_P_CHECK);
+ _screen->printShadedText(getMenuString(42), (_screen->_curDim->sx + 1) << 3, _screen->_curDim->sy + 5, 9, 0);
+ }
+
+ _screen->setCurPage(2);
+ _screen->printShadedText(Common::String::format(_vm->_menuStringsRest2[3], hours).c_str(), (_screen->_curDim->sx + 1) << 3, _screen->_curDim->sy + 20, 15, _vm->guiSettings()->colors.fill);
+ _screen->setCurPage(0);
+ _screen->copyRegion(((_screen->_curDim->sx + 1) << 3) - 1, _screen->_curDim->sy + 20, ((_screen->_curDim->sx + 1) << 3) - 1, _screen->_curDim->sy + 20, 144, 8, 2, 0, Screen::CR_NO_P_CHECK);
+ _screen->updateScreen();
+
+ _vm->delay(160);
+
+ _screen->setScreenDim(od);
+ _screen->setFont(of);
+}
+
+const EoBRect16 GUI_EoB::_highlightFrames[] = {
+ { 0x00B7, 0x0001, 0x00F7, 0x0034 },
+ { 0x00FF, 0x0001, 0x013F, 0x0034 },
+ { 0x00B7, 0x0035, 0x00F7, 0x0068 },
+ { 0x00FF, 0x0035, 0x013F, 0x0068 },
+ { 0x00B7, 0x0069, 0x00F7, 0x009C },
+ { 0x00FF, 0x0069, 0x013F, 0x009C },
+ { 0x0010, 0x003F, 0x0030, 0x0060 },
+ { 0x0050, 0x003F, 0x0070, 0x0060 },
+ { 0x0010, 0x007F, 0x0030, 0x00A0 },
+ { 0x0050, 0x007F, 0x0070, 0x00A0 },
+ { 0x00B0, 0x0042, 0x00D0, 0x0061 },
+ { 0x00D0, 0x0042, 0x00F0, 0x0061 },
+ { 0x00F0, 0x0042, 0x0110, 0x0061 },
+ { 0x0110, 0x0042, 0x0130, 0x0061 },
+ { 0x0004, 0x0018, 0x0024, 0x0039 },
+ { 0x00A3, 0x0018, 0x00C3, 0x0039 },
+ { 0x0004, 0x0040, 0x0024, 0x0061 },
+ { 0x00A3, 0x0040, 0x00C3, 0x0061 },
+ { 0x0004, 0x0068, 0x0024, 0x0089 },
+ { 0x00A3, 0x0068, 0x00C3, 0x0089 }
+};
+
+const uint8 GUI_EoB::_highlightColorTableVGA[] = { 0x0F, 0xB0, 0xB2, 0xB4, 0xB6, 0xB8, 0xBA, 0xBC, 0x0C, 0xBC, 0xBA, 0xB8, 0xB6, 0xB4, 0xB2, 0xB0, 0x00 };
+
+const uint8 GUI_EoB::_highlightColorTableEGA[] = { 0x0C, 0x0D, 0x0E, 0x0F, 0x0E, 0x0D, 0x00 };
+
+} // End of namespace Kyra
+
+#endif // ENABLE_EOB