diff options
Diffstat (limited to 'engines/xeen/dialogs_spells.cpp')
-rw-r--r-- | engines/xeen/dialogs_spells.cpp | 416 |
1 files changed, 416 insertions, 0 deletions
diff --git a/engines/xeen/dialogs_spells.cpp b/engines/xeen/dialogs_spells.cpp new file mode 100644 index 0000000000..7ae5e7ad90 --- /dev/null +++ b/engines/xeen/dialogs_spells.cpp @@ -0,0 +1,416 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "xeen/dialogs_spells.h" +#include "xeen/dialogs_confirm.h" +#include "xeen/resources.h" +#include "xeen/spells.h" +#include "xeen/sprites.h" +#include "xeen/xeen.h" + +namespace Xeen { + +Character *SpellsScroll::show(XeenEngine *vm, Character *c, int v2) { + SpellsScroll *dlg = new SpellsScroll(vm); + Character *result = dlg->execute(c, v2); + delete dlg; + + return result; +} + +Character *SpellsScroll::execute(Character *c, int v2) { + EventsManager &events = *_vm->_events; + Interface &intf = *_vm->_interface; + Party &party = *_vm->_party; + Screen &screen = *_vm->_screen; + SoundManager &sound = *_vm->_sound; + Spells &spells = *_vm->_spells; + bool isDarkCc = _vm->_files->_isDarkCc; + loadButtons(); + + int v2Copy = v2; + v2 &= 0x7f; + int selection = -1; + int topIndex = 0; + int newSelection; + screen._windows[25].open(); + + while (!_vm->shouldQuit()) { + if (!v2) { + if (!c->guildMember()) { + sound.playSample(nullptr, 0); + intf._overallFrame = 5; + File f(isDarkCc ? "skull1.voc" : "guild11.voc"); + sound.playSample(&f, 1); + break; + } + + Common::String title = Common::String::format(BUY_SPELLS, c->_name.c_str()); + Common::String msg = Common::String::format(GUILD_OPTIONS, + title.c_str(), XeenEngine::printMil(party._gold)); + screen._windows[10].writeString(msg); + + warning("TODO: Sprite draw using previously used button sprites"); + } + + _spells.clear(); + const char *errorMsg = setSpellText(c, v2Copy); + screen._windows[25].writeString(Common::String::format(SPELLS_FOR, + errorMsg == nullptr ? SPELL_LINES_0_TO_9 : nullptr)); + + screen._windows[37].writeString(Common::String::format(SPELLS_DIALOG_SPELLS, + (topIndex + 0) < _spells.size() ? _spells[topIndex + 0]._name.c_str() : nullptr, + (topIndex + 1) < _spells.size() ? _spells[topIndex + 1]._name.c_str() : nullptr, + (topIndex + 2) < _spells.size() ? _spells[topIndex + 2]._name.c_str() : nullptr, + (topIndex + 3) < _spells.size() ? _spells[topIndex + 3]._name.c_str() : nullptr, + (topIndex + 4) < _spells.size() ? _spells[topIndex + 4]._name.c_str() : nullptr, + (topIndex + 5) < _spells.size() ? _spells[topIndex + 5]._name.c_str() : nullptr, + (topIndex + 6) < _spells.size() ? _spells[topIndex + 6]._name.c_str() : nullptr, + (topIndex + 7) < _spells.size() ? _spells[topIndex + 7]._name.c_str() : nullptr, + (topIndex + 8) < _spells.size() ? _spells[topIndex + 8]._name.c_str() : nullptr, + (topIndex + 9) < _spells.size() ? _spells[topIndex + 9]._name.c_str() : nullptr, + v2 ? SPELL_PTS : GOLD, + v2 ? c->_currentSp : party._gold + )); + + _iconSprites.draw(screen, 4, Common::Point(39, 26)); + _iconSprites.draw(screen, 0, Common::Point(187, 26)); + _iconSprites.draw(screen, 2, Common::Point(187, 111)); + if (v2) + _iconSprites.draw(screen._windows[25], 5, Common::Point(132, 123)); + + screen._windows[25].update(); + + while (!_vm->shouldQuit() && !events.isKeyMousePressed()) + events.pollEventsAndWait(); + if (_vm->shouldQuit()) + break; + checkEvents(_vm); + + switch (_buttonValue) { + case Common::KEYCODE_F1: + case Common::KEYCODE_F6: + if (_vm->_mode != MODE_2) { + _buttonValue -= Common::KEYCODE_F1; + if (_buttonValue < party._partyCount) { + c = &party._activeParty[_buttonValue]; + spells._lastCaster = _buttonValue; + intf.highlightChar(_buttonValue); + + if (_vm->_mode == MODE_17) { + screen._windows[10].writeString(Common::String::format(GUILD_OPTIONS, + XeenEngine::printMil(party._gold).c_str(), GUILD_TEXT, c->_name.c_str())); + } else { + int category; + switch (c->_class) { + case CLASS_ARCHER: + case CLASS_SORCERER: + category = 1; + break; + case CLASS_DRUID: + case CLASS_RANGER: + category = 2; + break; + default: + category = 0; + break; + } + + int spellIndex = (c->_currentSp == -1) ? 39 : c->_currentSpell; + int spellId = SPELLS_ALLOWED[category][spellIndex]; + screen._windows[10].writeString(Common::String::format(SPELL_DETAILS, + spells._spellNames[spellId].c_str(), + spells.calcSpellPoints(spellId, c->getCurrentLevel()), + SPELL_GEM_COST[spellId], c->_currentSp)); + } + + drawButtons(&screen); + screen._windows[10].update(); + } + } + break; + + case Common::KEYCODE_RETURN: + case Common::KEYCODE_KP_ENTER: + case Common::KEYCODE_s: + if (selection != -1) + _buttonValue = Common::KEYCODE_ESCAPE; + break; + + case Common::KEYCODE_ESCAPE: + selection = -1; + _buttonValue = Common::KEYCODE_ESCAPE; + break; + + case Common::KEYCODE_0: + case Common::KEYCODE_1: + case Common::KEYCODE_2: + case Common::KEYCODE_3: + case Common::KEYCODE_4: + case Common::KEYCODE_5: + case Common::KEYCODE_6: + case Common::KEYCODE_7: + case Common::KEYCODE_8: + case Common::KEYCODE_9: + newSelection = topIndex + (_buttonValue == Common::KEYCODE_0) ? 9 : + (_buttonValue - Common::KEYCODE_1); + + if (newSelection < (int)_spells.size()) { + int expenseFactor = 0; + int category = 0; + + switch (c->_class) { + case CLASS_PALADIN: + expenseFactor = 1; + category = 0; + break; + case CLASS_ARCHER: + expenseFactor = 1; + category = 1; + break; + case CLASS_CLERIC: + category = 0; + break; + case CLASS_SORCERER: + category = 1; + break; + case CLASS_DRUID: + category = 2; + break; + case CLASS_RANGER: + expenseFactor = 1; + category = 2; + break; + default: + break; + } + + int spellId = _spells[newSelection]._spellId; + int spellIndex = _spells[newSelection]._spellIndex; + int spellCost = spells.calcSpellCost(spellId, expenseFactor); + if (v2) { + // TODO: Confirm this refactoring against against original + selection = _buttonValue; + } else { + Common::String spellName = _spells[_buttonValue]._name; + Common::String msg = (v2Copy & 0x80) ? + Common::String::format(SPELLS_PRESS_A_KEY, msg.c_str()) : + Common::String::format(SPELLS_PURCHASE, msg.c_str(), spellCost); + + if (ConfirmDialog::show(_vm, msg, v2Copy + 1)) { + if (party.subtract(0, spellCost, 0, WT_FREEZE_WAIT)) { + ++c->_spells[spellIndex]; + sound.playSample(nullptr, 0); + intf._overallFrame = 0; + File f(isDarkCc ? "guild12.voc" : "parrot2.voc"); + sound.playSample(&f, 1); + } else { + sound.playFX(21); + } + } + } + } + break; + + case Common::KEYCODE_PAGEUP: + case Common::KEYCODE_KP9: + topIndex = MAX(topIndex - 10, 0); + break; + + case Common::KEYCODE_PAGEDOWN: + case Common::KEYCODE_KP3: + topIndex = MIN(topIndex + 10, (((int)_spells.size() - 1) / 10) * 10); + break; + + case Common::KEYCODE_UP: + case Common::KEYCODE_KP8: + if (topIndex > 0) + --topIndex; + break; + + case Common::KEYCODE_DOWN: + case Common::KEYCODE_KP2: + if (topIndex < ((int)_spells.size() - 10)) + ++topIndex; + break; + } + } + + screen._windows[25].close(); + if (v2 && selection != -1) + c->_currentSpell = _spells[selection]._spellIndex; + + return c; +} + +void SpellsScroll::loadButtons() { + _iconSprites.load("main.icn"); + _scrollSprites.load("scroll.icn"); + addButton(Common::Rect(187, 26, 198, 36), Common::KEYCODE_UP, &_scrollSprites, true); + addButton(Common::Rect(187, 111, 198, 121), Common::KEYCODE_DOWN, &_scrollSprites, true); + addButton(Common::Rect(40, 28, 187, 36), Common::KEYCODE_1, &_scrollSprites, false); + addButton(Common::Rect(40, 37, 187, 45), Common::KEYCODE_2, &_scrollSprites, false); + addButton(Common::Rect(40, 46, 187, 54), Common::KEYCODE_3, &_scrollSprites, false); + addButton(Common::Rect(40, 55, 187, 63), Common::KEYCODE_4, &_scrollSprites, false); + addButton(Common::Rect(40, 64, 187, 72), Common::KEYCODE_5, &_scrollSprites, false); + addButton(Common::Rect(40, 73, 187, 81), Common::KEYCODE_6, &_scrollSprites, false); + addButton(Common::Rect(40, 82, 187, 90), Common::KEYCODE_7, &_scrollSprites, false); + addButton(Common::Rect(40, 91, 187, 99), Common::KEYCODE_8, &_scrollSprites, false); + addButton(Common::Rect(40, 100, 187, 108), Common::KEYCODE_9, &_scrollSprites, false); + addButton(Common::Rect(40, 109, 187, 117), Common::KEYCODE_0, &_scrollSprites, false); + addButton(Common::Rect(174, 123, 198, 133), Common::KEYCODE_ESCAPE, &_scrollSprites, false); + addButton(Common::Rect(187, 35, 198, 73), Common::KEYCODE_PAGEUP, &_scrollSprites, false); + addButton(Common::Rect(187, 74, 198, 112), Common::KEYCODE_PAGEDOWN, &_scrollSprites, false); + addButton(Common::Rect(132, 123, 168, 133), Common::KEYCODE_s, &_scrollSprites, false); +} + +const char *SpellsScroll::setSpellText(Character *c, int v2) { + Party &party = *_vm->_party; + Spells &spells = *_vm->_spells; + bool isDarkCc = _vm->_files->_isDarkCc; + int expenseFactor = 0; + int currLevel = c->getCurrentLevel(); + int category; + + if ((v2 & 0x7f) == 0) { + switch (c->_class) { + case CLASS_PALADIN: + expenseFactor = 1; + category = 0; + break; + case CLASS_ARCHER: + expenseFactor = 1; + category = 1; + break; + case CLASS_CLERIC: + category = 0; + break; + case CLASS_SORCERER: + category = 1; + break; + case CLASS_DRUID: + category = 2; + break; + case CLASS_RANGER: + expenseFactor = 1; + category = 2; + break; + default: + category = -1; + break; + } + + if (category != -1) { + if (party._mazeId == 49 || party._mazeId == 37) { + for (int spellId = 0; spellId < 76; ++spellId) { + int idx = 0; + while (idx < MAX_SPELLS_PER_CLASS && SPELLS_ALLOWED[category][idx] == spellId) + ++idx; + + // Handling if the spell is appropriate for the character's class + if (idx < MAX_SPELLS_PER_CLASS) { + if (!c->_spells[idx] || (v2 & 0x80)) { + int cost = spells.calcSpellCost(SPELLS_ALLOWED[category][idx], expenseFactor); + _spells.push_back(SpellEntry(Common::String::format("\x3l%s\x3r\x9""000%u", + spells._spellNames[SPELLS_ALLOWED[category][idx]], cost), + idx, spellId)); + } + } + } + } else if (isDarkCc) { + int groupIndex = (party._mazeId - 29) / 2; + for (int spellId = DARK_SPELL_RANGES[category][0]; + spellId < DARK_SPELL_RANGES[category][1]; ++spellId) { + int idx = 0; + while (idx < 40 && SPELLS_ALLOWED[category][idx] == + DARK_SPELL_OFFSETS[category][spellId]); + + if (idx < 40) { + if (!c->_spells[idx] || (v2 & 0x80)) { + int cost = spells.calcSpellCost(SPELLS_ALLOWED[category][idx], expenseFactor); + _spells.push_back(SpellEntry(Common::String::format("\x3l%s\x3r\x9""000%u", + spells._spellNames[SPELLS_ALLOWED[category][idx]], cost), + idx, spellId)); + } + } + } + } else { + for (int spellId = 0; spellId < 20; ++spellId) { + int idx = 0; + while (CLOUDS_SPELL_OFFSETS[party._mazeId - 29][spellId] != + SPELLS_ALLOWED[category][idx] && idx < 40) ; + + if (idx < 40) { + if (!c->_spells[idx] || (v2 & 0x80)) { + int cost = spells.calcSpellCost(SPELLS_ALLOWED[category][idx], expenseFactor); + _spells.push_back(SpellEntry(Common::String::format("\x3l%s\x3r\x9""000%u", + spells._spellNames[SPELLS_ALLOWED[category][idx]], cost), + idx, spellId)); + } + } + } + } + } + + if (c->getMaxSP() == 0) + return NOT_A_SPELL_CASTER; + + } else if ((v2 & 0x7f) == 1) { + switch (c->_class) { + case 0: + case 12: + category = 0; + break; + case 1: + case 3: + category = 1; + break; + case 7: + case 8: + category = 2; + break; + default: + category = 0; + break; + } + + if (c->getMaxSP() == 0) { + return NOT_A_SPELL_CASTER; + } else { + for (int spellIndex = 0; spellIndex < (MAX_SPELLS_PER_CLASS - 1); ++spellIndex) { + if (c->_spells[spellIndex]) { + int spellId = SPELLS_ALLOWED[category][spellIndex]; + int gemCost = SPELL_GEM_COST[spellId]; + int spCost = spells.calcSpellPoints(spellId, currLevel); + + Common::String msg = Common::String::format("\x3l%s\x3r\x9""000%u/%u", + spells._spellNames[spellId].c_str(), spCost, gemCost); + _spells.push_back(SpellEntry(msg, spellIndex, spellId)); + } + } + } + } + + return nullptr; +} + +} // End of namespace Xeen |