scummvm/engines/xeen/town.cpp
2016-10-09 14:59:58 +02:00

1297 lines
32 KiB
C++

/* 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/town.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 {
Town::Town(XeenEngine *vm) : ButtonContainer(vm) {
Common::fill(&_arr1[0], &_arr1[6], 0);
_townMaxId = 0;
_townActionId = 0;
_drawFrameIndex = 0;
_currentCharLevel = 0;
_v1 = 0;
_v2 = 0;
_donation = 0;
_healCost = 0;
_v5 = _v6 = 0;
_v10 = _v11 = 0;
_v12 = _v13 = 0;
_v14 = 0;
_v20 = 0;
_v21 = 0;
_v22 = 0;
_v23 = 0;
_v24 = 0;
_dayOfWeek = 0;
_uncurseCost = 0;
_flag1 = false;
_experienceToNextLevel = 0;
_drawCtr1 = _drawCtr2 = 0;
}
void Town::loadStrings(const Common::String &name) {
File f(name);
_textStrings.clear();
while (f.pos() < f.size())
_textStrings.push_back(f.readString());
f.close();
}
int Town::townAction(int actionId) {
Interface &intf = *_vm->_interface;
Map &map = *_vm->_map;
Party &party = *_vm->_party;
Screen &screen = *_vm->_screen;
Sound &sound = *_vm->_sound;
bool isDarkCc = _vm->_files->_isDarkCc;
if (actionId == 12) {
pyramidEvent();
return 0;
}
_townMaxId = Res.TOWN_MAXES[_vm->_files->_isDarkCc][actionId];
_townActionId = actionId;
_drawFrameIndex = 0;
_v1 = 0;
_townPos = Common::Point(8, 8);
intf._overallFrame = 0;
// This area sets up the GUI buttos and startup sample to play for the
// given town action
Common::String vocName = "hello1.voc";
clearButtons();
_icons1.clear();
_icons2.clear();
switch (actionId) {
case 0:
// 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);
intf._overallFrame = 1;
sound.stopSound();
vocName = isDarkCc ? "bank1.voc" : "banker.voc";
break;
case 1:
// Blacksmith
_icons1.load("esc.icn");
addButton(Common::Rect(261, 100, 285, 120), 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);
sound.stopSound();
vocName = isDarkCc ? "see2.voc" : "whaddayo.voc";
break;
case 2:
// Guild
loadStrings("spldesc.bin");
_icons1.load("esc.icn");
addButton(Common::Rect(261, 100, 285, 120), 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);
_vm->_mode = MODE_17;
sound.stopSound();
vocName = isDarkCc ? "parrot1.voc" : "guild10.voc";
break;
case 3:
// Tavern
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);
_vm->_mode = MODE_17;
sound.stopSound();
vocName = isDarkCc ? "hello1.voc" : "hello.voc";
break;
case 4:
// Temple
_icons1.load("esc.icn");
addButton(Common::Rect(261, 100, 285, 120), 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);
sound.stopSound();
vocName = isDarkCc ? "help2.voc" : "maywe2.voc";
break;
case 5:
// Training
Common::fill(&_arr1[0], &_arr1[6], 0);
_v2 = 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);
sound.stopSound();
vocName = isDarkCc ? "training.voc" : "youtrn1.voc";
break;
case 6:
// Arena event
arenaEvent();
return false;
case 8:
// Reaper event
reaperEvent();
return false;
case 9:
// Golem event
golemEvent();
return false;
case 10:
case 13:
dwarfEvent();
return false;
case 11:
sphinxEvent();
return false;
default:
break;
}
sound.playSong(Res.TOWN_ACTION_MUSIC[actionId], 223);
_townSprites.resize(Res.TOWN_ACTION_FILES[isDarkCc][actionId]);
for (uint idx = 0; idx < _townSprites.size(); ++idx) {
Common::String shapesName = Common::String::format("%s%d.twn",
Res.TOWN_ACTION_SHAPES[actionId], idx + 1);
_townSprites[idx].load(shapesName);
}
Character *charP = &party._activeParty[0];
Common::String title = createTownText(*charP);
intf._face1UIFrame = intf._face2UIFrame = 0;
intf._dangerSenseUIFrame = 0;
intf._spotDoorsUIFrame = 0;
intf._levitateUIFrame = 0;
_townSprites[_drawFrameIndex / 8].draw(screen, _drawFrameIndex % 8, _townPos);
if (actionId == 0 && isDarkCc) {
_townSprites[4].draw(screen, _vm->getRandomNumber(13, 18),
Common::Point(8, 30));
}
intf.assembleBorder();
// Open up the window and write the string
screen._windows[10].open();
screen._windows[10].writeString(title);
drawButtons(&screen);
screen._windows[0].update();
intf.highlightChar(0);
drawTownAnim(1);
if (actionId == 0)
intf._overallFrame = 2;
sound.playSound(vocName, 1);
do {
townWait();
charP = doTownOptions(charP);
screen._windows[10].writeString(title);
drawButtons(&screen);
} while (!_vm->shouldQuit() && _buttonValue != Common::KEYCODE_ESCAPE);
switch (actionId) {
case 1:
// Leave blacksmith
if (isDarkCc) {
sound.stopSound();
sound.playSound("come1.voc", 1);
}
break;
case 3: {
// Leave Tavern
sound.stopSound();
sound.playSound(isDarkCc ? "gdluck1.voc" : "goodbye.voc", 1);
map.mazeData()._mazeNumber = party._mazeId;
break;
}
default:
break;
}
int result;
if (party._mazeId != 0) {
map.load(party._mazeId);
_v1 += 1440;
party.addTime(_v1);
result = 0;
} else {
_vm->_saves->saveChars();
result = 2;
}
for (uint idx = 0; idx < _townSprites.size(); ++idx)
_townSprites[idx].clear();
intf.mainIconsPrint();
_buttonValue = 0;
return result;
}
int Town::townWait() {
EventsManager &events = *_vm->_events;
_buttonValue = 0;
while (!_vm->shouldQuit() && !_buttonValue) {
events.updateGameCounter();
while (!_vm->shouldQuit() && !_buttonValue && events.timeElapsed() < 3) {
events.pollEventsAndWait();
checkEvents(_vm);
}
if (!_buttonValue)
drawTownAnim(!_vm->_screen->_windows[11]._enabled);
}
return _buttonValue;
}
void Town::pyramidEvent() {
error("TODO: pyramidEvent");
}
void Town::arenaEvent() {
error("TODO: arenaEvent");
}
void Town::reaperEvent() {
error("TODO: repearEvent");
}
void Town::golemEvent() {
error("TODO: golemEvent");
}
void Town::sphinxEvent() {
error("TODO: sphinxEvent");
}
void Town::dwarfEvent() {
error("TODO: dwarfEvent");
}
Common::String Town::createTownText(Character &ch) {
Party &party = *_vm->_party;
Common::String msg;
switch (_townActionId) {
case 0:
// Bank
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());
case 1:
// Blacksmith
return Common::String::format(Res.BLACKSMITH_TEXT,
XeenEngine::printMil(party._gold).c_str());
case 2:
// Guild
return !ch.guildMember() ? Res.GUILD_NOT_MEMBER_TEXT :
Common::String::format(Res.GUILD_TEXT, ch._name.c_str());
case 3:
// Tavern
return Common::String::format(Res.TAVERN_TEXT, ch._name.c_str(),
Res.FOOD_AND_DRINK, XeenEngine::printMil(party._gold).c_str());
case 4:
// Temple
_donation = 0;
_uncurseCost = 0;
_v5 = 0;
_v6 = 0;
_healCost = 0;
if (party._mazeId == (_vm->_files->_isDarkCc ? 29 : 28)) {
_v10 = _v11 = _v12 = _v13 = 0;
_v14 = 10;
} else if (party._mazeId == (_vm->_files->_isDarkCc ? 31 : 30)) {
_v13 = 10;
_v12 = 50;
_v11 = 500;
_v10 = 100;
_v14 = 25;
} else if (party._mazeId == (_vm->_files->_isDarkCc ? 37 : 73)) {
_v13 = 20;
_v12 = 100;
_v11 = 1000;
_v10 = 200;
_v14 = 50;
} else if (_vm->_files->_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());
case 5:
// Training
if (_vm->_files->_isDarkCc) {
switch (party._mazeId) {
case 29:
_v20 = 30;
break;
case 31:
_v20 = 50;
break;
case 37:
_v20 = 200;
break;
default:
_v20 = 100;
break;
}
} else {
switch (party._mazeId) {
case 28:
_v20 = 10;
break;
case 30:
_v20 = 15;
break;
default:
_v20 = 20;
break;
}
}
_experienceToNextLevel = ch.experienceToNextLevel();
if (_experienceToNextLevel >= 0x10000 && ch._level._permanent < _v20) {
int nextLevel = ch._level._permanent + 1;
return Common::String::format(Res.EXPERIENCE_FOR_LEVEL,
ch._name.c_str(), _experienceToNextLevel, nextLevel);
} else if (ch._level._permanent >= 20) {
_experienceToNextLevel = 1;
msg = Common::String::format(Res.LEARNED_ALL, ch._name.c_str());
} else {
msg = Common::String::format(Res.ELIGIBLE_FOR_LEVEL,
ch._name.c_str(), ch._level._permanent + 1);
}
return Common::String::format(Res.TRAINING_TEXT,
XeenEngine::printMil(party._gold).c_str());
default:
return "";
}
}
Character *Town::doTownOptions(Character *c) {
switch (_townActionId) {
case 0:
// Bank
c = doBankOptions(c);
break;
case 1:
// Blacksmith
c = doBlacksmithOptions(c);
break;
case 2:
// Guild
c = doGuildOptions(c);
break;
case 3:
// Tavern
c = doTavernOptions(c);
break;
case 4:
// Temple
c = doTempleOptions(c);
case 5:
// Training
c = doTrainingOptions(c);
break;
default:
break;
}
return c;
}
Character *Town::doBankOptions(Character *c) {
if (_buttonValue == Common::KEYCODE_d)
_buttonValue = 0;
else if (_buttonValue == Common::KEYCODE_w)
_buttonValue = 1;
else
return c;
depositWithdrawl(_buttonValue);
return c;
}
Character *Town::doBlacksmithOptions(Character *c) {
Interface &intf = *_vm->_interface;
Party &party = *_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;
}
Character *Town::doGuildOptions(Character *c) {
Interface &intf = *_vm->_interface;
Party &party = *_vm->_party;
Sound &sound = *_vm->_sound;
bool isDarkCc = _vm->_files->_isDarkCc;
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();
intf._overallFrame = 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;
}
Character *Town::doTavernOptions(Character *c) {
Interface &intf = *_vm->_interface;
Map &map = *_vm->_map;
Party &party = *_vm->_party;
Sound &sound = *_vm->_sound;
Screen &screen = *_vm->_screen;
bool isDarkCc = _vm->_files->_isDarkCc;
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(0, 1, 0, WT_2)) {
sound.stopSound();
sound.playSound("gulp.voc");
_v21 = 1;
screen._windows[10].writeString(Common::String::format(Res.TAVERN_TEXT,
c->_name.c_str(), Res.GOOD_STUFF,
XeenEngine::printMil(party._gold).c_str()));
drawButtons(&screen._windows[0]);
screen._windows[10].update();
if (_vm->getRandomNumber(100) < 26) {
++c->_conditions[DRUNK];
intf.drawParty(true);
sound.playFX(28);
}
townWait();
}
}
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];
screen._windows[10].close();
screen._windows[12].open();
screen._windows[12].writeString(msg);
screen._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(0, _v23, 0, WT_2)) {
party._food = _v22;
sound.stopSound();
sound.playSound(isDarkCc ? "thanks2.voc" : "thankyou.voc", 1);
}
}
screen._windows[12].close();
screen._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 = screen._windows[12];
w.open();
w.writeString(msg);
w.update();
townWait();
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][_townActionId][idx][0];
party._mazePosition.y = Res.TAVERN_EXIT_LIST[isDarkCc ? 1 : 0][_townActionId][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) {
screen._windows[10].writeString(Common::String::format(Res.TAVERN_TEXT,
c->_name.c_str(), Res.HAVE_A_DRINK,
XeenEngine::printMil(party._gold).c_str()));
drawButtons(&screen);
screen._windows[10].update();
townWait();
} else {
_v21 = 0;
if (c->_conditions[DRUNK]) {
screen._windows[10].writeString(Common::String::format(Res.TAVERN_TEXT,
c->_name.c_str(), Res.YOURE_DRUNK,
XeenEngine::printMil(party._gold).c_str()));
drawButtons(&screen);
screen._windows[10].update();
townWait();
} else if (party.subtract(0, 1, 0, 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 = screen._windows[12];
w.open();
w.writeString(Common::String::format("\x03""c\x0B""012%s", msg.c_str()));
w.update();
townWait();
w.close();
}
}
}
break;
default:
break;
}
return c;
}
Character *Town::doTempleOptions(Character *c) {
Interface &intf = *_vm->_interface;
Party &party = *_vm->_party;
Sound &sound = *_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(0, _donation, 0, 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(0, _healCost, 0, 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);
_v1 = 1440;
intf.drawParty(true);
sound.stopSound();
sound.playSound("ahh.voc", 1);
}
break;
case Common::KEYCODE_u:
if (_uncurseCost && party.subtract(0, _uncurseCost, 0, 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;
}
_v1 = 1440;
intf.drawParty(true);
sound.stopSound();
sound.playSound("ahh.voc", 1);
}
break;
default:
break;
}
return c;
}
Character *Town::doTrainingOptions(Character *c) {
Interface &intf = *_vm->_interface;
Party &party = *_vm->_party;
Sound &sound = *_vm->_sound;
bool isDarkCc = _vm->_files->_isDarkCc;
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()) {
_v2 = _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 >= _v20) {
name = isDarkCc ? "gtlost.voc" : "trainin1.voc";
} else {
name = isDarkCc ? "gtlost.voc" : "trainin0.voc";
}
sound.playSound(name);
} else if (!c->noActions()) {
if (party.subtract(0, (c->_level._permanent * c->_level._permanent) * 10, 0, 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 (!_arr1[_v2]) {
party.addTime(1440);
_arr1[_v2] = 1;
}
party.resetTemps();
c->_currentHp = c->getMaxHP();
c->_currentSp = c->getMaxSP();
intf.drawParty(true);
}
}
break;
default:
break;
}
return c;
}
void Town::depositWithdrawl(int choice) {
Party &party = *_vm->_party;
Screen &screen = *_vm->_screen;
Sound &sound = *_vm->_sound;
int gold, gems;
if (choice) {
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[choice],
XeenEngine::printMil(gold).c_str(),
XeenEngine::printMil(gems).c_str());
screen._windows[35].open();
screen._windows[35].writeString(msg);
drawButtons(&screen._windows[35]);
screen._windows[35].update();
sound.stopSound();
File voc("coina.voc");
bool flag = false;
do {
switch (townWait()) {
case Common::KEYCODE_o:
flag = false;
break;
case Common::KEYCODE_e:
flag = true;
break;
case Common::KEYCODE_ESCAPE:
break;
default:
continue;
}
if ((choice && !party._bankGems && flag) ||
(choice && !party._bankGold && !flag) ||
(!choice && !party._gems && flag) ||
(!choice && !party._gold && !flag)) {
party.notEnough(flag, choice, 1, WT_2);
} else {
screen._windows[35].writeString(Res.AMOUNT);
int amount = NumericInput::show(_vm, 35, 10, 77);
if (amount) {
if (flag) {
if (party.subtract(true, amount, choice, WT_2)) {
if (choice) {
party._gems += amount;
} else {
party._bankGems += amount;
}
}
} else {
if (party.subtract(false, amount, choice, WT_2)) {
if (choice) {
party._gold += amount;
} else {
party._bankGold += amount;
}
}
}
}
if (choice) {
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[choice],
XeenEngine::printMil(gold).c_str(), XeenEngine::printMil(gems).c_str());
screen._windows[35].writeString(msg);
screen._windows[35].update();
}
// TODO
} while (!_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;
}
void Town::drawTownAnim(bool flag) {
Interface &intf = *_vm->_interface;
Screen &screen = *_vm->_screen;
Sound &sound = *_vm->_sound;
bool isDarkCc = _vm->_files->_isDarkCc;
if (_townActionId == 1) {
if (sound.isPlaying()) {
if (isDarkCc) {
_townSprites[_drawFrameIndex / 8].draw(screen, _drawFrameIndex % 8, _townPos);
_townSprites[2].draw(screen, _vm->getRandomNumber(11) == 1 ? 9 : 10,
Common::Point(34, 33));
_townSprites[2].draw(screen, _vm->getRandomNumber(5) + 3,
Common::Point(34, 54));
}
} else {
_townSprites[_drawFrameIndex / 8].draw(screen, _drawFrameIndex % 8, _townPos);
if (isDarkCc) {
_townSprites[2].draw(screen, _vm->getRandomNumber(11) == 1 ? 9 : 10,
Common::Point(34, 33));
}
}
} else {
if (!isDarkCc || _townActionId != 5) {
if (!_townSprites[_drawFrameIndex / 8].empty())
_townSprites[_drawFrameIndex / 8].draw(screen, _drawFrameIndex % 8, _townPos);
}
}
switch (_townActionId) {
case 0:
if (sound.isPlaying() || (isDarkCc && intf._overallFrame)) {
if (isDarkCc) {
if (sound.isPlaying() || intf._overallFrame == 1) {
_townSprites[4].draw(screen, _vm->getRandomNumber(13, 18),
Common::Point(8, 30));
} else if (intf._overallFrame > 1) {
_townSprites[4].draw(screen, 13 - intf._overallFrame++,
Common::Point(8, 30));
if (intf._overallFrame > 14)
intf._overallFrame = 0;
}
} else {
_townSprites[2].draw(screen, _vm->getRandomNumber(7, 11), Common::Point(8, 8));
}
}
break;
case 2:
if (sound.isPlaying()) {
if (isDarkCc) {
if (intf._overallFrame) {
intf._overallFrame ^= 1;
_townSprites[6].draw(screen, intf._overallFrame, Common::Point(8, 106));
} else {
_townSprites[6].draw(screen, _vm->getRandomNumber(3), Common::Point(16, 48));
}
}
}
break;
case 3:
if (sound.isPlaying() && isDarkCc) {
_townSprites[4].draw(screen, _vm->getRandomNumber(7), Common::Point(153, 49));
}
break;
case 4:
if (sound.isPlaying()) {
_townSprites[3].draw(screen, _vm->getRandomNumber(2, 4), Common::Point(8, 8));
}
break;
case 5:
if (sound.isPlaying()) {
if (isDarkCc) {
_townSprites[_drawFrameIndex / 8].draw(screen, _drawFrameIndex % 8, _townPos);
}
} else {
if (isDarkCc) {
_townSprites[0].draw(screen, ++intf._overallFrame % 8, Common::Point(8, 8));
_townSprites[5].draw(screen, _vm->getRandomNumber(5), Common::Point(61, 74));
} else {
_townSprites[1].draw(screen, _vm->getRandomNumber(8, 12), Common::Point(8, 8));
}
}
}
if (flag) {
intf._face1UIFrame = 0;
intf._face2UIFrame = 0;
intf._dangerSenseUIFrame = 0;
intf._spotDoorsUIFrame = 0;
intf._levitateUIFrame = 0;
intf.assembleBorder();
}
if (screen._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 (_townActionId == 1 && (_drawFrameIndex == 4 || _drawFrameIndex == 13))
sound.playFX(45);
if (_townActionId == 5 && _drawFrameIndex == 23) {
sound.playSound("spit1.voc");
}
} else {
if (_townMaxId == 32 && _drawFrameIndex == 0)
_drawFrameIndex = 17;
if (_townMaxId == 26 && _drawFrameIndex == 0)
_drawFrameIndex = 20;
if (_townActionId == 1 && (_drawFrameIndex == 3 || _drawFrameIndex == 9))
sound.playFX(45);
}
screen._windows[3].update();
}
bool Town::isActive() const {
return _townSprites.size() > 0 && !_townSprites[0].empty();
}
void Town::clearSprites() {
_townSprites.clear();
}
/*------------------------------------------------------------------------*/
bool TownMessage::show(XeenEngine *vm, int portrait, const Common::String &name,
const Common::String &text, int confirm) {
TownMessage *dlg = new TownMessage(vm);
bool result = dlg->execute(portrait, name, text, confirm);
delete dlg;
return result;
}
bool TownMessage::execute(int portrait, const Common::String &name, const Common::String &text,
int confirm) {
EventsManager &events = *_vm->_events;
Interface &intf = *_vm->_interface;
Screen &screen = *_vm->_screen;
Town &town = *_vm->_town;
Window &w = screen._windows[11];
town._townMaxId = 4;
town._townActionId = 7;
town._drawFrameIndex = 0;
town._townPos = Common::Point(23, 22);
if (!confirm)
loadButtons();
if (town._townSprites[0].empty()) {
town._townSprites[0].load(Common::String::format("face%02d.fac", portrait));
town._townSprites[1].load("frame.fac");
}
if (!w._enabled)
w.open();
int result = -1;
Common::String msgText = text;
for (;;) {
Common::String msg = Common::String::format("\r\v014\x03c\t125%s\t000\v054%s",
name.c_str(), msgText.c_str());
const char *msgEnd = w.writeString(msg.c_str());
int wordCount = 0;
for (const char *msgP = msg.c_str(); msgP < msgEnd; ++msgP) {
if (*msgP == ' ')
++wordCount;
}
town._drawCtr2 = wordCount * 2;
town._townSprites[1].draw(screen, 0, Common::Point(16, 16));
town._townSprites[0].draw(screen, town._drawFrameIndex, Common::Point(23, 22));
w.update();
if (!msgEnd) {
// Doesn't look like the code here in original can ever be reached
assert(0);
}
if (confirm == 2) {
intf._face1State = intf._face2State = 2;
return false;
}
do {
events.clearEvents();
events.updateGameCounter();
if (msgEnd)
clearButtons();
do {
events.wait(3);
checkEvents(_vm);
if (_vm->shouldQuit())
return false;
town.drawTownAnim(false);
events.updateGameCounter();
} while (!_buttonValue);
if (msgEnd)
break;
if (!msgEnd) {
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) {
msgText = Common::String(msgEnd);
town._drawCtr2 = wordCount;
continue;
}
} while (result == -1);
intf._face1State = intf._face2State = 2;
if (!confirm)
intf.mainIconsPrint();
town._townSprites[0].clear();
town._townSprites[1].clear();
return result == 1;
}
void TownMessage::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