aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Gilbert2015-01-30 19:18:43 -0500
committerPaul Gilbert2015-01-30 19:18:43 -0500
commit29753a29a4b82d8cac78223232dc84c003d8f210 (patch)
treed25360ef31ae4650facfd70191eb74446d5851e1
parentbe327cb7672652a44294a13b9fa4215ae6358b6a (diff)
downloadscummvm-rg350-29753a29a4b82d8cac78223232dc84c003d8f210.tar.gz
scummvm-rg350-29753a29a4b82d8cac78223232dc84c003d8f210.tar.bz2
scummvm-rg350-29753a29a4b82d8cac78223232dc84c003d8f210.zip
XEEN: Implemented SpellsDialog and ConfirmDialog classes
-rw-r--r--engines/xeen/dialogs_confirm.cpp85
-rw-r--r--engines/xeen/dialogs_confirm.h43
-rw-r--r--engines/xeen/dialogs_spells.cpp416
-rw-r--r--engines/xeen/dialogs_spells.h61
-rw-r--r--engines/xeen/dialogs_yesno.cpp4
-rw-r--r--engines/xeen/module.mk1
-rw-r--r--engines/xeen/party.cpp66
-rw-r--r--engines/xeen/party.h5
-rw-r--r--engines/xeen/resources.cpp47
-rw-r--r--engines/xeen/resources.h20
-rw-r--r--engines/xeen/spells.cpp2
-rw-r--r--engines/xeen/spells.h1
-rw-r--r--engines/xeen/town.cpp86
-rw-r--r--engines/xeen/town.h4
14 files changed, 755 insertions, 86 deletions
diff --git a/engines/xeen/dialogs_confirm.cpp b/engines/xeen/dialogs_confirm.cpp
new file mode 100644
index 0000000000..13a41e76ca
--- /dev/null
+++ b/engines/xeen/dialogs_confirm.cpp
@@ -0,0 +1,85 @@
+/* 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.
+ *
+ */
+
+#include "xeen/dialogs_confirm.h"
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+bool ConfirmDialog::show(XeenEngine *vm, const Common::String &msg, int v2) {
+ ConfirmDialog *dlg = new ConfirmDialog(vm);
+ bool result = dlg->execute(msg, v2);
+ delete dlg;
+
+ return result;
+}
+
+bool ConfirmDialog::execute(const Common::String &msg, int v2) {
+ Screen &screen = *_vm->_screen;
+ EventsManager &events = *_vm->_events;
+ SpriteResource confirmSprites;
+ confirmSprites.load("confirm.icn");
+
+ addButton(Common::Rect(129, 112, 153, 132), Common::KEYCODE_y, &confirmSprites);
+ addButton(Common::Rect(185, 112, 209, 132), Common::KEYCODE_n, &confirmSprites);
+
+ Window &w = screen._windows[v2 ? 21 : 22];
+ w.open();
+
+ if (v2) {
+ confirmSprites.draw(screen._windows[21], 0, Common::Point(129, 112));
+ confirmSprites.draw(screen._windows[21], 2, Common::Point(185, 112));
+
+ _buttons[0]._bounds.moveTo(129, 112);
+ _buttons[1]._bounds.moveTo(185, 112);
+ } else if (v2 & 0x80) {
+ clearButtons();
+ } else {
+ confirmSprites.draw(screen._windows[22], 0, Common::Point(120, 133));
+ confirmSprites.draw(screen._windows[22], 2, Common::Point(176, 133));
+
+ _buttons[0]._bounds.moveTo(120, 133);
+ _buttons[1]._bounds.moveTo(176, 133);
+ }
+
+ w.writeString(msg);
+ w.update();
+
+ bool result = false;
+ while (!_vm->shouldQuit()) {
+ while (!events.isKeyMousePressed())
+ events.pollEventsAndWait();
+
+ if ((v2 & 0x80) || _buttonValue == Common::KEYCODE_ESCAPE ||
+ _buttonValue == Common::KEYCODE_y)
+ break;
+ else if (_buttonValue == Common::KEYCODE_y) {
+ result = true;
+ break;
+ }
+ }
+
+ w.close();
+ return result;
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/dialogs_confirm.h b/engines/xeen/dialogs_confirm.h
new file mode 100644
index 0000000000..825be5e764
--- /dev/null
+++ b/engines/xeen/dialogs_confirm.h
@@ -0,0 +1,43 @@
+/* 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.
+ *
+ */
+
+#ifndef XEEN_DIALOGS_CONFIRM_H
+#define XEEN_DIALOGS_CONFIRM_H
+
+#include "xeen/dialogs.h"
+
+namespace Xeen {
+
+class ConfirmDialog : public ButtonContainer {
+private:
+ XeenEngine *_vm;
+
+ ConfirmDialog(XeenEngine *vm) : ButtonContainer(), _vm(vm) {}
+
+ bool execute(const Common::String &msg, int v2);
+public:
+ static bool show(XeenEngine *vm, const Common::String &msg, int v2);
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_DIALOGS_CONFIRM_H */
diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp
new file mode 100644
index 0000000000..7ae5e7ad90
--- /dev/null
+++ b/engines/xeen/dialogs_spells.cpp
@@ -0,0 +1,416 @@
+/* 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.
+ *
+ */
+
+#include "xeen/dialogs_spells.h"
+#include "xeen/dialogs_confirm.h"
+#include "xeen/resources.h"
+#include "xeen/spells.h"
+#include "xeen/sprites.h"
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+Character *SpellsScroll::show(XeenEngine *vm, Character *c, int v2) {
+ SpellsScroll *dlg = new SpellsScroll(vm);
+ Character *result = dlg->execute(c, v2);
+ delete dlg;
+
+ return result;
+}
+
+Character *SpellsScroll::execute(Character *c, int v2) {
+ EventsManager &events = *_vm->_events;
+ Interface &intf = *_vm->_interface;
+ Party &party = *_vm->_party;
+ Screen &screen = *_vm->_screen;
+ SoundManager &sound = *_vm->_sound;
+ Spells &spells = *_vm->_spells;
+ bool isDarkCc = _vm->_files->_isDarkCc;
+ loadButtons();
+
+ int v2Copy = v2;
+ v2 &= 0x7f;
+ int selection = -1;
+ int topIndex = 0;
+ int newSelection;
+ screen._windows[25].open();
+
+ while (!_vm->shouldQuit()) {
+ if (!v2) {
+ if (!c->guildMember()) {
+ sound.playSample(nullptr, 0);
+ intf._overallFrame = 5;
+ File f(isDarkCc ? "skull1.voc" : "guild11.voc");
+ sound.playSample(&f, 1);
+ break;
+ }
+
+ Common::String title = Common::String::format(BUY_SPELLS, c->_name.c_str());
+ Common::String msg = Common::String::format(GUILD_OPTIONS,
+ title.c_str(), XeenEngine::printMil(party._gold));
+ screen._windows[10].writeString(msg);
+
+ warning("TODO: Sprite draw using previously used button sprites");
+ }
+
+ _spells.clear();
+ const char *errorMsg = setSpellText(c, v2Copy);
+ screen._windows[25].writeString(Common::String::format(SPELLS_FOR,
+ errorMsg == nullptr ? SPELL_LINES_0_TO_9 : nullptr));
+
+ screen._windows[37].writeString(Common::String::format(SPELLS_DIALOG_SPELLS,
+ (topIndex + 0) < _spells.size() ? _spells[topIndex + 0]._name.c_str() : nullptr,
+ (topIndex + 1) < _spells.size() ? _spells[topIndex + 1]._name.c_str() : nullptr,
+ (topIndex + 2) < _spells.size() ? _spells[topIndex + 2]._name.c_str() : nullptr,
+ (topIndex + 3) < _spells.size() ? _spells[topIndex + 3]._name.c_str() : nullptr,
+ (topIndex + 4) < _spells.size() ? _spells[topIndex + 4]._name.c_str() : nullptr,
+ (topIndex + 5) < _spells.size() ? _spells[topIndex + 5]._name.c_str() : nullptr,
+ (topIndex + 6) < _spells.size() ? _spells[topIndex + 6]._name.c_str() : nullptr,
+ (topIndex + 7) < _spells.size() ? _spells[topIndex + 7]._name.c_str() : nullptr,
+ (topIndex + 8) < _spells.size() ? _spells[topIndex + 8]._name.c_str() : nullptr,
+ (topIndex + 9) < _spells.size() ? _spells[topIndex + 9]._name.c_str() : nullptr,
+ v2 ? SPELL_PTS : GOLD,
+ v2 ? c->_currentSp : party._gold
+ ));
+
+ _iconSprites.draw(screen, 4, Common::Point(39, 26));
+ _iconSprites.draw(screen, 0, Common::Point(187, 26));
+ _iconSprites.draw(screen, 2, Common::Point(187, 111));
+ if (v2)
+ _iconSprites.draw(screen._windows[25], 5, Common::Point(132, 123));
+
+ screen._windows[25].update();
+
+ while (!_vm->shouldQuit() && !events.isKeyMousePressed())
+ events.pollEventsAndWait();
+ if (_vm->shouldQuit())
+ break;
+ checkEvents(_vm);
+
+ switch (_buttonValue) {
+ case Common::KEYCODE_F1:
+ case Common::KEYCODE_F6:
+ if (_vm->_mode != MODE_2) {
+ _buttonValue -= Common::KEYCODE_F1;
+ if (_buttonValue < party._partyCount) {
+ c = &party._activeParty[_buttonValue];
+ spells._lastCaster = _buttonValue;
+ intf.highlightChar(_buttonValue);
+
+ if (_vm->_mode == MODE_17) {
+ screen._windows[10].writeString(Common::String::format(GUILD_OPTIONS,
+ XeenEngine::printMil(party._gold).c_str(), GUILD_TEXT, c->_name.c_str()));
+ } else {
+ int category;
+ switch (c->_class) {
+ case CLASS_ARCHER:
+ case CLASS_SORCERER:
+ category = 1;
+ break;
+ case CLASS_DRUID:
+ case CLASS_RANGER:
+ category = 2;
+ break;
+ default:
+ category = 0;
+ break;
+ }
+
+ int spellIndex = (c->_currentSp == -1) ? 39 : c->_currentSpell;
+ int spellId = SPELLS_ALLOWED[category][spellIndex];
+ screen._windows[10].writeString(Common::String::format(SPELL_DETAILS,
+ spells._spellNames[spellId].c_str(),
+ spells.calcSpellPoints(spellId, c->getCurrentLevel()),
+ SPELL_GEM_COST[spellId], c->_currentSp));
+ }
+
+ drawButtons(&screen);
+ screen._windows[10].update();
+ }
+ }
+ break;
+
+ case Common::KEYCODE_RETURN:
+ case Common::KEYCODE_KP_ENTER:
+ case Common::KEYCODE_s:
+ if (selection != -1)
+ _buttonValue = Common::KEYCODE_ESCAPE;
+ break;
+
+ case Common::KEYCODE_ESCAPE:
+ selection = -1;
+ _buttonValue = Common::KEYCODE_ESCAPE;
+ break;
+
+ case Common::KEYCODE_0:
+ case Common::KEYCODE_1:
+ case Common::KEYCODE_2:
+ case Common::KEYCODE_3:
+ case Common::KEYCODE_4:
+ case Common::KEYCODE_5:
+ case Common::KEYCODE_6:
+ case Common::KEYCODE_7:
+ case Common::KEYCODE_8:
+ case Common::KEYCODE_9:
+ newSelection = topIndex + (_buttonValue == Common::KEYCODE_0) ? 9 :
+ (_buttonValue - Common::KEYCODE_1);
+
+ if (newSelection < (int)_spells.size()) {
+ int expenseFactor = 0;
+ int category = 0;
+
+ switch (c->_class) {
+ case CLASS_PALADIN:
+ expenseFactor = 1;
+ category = 0;
+ break;
+ case CLASS_ARCHER:
+ expenseFactor = 1;
+ category = 1;
+ break;
+ case CLASS_CLERIC:
+ category = 0;
+ break;
+ case CLASS_SORCERER:
+ category = 1;
+ break;
+ case CLASS_DRUID:
+ category = 2;
+ break;
+ case CLASS_RANGER:
+ expenseFactor = 1;
+ category = 2;
+ break;
+ default:
+ break;
+ }
+
+ int spellId = _spells[newSelection]._spellId;
+ int spellIndex = _spells[newSelection]._spellIndex;
+ int spellCost = spells.calcSpellCost(spellId, expenseFactor);
+ if (v2) {
+ // TODO: Confirm this refactoring against against original
+ selection = _buttonValue;
+ } else {
+ Common::String spellName = _spells[_buttonValue]._name;
+ Common::String msg = (v2Copy & 0x80) ?
+ Common::String::format(SPELLS_PRESS_A_KEY, msg.c_str()) :
+ Common::String::format(SPELLS_PURCHASE, msg.c_str(), spellCost);
+
+ if (ConfirmDialog::show(_vm, msg, v2Copy + 1)) {
+ if (party.subtract(0, spellCost, 0, WT_FREEZE_WAIT)) {
+ ++c->_spells[spellIndex];
+ sound.playSample(nullptr, 0);
+ intf._overallFrame = 0;
+ File f(isDarkCc ? "guild12.voc" : "parrot2.voc");
+ sound.playSample(&f, 1);
+ } else {
+ sound.playFX(21);
+ }
+ }
+ }
+ }
+ break;
+
+ case Common::KEYCODE_PAGEUP:
+ case Common::KEYCODE_KP9:
+ topIndex = MAX(topIndex - 10, 0);
+ break;
+
+ case Common::KEYCODE_PAGEDOWN:
+ case Common::KEYCODE_KP3:
+ topIndex = MIN(topIndex + 10, (((int)_spells.size() - 1) / 10) * 10);
+ break;
+
+ case Common::KEYCODE_UP:
+ case Common::KEYCODE_KP8:
+ if (topIndex > 0)
+ --topIndex;
+ break;
+
+ case Common::KEYCODE_DOWN:
+ case Common::KEYCODE_KP2:
+ if (topIndex < ((int)_spells.size() - 10))
+ ++topIndex;
+ break;
+ }
+ }
+
+ screen._windows[25].close();
+ if (v2 && selection != -1)
+ c->_currentSpell = _spells[selection]._spellIndex;
+
+ return c;
+}
+
+void SpellsScroll::loadButtons() {
+ _iconSprites.load("main.icn");
+ _scrollSprites.load("scroll.icn");
+ addButton(Common::Rect(187, 26, 198, 36), Common::KEYCODE_UP, &_scrollSprites, true);
+ addButton(Common::Rect(187, 111, 198, 121), Common::KEYCODE_DOWN, &_scrollSprites, true);
+ addButton(Common::Rect(40, 28, 187, 36), Common::KEYCODE_1, &_scrollSprites, false);
+ addButton(Common::Rect(40, 37, 187, 45), Common::KEYCODE_2, &_scrollSprites, false);
+ addButton(Common::Rect(40, 46, 187, 54), Common::KEYCODE_3, &_scrollSprites, false);
+ addButton(Common::Rect(40, 55, 187, 63), Common::KEYCODE_4, &_scrollSprites, false);
+ addButton(Common::Rect(40, 64, 187, 72), Common::KEYCODE_5, &_scrollSprites, false);
+ addButton(Common::Rect(40, 73, 187, 81), Common::KEYCODE_6, &_scrollSprites, false);
+ addButton(Common::Rect(40, 82, 187, 90), Common::KEYCODE_7, &_scrollSprites, false);
+ addButton(Common::Rect(40, 91, 187, 99), Common::KEYCODE_8, &_scrollSprites, false);
+ addButton(Common::Rect(40, 100, 187, 108), Common::KEYCODE_9, &_scrollSprites, false);
+ addButton(Common::Rect(40, 109, 187, 117), Common::KEYCODE_0, &_scrollSprites, false);
+ addButton(Common::Rect(174, 123, 198, 133), Common::KEYCODE_ESCAPE, &_scrollSprites, false);
+ addButton(Common::Rect(187, 35, 198, 73), Common::KEYCODE_PAGEUP, &_scrollSprites, false);
+ addButton(Common::Rect(187, 74, 198, 112), Common::KEYCODE_PAGEDOWN, &_scrollSprites, false);
+ addButton(Common::Rect(132, 123, 168, 133), Common::KEYCODE_s, &_scrollSprites, false);
+}
+
+const char *SpellsScroll::setSpellText(Character *c, int v2) {
+ Party &party = *_vm->_party;
+ Spells &spells = *_vm->_spells;
+ bool isDarkCc = _vm->_files->_isDarkCc;
+ int expenseFactor = 0;
+ int currLevel = c->getCurrentLevel();
+ int category;
+
+ if ((v2 & 0x7f) == 0) {
+ switch (c->_class) {
+ case CLASS_PALADIN:
+ expenseFactor = 1;
+ category = 0;
+ break;
+ case CLASS_ARCHER:
+ expenseFactor = 1;
+ category = 1;
+ break;
+ case CLASS_CLERIC:
+ category = 0;
+ break;
+ case CLASS_SORCERER:
+ category = 1;
+ break;
+ case CLASS_DRUID:
+ category = 2;
+ break;
+ case CLASS_RANGER:
+ expenseFactor = 1;
+ category = 2;
+ break;
+ default:
+ category = -1;
+ break;
+ }
+
+ if (category != -1) {
+ if (party._mazeId == 49 || party._mazeId == 37) {
+ for (int spellId = 0; spellId < 76; ++spellId) {
+ int idx = 0;
+ while (idx < MAX_SPELLS_PER_CLASS && SPELLS_ALLOWED[category][idx] == spellId)
+ ++idx;
+
+ // Handling if the spell is appropriate for the character's class
+ if (idx < MAX_SPELLS_PER_CLASS) {
+ if (!c->_spells[idx] || (v2 & 0x80)) {
+ int cost = spells.calcSpellCost(SPELLS_ALLOWED[category][idx], expenseFactor);
+ _spells.push_back(SpellEntry(Common::String::format("\x3l%s\x3r\x9""000%u",
+ spells._spellNames[SPELLS_ALLOWED[category][idx]], cost),
+ idx, spellId));
+ }
+ }
+ }
+ } else if (isDarkCc) {
+ int groupIndex = (party._mazeId - 29) / 2;
+ for (int spellId = DARK_SPELL_RANGES[category][0];
+ spellId < DARK_SPELL_RANGES[category][1]; ++spellId) {
+ int idx = 0;
+ while (idx < 40 && SPELLS_ALLOWED[category][idx] ==
+ DARK_SPELL_OFFSETS[category][spellId]);
+
+ if (idx < 40) {
+ if (!c->_spells[idx] || (v2 & 0x80)) {
+ int cost = spells.calcSpellCost(SPELLS_ALLOWED[category][idx], expenseFactor);
+ _spells.push_back(SpellEntry(Common::String::format("\x3l%s\x3r\x9""000%u",
+ spells._spellNames[SPELLS_ALLOWED[category][idx]], cost),
+ idx, spellId));
+ }
+ }
+ }
+ } else {
+ for (int spellId = 0; spellId < 20; ++spellId) {
+ int idx = 0;
+ while (CLOUDS_SPELL_OFFSETS[party._mazeId - 29][spellId] !=
+ SPELLS_ALLOWED[category][idx] && idx < 40) ;
+
+ if (idx < 40) {
+ if (!c->_spells[idx] || (v2 & 0x80)) {
+ int cost = spells.calcSpellCost(SPELLS_ALLOWED[category][idx], expenseFactor);
+ _spells.push_back(SpellEntry(Common::String::format("\x3l%s\x3r\x9""000%u",
+ spells._spellNames[SPELLS_ALLOWED[category][idx]], cost),
+ idx, spellId));
+ }
+ }
+ }
+ }
+ }
+
+ if (c->getMaxSP() == 0)
+ return NOT_A_SPELL_CASTER;
+
+ } else if ((v2 & 0x7f) == 1) {
+ switch (c->_class) {
+ case 0:
+ case 12:
+ category = 0;
+ break;
+ case 1:
+ case 3:
+ category = 1;
+ break;
+ case 7:
+ case 8:
+ category = 2;
+ break;
+ default:
+ category = 0;
+ break;
+ }
+
+ if (c->getMaxSP() == 0) {
+ return NOT_A_SPELL_CASTER;
+ } else {
+ for (int spellIndex = 0; spellIndex < (MAX_SPELLS_PER_CLASS - 1); ++spellIndex) {
+ if (c->_spells[spellIndex]) {
+ int spellId = SPELLS_ALLOWED[category][spellIndex];
+ int gemCost = SPELL_GEM_COST[spellId];
+ int spCost = spells.calcSpellPoints(spellId, currLevel);
+
+ Common::String msg = Common::String::format("\x3l%s\x3r\x9""000%u/%u",
+ spells._spellNames[spellId].c_str(), spCost, gemCost);
+ _spells.push_back(SpellEntry(msg, spellIndex, spellId));
+ }
+ }
+ }
+ }
+
+ return nullptr;
+}
+
+} // End of namespace Xeen
diff --git a/engines/xeen/dialogs_spells.h b/engines/xeen/dialogs_spells.h
new file mode 100644
index 0000000000..69e339fa79
--- /dev/null
+++ b/engines/xeen/dialogs_spells.h
@@ -0,0 +1,61 @@
+/* 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.
+ *
+ */
+
+#ifndef XEEN_DIALOGS_SPELLS_H
+#define XEEN_DIALOGS_SPELLS_H
+
+#include "common/array.h"
+#include "xeen/dialogs.h"
+#include "xeen/party.h"
+
+namespace Xeen {
+
+struct SpellEntry {
+ Common::String _name;
+ int _spellIndex;
+ int _spellId;
+
+ SpellEntry(const Common::String &name, int spellIndex, int spellId) :
+ _name(name), _spellIndex(spellIndex), _spellId(spellId) {}
+};
+
+class SpellsScroll : public ButtonContainer {
+private:
+ XeenEngine *_vm;
+ SpriteResource _iconSprites;
+ SpriteResource _scrollSprites;
+ Common::Array<SpellEntry> _spells;
+
+ SpellsScroll(XeenEngine *vm) : ButtonContainer(), _vm(vm) {}
+
+ Character *execute(Character *c, int v2);
+
+ void loadButtons();
+
+ const char *setSpellText(Character *c, int v2);
+public:
+ static Character *show(XeenEngine *vm, Character *c, int v2);
+};
+
+} // End of namespace Xeen
+
+#endif /* XEEN_DIALOGS_SPELLS_H */
diff --git a/engines/xeen/dialogs_yesno.cpp b/engines/xeen/dialogs_yesno.cpp
index 8ea27ebd6c..17ca9a0c3e 100644
--- a/engines/xeen/dialogs_yesno.cpp
+++ b/engines/xeen/dialogs_yesno.cpp
@@ -25,9 +25,9 @@
namespace Xeen {
-bool YesNo::show(XeenEngine *vm, bool type, bool v2) {
+bool YesNo::show(XeenEngine *vm, bool type, bool townFlag) {
YesNo *dlg = new YesNo(vm);
- bool result = dlg->execute(type, v2);
+ bool result = dlg->execute(type, townFlag);
delete dlg;
return result;
diff --git a/engines/xeen/module.mk b/engines/xeen/module.mk
index 9d252b14c2..be951239d3 100644
--- a/engines/xeen/module.mk
+++ b/engines/xeen/module.mk
@@ -8,6 +8,7 @@ MODULE_OBJS := \
debugger.o \
detection.o \
dialogs.o \
+ dialogs_confirm.o \
dialogs_error.o \
dialogs_options.o \
dialogs_input.o \
diff --git a/engines/xeen/party.cpp b/engines/xeen/party.cpp
index 2138ca6154..66078b67e8 100644
--- a/engines/xeen/party.cpp
+++ b/engines/xeen/party.cpp
@@ -1218,4 +1218,70 @@ void Party::handleLight() {
(map.mazeData()._mazeFlags2 & FLAG_IS_DARK) == 0 ? 4 : 0;
}
+int Party::subtract(int mode, uint amount, int whereId, ErrorWaitType wait) {
+ switch (mode) {
+ case 0:
+ // Gold
+ if (whereId) {
+ if (amount <= _bankGold) {
+ _bankGold -= amount;
+ } else {
+ notEnough(0, whereId, false, wait);
+ return false;
+ }
+ }
+ else {
+ if (amount <= _gold) {
+ _gold -= amount;
+ } else {
+ notEnough(0, whereId, false, wait);
+ return false;
+ }
+ }
+ break;
+
+ case 1:
+ // Gems
+ if (whereId) {
+ if (amount <= _bankGems) {
+ _bankGems -= amount;
+ } else {
+ notEnough(0, whereId, false, wait);
+ return false;
+ }
+ }
+ else {
+ if (amount <= _gems) {
+ _gems -= amount;
+ } else {
+ notEnough(0, whereId, false, wait);
+ return false;
+ }
+ }
+ break;
+
+ case 2:
+ // Food
+ if (amount > _food) {
+ _food -= amount;
+ } else {
+ notEnough(5, 0, 0, wait);
+ return false;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return true;
+}
+
+void Party::notEnough(int consumableId, int whereId, bool mode, ErrorWaitType wait) {
+ Common::String msg = Common::String::format(
+ mode ? NO_X_IN_THE_Y : NOT_ENOUGH_X_IN_THE_Y,
+ CONSUMABLE_NAMES[consumableId], WHERE_NAMES[whereId]);
+ ErrorScroll::show(_vm, msg, wait);
+}
+
} // End of namespace Xeen
diff --git a/engines/xeen/party.h b/engines/xeen/party.h
index 035e76c098..e00b42476a 100644
--- a/engines/xeen/party.h
+++ b/engines/xeen/party.h
@@ -28,6 +28,7 @@
#include "common/rect.h"
#include "common/serializer.h"
#include "xeen/combat.h"
+#include "xeen/dialogs_error.h"
#include "xeen/items.h"
namespace Xeen {
@@ -274,6 +275,10 @@ public:
void resetTemps();
void handleLight();
+
+ int subtract(int mode, uint amount, int whereId, ErrorWaitType wait);
+
+ void notEnough(int consumableId, int whereId, bool mode, ErrorWaitType wait);
};
} // End of namespace Xeen
diff --git a/engines/xeen/resources.cpp b/engines/xeen/resources.cpp
index 57e16d74d0..ed304dc9e1 100644
--- a/engines/xeen/resources.cpp
+++ b/engines/xeen/resources.cpp
@@ -492,7 +492,7 @@ const int MONSTER_EFFECT_FLAGS[15][8] = {
{ 0x108, 0x108, 0x108, 0x108, 0x108, 0x108, 0x108, 0x108 }
};
-const uint SPELLS_ALLOWED[3][40] = {
+const int SPELLS_ALLOWED[3][40] = {
{
0, 1, 2, 3, 5, 6, 7, 8, 9, 10,
12, 14, 16, 23, 26, 27, 28, 30, 31, 32,
@@ -781,6 +781,49 @@ const int SPELL_GEM_COST[77] = {
5, 0, 0, 0, 0, 5, 1, 2, 0, 2, 0
};
-extern const char *NOT_A_SPELL_CASTER = "Not a spell caster...";
+const char *const NOT_A_SPELL_CASTER = "Not a spell caster...";
+
+const char *const SPELLS_FOR = "\xD\xC""d%s\x2\x3""c\x9""000\xB""002Spells for %s";
+
+const char *const SPELL_LINES_0_TO_9 =
+ "\x2\x3l\xB""015\x9""0011\n2\n3\n4\n5\n6\n7\n8\n9\n0";
+
+const char *const SPELLS_DIALOG_SPELLS = "\x3l\xB""015"
+ "\x9""010\xC""%2u%s\xC""d\x3l\n"
+ "\x9""010\xC""%2u%s\xC""d\x3l\n"
+ "\x9""010\xC""%2u%s\xC""d\x3l\n"
+ "\x9""010\xC""%2u%s\xC""d\x3l\n"
+ "\x9""010\xC""%2u%s\xC""d\x3l\n"
+ "\x9""010\xC""%2u%s\xC""d\x3l\n"
+ "\x9""010\xC""%2u%s\xC""d\x3l\n"
+ "\x9""010\xC""%2u%s\xC""d\x3l\n"
+ "\x9""010\xC""%2u%s\xC""d\x3l\n"
+ "\x9""010\xC""%2u%s\xC""d\x3l"
+ "\x9""004\xB""110%s - %lu\x1";
+
+const char *const SPELL_PTS = "Spell Pts";
+
+const char *const GOLD = "Gold";
+
+const char *const SPELLS_PRESS_A_KEY =
+ "\x3""c\xC""09%s\xC""d\x3l\n"
+ "\n"
+ "%s\x3""c\x9""000\xB""100Press a Key!";
+
+const char *const SPELLS_PURCHASE =
+ "\x3l\xB""000\x9""000\xC""d%s Do you wish to purchase "
+ "\xC""09%s\xC""d for %u?";
+
+const char *const SPELL_DETAILS =
+"\xD\x2\x3""c\xB""122\x9""013\xC""37C\xC""dast"
+"\x9""040\xC""37N\xC""dew\x9""067ESC\x1""000\xB""000\x3""cCast Spell\n"
+"\n"
+"%s\x3l\n"
+"\n"
+"Spell Ready:\x3""c\n"
+"\n"
+"\xC""09%s\xC""d\x2\x3l\n"
+"\xB""082Cost\x3r\x9""000%u/%u\x3l\n"
+"Cur SP\x3r\x9""000%u\x1";
} // End of namespace Xeen
diff --git a/engines/xeen/resources.h b/engines/xeen/resources.h
index 60f4848c00..37afb2cc76 100644
--- a/engines/xeen/resources.h
+++ b/engines/xeen/resources.h
@@ -124,7 +124,7 @@ extern const int COMBAT_FLOAT_Y[8];
extern const int MONSTER_EFFECT_FLAGS[15][8];
-extern const uint SPELLS_ALLOWED[3][40];
+extern const int SPELLS_ALLOWED[3][40];
extern const int BASE_HP_BY_CLASS[10];
@@ -226,7 +226,23 @@ extern const int SPELL_LEVEL_OFFSETS[3][39];
extern const int SPELL_GEM_COST[77];
-extern const char *NOT_A_SPELL_CASTER;
+extern const char *const NOT_A_SPELL_CASTER;
+
+extern const char *const SPELLS_FOR;
+
+extern const char *const SPELL_LINES_0_TO_9;
+
+extern const char *const SPELLS_DIALOG_SPELLS;
+
+extern const char *const SPELL_PTS;
+
+extern const char *const GOLD;
+
+extern const char *const SPELLS_PRESS_A_KEY;
+
+extern const char *const SPELLS_PURCHASE;
+
+extern const char *const SPELL_DETAILS;
} // End of namespace Xeen
diff --git a/engines/xeen/spells.cpp b/engines/xeen/spells.cpp
index 922f6fcb84..588fa1b510 100644
--- a/engines/xeen/spells.cpp
+++ b/engines/xeen/spells.cpp
@@ -28,6 +28,8 @@
namespace Xeen {
Spells::Spells(XeenEngine *vm) : _vm(vm) {
+ _lastCaster = 0;
+
load();
}
diff --git a/engines/xeen/spells.h b/engines/xeen/spells.h
index 97e3c80bba..96f491684e 100644
--- a/engines/xeen/spells.h
+++ b/engines/xeen/spells.h
@@ -40,6 +40,7 @@ private:
public:
Common::StringArray _spellNames;
Common::StringArray _maeNames;
+ int _lastCaster;
public:
Spells(XeenEngine *vm);
diff --git a/engines/xeen/town.cpp b/engines/xeen/town.cpp
index d773f6d4f2..2f31113146 100644
--- a/engines/xeen/town.cpp
+++ b/engines/xeen/town.cpp
@@ -606,7 +606,7 @@ Character *Town::doTavernOptions(Character *c) {
case Common::KEYCODE_d:
// Drink
if (!c->noActions()) {
- if (subtract(0, 1, 0, WT_2)) {
+ if (party.subtract(0, 1, 0, WT_2)) {
sound.playSample(nullptr, 0);
File f("gulp.voc");
sound.playSample(&f, 0);
@@ -664,7 +664,7 @@ Character *Town::doTavernOptions(Character *c) {
if (YesNo::show(_vm, false, true)) {
if (party._food >= _v22) {
ErrorScroll::show(_vm, FOOD_PACKS_FULL, WT_2);
- } else if (subtract(0, _v23, 0, WT_2)) {
+ } else if (party.subtract(0, _v23, 0, WT_2)) {
party._food = _v22;
sound.playSample(nullptr, 0);
File f(isDarkCc ? "thanks2.voc" : "thankyou.voc");
@@ -744,7 +744,7 @@ Character *Town::doTavernOptions(Character *c) {
drawButtons(&screen);
screen._windows[10].update();
townWait();
- } else if (subtract(0, 1, 0, WT_2)) {
+ } else if (party.subtract(0, 1, 0, WT_2)) {
sound.playSample(nullptr, 0);
File f(isDarkCc ? "thanks2.voc" : "thankyou.voc");
sound.playSample(&f, 1);
@@ -805,7 +805,7 @@ Character *Town::doTempleOptions(Character *c) {
break;
case Common::KEYCODE_d:
- if (_donation && subtract(0, _donation, 0, WT_2)) {
+ if (_donation && party.subtract(0, _donation, 0, WT_2)) {
sound.playSample(nullptr, 0);
File f("coina.voc");
sound.playSample(&f, 1);
@@ -832,7 +832,7 @@ Character *Town::doTempleOptions(Character *c) {
break;
case Common::KEYCODE_h:
- if (_healCost && subtract(0, _healCost, 0, WT_2)) {
+ if (_healCost && party.subtract(0, _healCost, 0, WT_2)) {
c->_magicResistence._temporary = 0;
c->_energyResistence._temporary = 0;
c->_poisonResistence._temporary = 0;
@@ -860,7 +860,7 @@ Character *Town::doTempleOptions(Character *c) {
break;
case Common::KEYCODE_u:
- if (_uncurseCost && subtract(0, _uncurseCost, 0, WT_2)) {
+ if (_uncurseCost && party.subtract(0, _uncurseCost, 0, WT_2)) {
for (int idx = 0; idx < 9; ++idx) {
c->_weapons[idx]._bonusFlags &= ~FLAG_CURSED;
c->_armor[idx]._bonusFlags &= ~FLAG_CURSED;
@@ -921,7 +921,7 @@ Character *Town::doTrainingOptions(Character *c) {
sound.playSample(&f);
} else if (!c->noActions()) {
- if (subtract(0, (c->_level._permanent * c->_level._permanent) * 10, 0, WT_2)) {
+ if (party.subtract(0, (c->_level._permanent * c->_level._permanent) * 10, 0, WT_2)) {
_drawFrameIndex = 0;
sound.playSample(nullptr, 0);
File f(isDarkCc ? "prtygd.voc" : "trainin2.voc");
@@ -1003,14 +1003,14 @@ void Town::depositWithdrawl(int choice) {
(choice && !party._bankGold && !flag) ||
(!choice && !party._gems && flag) ||
(!choice && !party._gold && !flag)) {
- notEnough(flag, choice, 1, WT_2);
+ party.notEnough(flag, choice, 1, WT_2);
} else {
screen._windows[35].writeString(AMOUNT);
int amount = NumericInput::show(_vm, 35, 10, 77);
if (amount) {
if (flag) {
- if (subtract(true, amount, choice, WT_2)) {
+ if (party.subtract(true, amount, choice, WT_2)) {
if (choice) {
party._gems += amount;
} else {
@@ -1018,7 +1018,7 @@ void Town::depositWithdrawl(int choice) {
}
}
} else {
- if (subtract(false, amount, choice, WT_2)) {
+ if (party.subtract(false, amount, choice, WT_2)) {
if (choice) {
party._gold += amount;
} else {
@@ -1053,72 +1053,6 @@ void Town::depositWithdrawl(int choice) {
_buttons[2]._value = Common::KEYCODE_ESCAPE;
}
-void Town::notEnough(int consumableId, int whereId, bool mode, ErrorWaitType wait) {
- Common::String msg = Common::String::format(
- mode ? NO_X_IN_THE_Y : NOT_ENOUGH_X_IN_THE_Y,
- CONSUMABLE_NAMES[consumableId], WHERE_NAMES[whereId]);
- ErrorScroll::show(_vm, msg, wait);
-}
-
-int Town::subtract(int mode, uint amount, int whereId, ErrorWaitType wait) {
- Party &party = *_vm->_party;
-
- switch (mode) {
- case 0:
- // Gold
- if (whereId) {
- if (amount <= party._bankGold) {
- party._bankGold -= amount;
- } else {
- notEnough(0, whereId, false, wait);
- return false;
- }
- } else {
- if (amount <= party._gold) {
- party._gold -= amount;
- } else {
- notEnough(0, whereId, false, wait);
- return false;
- }
- }
- break;
-
- case 1:
- // Gems
- if (whereId) {
- if (amount <= party._bankGems) {
- party._bankGems -= amount;
- } else {
- notEnough(0, whereId, false, wait);
- return false;
- }
- } else {
- if (amount <= party._gems) {
- party._gems -= amount;
- } else {
- notEnough(0, whereId, false, wait);
- return false;
- }
- }
- break;
-
- case 2:
- // Food
- if (amount > party._food) {
- party._food -= amount;
- } else {
- notEnough(5, 0, 0, wait);
- return false;
- }
- break;
-
- default:
- break;
- }
-
- return true;
-}
-
void Town::drawTownAnim(bool flag) {
Interface &intf = *_vm->_interface;
Screen &screen = *_vm->_screen;
diff --git a/engines/xeen/town.h b/engines/xeen/town.h
index 27b1fe2121..8237f8102e 100644
--- a/engines/xeen/town.h
+++ b/engines/xeen/town.h
@@ -96,10 +96,6 @@ private:
void depositWithdrawl(int choice);
- void notEnough(int consumableId, int whereId, bool mode, ErrorWaitType wait);
-
- int subtract(int mode, uint amount, int whereId, ErrorWaitType wait);
-
Character *showItems(Character *c, int v2);
public:
Town(XeenEngine *vm);