aboutsummaryrefslogtreecommitdiff
path: root/engines/xeen/locations.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/xeen/locations.cpp')
-rw-r--r--engines/xeen/locations.cpp1661
1 files changed, 1661 insertions, 0 deletions
diff --git a/engines/xeen/locations.cpp b/engines/xeen/locations.cpp
new file mode 100644
index 0000000000..cc2320a7d9
--- /dev/null
+++ b/engines/xeen/locations.cpp
@@ -0,0 +1,1661 @@
+/* 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/locations.h"
+#include "xeen/dialogs_input.h"
+#include "xeen/dialogs_items.h"
+#include "xeen/dialogs_query.h"
+#include "xeen/dialogs_spells.h"
+#include "xeen/resources.h"
+#include "xeen/xeen.h"
+
+namespace Xeen {
+namespace Locations {
+
+BaseLocation::BaseLocation(LocationAction action) : ButtonContainer(g_vm),
+ _LocationActionId(action), _isDarkCc(g_vm->_files->_isDarkCc),
+ _vocName("hello1.voc") {
+ _townMaxId = (action >= SPHINX) ? 0 : Res.TOWN_MAXES[_isDarkCc][action];
+ if (action < NO_ACTION) {
+ _songName = Res.TOWN_ACTION_MUSIC[_isDarkCc][action];
+ _townSprites.resize(Res.TOWN_ACTION_FILES[_isDarkCc][action]);
+ }
+
+ _animFrame = 0;
+ _drawFrameIndex = 0;
+ _farewellTime = 0;
+ _drawCtr1 = _drawCtr2 = 0;
+ _townPos = Common::Point(8, 8);
+}
+
+BaseLocation::~BaseLocation() {
+ Interface &intf = *g_vm->_interface;
+
+ for (uint idx = 0; idx < _townSprites.size(); ++idx)
+ _townSprites[idx].clear();
+ intf.mainIconsPrint();
+}
+
+int BaseLocation::show() {
+ Map &map = *g_vm->_map;
+ Party &party = *g_vm->_party;
+ Sound &sound = *g_vm->_sound;
+ Windows &windows = *g_vm->_windows;
+
+ // Play the appropriate music
+ sound.stopSound();
+ sound.playSong(_songName, 223);
+
+ // Load the needed sprite sets for the location
+ for (uint idx = 0; idx < _townSprites.size(); ++idx) {
+ Common::String shapesName = Common::String::format("%s%d.twn",
+ Res.TOWN_ACTION_SHAPES[_LocationActionId], idx + 1);
+ _townSprites[idx].load(shapesName);
+ }
+
+ Character *charP = &party._activeParty[0];
+
+ // Draw the background and the text window
+ drawBackground();
+ drawWindow();
+ drawAnim(true);
+
+ // Play the welcome speech
+ sound.playSound(_vocName, 1);
+
+ do {
+ wait();
+ charP = doOptions(charP);
+ if (_vm->shouldQuit())
+ return 0;
+
+ Common::String msg = createLocationText(*charP);
+ windows[10].writeString(msg);
+ drawButtons(&windows[0]);
+ } while (_buttonValue != Common::KEYCODE_ESCAPE);
+
+ // Handle any farewell message
+ farewell();
+
+ int result;
+ if (party._mazeId != 0) {
+ map.load(party._mazeId);
+ _farewellTime += 1440;
+ party.addTime(_farewellTime);
+ result = 0;
+ } else {
+ _vm->_saves->saveChars();
+ result = 2;
+ }
+
+ return result;
+}
+
+void BaseLocation::drawBackground() {
+ Interface &intf = *g_vm->_interface;
+
+ intf._face1UIFrame = intf._face2UIFrame = 0;
+ intf._dangerSenseUIFrame = 0;
+ intf._spotDoorsUIFrame = 0;
+ intf._levitateUIFrame = 0;
+ _townSprites[_drawFrameIndex / 8].draw(0, _drawFrameIndex % 8, _townPos);
+}
+
+void BaseLocation::drawWindow() {
+ Interface &intf = *g_vm->_interface;
+ Party &party = *g_vm->_party;
+ Windows &windows = *g_vm->_windows;
+
+ Character *charP = &party._activeParty[0];
+ Common::String title = createLocationText(*charP);
+
+ // Open up the window and write the string
+ intf.assembleBorder();
+ windows[10].open();
+ windows[10].writeString(title);
+ drawButtons(&windows[0]);
+
+ windows[0].update();
+ intf.highlightChar(0);
+}
+
+void BaseLocation::drawAnim(bool flag) {
+ Interface &intf = *g_vm->_interface;
+ Sound &sound = *g_vm->_sound;
+ Windows &windows = *g_vm->_windows;
+
+ // TODO: Figure out a clean way to split method into individual location classes
+ if (_LocationActionId == BLACKSMITH) {
+ if (sound.isPlaying()) {
+ if (_isDarkCc) {
+ _townSprites[_drawFrameIndex / 8].draw(0, _drawFrameIndex % 8, _townPos);
+ _townSprites[2].draw(0, _vm->getRandomNumber(11) == 1 ? 9 : 10,
+ Common::Point(34, 33));
+ _townSprites[2].draw(0, _vm->getRandomNumber(5) + 3,
+ Common::Point(34, 54));
+ }
+ } else {
+ _townSprites[_drawFrameIndex / 8].draw(0, _drawFrameIndex % 8, _townPos);
+ if (_isDarkCc) {
+ _townSprites[2].draw(0, _vm->getRandomNumber(11) == 1 ? 9 : 10,
+ Common::Point(34, 33));
+ }
+ }
+ } else if (!_isDarkCc || _LocationActionId != TRAINING) {
+ if (!_townSprites[_drawFrameIndex / 8].empty())
+ _townSprites[_drawFrameIndex / 8].draw(0, _drawFrameIndex % 8, _townPos);
+ }
+
+ switch (_LocationActionId) {
+ case BANK:
+ if (sound.isPlaying() || (_isDarkCc && _animFrame)) {
+ if (_isDarkCc) {
+ if (sound.isPlaying() || _animFrame == 1) {
+ _townSprites[4].draw(0, _vm->getRandomNumber(13, 18),
+ Common::Point(8, 30));
+ } else if (_animFrame > 1) {
+ _townSprites[4].draw(0, 13 - _animFrame++,
+ Common::Point(8, 30));
+ if (_animFrame > 14)
+ _animFrame = 0;
+ }
+ } else {
+ _townSprites[2].draw(0, _vm->getRandomNumber(7, 11), Common::Point(8, 8));
+ }
+ }
+ break;
+
+ case GUILD:
+ if (sound.isPlaying()) {
+ if (_isDarkCc) {
+ if (_animFrame) {
+ _animFrame ^= 1;
+ _townSprites[6].draw(0, _animFrame, Common::Point(8, 106));
+ } else {
+ _townSprites[6].draw(0, _vm->getRandomNumber(3), Common::Point(16, 48));
+ }
+ }
+ }
+ break;
+
+ case TAVERN:
+ if (sound.isPlaying() && _isDarkCc) {
+ _townSprites[4].draw(0, _vm->getRandomNumber(7), Common::Point(153, 49));
+ }
+ break;
+
+ case TEMPLE:
+ if (sound.isPlaying()) {
+ _townSprites[3].draw(0, _vm->getRandomNumber(2, 4), Common::Point(8, 8));
+
+ }
+ break;
+
+ case TRAINING:
+ if (sound.isPlaying()) {
+ if (_isDarkCc) {
+ _townSprites[_drawFrameIndex / 8].draw(0, _drawFrameIndex % 8, _townPos);
+ }
+ } else {
+ if (_isDarkCc) {
+ _townSprites[0].draw(0, ++_animFrame % 8, Common::Point(8, 8));
+ _townSprites[5].draw(0, _vm->getRandomNumber(5), Common::Point(61, 74));
+ } else {
+ _townSprites[1].draw(0, _vm->getRandomNumber(8, 12), Common::Point(8, 8));
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if (flag) {
+ intf._face1UIFrame = 0;
+ intf._face2UIFrame = 0;
+ intf._dangerSenseUIFrame = 0;
+ intf._spotDoorsUIFrame = 0;
+ intf._levitateUIFrame = 0;
+
+ intf.assembleBorder();
+ }
+
+ if (windows[11]._enabled) {
+ _drawCtr1 = (_drawCtr1 + 1) % 2;
+ if (!_drawCtr1 || !_drawCtr2) {
+ _drawFrameIndex = 0;
+ _drawCtr2 = 0;
+ } else {
+ _drawFrameIndex = _vm->getRandomNumber(3);
+ }
+ } else {
+ _drawFrameIndex = (_drawFrameIndex + 1) % _townMaxId;
+ }
+
+ if (_isDarkCc) {
+ if (_LocationActionId == BLACKSMITH && (_drawFrameIndex == 4 || _drawFrameIndex == 13))
+ sound.playFX(45);
+
+ if (_LocationActionId == TRAINING && _drawFrameIndex == 23) {
+ sound.playSound("spit1.voc");
+ }
+ } else {
+ if (_townMaxId == 32 && _drawFrameIndex == 0)
+ _drawFrameIndex = 17;
+ if (_townMaxId == 26 && _drawFrameIndex == 0)
+ _drawFrameIndex = 20;
+ if (_LocationActionId == BLACKSMITH && (_drawFrameIndex == 3 || _drawFrameIndex == 9))
+ sound.playFX(45);
+ }
+
+ windows[3].update();
+
+ if (_LocationActionId == BANK)
+ _animFrame = 2;
+}
+
+int BaseLocation::wait() {
+ EventsManager &events = *g_vm->_events;
+ Windows &windows = *g_vm->_windows;
+
+ _buttonValue = 0;
+ while (!_vm->shouldQuit() && !_buttonValue) {
+ events.updateGameCounter();
+ while (!_vm->shouldQuit() && !_buttonValue && events.timeElapsed() < 3) {
+ events.pollEventsAndWait();
+ checkEvents(_vm);
+ }
+ if (!_buttonValue)
+ drawAnim(!windows[11]._enabled);
+ }
+
+ return _buttonValue;
+}
+
+/*------------------------------------------------------------------------*/
+
+BankLocation::BankLocation() : BaseLocation(BANK) {
+ _icons1.load("bank.icn");
+ _icons2.load("bank2.icn");
+ addButton(Common::Rect(234, 108, 259, 128), Common::KEYCODE_d, &_icons1);
+ addButton(Common::Rect(261, 108, 285, 128), Common::KEYCODE_w, &_icons1);
+ addButton(Common::Rect(288, 108, 312, 128), Common::KEYCODE_ESCAPE, &_icons1);
+ _animFrame = 1;
+
+ _vocName = _isDarkCc ? "bank1.voc" : "banker.voc";
+}
+
+Common::String BankLocation::createLocationText(Character &ch) {
+ Party &party = *g_vm->_party;
+ return Common::String::format(Res.BANK_TEXT,
+ XeenEngine::printMil(party._bankGold).c_str(),
+ XeenEngine::printMil(party._bankGems).c_str(),
+ XeenEngine::printMil(party._gold).c_str(),
+ XeenEngine::printMil(party._gems).c_str());
+}
+
+void BankLocation::drawBackground() {
+ if (_isDarkCc) {
+ _townSprites[4].draw(0, _vm->getRandomNumber(13, 18),
+ Common::Point(8, 30));
+ }
+}
+
+Character *BankLocation::doOptions(Character *c) {
+ if (_buttonValue == Common::KEYCODE_d)
+ _buttonValue = (int)WHERE_PARTY;
+ else if (_buttonValue == Common::KEYCODE_w)
+ _buttonValue = (int)WHERE_BANK;
+ else
+ return c;
+
+ depositWithdrawl((PartyBank)_buttonValue);
+ return c;
+}
+
+void BankLocation::depositWithdrawl(PartyBank whereId) {
+ Party &party = *g_vm->_party;
+ Sound &sound = *g_vm->_sound;
+ Windows &windows = *g_vm->_windows;
+ int gold, gems;
+
+ if (whereId == WHERE_BANK) {
+ gold = party._bankGold;
+ gems = party._bankGems;
+ } else {
+ gold = party._gold;
+ gems = party._gems;
+ }
+
+ for (uint idx = 0; idx < _buttons.size(); ++idx)
+ _buttons[idx]._sprites = &_icons2;
+ _buttons[0]._value = Common::KEYCODE_o;
+ _buttons[1]._value = Common::KEYCODE_e;
+ _buttons[2]._value = Common::KEYCODE_ESCAPE;
+
+ Common::String msg = Common::String::format(Res.GOLD_GEMS,
+ Res.DEPOSIT_WITHDRAWL[whereId],
+ XeenEngine::printMil(gold).c_str(),
+ XeenEngine::printMil(gems).c_str());
+
+ windows[35].open();
+ windows[35].writeString(msg);
+ drawButtons(&windows[35]);
+ windows[35].update();
+
+ sound.stopSound();
+ File voc("coina.voc");
+ ConsumableType consType = CONS_GOLD;
+
+ do {
+ switch (wait()) {
+ case Common::KEYCODE_o:
+ consType = CONS_GOLD;
+ break;
+ case Common::KEYCODE_e:
+ consType = CONS_GEMS;
+ break;
+ case Common::KEYCODE_ESCAPE:
+ break;
+ default:
+ continue;
+ }
+
+ if ((whereId == WHERE_BANK && !party._bankGems && consType == CONS_GEMS) ||
+ (whereId == WHERE_BANK && !party._bankGold && consType == CONS_GOLD) ||
+ (whereId == WHERE_PARTY && !party._gems && consType == CONS_GEMS) ||
+ (whereId == WHERE_PARTY && !party._gold && consType == CONS_GOLD)) {
+ party.notEnough(consType, whereId, WHERE_BANK, WT_2);
+ } else {
+ windows[35].writeString(Res.AMOUNT);
+ int amount = NumericInput::show(_vm, 35, 10, 77);
+
+ if (amount) {
+ if (consType == CONS_GEMS) {
+ if (party.subtract(CONS_GEMS, amount, whereId, WT_2)) {
+ if (whereId == WHERE_BANK) {
+ party._gems += amount;
+ } else {
+ party._bankGems += amount;
+ }
+ }
+ } else {
+ if (party.subtract(CONS_GOLD, amount, whereId, WT_2)) {
+ if (whereId == WHERE_BANK) {
+ party._gold += amount;
+ } else {
+ party._bankGold += amount;
+ }
+ }
+ }
+ }
+
+ if (whereId == WHERE_BANK) {
+ gold = party._bankGold;
+ gems = party._bankGems;
+ }
+ else {
+ gold = party._gold;
+ gems = party._gems;
+ }
+
+ sound.playSound(voc);
+ msg = Common::String::format(Res.GOLD_GEMS_2, Res.DEPOSIT_WITHDRAWL[whereId],
+ XeenEngine::printMil(gold).c_str(), XeenEngine::printMil(gems).c_str());
+ windows[35].writeString(msg);
+ windows[35].update();
+ }
+ // TODO
+ } while (!g_vm->shouldQuit() && _buttonValue != Common::KEYCODE_ESCAPE);
+
+ for (uint idx = 0; idx < _buttons.size(); ++idx)
+ _buttons[idx]._sprites = &_icons1;
+ _buttons[0]._value = Common::KEYCODE_d;
+ _buttons[1]._value = Common::KEYCODE_w;
+ _buttons[2]._value = Common::KEYCODE_ESCAPE;
+}
+
+/*------------------------------------------------------------------------*/
+
+BlacksmithLocation::BlacksmithLocation() : BaseLocation(BLACKSMITH) {
+ _icons1.load("esc.icn");
+ addButton(Common::Rect(261, 108, 285, 128), Common::KEYCODE_ESCAPE, &_icons1);
+ addButton(Common::Rect(234, 54, 308, 62), 0);
+ addButton(Common::Rect(234, 64, 308, 72), Common::KEYCODE_b);
+ addButton(Common::Rect(234, 74, 308, 82), 0);
+ addButton(Common::Rect(234, 84, 308, 92), 0);
+
+ _vocName = _isDarkCc ? "see2.voc" : "whaddayo.voc";
+}
+
+Common::String BlacksmithLocation::createLocationText(Character &ch) {
+ Party &party = *g_vm->_party;
+ return Common::String::format(Res.BLACKSMITH_TEXT,
+ ch._name.c_str(), XeenEngine::printMil(party._gold).c_str());
+}
+
+Character *BlacksmithLocation::doOptions(Character *c) {
+ Interface &intf = *g_vm->_interface;
+ Party &party = *g_vm->_party;
+
+ if (_buttonValue >= Common::KEYCODE_F1 && _buttonValue <= Common::KEYCODE_F6) {
+ // Switch character
+ _buttonValue -= Common::KEYCODE_F1;
+ if (_buttonValue < (int)party._activeParty.size()) {
+ c = &party._activeParty[_buttonValue];
+ intf.highlightChar(_buttonValue);
+ }
+ } else if (_buttonValue == Common::KEYCODE_b) {
+ c = ItemsDialog::show(_vm, c, ITEMMODE_BLACKSMITH);
+ _buttonValue = 0;
+ }
+
+ return c;
+}
+
+void BlacksmithLocation::farewell() {
+ Sound &sound = *g_vm->_sound;
+
+ if (_isDarkCc) {
+ sound.stopSound();
+ sound.playSound("come1.voc", 1);
+ }
+}
+
+/*------------------------------------------------------------------------*/
+
+GuildLocation::GuildLocation() : BaseLocation(GUILD) {
+ loadStrings("spldesc.bin");
+ _icons1.load("esc.icn");
+ addButton(Common::Rect(261, 108, 285, 128), Common::KEYCODE_ESCAPE, &_icons1);
+ addButton(Common::Rect(234, 54, 308, 62), 0);
+ addButton(Common::Rect(234, 64, 308, 72), Common::KEYCODE_b);
+ addButton(Common::Rect(234, 74, 308, 82), Common::KEYCODE_s);
+ addButton(Common::Rect(234, 84, 308, 92), 0);
+ g_vm->_mode = MODE_17;
+
+ _vocName = _isDarkCc ? "parrot1.voc" : "guild10.voc";
+}
+
+Common::String GuildLocation::createLocationText(Character &ch) {
+ return !ch.guildMember() ? Res.GUILD_NOT_MEMBER_TEXT :
+ Common::String::format(Res.GUILD_TEXT, ch._name.c_str());
+}
+
+Character *GuildLocation::doOptions(Character *c) {
+ Interface &intf = *g_vm->_interface;
+ Party &party = *g_vm->_party;
+ Sound &sound = *g_vm->_sound;
+
+ if (_buttonValue >= Common::KEYCODE_F1 && _buttonValue <= Common::KEYCODE_F6) {
+ // Switch character
+ _buttonValue -= Common::KEYCODE_F1;
+ if (_buttonValue < (int)party._activeParty.size()) {
+ c = &party._activeParty[_buttonValue];
+ intf.highlightChar(_buttonValue);
+
+ if (!c->guildMember()) {
+ sound.stopSound();
+ _animFrame = 5;
+ sound.playSound(_isDarkCc ? "skull1.voc" : "guild11.voc", 1);
+ }
+ }
+ } else if (_buttonValue == Common::KEYCODE_s) {
+ if (c->guildMember())
+ c = SpellsDialog::show(_vm, nullptr, c, 0x80);
+ _buttonValue = 0;
+ } else if (_buttonValue == Common::KEYCODE_c) {
+ if (!c->noActions()) {
+ if (c->guildMember())
+ c = SpellsDialog::show(_vm, nullptr, c, 0);
+ _buttonValue = 0;
+ }
+ }
+
+ return c;
+}
+
+/*------------------------------------------------------------------------*/
+
+TavernLocation::TavernLocation() : BaseLocation(TAVERN) {
+ _v21 = 0;
+ _v22 = 0;
+ _v23 = 0;
+ _v24 = 0;
+
+ loadStrings("tavern.bin");
+ _icons1.load("tavern.icn");
+ addButton(Common::Rect(281, 108, 305, 128), Common::KEYCODE_ESCAPE, &_icons1);
+ addButton(Common::Rect(242, 108, 266, 128), Common::KEYCODE_s, &_icons1);
+ addButton(Common::Rect(234, 54, 308, 62), Common::KEYCODE_d);
+ addButton(Common::Rect(234, 64, 308, 72), Common::KEYCODE_f);
+ addButton(Common::Rect(234, 74, 308, 82), Common::KEYCODE_t);
+ addButton(Common::Rect(234, 84, 308, 92), Common::KEYCODE_r);
+ g_vm->_mode = MODE_17;
+
+ _vocName = _isDarkCc ? "hello1.voc" : "hello.voc";
+}
+
+Common::String TavernLocation::createLocationText(Character &ch) {
+ Party &party = *g_vm->_party;
+ return Common::String::format(Res.TAVERN_TEXT, ch._name.c_str(),
+ Res.FOOD_AND_DRINK, XeenEngine::printMil(party._gold).c_str());
+}
+
+Character *TavernLocation::doOptions(Character *c) {
+ Interface &intf = *g_vm->_interface;
+ Map &map = *g_vm->_map;
+ Party &party = *g_vm->_party;
+ Sound &sound = *g_vm->_sound;
+ Windows &windows = *g_vm->_windows;
+ int idx = 0;
+
+ 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:
+ // Switch character
+ _buttonValue -= Common::KEYCODE_F1;
+ if (_buttonValue < (int)party._activeParty.size()) {
+ c = &party._activeParty[_buttonValue];
+ intf.highlightChar(_buttonValue);
+ _v21 = 0;
+ }
+ break;
+
+ case Common::KEYCODE_d:
+ // Drink
+ if (!c->noActions()) {
+ if (party.subtract(CONS_GOLD, 1, WHERE_PARTY, WT_2)) {
+ sound.stopSound();
+ sound.playSound("gulp.voc");
+ _v21 = 1;
+
+ windows[10].writeString(Common::String::format(Res.TAVERN_TEXT,
+ c->_name.c_str(), Res.GOOD_STUFF,
+ XeenEngine::printMil(party._gold).c_str()));
+ drawButtons(&windows[0]);
+ windows[10].update();
+
+ if (_vm->getRandomNumber(100) < 26) {
+ ++c->_conditions[DRUNK];
+ intf.drawParty(true);
+ sound.playFX(28);
+ }
+
+ wait();
+ }
+ }
+ break;
+
+ case Common::KEYCODE_f: {
+ // Food
+ if (party._mazeId == (_isDarkCc ? 29 : 28)) {
+ _v22 = party._activeParty.size() * 15;
+ _v23 = 10;
+ idx = 0;
+ } else if (_isDarkCc && party._mazeId == 31) {
+ _v22 = party._activeParty.size() * 60;
+ _v23 = 100;
+ idx = 1;
+ } else if (!_isDarkCc && party._mazeId == 30) {
+ _v22 = party._activeParty.size() * 50;
+ _v23 = 50;
+ idx = 1;
+ } else if (_isDarkCc) {
+ _v22 = party._activeParty.size() * 120;
+ _v23 = 250;
+ idx = 2;
+ } else if (party._mazeId == 49) {
+ _v22 = party._activeParty.size() * 120;
+ _v23 = 100;
+ idx = 2;
+ } else {
+ _v22 = party._activeParty.size() * 15;
+ _v23 = 10;
+ idx = 0;
+ }
+
+ Common::String msg = _textStrings[(_isDarkCc ? 60 : 75) + idx];
+ windows[10].close();
+ windows[12].open();
+ windows[12].writeString(msg);
+ windows[12].update();
+
+ if (YesNo::show(_vm, false, true)) {
+ if (party._food >= _v22) {
+ ErrorScroll::show(_vm, Res.FOOD_PACKS_FULL, WT_2);
+ } else if (party.subtract(CONS_GOLD, _v23, WHERE_PARTY, WT_2)) {
+ party._food = _v22;
+ sound.stopSound();
+ sound.playSound(_isDarkCc ? "thanks2.voc" : "thankyou.voc", 1);
+ }
+ }
+
+ windows[12].close();
+ windows[10].open();
+ _buttonValue = 0;
+ break;
+ }
+
+ case Common::KEYCODE_r: {
+ // Rumors
+ if (party._mazeId == (_isDarkCc ? 29 : 28)) {
+ idx = 0;
+ } else if (party._mazeId == (_isDarkCc ? 31 : 30)) {
+ idx = 10;
+ } else if (_isDarkCc || party._mazeId == 49) {
+ idx = 20;
+ }
+
+ Common::String msg = Common::String::format("\x03""c\x0B""012%s",
+ _textStrings[(party._day % 10) + idx].c_str());
+ Window &w = windows[12];
+ w.open();
+ w.writeString(msg);
+ w.update();
+
+ wait();
+ w.close();
+ break;
+ }
+
+ case Common::KEYCODE_s: {
+ // Sign In
+ idx = _isDarkCc ? (party._mazeId - 29) >> 1 : party._mazeId - 28;
+ assert(idx >= 0);
+ party._mazePosition.x = Res.TAVERN_EXIT_LIST[_isDarkCc ? 1 : 0][_LocationActionId][idx][0];
+ party._mazePosition.y = Res.TAVERN_EXIT_LIST[_isDarkCc ? 1 : 0][_LocationActionId][idx][1];
+
+ if (!_isDarkCc || party._mazeId == 29)
+ party._mazeDirection = DIR_WEST;
+ else if (party._mazeId == 31)
+ party._mazeDirection = DIR_EAST;
+ else
+ party._mazeDirection = DIR_SOUTH;
+
+ party._priorMazeId = party._mazeId;
+ for (idx = 0; idx < (int)party._activeParty.size(); ++idx) {
+ party._activeParty[idx]._savedMazeId = party._mazeId;
+ party._activeParty[idx]._xeenSide = map._loadDarkSide;
+ }
+
+ party.addTime(1440);
+ party._mazeId = 0;
+ _vm->_quitMode = 2;
+ break;
+ }
+
+ case Common::KEYCODE_t:
+ if (!c->noActions()) {
+ if (!_v21) {
+ windows[10].writeString(Common::String::format(Res.TAVERN_TEXT,
+ c->_name.c_str(), Res.HAVE_A_DRINK,
+ XeenEngine::printMil(party._gold).c_str()));
+ drawButtons(&windows[0]);
+ windows[10].update();
+ wait();
+ } else {
+ _v21 = 0;
+ if (c->_conditions[DRUNK]) {
+ windows[10].writeString(Common::String::format(Res.TAVERN_TEXT,
+ c->_name.c_str(), Res.YOURE_DRUNK,
+ XeenEngine::printMil(party._gold).c_str()));
+ drawButtons(&windows[0]);
+ windows[10].update();
+ wait();
+ } else if (party.subtract(CONS_GOLD, 1, WHERE_PARTY, WT_2)) {
+ sound.stopSound();
+ sound.playSound(_isDarkCc ? "thanks2.voc" : "thankyou.voc", 1);
+
+ if (party._mazeId == (_isDarkCc ? 29 : 28)) {
+ _v24 = 30;
+ } else if (_isDarkCc && party._mazeId == 31) {
+ _v24 = 40;
+ } else if (!_isDarkCc && party._mazeId == 45) {
+ _v24 = 45;
+ } else if (!_isDarkCc && party._mazeId == 49) {
+ _v24 = 60;
+ } else if (_isDarkCc) {
+ _v24 = 50;
+ }
+
+ Common::String msg = _textStrings[map.mazeData()._tavernTips + _v24];
+ map.mazeData()._tavernTips = (map.mazeData()._tavernTips + 1) /
+ (_isDarkCc ? 10 : 15);
+
+ Window &w = windows[12];
+ w.open();
+ w.writeString(Common::String::format("\x03""c\x0B""012%s", msg.c_str()));
+ w.update();
+ wait();
+ w.close();
+ }
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return c;
+}
+
+void TavernLocation::farewell() {
+ Map &map = *g_vm->_map;
+ Party &party = *g_vm->_party;
+ Sound &sound = *g_vm->_sound;
+
+ sound.stopSound();
+ sound.playSound(_isDarkCc ? "gdluck1.voc" : "goodbye.voc", 1);
+
+ map.mazeData()._mazeNumber = party._mazeId;
+}
+
+/*------------------------------------------------------------------------*/
+
+TempleLocation::TempleLocation() : BaseLocation(TEMPLE) {
+ _currentCharLevel = 0;
+ _donation = 0;
+ _healCost = 0;
+ _uncurseCost = 0;
+ _dayOfWeek = 0;
+ _v10 = _v11 = 0;
+ _v12 = _v13 = 0;
+ _v14 = 0;
+ _flag1 = false;
+ _v5 = _v6 = 0;
+
+ _icons1.load("esc.icn");
+ addButton(Common::Rect(261, 108, 285, 128), Common::KEYCODE_ESCAPE, &_icons1);
+ addButton(Common::Rect(234, 54, 308, 62), Common::KEYCODE_h);
+ addButton(Common::Rect(234, 64, 308, 72), Common::KEYCODE_d);
+ addButton(Common::Rect(234, 74, 308, 82), Common::KEYCODE_u);
+ addButton(Common::Rect(234, 84, 308, 92), 0);
+
+ _vocName = _isDarkCc ? "help2.voc" : "maywe2.voc";
+}
+
+Common::String TempleLocation::createLocationText(Character &ch) {
+ Party &party = *g_vm->_party;
+
+ if (party._mazeId == (_isDarkCc ? 29 : 28)) {
+ _v10 = _v11 = _v12 = _v13 = 0;
+ _v14 = 10;
+ } else if (party._mazeId == (_isDarkCc ? 31 : 30)) {
+ _v13 = 10;
+ _v12 = 50;
+ _v11 = 500;
+ _v10 = 100;
+ _v14 = 25;
+ } else if (party._mazeId == (_isDarkCc ? 37 : 73)) {
+ _v13 = 20;
+ _v12 = 100;
+ _v11 = 1000;
+ _v10 = 200;
+ _v14 = 50;
+ } else if (_isDarkCc || party._mazeId == 49) {
+ _v13 = 100;
+ _v12 = 500;
+ _v11 = 5000;
+ _v10 = 300;
+ _v14 = 100;
+ }
+
+ _currentCharLevel = ch.getCurrentLevel();
+ if (ch._currentHp < ch.getMaxHP()) {
+ _healCost = _currentCharLevel * 10 + _v13;
+ }
+
+ for (int attrib = HEART_BROKEN; attrib <= UNCONSCIOUS; ++attrib) {
+ if (ch._conditions[attrib])
+ _healCost += _currentCharLevel * 10;
+ }
+
+ _v6 = 0;
+ if (ch._conditions[DEAD]) {
+ _v6 += (_currentCharLevel * 100) + (ch._conditions[DEAD] * 50) + _v12;
+ }
+ if (ch._conditions[STONED]) {
+ _v6 += (_currentCharLevel * 100) + (ch._conditions[STONED] * 50) + _v12;
+ }
+ if (ch._conditions[ERADICATED]) {
+ _v5 = (_currentCharLevel * 1000) + (ch._conditions[ERADICATED] * 500) + _v11;
+ }
+
+ for (int idx = 0; idx < 9; ++idx) {
+ _uncurseCost |= ch._weapons[idx]._bonusFlags & 0x40;
+ _uncurseCost |= ch._armor[idx]._bonusFlags & 0x40;
+ _uncurseCost |= ch._accessories[idx]._bonusFlags & 0x40;
+ _uncurseCost |= ch._misc[idx]._bonusFlags & 0x40;
+ }
+
+ if (_uncurseCost || ch._conditions[CURSED])
+ _v5 = (_currentCharLevel * 20) + _v10;
+
+ _donation = _flag1 ? 0 : _v14;
+ _healCost += _v6 + _v5;
+
+ return Common::String::format(Res.TEMPLE_TEXT, ch._name.c_str(),
+ _healCost, _donation, XeenEngine::printK(_uncurseCost).c_str(),
+ XeenEngine::printMil(party._gold).c_str());
+}
+
+Character *TempleLocation::doOptions(Character *c) {
+ Interface &intf = *g_vm->_interface;
+ Party &party = *g_vm->_party;
+ Sound &sound = *g_vm->_sound;
+
+ 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:
+ // Switch character
+ _buttonValue -= Common::KEYCODE_F1;
+ if (_buttonValue < (int)party._activeParty.size()) {
+ c = &party._activeParty[_buttonValue];
+ intf.highlightChar(_buttonValue);
+ _dayOfWeek = 0;
+ }
+ break;
+
+ case Common::KEYCODE_d:
+ if (_donation && party.subtract(CONS_GOLD, _donation, WHERE_PARTY, WT_2)) {
+ sound.stopSound();
+ sound.playSound("coina.voc", 1);
+ _dayOfWeek = (_dayOfWeek + 1) / 10;
+
+ if (_dayOfWeek == (party._day / 10)) {
+ party._clairvoyanceActive = true;
+ party._lightCount = 1;
+
+ int amt = _dayOfWeek ? _dayOfWeek : 10;
+ party._heroism = amt;
+ party._holyBonus = amt;
+ party._powerShield = amt;
+ party._blessed = amt;
+
+ intf.drawParty(true);
+ sound.stopSound();
+ sound.playSound("ahh.voc");
+ _flag1 = true;
+ _donation = 0;
+ }
+ }
+ break;
+
+ case Common::KEYCODE_h:
+ if (_healCost && party.subtract(CONS_GOLD, _healCost, WHERE_PARTY, WT_2)) {
+ c->_magicResistence._temporary = 0;
+ c->_energyResistence._temporary = 0;
+ c->_poisonResistence._temporary = 0;
+ c->_electricityResistence._temporary = 0;
+ c->_coldResistence._temporary = 0;
+ c->_fireResistence._temporary = 0;
+ c->_ACTemp = 0;
+ c->_level._temporary = 0;
+ c->_luck._temporary = 0;
+ c->_accuracy._temporary = 0;
+ c->_speed._temporary = 0;
+ c->_endurance._temporary = 0;
+ c->_personality._temporary = 0;
+ c->_intellect._temporary = 0;
+ c->_might._temporary = 0;
+ c->_currentHp = c->getMaxHP();
+ Common::fill(&c->_conditions[HEART_BROKEN], &c->_conditions[NO_CONDITION], 0);
+
+ _farewellTime = 1440;
+ intf.drawParty(true);
+ sound.stopSound();
+ sound.playSound("ahh.voc", 1);
+ }
+ break;
+
+ case Common::KEYCODE_u:
+ if (_uncurseCost && party.subtract(CONS_GOLD, _uncurseCost, WHERE_PARTY, WT_2)) {
+ for (int idx = 0; idx < 9; ++idx) {
+ c->_weapons[idx]._bonusFlags &= ~ITEMFLAG_CURSED;
+ c->_armor[idx]._bonusFlags &= ~ITEMFLAG_CURSED;
+ c->_accessories[idx]._bonusFlags &= ~ITEMFLAG_CURSED;
+ c->_misc[idx]._bonusFlags &= ~ITEMFLAG_CURSED;
+ }
+
+ _farewellTime = 1440;
+ intf.drawParty(true);
+ sound.stopSound();
+ sound.playSound("ahh.voc", 1);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return c;
+}
+
+/*------------------------------------------------------------------------*/
+
+TrainingLocation::TrainingLocation() : BaseLocation(TRAINING) {
+ Common::fill(&_charsTrained[0], &_charsTrained[6], 0);
+ _maxLevel = 0;
+ _experienceToNextLevel = 0;
+ _charIndex = 0;
+
+ _icons1.load("train.icn");
+ addButton(Common::Rect(281, 108, 305, 128), Common::KEYCODE_ESCAPE, &_icons1);
+ addButton(Common::Rect(242, 108, 266, 128), Common::KEYCODE_t, &_icons1);
+
+ _vocName = _isDarkCc ? "training.voc" : "youtrn1.voc";
+}
+
+Common::String TrainingLocation::createLocationText(Character &ch) {
+ Party &party = *g_vm->_party;
+ if (_isDarkCc) {
+ switch (party._mazeId) {
+ case 29:
+ // Castleview
+ _maxLevel = 30;
+ break;
+ case 31:
+ // Sandcaster
+ _maxLevel = 50;
+ break;
+ case 37:
+ // Olympus
+ _maxLevel = 200;
+ break;
+ default:
+ // Kalindra's Castle
+ _maxLevel = 100;
+ break;
+ }
+ } else {
+ switch (party._mazeId) {
+ case 28:
+ // Vertigo
+ _maxLevel = 10;
+ break;
+ case 30:
+ // Rivercity
+ _maxLevel = 15;
+ break;
+ default:
+ // Newcastle
+ _maxLevel = 20;
+ break;
+ }
+ }
+
+ _experienceToNextLevel = ch.experienceToNextLevel();
+
+ Common::String msg;
+ if (_experienceToNextLevel && ch._level._permanent < _maxLevel) {
+ // Need more experience
+ int nextLevel = ch._level._permanent + 1;
+ msg = Common::String::format(Res.EXPERIENCE_FOR_LEVEL,
+ ch._name.c_str(), _experienceToNextLevel, nextLevel);
+ } else if (ch._level._permanent >= _maxLevel) {
+ // At maximum level
+ _experienceToNextLevel = 1;
+ msg = Common::String::format(Res.LEARNED_ALL, ch._name.c_str());
+ } else {
+ // Eligble for level increase
+ msg = Common::String::format(Res.ELIGIBLE_FOR_LEVEL,
+ ch._name.c_str(), ch._level._permanent + 1);
+ }
+
+ return Common::String::format(Res.TRAINING_TEXT, msg.c_str(),
+ XeenEngine::printMil(party._gold).c_str());
+}
+
+Character *TrainingLocation::doOptions(Character *c) {
+ Interface &intf = *g_vm->_interface;
+ Party &party = *g_vm->_party;
+ Sound &sound = *g_vm->_sound;
+
+ 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:
+ // Switch character
+ _buttonValue -= Common::KEYCODE_F1;
+ if (_buttonValue < (int)party._activeParty.size()) {
+ _charIndex = _buttonValue;
+ c = &party._activeParty[_buttonValue];
+ intf.highlightChar(_buttonValue);
+ }
+ break;
+
+ case Common::KEYCODE_t:
+ if (_experienceToNextLevel) {
+ sound.stopSound();
+ _drawFrameIndex = 0;
+
+ Common::String name;
+ if (c->_level._permanent >= _maxLevel) {
+ name = _isDarkCc ? "gtlost.voc" : "trainin1.voc";
+ } else {
+ name = _isDarkCc ? "gtlost.voc" : "trainin0.voc";
+ }
+
+ sound.playSound(name);
+
+ } else if (!c->noActions()) {
+ if (party.subtract(CONS_GOLD, (c->_level._permanent * c->_level._permanent) * 10, WHERE_PARTY, WT_2)) {
+ _drawFrameIndex = 0;
+ sound.stopSound();
+ sound.playSound(_isDarkCc ? "prtygd.voc" : "trainin2.voc", 1);
+
+ c->_experience -= c->nextExperienceLevel() -
+ (c->getCurrentExperience() - c->_experience);
+ c->_level._permanent++;
+
+ if (!_charsTrained[_charIndex]) {
+ party.addTime(1440);
+ _charsTrained[_charIndex] = true;
+ }
+
+ party.resetTemps();
+ c->_currentHp = c->getMaxHP();
+ c->_currentSp = c->getMaxSP();
+ intf.drawParty(true);
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return c;
+}
+
+/*------------------------------------------------------------------------*/
+
+ArenaLocation::ArenaLocation() : BaseLocation(ARENA) {
+ // TODO
+}
+
+/*------------------------------------------------------------------------*/
+
+CutsceneLocation::CutsceneLocation(LocationAction action) : BaseLocation(action),
+ _animCtr(0), _mazeFlag(false) {
+ Party &party = *g_vm->_party;
+ _mazeId = party._mazeId;
+ _mazePos = party._mazePosition;
+ _mazeDir = party._mazeDirection;
+}
+
+void CutsceneLocation::cutsceneAnimUpdate() {
+ // TODO
+}
+
+void CutsceneLocation::setNewLocation() {
+ Map &map = *g_vm->_map;
+ Party &party = *g_vm->_party;
+ map.load(_mazeId);
+ party._mazePosition = _mazePos;
+ party._mazeDirection = _mazeDir;
+}
+
+/*------------------------------------------------------------------------*/
+
+ReaperCutscene::ReaperCutscene() : CutsceneLocation(REAPER) {
+ // TODO
+}
+
+/*------------------------------------------------------------------------*/
+
+GolemCutscene::GolemCutscene() : CutsceneLocation(GOLEM) {
+ // TODO
+}
+
+/*------------------------------------------------------------------------*/
+
+const int16 DWARF_X0[2][13] = {
+ { 0, -5, -7, -8, -11, -9, -3, 1, 6, 10, 15, 18, 23 },
+ { 0, 4, 6, 8, 11, 12, 15, 17, 19, 22, 25, 0, 0 }
+};
+const int DWARF_X1[2][13] = {
+ { 160, 145, 133, 122, 109, 101, 97, 91, 86, 80, 75, 68, 63 },
+ { 160, 154, 146, 138, 131, 122, 115, 107, 99, 92, 85, 0, 0 }
+};
+const int DWARF_X2[13] = {
+ 0, -1, -4, -7, -9, -13, -15, -18, -21, -23, -25, 0, 0
+};
+const int16 DWARF_Y[2][13] = {
+ { 0, 0, 4, 9, 13, 15, 20, 24, 30, 37, 45, 51, 58 },
+ { 0, 12, 25, 36, 38, 40, 41, 42, 44, 45, 50, 0, 0 }
+};
+const int16 DWARF2_X[2][16] = {
+ { 0, -2, -4, -6, -8, -10, -12, -14, -16, -18, -20, -20, -20, -20, -20, -20 },
+ { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150 }
+};
+const int16 DWARF2_Y[2][16] = {
+ { 0, 12, 25, 37, 50, 62, 75, 87, 100, 112, 125, 137, 150, 162, 175, 187 },
+ { 0, 12, 25, 37, 50, 62, 75, 87, 100, 112, 125, 137, 150, 162, 175, 186 }
+};
+
+DwarfCutscene::DwarfCutscene(bool isDwarf) : CutsceneLocation(NO_ACTION) {
+ _townMaxId = Res.TOWN_MAXES[_isDarkCc][isDwarf ? DWARF1 : DWARF2];
+}
+
+int DwarfCutscene::show() {
+ EventsManager &events = *g_vm->_events;
+ Interface &intf = *g_vm->_interface;
+ Screen &screen = *g_vm->_screen;
+ Sound &sound = *g_vm->_sound;
+ Windows &windows = *g_vm->_windows;
+
+ SpriteResource sprites1(_isDarkCc ? "town1.zom" : "dwarf1.vga");
+ SpriteResource sprites2(_isDarkCc ? "town2.zom" : "dwarf2.vga");
+ SpriteResource sprites3(_isDarkCc ? "town3.zom" : "dwarf3.vga");
+ SpriteResource boxSprites("box.vga");
+ getNewLocation();
+
+ // Save the screen contents
+ Graphics::ManagedSurface savedBg;
+ savedBg.copyFrom(screen);
+
+ for (int idx = 0; idx < (_isDarkCc ? 10 : 12); ++idx) {
+ screen.copyFrom(savedBg);
+ sprites1.draw(0, 0,
+ Common::Point(DWARF_X0[_isDarkCc][idx], DWARF_Y[_isDarkCc][idx]));
+ sprites1.draw(0, 1,
+ Common::Point(DWARF_X1[_isDarkCc][idx], DWARF_Y[_isDarkCc][idx]));
+ if (_isDarkCc)
+ sprites1.draw(0, 2,
+ Common::Point(DWARF_X2[idx], DWARF_Y[_isDarkCc][idx]));
+
+ windows[0].update();
+ events.wait(1);
+ }
+
+ savedBg.copyFrom(screen);
+ for (int idx = 15; idx >= 0; --idx) {
+ screen.copyFrom(savedBg);
+ sprites2.draw(0, 0, Common::Point(DWARF2_X[_isDarkCc][idx], DWARF2_Y[_isDarkCc][idx]));
+ windows[0].update();
+ events.wait(1);
+ }
+
+ sound.setMusicVolume(48);
+ screen.copyFrom(savedBg);
+ sprites2.draw(0, 0);
+ windows[0].update();
+
+ for (int idx = 0; idx < (_isDarkCc ? 2 : 3); ++idx) {
+ switch (idx) {
+ case 0:
+ sound.playSound(_isDarkCc ? "pass2.voc" : "dwarf10.voc");
+ break;
+
+ case 1:
+ if (_isDarkCc) {
+ sprites2.draw(0, 0);
+ sprites3.draw(0, 0);
+ cutsceneAnimUpdate();
+
+ events.timeMark5();
+ while (!g_vm->shouldQuit() && events.timeElapsed5() < 7)
+ events.pollEventsAndWait();
+
+ sound.playSound(_mazeFlag ? "ok2.voc" : "back2.voc");
+ } else {
+ sound.playSound("dwarf11.voc");
+ }
+ break;
+
+ case 2:
+ sound.playSound("dwarf12.voc");
+ break;
+ }
+
+ events.updateGameCounter();
+ do {
+ sprites2.draw(0, 0);
+ sprites3.draw(0, g_vm->getRandomNumber(_isDarkCc ? 8 : 9));
+ cutsceneAnimUpdate();
+
+ events.timeMark5();
+ while (!g_vm->shouldQuit() && events.timeElapsed5() < 2)
+ events.pollEventsAndWait();
+ } while (!g_vm->shouldQuit() && (sound.isPlaying() || _animCtr));
+
+ while (!g_vm->shouldQuit() && events.timeElapsed() < 3)
+ events.pollEventsAndWait();
+ }
+
+ sprites2.draw(0, 0);
+ if (!_isDarkCc)
+ sprites3.draw(0, 1);
+ windows[0].update();
+
+ setNewLocation();
+
+ // Restore game screen
+ sound.setMusicVolume(95);
+ screen.loadBackground("back.raw");
+ intf.drawParty(false);
+ intf.draw3d(false, false);
+
+ events.clearEvents();
+ return 0;
+}
+
+void DwarfCutscene::getNewLocation() {
+ Party &party = *g_vm->_party;
+
+ if (_isDarkCc) {
+ switch (party._mazeId) {
+ case 4:
+ if (party._questItems[35]) {
+ _mazeId = 29;
+ _mazePos = Common::Point(15, 31);
+ _mazeDir = DIR_SOUTH;
+ }
+ break;
+
+ case 6:
+ if (party._questItems[38]) {
+ _mazeId = 35;
+ _mazePos = Common::Point(15, 8);
+ _mazeDir = DIR_WEST;
+ }
+ break;
+
+ case 19:
+ if (party._questItems[36]) {
+ _mazeId = 31;
+ _mazePos = Common::Point(31, 16);
+ _mazeDir = DIR_WEST;
+ }
+ break;
+
+ case 22:
+ if (party._questItems[37]) {
+ _mazeId = 33;
+ _mazePos = Common::Point(0, 3);
+ _mazeDir = DIR_EAST;
+ }
+ break;
+
+ case 98:
+ if (party._questItems[39]) {
+ _mazeId = 37;
+ _mazePos = Common::Point(7, 0);
+ _mazeDir = DIR_NORTH;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ _mazeFlag = _mazeId != 0;
+ } else {
+ switch (party._mazeId) {
+ case 14:
+ _mazeId = 37;
+ _mazePos = Common::Point(1, 4);
+ _mazeDir = DIR_EAST;
+ break;
+
+ case 18:
+ if (party._mazePosition.x == 9) {
+ _mazeId = 35;
+ _mazePos = Common::Point(1, 12);
+ _mazeDir = DIR_EAST;
+ } else {
+ _mazeId = 36;
+ _mazePos = Common::Point(7, 1);
+ _mazeDir = DIR_NORTH;
+ }
+ break;
+
+ case 23:
+ if (party._mazePosition.x == 5) {
+ _mazeId = 33;
+ _mazePos = Common::Point(7, 1);
+ _mazeDir = DIR_NORTH;
+ } else {
+ _mazeId = 34;
+ _mazePos = Common::Point(7, 30);
+ _mazeDir = DIR_SOUTH;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+/*------------------------------------------------------------------------*/
+
+SphinxCutscene::SphinxCutscene() : CutsceneLocation(SPHINX) {
+ SpriteResource sprites1("sphinx.vga");
+ _boxSprites.load("box.vga");
+
+
+ // TODO
+}
+
+void SphinxCutscene::getNewLocation() {
+ Map &map = *g_vm->_map;
+ Party &party = *g_vm->_party;
+
+ switch (party._mazeId) {
+ case 2:
+ if (party._questItems[51]) {
+ map._loadDarkSide = true;
+ _mazeId = 125;
+ _mazePos = Common::Point(7, 6);
+ _mazeDir = DIR_NORTH;
+ _mazeFlag = true;
+ }
+ break;
+
+ case 5:
+ if (party._questItems[4]) {
+ _mazeId = 82;
+ _mazePos = Common::Point(7, 5);
+ _mazeDir = DIR_NORTH;
+ _mazeFlag = true;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ if (!_mazeFlag) {
+ _mazeId = party._mazeId;
+ _mazePos = party._mazePosition;
+ _mazeDir = party._mazeDirection;
+ }
+}
+
+
+/*------------------------------------------------------------------------*/
+
+PyramidLocation::PyramidLocation() : BaseLocation(PYRAMID) {
+}
+
+int PyramidLocation::show() {
+ EventsManager &events = *g_vm->_events;
+ Map &map = *g_vm->_map;
+ Party &party = *g_vm->_party;
+ Windows &windows = *g_vm->_windows;
+ int mapId;
+ Direction dir = DIR_NORTH;
+ Common::Point pt;
+
+ if (g_vm->getGameID() == GType_WorldOfXeen) {
+ if (_isDarkCc) {
+ if (party._mazeId == 52) {
+ mapId = 49;
+ pt = Common::Point(7, 14);
+ dir = DIR_SOUTH;
+ } else {
+ mapId = 23;
+ pt = Common::Point(8, 10);
+ }
+ } else {
+ if (party._mazeId == 49) {
+ mapId = 52;
+ pt = Common::Point(2, 2);
+ } else {
+ mapId = 29;
+ pt = Common::Point(25, 21);
+ }
+ }
+
+ // Load the destination map and set position and direction
+ map._loadDarkSide = !_isDarkCc;
+ map.load(mapId);
+ party._mazePosition = pt;
+ party._mazeDirection = dir;
+ } else {
+ // Playing Clouds or Dark Side on it's own, so can't switch sides
+ Window &win = windows[12];
+ Common::String msg = Common::String::format(Res.MOONS_NOT_ALIGNED,
+ _isDarkCc ? "Clouds" : "Darkside");
+ win.open();
+ win.writeString(msg);
+ win.update();
+
+ events.waitForPressAnimated();
+ win.close();
+ }
+
+ return 0;
+}
+
+} // End of namespace Locations
+
+/*------------------------------------------------------------------------*/
+
+LocationManager::LocationManager() : _location(nullptr) {
+}
+
+int LocationManager::doAction(LocationAction actionId) {
+ // Create the desired location
+ switch (actionId) {
+ case BANK:
+ _location = new Locations::BankLocation();
+ break;
+ case BLACKSMITH:
+ _location = new Locations::BlacksmithLocation();
+ break;
+ case GUILD:
+ _location = new Locations::GuildLocation();
+ break;
+ case TAVERN:
+ _location = new Locations::TavernLocation();
+ break;
+ case TEMPLE:
+ _location = new Locations::TempleLocation();
+ break;
+ case TRAINING:
+ _location = new Locations::TrainingLocation();
+ break;
+ case ARENA:
+ _location = new Locations::ArenaLocation();
+ break;
+ case REAPER:
+ _location = new Locations::ReaperCutscene();
+ break;
+ case GOLEM:
+ _location = new Locations::GolemCutscene();
+ break;
+ case DWARF1:
+ _location = new Locations::DwarfCutscene(true);
+ break;
+ case DWARF2:
+ _location = new Locations::DwarfCutscene(false);
+ break;
+ case SPHINX:
+ _location = new Locations::SphinxCutscene();
+ break;
+ case PYRAMID:
+ _location = new Locations::PyramidLocation();
+ break;
+ default:
+ return 0;
+ }
+
+ // Show the location
+ int result = _location->show();
+ delete _location;
+ _location = nullptr;
+
+ return result;
+}
+
+bool LocationManager::isActive() const {
+ return _location != nullptr;
+}
+
+void LocationManager::drawAnim(bool flag) {
+ if (_location)
+ _location->drawAnim(flag);
+}
+
+/*------------------------------------------------------------------------*/
+
+bool LocationMessage::show(int portrait, const Common::String &name,
+ const Common::String &text, int confirm) {
+ LocationMessage *dlg = new LocationMessage();
+ bool result = dlg->execute(portrait, name, text, confirm);
+ delete dlg;
+
+ return result;
+}
+
+bool LocationMessage::execute(int portrait, const Common::String &name, const Common::String &text,
+ int confirm) {
+ EventsManager &events = *g_vm->_events;
+ Interface &intf = *g_vm->_interface;
+ Map &map = *g_vm->_map;
+ Party &party = *g_vm->_party;
+ Resources &res = *g_vm->_resources;
+ Windows &windows = *g_vm->_windows;
+ Window &w = windows[11];
+
+ _townMaxId = 4;
+ _drawFrameIndex = 0;
+ _townPos = Common::Point(23, 22);
+
+ if (!confirm)
+ loadButtons();
+
+ _townSprites.resize(2);
+ _townSprites[0].load(Common::String::format("face%02d.fac", portrait));
+ _townSprites[1].load("frame.fac");
+
+ if (!w._enabled)
+ w.open();
+
+ int result = -1;
+ Common::String msgText = text;
+ do {
+ Common::String msg = Common::String::format("\r\v014\x03""c\t125%s\t000\v054%s",
+ name.c_str(), msgText.c_str());
+
+ // Count the number of words
+ const char *msgEnd = w.writeString(msg);
+ int wordCount = 0;
+
+ for (const char *msgP = msg.c_str(); msgP != msgEnd && *msgP; ++msgP) {
+ if (*msgP == ' ')
+ ++wordCount;
+ }
+
+ _drawCtr2 = wordCount * 2; // Set timeout
+ _townSprites[1].draw(0, 0, Common::Point(16, 16));
+ _townSprites[0].draw(0, _drawFrameIndex, Common::Point(23, 22));
+ w.update();
+
+ if (!msgEnd && !confirm) {
+ res._globalSprites.draw(0, 7, Common::Point(232, 74));
+ res._globalSprites.draw(0, 0, Common::Point(235, 75));
+ res._globalSprites.draw(0, 2, Common::Point(260, 75));
+ windows[34].update();
+
+ intf._face1State = map._headData[party._mazePosition.y][party._mazePosition.x]._left;
+ intf._face2State = map._headData[party._mazePosition.y][party._mazePosition.x]._right;
+ }
+
+ if (confirm == 2) {
+ intf._face1State = intf._face2State = 2;
+ return false;
+ }
+
+ do {
+ events.clearEvents();
+ events.updateGameCounter();
+ if (msgEnd)
+ clearButtons();
+
+ do {
+ events.pollEventsAndWait();
+ checkEvents(_vm);
+
+ if (_vm->shouldQuit())
+ return false;
+
+ while (events.timeElapsed() >= 3) {
+ drawAnim(false);
+ events.updateGameCounter();
+ }
+ } while (!_buttonValue);
+
+ if (msgEnd)
+ // Another screen of text remaining
+ break;
+
+ if (confirm || _buttonValue == Common::KEYCODE_ESCAPE ||
+ _buttonValue == Common::KEYCODE_n)
+ result = 0;
+ else if (_buttonValue == Common::KEYCODE_y)
+ result = 1;
+ } while (result == -1);
+
+ if (msgEnd) {
+ // Text remaining, so cut off already displayed page's
+ msgText = Common::String(msgEnd);
+ _drawCtr2 = wordCount;
+ continue;
+ }
+ } while (result == -1);
+
+ intf._face1State = intf._face2State = 2;
+ if (!confirm)
+ intf.mainIconsPrint();
+
+ _townSprites[0].clear();
+ _townSprites[1].clear();
+ events.clearEvents();
+ return result == 1;
+}
+
+void LocationMessage::loadButtons() {
+ _iconSprites.load("confirm.icn");
+
+ addButton(Common::Rect(235, 75, 259, 95), Common::KEYCODE_y, &_iconSprites);
+ addButton(Common::Rect(260, 75, 284, 95), Common::KEYCODE_n, &_iconSprites);
+ addButton(Common::Rect(), Common::KEYCODE_ESCAPE);
+}
+
+} // End of namespace Xeen