aboutsummaryrefslogtreecommitdiff
path: root/engines/xeen/dialogs/dialogs_spells.cpp
diff options
context:
space:
mode:
authorPaul Gilbert2018-03-04 18:12:09 -0500
committerPaul Gilbert2018-03-04 22:40:42 -0500
commitf2b574d64762d23a83cc682da0e622be99080688 (patch)
tree1ccbabbda83e70911dae0d4042223ee81a006d1d /engines/xeen/dialogs/dialogs_spells.cpp
parent50630efde6d0f42f4d5f371d6818afac64ba86f5 (diff)
downloadscummvm-rg350-f2b574d64762d23a83cc682da0e622be99080688.tar.gz
scummvm-rg350-f2b574d64762d23a83cc682da0e622be99080688.tar.bz2
scummvm-rg350-f2b574d64762d23a83cc682da0e622be99080688.zip
XEEN: Move all the dialog classes to their own sub-folder
Diffstat (limited to 'engines/xeen/dialogs/dialogs_spells.cpp')
-rw-r--r--engines/xeen/dialogs/dialogs_spells.cpp1045
1 files changed, 1045 insertions, 0 deletions
diff --git a/engines/xeen/dialogs/dialogs_spells.cpp b/engines/xeen/dialogs/dialogs_spells.cpp
new file mode 100644
index 0000000000..3da5a5149e
--- /dev/null
+++ b/engines/xeen/dialogs/dialogs_spells.cpp
@@ -0,0 +1,1045 @@
+/* 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/dialogs_spells.h"
+#include "xeen/dialogs/dialogs_input.h"
+#include "xeen/dialogs/dialogs_query.h"
+#include "xeen/resources.h"
+#include "xeen/spells.h"
+#include "xeen/sprites.h"
+#include "xeen/xeen.h"
+
+namespace Xeen {
+
+Character *SpellsDialog::show(XeenEngine *vm, ButtonContainer *priorDialog,
+ Character *c, int isCasting) {
+ SpellsDialog *dlg = new SpellsDialog(vm);
+ Character *result = dlg->execute(priorDialog, c, isCasting);
+ delete dlg;
+
+ return result;
+}
+
+Character *SpellsDialog::execute(ButtonContainer *priorDialog, Character *c, int isCasting) {
+ EventsManager &events = *_vm->_events;
+ Interface &intf = *_vm->_interface;
+ Party &party = *_vm->_party;
+ Sound &sound = *_vm->_sound;
+ Spells &spells = *_vm->_spells;
+ Windows &windows = *_vm->_windows;
+ bool isDarkCc = _vm->_files->_isDarkCc;
+ loadButtons();
+
+ int castingCopy = isCasting;
+ isCasting &= 0x7f;
+ int selection = -1;
+ int topIndex = 0;
+ int newSelection;
+ windows[25].open();
+
+ do {
+ if (!isCasting) {
+ if (!c->guildMember()) {
+ sound.stopSound();
+ intf._overallFrame = 5;
+ sound.playSound(isDarkCc ? "skull1.voc" : "guild11.voc", 1);
+ break;
+ }
+
+ Common::String title = Common::String::format(Res.BUY_SPELLS, c->_name.c_str());
+ Common::String msg = Common::String::format(Res.GUILD_OPTIONS,
+ title.c_str(), XeenEngine::printMil(party._gold).c_str());
+ windows[10].writeString(msg);
+
+ warning("TODO: Sprite draw using previously used button sprites");
+ }
+
+ _spells.clear();
+ const char *errorMsg = setSpellText(c, castingCopy);
+ windows[25].writeString(Common::String::format(Res.SPELLS_FOR,
+ errorMsg == nullptr ? Res.SPELL_LINES_0_TO_9 : "",
+ c->_name.c_str()));
+
+ // Setup and write out spell list
+ const char *names[10];
+ int colors[10];
+ Common::String emptyStr = "";
+ Common::fill(&names[0], &names[10], emptyStr.c_str());
+ Common::fill(&colors[0], &colors[10], 9);
+
+ for (int idx = 0; idx < 10; ++idx) {
+ if ((topIndex + idx) < (int)_spells.size()) {
+ names[idx] = _spells[topIndex + idx]._name.c_str();
+ colors[idx] = _spells[topIndex + idx]._color;
+ }
+ }
+
+ if (selection >= topIndex && selection < (topIndex + 10))
+ colors[selection - topIndex] = 15;
+ if (_spells.size() == 0)
+ names[0] = errorMsg;
+
+ windows[37].writeString(Common::String::format(Res.SPELLS_DIALOG_SPELLS,
+ colors[0], names[0], colors[1], names[1], colors[2], names[2],
+ colors[3], names[3], colors[4], names[4], colors[5], names[5],
+ colors[6], names[6], colors[7], names[7], colors[8], names[8],
+ colors[9], names[9],
+ isCasting ? Res.SPELL_PTS : Res.GOLD,
+ isCasting ? c->_currentSp : party._gold
+ ));
+
+ _scrollSprites.draw(0, 4, Common::Point(39, 26));
+ _scrollSprites.draw(0, 0, Common::Point(187, 26));
+ _scrollSprites.draw(0, 2, Common::Point(187, 111));
+ if (isCasting)
+ _scrollSprites.draw(windows[25], 5, Common::Point(132, 123));
+
+ windows[25].update();
+
+ do {
+ events.pollEventsAndWait();
+ checkEvents(_vm);
+ } while (!_vm->shouldExit() && !_buttonValue);
+
+ switch (_buttonValue) {
+ case Common::KEYCODE_F1:
+ case Common::KEYCODE_F2:
+ case Common::KEYCODE_F3:
+ case Common::KEYCODE_F4:
+ case Common::KEYCODE_F5:
+ case Common::KEYCODE_F6:
+ if (_vm->_mode != MODE_COMBAT) {
+ _buttonValue -= Common::KEYCODE_F1;
+ if (_buttonValue < (int)party._activeParty.size()) {
+ c = &party._activeParty[_buttonValue];
+ spells._lastCaster = _buttonValue;
+ intf.highlightChar(_buttonValue);
+
+ if (_vm->_mode == MODE_17) {
+ windows[10].writeString(Common::String::format(Res.GUILD_OPTIONS,
+ XeenEngine::printMil(party._gold).c_str(), Res.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->_currentSpell == -1) ? 39 : c->_currentSpell;
+ int spellId = Res.SPELLS_ALLOWED[category][spellIndex];
+ windows[10].writeString(Common::String::format(Res.CAST_SPELL_DETAILS,
+ c->_name.c_str(), spells._spellNames[spellId].c_str(),
+ spells.calcSpellPoints(spellId, c->getCurrentLevel()),
+ Res.SPELL_GEM_COST[spellId], c->_currentSp));
+ }
+
+ if (priorDialog != nullptr)
+ priorDialog->drawButtons(&windows[0]);
+ 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 spellIndex = _spells[newSelection]._spellIndex;
+ int spellId = Res.SPELLS_ALLOWED[category][spellIndex];
+ int spellCost = spells.calcSpellCost(spellId, expenseFactor);
+
+ if (isCasting) {
+ selection = newSelection;
+ } else {
+ Common::String spellName = _spells[newSelection]._name;
+ Common::String msg = (castingCopy & 0x80) ?
+ Common::String::format(Res.SPELLS_PRESS_A_KEY, spellName.c_str()) :
+ Common::String::format(Res.SPELLS_PURCHASE, spellName.c_str(), spellCost);
+
+ if (Confirm::show(_vm, msg, castingCopy + 1)) {
+ if (party.subtract(CONS_GOLD, spellCost, WHERE_PARTY, WT_FREEZE_WAIT)) {
+ c->_spells[spellIndex] = true;
+ sound.stopSound();
+ intf._overallFrame = 0;
+ sound.playSound(isDarkCc ? "guild12.voc" : "parrot2.voc", 1);
+ } else {
+ sound.playFX(21);
+ }
+ }
+ }
+ }
+ break;
+
+ case Common::KEYCODE_PAGEUP:
+ case Common::KEYCODE_KP9:
+ topIndex = MAX((int)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;
+ }
+ } while (!_vm->shouldExit() && _buttonValue != Common::KEYCODE_ESCAPE);
+
+ windows[25].close();
+
+ if (_vm->shouldExit())
+ selection = -1;
+ if (isCasting && selection != -1)
+ c->_currentSpell = _spells[selection]._spellIndex;
+
+ return c;
+}
+
+void SpellsDialog::loadButtons() {
+ _iconSprites.load("main.icn");
+ _scrollSprites.load("scroll.icn");
+ addButton(Common::Rect(187, 26, 198, 36), Common::KEYCODE_UP, &_scrollSprites);
+ addButton(Common::Rect(187, 111, 198, 121), Common::KEYCODE_DOWN, &_scrollSprites);
+ addButton(Common::Rect(40, 28, 187, 36), Common::KEYCODE_1);
+ addButton(Common::Rect(40, 37, 187, 45), Common::KEYCODE_2);
+ addButton(Common::Rect(40, 46, 187, 54), Common::KEYCODE_3);
+ addButton(Common::Rect(40, 55, 187, 63), Common::KEYCODE_4);
+ addButton(Common::Rect(40, 64, 187, 72), Common::KEYCODE_5);
+ addButton(Common::Rect(40, 73, 187, 81), Common::KEYCODE_6);
+ addButton(Common::Rect(40, 82, 187, 90), Common::KEYCODE_7);
+ addButton(Common::Rect(40, 91, 187, 99), Common::KEYCODE_8);
+ addButton(Common::Rect(40, 100, 187, 108), Common::KEYCODE_9);
+ addButton(Common::Rect(40, 109, 187, 117), Common::KEYCODE_0);
+ addButton(Common::Rect(174, 123, 198, 133), Common::KEYCODE_ESCAPE);
+ addButton(Common::Rect(187, 35, 198, 73), Common::KEYCODE_PAGEUP);
+ addButton(Common::Rect(187, 74, 198, 112), Common::KEYCODE_PAGEDOWN);
+ addButton(Common::Rect(132, 123, 168, 133), Common::KEYCODE_s);
+ addPartyButtons(_vm);
+}
+
+const char *SpellsDialog::setSpellText(Character *c, int isCasting) {
+ Party &party = *_vm->_party;
+ Spells &spells = *_vm->_spells;
+ bool isDarkCc = _vm->_files->_isDarkCc;
+ int expenseFactor = 0;
+ int currLevel = c->getCurrentLevel();
+ int category;
+
+ if ((isCasting & 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 (uint spellId = 0; spellId < 76; ++spellId) {
+ int idx = 0;
+ while (idx < MAX_SPELLS_PER_CLASS && Res.SPELLS_ALLOWED[category][idx] != (int)spellId)
+ ++idx;
+
+ // Handling if the spell is appropriate for the character's class
+ if (idx < MAX_SPELLS_PER_CLASS) {
+ if (!c->_spells[idx] || (isCasting & 0x80)) {
+ int cost = spells.calcSpellCost(Res.SPELLS_ALLOWED[category][idx], expenseFactor);
+ _spells.push_back(SpellEntry(Common::String::format("\x3l%s\x3r\x9""000%u",
+ spells._spellNames[Res.SPELLS_ALLOWED[category][idx]].c_str(), cost),
+ idx, spellId));
+ }
+ }
+ }
+ } else if (isDarkCc) {
+ int groupIndex = (party._mazeId - 29) / 2;
+ for (int spellId = Res.DARK_SPELL_RANGES[groupIndex][0];
+ spellId < Res.DARK_SPELL_RANGES[groupIndex][1]; ++spellId) {
+ int idx = 0;
+ while (idx < 40 && Res.SPELLS_ALLOWED[category][idx] ==
+ Res.DARK_SPELL_OFFSETS[category][spellId]);
+
+ if (idx < 40) {
+ if (!c->_spells[idx] || (isCasting & 0x80)) {
+ int cost = spells.calcSpellCost(Res.SPELLS_ALLOWED[category][idx], expenseFactor);
+ _spells.push_back(SpellEntry(Common::String::format("\x3l%s\x3r\x9""000%u",
+ spells._spellNames[Res.SPELLS_ALLOWED[category][idx]].c_str(), cost),
+ idx, spellId));
+ }
+ }
+ }
+ } else {
+ for (int spellId = 0; spellId < 20; ++spellId) {
+ int idx = 0;
+ while (Res.CLOUDS_SPELL_OFFSETS[party._mazeId - 29][spellId] !=
+ (int)Res.SPELLS_ALLOWED[category][idx] && idx < 40) ;
+
+ if (idx < 40) {
+ if (!c->_spells[idx] || (isCasting & 0x80)) {
+ int cost = spells.calcSpellCost(Res.SPELLS_ALLOWED[category][idx], expenseFactor);
+ _spells.push_back(SpellEntry(Common::String::format("\x3l%s\x3r\x9""000%u",
+ spells._spellNames[Res.SPELLS_ALLOWED[category][idx]].c_str(), cost),
+ idx, spellId));
+ }
+ }
+ }
+ }
+ }
+
+ if (c->getMaxSP() == 0)
+ return Res.NOT_A_SPELL_CASTER;
+
+ } else if ((isCasting & 0x7f) == 1) {
+ switch (c->_class) {
+ case CLASS_ARCHER:
+ case CLASS_SORCERER:
+ category = 1;
+ break;
+ case CLASS_DRUID:
+ case CLASS_RANGER:
+ category = 2;
+ break;
+ case CLASS_PALADIN:
+ case CLASS_CLERIC:
+ default:
+ category = 0;
+ break;
+ }
+
+ if (c->getMaxSP() == 0) {
+ return Res.NOT_A_SPELL_CASTER;
+ } else {
+ for (int spellIndex = 0; spellIndex < MAX_SPELLS_PER_CLASS; ++spellIndex) {
+ if (c->_spells[spellIndex]) {
+ int spellId = Res.SPELLS_ALLOWED[category][spellIndex];
+ int gemCost = Res.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;
+}
+
+/*------------------------------------------------------------------------*/
+
+CastSpell::CastSpell(XeenEngine *vm) : ButtonContainer(vm) {
+ Windows &windows = *_vm->_windows;
+ _oldMode = _vm->_mode;
+ _vm->_mode = MODE_3;
+
+ windows[10].open();
+ loadButtons();
+}
+
+CastSpell::~CastSpell() {
+ Interface &intf = *_vm->_interface;
+ Windows &windows = *_vm->_windows;
+
+ windows[10].close();
+ intf.unhighlightChar();
+
+ _vm->_mode = (Mode)_oldMode;
+}
+
+
+int CastSpell::show(XeenEngine *vm) {
+ Combat &combat = *vm->_combat;
+ Interface &intf = *vm->_interface;
+ Party &party = *vm->_party;
+ Spells &spells = *vm->_spells;
+ int charNum;
+
+ // Get which character is doing the casting
+ if (vm->_mode == MODE_COMBAT) {
+ charNum = combat._whosTurn;
+ } else if (spells._lastCaster >= 0 && spells._lastCaster < (int)party._activeParty.size()) {
+ charNum = spells._lastCaster;
+ } else {
+ for (charNum = (int)party._activeParty.size() - 1; charNum >= 0; --charNum) {
+ if (party._activeParty[charNum]._hasSpells) {
+ spells._lastCaster = charNum;
+ break;
+ }
+ }
+ }
+
+ Character *c = &party._activeParty[charNum];
+ intf.highlightChar(charNum);
+
+ return show(vm, c);
+}
+
+int CastSpell::show(XeenEngine *vm, Character *&c) {
+ Spells &spells = *vm->_spells;
+ CastSpell *dlg = new CastSpell(vm);
+ int spellId;
+ int result = -1;
+
+ do {
+ spellId = dlg->execute(c);
+
+ if (g_vm->shouldExit() || spellId == -1) {
+ result = 0;
+ } else {
+ result = spells.castSpell(c, (MagicSpell)spellId);
+ }
+ } while (result == -1);
+
+ delete dlg;
+ return result;
+}
+
+int CastSpell::execute(Character *&c) {
+ EventsManager &events = *_vm->_events;
+ Interface &intf = *_vm->_interface;
+ Party &party = *_vm->_party;
+ Spells &spells = *_vm->_spells;
+ Windows &windows = *_vm->_windows;
+ Window &w = windows[10];
+
+ int spellId = -1;
+ bool redrawFlag = true;
+ do {
+ if (redrawFlag) {
+ int category = c->getClassCategory();
+ int spellIndex = c->_currentSpell != -1 ? c->_currentSpell : 39;
+ spellId = Res.SPELLS_ALLOWED[category][spellIndex];
+ int gemCost = Res.SPELL_GEM_COST[spellId];
+ int spCost = spells.calcSpellPoints(spellId, c->getCurrentLevel());
+
+ w.writeString(Common::String::format(Res.CAST_SPELL_DETAILS,
+ c->_name.c_str(), spells._spellNames[spellId].c_str(),
+ spCost, gemCost, c->_currentSp));
+ drawButtons(&windows[0]);
+ w.update();
+
+ redrawFlag = false;
+ }
+
+ events.updateGameCounter();
+ intf.draw3d(true);
+
+ // Wait for event or time expiry
+ do {
+ events.pollEventsAndWait();
+ checkEvents(_vm);
+ } while (!_vm->shouldExit() && events.timeElapsed() < 1 && !_buttonValue);
+
+ switch (_buttonValue) {
+ case Common::KEYCODE_F1:
+ case Common::KEYCODE_F2:
+ case Common::KEYCODE_F3:
+ case Common::KEYCODE_F4:
+ case Common::KEYCODE_F5:
+ case Common::KEYCODE_F6:
+ // Only allow changing character if the party is not in combat
+ if (_oldMode != MODE_COMBAT) {
+ _vm->_mode = (Mode)_oldMode;
+ _buttonValue -= Common::KEYCODE_F1;
+
+ if (_buttonValue < (int)party._activeParty.size()) {
+ c = &party._activeParty[_buttonValue];
+ intf.highlightChar(_buttonValue);
+ redrawFlag = true;
+ break;
+ }
+ }
+ break;
+
+ case Common::KEYCODE_ESCAPE:
+ spellId = -1;
+ break;
+
+ case Common::KEYCODE_c:
+ // Cast spell - return the selected spell Id to be cast
+ if (c->_currentSpell != -1 && !c->noActions())
+ _buttonValue = Common::KEYCODE_ESCAPE;
+ break;
+
+ case Common::KEYCODE_n:
+ // Select new spell
+ _vm->_mode = (Mode)_oldMode;
+ c = SpellsDialog::show(_vm, this, c, 1);
+ redrawFlag = true;
+ break;
+
+ default:
+ break;
+ }
+ } while (!_vm->shouldExit() && _buttonValue != Common::KEYCODE_ESCAPE);
+
+ if (_vm->shouldExit())
+ spellId = -1;
+ return spellId;
+}
+
+void CastSpell::loadButtons() {
+ _iconSprites.load("cast.icn");
+ addButton(Common::Rect(234, 108, 259, 128), Common::KEYCODE_c, &_iconSprites);
+ addButton(Common::Rect(261, 108, 285, 128), Common::KEYCODE_n, &_iconSprites);
+ addButton(Common::Rect(288, 108, 312, 128), Common::KEYCODE_ESCAPE, &_iconSprites);
+ addPartyButtons(_vm);
+}
+
+/*------------------------------------------------------------------------*/
+
+Character *SpellOnWho::show(XeenEngine *vm, int spellId) {
+ SpellOnWho *dlg = new SpellOnWho(vm);
+ int result = dlg->execute(spellId);
+ delete dlg;
+
+ if (result == -1)
+ return nullptr;
+
+ Combat &combat = *vm->_combat;
+ Party &party = *vm->_party;
+ return combat._combatMode == 2 ? combat._combatParty[result] :
+ &party._activeParty[result];
+}
+
+int SpellOnWho::execute(int spellId) {
+ Combat &combat = *_vm->_combat;
+ EventsManager &events = *_vm->_events;
+ Interface &intf = *_vm->_interface;
+ Party &party = *_vm->_party;
+ Spells &spells = *_vm->_spells;
+ Windows &windows = *_vm->_windows;
+ Window &w = windows[16];
+ Mode oldMode = _vm->_mode;
+ _vm->_mode = MODE_3;
+ int result = 999;
+
+ w.open();
+ w.writeString(Res.ON_WHO);
+ w.update();
+ addPartyButtons(_vm);
+
+ while (result == 999) {
+ do {
+ events.updateGameCounter();
+ intf.draw3d(true);
+
+ do {
+ events.pollEventsAndWait();
+ if (_vm->shouldExit())
+ return -1;
+
+ checkEvents(_vm);
+ } while (!_buttonValue && events.timeElapsed() < 1);
+ } while (!_buttonValue);
+
+ switch (_buttonValue) {
+ case Common::KEYCODE_ESCAPE:
+ result = -1;
+ spells.addSpellCost(*combat._oldCharacter, spellId);
+ break;
+
+ case Common::KEYCODE_F1:
+ case Common::KEYCODE_F2:
+ case Common::KEYCODE_F3:
+ case Common::KEYCODE_F4:
+ case Common::KEYCODE_F5:
+ case Common::KEYCODE_F6:
+ _buttonValue -= Common::KEYCODE_F1;
+ if (_buttonValue < (int)(combat._combatMode == 2 ? combat._combatParty.size() :
+ party._activeParty.size())) {
+ result = _buttonValue;
+ }
+ break;
+ }
+ }
+
+ w.close();
+ _vm->_mode = oldMode;
+ return result;
+}
+
+/*------------------------------------------------------------------------*/
+
+int SelectElement::show(XeenEngine *vm, int spellId) {
+ SelectElement *dlg = new SelectElement(vm);
+ int result = dlg->execute(spellId);
+ delete dlg;
+
+ return result;
+}
+
+int SelectElement::execute(int spellId) {
+ Combat &combat = *_vm->_combat;
+ EventsManager &events = *_vm->_events;
+ Interface &intf = *_vm->_interface;
+ Spells &spells = *_vm->_spells;
+ Windows &windows = *_vm->_windows;
+ Window &w = windows[15];
+ Mode oldMode = _vm->_mode;
+ _vm->_mode = MODE_3;
+ int result = 999;
+
+ loadButtons();
+
+ w.open();
+ w.writeString(Res.WHICH_ELEMENT1);
+ drawButtons(&windows[0]);
+ w.update();
+
+ while (result == 999) {
+ do {
+ events.updateGameCounter();
+ intf.draw3d(true);
+ w.frame();
+ w.writeString(Res.WHICH_ELEMENT2);
+ drawButtons(&windows[0]);
+ w.update();
+
+ do {
+ events.pollEventsAndWait();
+ if (_vm->shouldExit())
+ return -1;
+
+ checkEvents(_vm);
+ } while (!_buttonValue && events.timeElapsed() < 1);
+ } while (!_buttonValue);
+
+ switch (_buttonValue) {
+ case Common::KEYCODE_ESCAPE:
+ result = -1;
+ spells.addSpellCost(*combat._oldCharacter, spellId);
+ break;
+
+ case Common::KEYCODE_a:
+ result = DT_POISON;
+ break;
+ case Common::KEYCODE_c:
+ result = DT_COLD;
+ break;
+ case Common::KEYCODE_e:
+ result = DT_ELECTRICAL;
+ break;
+ case Common::KEYCODE_f:
+ result = DT_FIRE;
+ break;
+ default:
+ break;
+ }
+ }
+
+ w.close();
+ _vm->_mode = oldMode;
+ return result;
+}
+
+void SelectElement::loadButtons() {
+ _iconSprites.load("element.icn");
+ addButton(Common::Rect(60, 92, 84, 112), Common::KEYCODE_f, &_iconSprites);
+ addButton(Common::Rect(90, 92, 114, 112), Common::KEYCODE_e, &_iconSprites);
+ addButton(Common::Rect(120, 92, 144, 112), Common::KEYCODE_c, &_iconSprites);
+ addButton(Common::Rect(150, 92, 174, 112), Common::KEYCODE_a, &_iconSprites);
+}
+
+/*------------------------------------------------------------------------*/
+
+void NotWhileEngaged::show(XeenEngine *vm, int spellId) {
+ NotWhileEngaged *dlg = new NotWhileEngaged(vm);
+ dlg->execute(spellId);
+ delete dlg;
+}
+
+void NotWhileEngaged::execute(int spellId) {
+ EventsManager &events = *_vm->_events;
+ Spells &spells = *_vm->_spells;
+ Windows &windows = *_vm->_windows;
+ Window &w = windows[6];
+ Mode oldMode = _vm->_mode;
+ _vm->_mode = MODE_3;
+
+ w.open();
+ w.writeString(Common::String::format(Res.CANT_CAST_WHILE_ENGAGED,
+ spells._spellNames[spellId].c_str()));
+ w.update();
+
+ while (!_vm->shouldExit() && !events.isKeyMousePressed())
+ events.pollEventsAndWait();
+ events.clearEvents();
+
+ w.close();
+ _vm->_mode = oldMode;
+}
+
+/*------------------------------------------------------------------------*/
+
+bool LloydsBeacon::show(XeenEngine *vm) {
+ LloydsBeacon *dlg = new LloydsBeacon(vm);
+ bool result = dlg->execute();
+ delete dlg;
+
+ return result;
+}
+
+bool LloydsBeacon::execute() {
+ Combat &combat = *_vm->_combat;
+ EventsManager &events = *_vm->_events;
+ Interface &intf = *_vm->_interface;
+ Map &map = *_vm->_map;
+ Party &party = *_vm->_party;
+ Sound &sound = *_vm->_sound;
+ Windows &windows = *_vm->_windows;
+ Window &w = windows[10];
+ bool isDarkCc = _vm->_files->_isDarkCc;
+ Character &c = *combat._oldCharacter;
+
+ loadButtons();
+
+ if (!c._lloydMap) {
+ // No destination previously set, so have a default ready
+ if (isDarkCc) {
+ c._lloydSide = 1;
+ c._lloydPosition = Common::Point(25, 21);
+ c._lloydMap = 29;
+ } else {
+ c._lloydSide = 0;
+ c._lloydPosition = Common::Point(18, 4);
+ c._lloydMap = 28;
+ }
+ }
+
+ // Open up the text file for the destination map and read in it's name
+ File textFile(Common::String::format("%s%c%03d.txt",
+ c._lloydSide == 0 ? "xeen" : "dark",
+ c._lloydMap >= 100 ? 'x' : '0',
+ c._lloydMap));
+ Common::String mapName = textFile.readString();
+ textFile.close();
+
+ // Display the dialog
+ w.open();
+ w.writeString(Common::String::format(Res.LLOYDS_BEACON,
+ mapName.c_str(), c._lloydPosition.x, c._lloydPosition.y));
+ drawButtons(&windows[0]);
+ w.update();
+
+ bool result = true;
+ do {
+ do {
+ events.updateGameCounter();
+ intf.draw3d(true);
+
+ do {
+ events.pollEventsAndWait();
+ if (_vm->shouldExit())
+ return true;
+
+ checkEvents(_vm);
+ } while (!_buttonValue && events.timeElapsed() < 1);
+ } while (!_buttonValue);
+
+ switch (_buttonValue) {
+ case Common::KEYCODE_r:
+ if (!isDarkCc && c._lloydMap >= 75 && c._lloydMap <= 78 && !party._cloudsEnd) {
+ result = false;
+ } else {
+ sound.playFX(51);
+ map._loadDarkSide = isDarkCc;
+ if (c._lloydMap != party._mazeId || c._lloydSide != (isDarkCc ? 1 : 0)) {
+ map.load(c._lloydMap);
+ }
+
+ party._mazePosition = c._lloydPosition;
+ }
+
+ _buttonValue = Common::KEYCODE_ESCAPE;
+ break;
+
+ case Common::KEYCODE_s:
+ case Common::KEYCODE_t:
+ sound.playFX(20);
+ c._lloydMap = party._mazeId;
+ c._lloydPosition = party._mazePosition;
+ c._lloydSide = isDarkCc ? 1 : 0;
+
+ _buttonValue = Common::KEYCODE_ESCAPE;
+ break;
+ }
+ } while (_buttonValue != Common::KEYCODE_ESCAPE);
+
+ w.close();
+ return result;
+}
+
+void LloydsBeacon::loadButtons() {
+ _iconSprites.load("lloyds.icn");
+
+ addButton(Common::Rect(281, 108, 305, 128), Common::KEYCODE_r, &_iconSprites);
+ addButton(Common::Rect(242, 108, 266, 128), Common::KEYCODE_t, &_iconSprites);
+}
+
+/*------------------------------------------------------------------------*/
+
+int Teleport::show(XeenEngine *vm) {
+ Teleport *dlg = new Teleport(vm);
+ int result = dlg->execute();
+ delete dlg;
+
+ return result;
+}
+
+int Teleport::execute() {
+ Map &map = *_vm->_map;
+ Party &party = *_vm->_party;
+ Windows &windows = *_vm->_windows;
+ Window &w = windows[6];
+ Common::String num;
+
+ w.open();
+ w.writeString(Common::String::format(Res.HOW_MANY_SQUARES,
+ Res.DIRECTION_TEXT[party._mazeDirection]));
+ w.update();
+ int lineSize = Input::show(_vm, &w, num, 1, 200, true);
+ w.close();
+
+ if (!lineSize)
+ return -1;
+ int numSquares = atoi(num.c_str());
+ Common::Point pt = party._mazePosition;
+ int v;
+
+ switch (party._mazeDirection) {
+ case DIR_NORTH:
+ pt.y += numSquares;
+ break;
+ case DIR_EAST:
+ pt.x += numSquares;
+ break;
+ case DIR_SOUTH:
+ pt.y -= numSquares;
+ break;
+ case DIR_WEST:
+ pt.x -= numSquares;
+ break;
+ default:
+ break;
+ }
+
+ v = map.mazeLookup(pt, map._isOutdoors ? 0xF : 0xFFFF, 0);
+
+ if ((v != (map._isOutdoors ? 0 : INVALID_CELL)) &&
+ (!map._isOutdoors || v == SURFTYPE_DWATER)) {
+ party._mazePosition = pt;
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+/*------------------------------------------------------------------------*/
+
+int TownPortal::show(XeenEngine *vm) {
+ TownPortal *dlg = new TownPortal(vm);
+ int townNumber = dlg->execute();
+ delete dlg;
+
+ return townNumber;
+}
+
+int TownPortal::execute() {
+ Map &map = *_vm->_map;
+ Windows &windows = *_vm->_windows;
+ Window &w = windows[20];
+ Common::String townNames[5];
+ Mode oldMode = _vm->_mode;
+ _vm->_mode = MODE_FF;
+
+ // Build up a lsit of the names of the towns on the current side of Xeen
+ for (int idx = 0; idx < 5; ++idx) {
+ File f(Common::String::format("%s%04d.txt",
+ map._sideTownPortal ? "dark" : "xeen",
+ Res.TOWN_MAP_NUMBERS[map._sideTownPortal][idx]));
+ townNames[idx] = f.readString();
+ f.close();
+ }
+
+ w.open();
+ w.writeString(Common::String::format(Res.TOWN_PORTAL,
+ townNames[0].c_str(), townNames[1].c_str(), townNames[2].c_str(),
+ townNames[3].c_str(), townNames[4].c_str()
+ ));
+ w.update();
+
+ // Get the town number
+ int townNumber;
+ Common::String num;
+ do {
+ int result = Input::show(_vm, &w, num, 1, 160, true);
+ townNumber = !result ? 0 : atoi(num.c_str());
+ } while (townNumber > 5);
+
+ w.close();
+ _vm->_mode = oldMode;
+
+ return townNumber;
+}
+
+/*------------------------------------------------------------------------*/
+
+void IdentifyMonster::show(XeenEngine *vm) {
+ IdentifyMonster *dlg = new IdentifyMonster(vm);
+ dlg->execute();
+ delete dlg;
+}
+
+void IdentifyMonster::execute() {
+ Combat &combat = *_vm->_combat;
+ EventsManager &events = *_vm->_events;
+ Interface &intf = *_vm->_interface;
+ Map &map = *_vm->_map;
+ Sound &sound = *_vm->_sound;
+ Windows &windows = *_vm->_windows;
+ Window &w = windows[17];
+ Common::String monsterDesc[3];
+
+ for (int monIndex = 0; monIndex < 3; ++monIndex) {
+ if (combat._attackMonsters[monIndex] == -1)
+ continue;
+
+ MazeMonster &monster = map._mobData._monsters[combat._attackMonsters[monIndex]];
+ MonsterStruct &monsterData = *monster._monsterData;
+
+ monsterDesc[monIndex] = Common::String::format(Res.MONSTER_DETAILS,
+ monsterData._name.c_str(),
+ _vm->printK2(monster._hp).c_str(),
+ monsterData._armorClass, monsterData._numberOfAttacks,
+ Res.MONSTER_SPECIAL_ATTACKS[monsterData._specialAttack]
+ );
+ }
+
+ sound.playFX(20);
+ w.open();
+ w.writeString(Common::String::format(Res.IDENTIFY_MONSTERS,
+ monsterDesc[0].c_str(), monsterDesc[1].c_str(), monsterDesc[2].c_str()));
+ w.update();
+
+ do {
+ events.updateGameCounter();
+ intf.draw3d(false);
+ w.frame();
+ windows[3].update();
+
+ events.wait(1, false);
+ } while (!events.isKeyMousePressed());
+
+ w.close();
+}
+
+} // End of namespace Xeen