1201 lines
36 KiB
C++
1201 lines
36 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 3 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, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
#include "mm/xeen/dialogs/dialogs_items.h"
|
|
#include "mm/xeen/dialogs/dialogs_query.h"
|
|
#include "mm/xeen/dialogs/dialogs_quests.h"
|
|
#include "mm/xeen/resources.h"
|
|
#include "mm/xeen/xeen.h"
|
|
|
|
namespace MM {
|
|
namespace Xeen {
|
|
|
|
enum ItemsButtonEnchantTTSTextIndex {
|
|
kItemsEnchantWeapons = 0,
|
|
kItemsEnchantArmor = 1,
|
|
kItemsEnchantAccessories = 2,
|
|
kItemsEnchantMisc = 3,
|
|
kItemsEnchantEnchant = 4,
|
|
kItemsEnchantExit = 5,
|
|
kItemsEnchantUse = 6,
|
|
kItemsEnchantItem1 = 7,
|
|
kItemsEnchantItem2 = 8,
|
|
kItemsEnchantItem3 = 9,
|
|
kItemsEnchantItem4 = 10,
|
|
kItemsEnchantItem5 = 11,
|
|
kItemsEnchantItem6 = 12,
|
|
kItemsEnchantItem7 = 13,
|
|
kItemsEnchantItem8 = 14,
|
|
kItemsEnchantItem9 = 15
|
|
};
|
|
|
|
enum kItemsButtonTTSTextIndex {
|
|
kItemsWeapons = 0,
|
|
kItemsArmor = 1,
|
|
kItemsAccessories = 2,
|
|
kItemsMisc = 3,
|
|
kItemsBuyOrEquip = 4,
|
|
kItemsSellOrRemove = 5,
|
|
kItemsIdentifyOrDiscard = 6,
|
|
kItemsFixOrQuest = 7,
|
|
kItemsExit = 8,
|
|
kItemsItem1 = 9,
|
|
kItemsItem2 = 10,
|
|
kItemsItem3 = 11,
|
|
kItemsItem4 = 12,
|
|
kItemsItem5 = 13,
|
|
kItemsItem6 = 14,
|
|
kItemsItem7 = 15,
|
|
kItemsItem8 = 16,
|
|
kItemsItem9 = 17
|
|
};
|
|
|
|
enum ItemSelectionButtonTTSTextIndex {
|
|
kItemSelectionItem1 = 0,
|
|
kItemSelectionItem2 = 1,
|
|
kItemSelectionItem3 = 2,
|
|
kItemSelectionItem4 = 3,
|
|
kItemSelectionItem5 = 4,
|
|
kItemSelectionItem6 = 5,
|
|
kItemSelectionItem7 = 6,
|
|
kItemSelectionItem8 = 7,
|
|
kItemSelectionItem9 = 8
|
|
};
|
|
|
|
Character *ItemsDialog::show(XeenEngine *vm, Character *c, ItemsMode mode) {
|
|
ItemsDialog *dlg = new ItemsDialog(vm);
|
|
Character *result = dlg->execute(c, mode);
|
|
delete dlg;
|
|
|
|
return result;
|
|
}
|
|
|
|
Character *ItemsDialog::execute(Character *c, ItemsMode mode) {
|
|
Combat &combat = *_vm->_combat;
|
|
EventsManager &events = *_vm->_events;
|
|
Interface &intf = *_vm->_interface;
|
|
Party &party = *_vm->_party;
|
|
Windows &windows = *_vm->_windows;
|
|
|
|
ItemsMode priorMode = ITEMMODE_INVALID;
|
|
Character *startingChar = c;
|
|
ItemCategory category = mode == ITEMMODE_RECHARGE || mode == ITEMMODE_COMBAT ?
|
|
CATEGORY_MISC : CATEGORY_WEAPON;
|
|
int varA = mode == ITEMMODE_COMBAT ? 1 : 0;
|
|
if (varA != 0)
|
|
mode = ITEMMODE_CHAR_INFO;
|
|
bool updateStock = mode == ITEMMODE_BUY;
|
|
int itemIndex = -1;
|
|
Common::StringArray lines;
|
|
uint arr[40];
|
|
int actionIndex = -1;
|
|
|
|
if (mode == ITEMMODE_BUY) {
|
|
_oldCharacter = c;
|
|
c = &_itemsCharacter;
|
|
party._blacksmithWares.blackData2CharData(_itemsCharacter);
|
|
_itemsCharacter._class = _oldCharacter->_class;
|
|
setEquipmentIcons();
|
|
} else if (mode == ITEMMODE_ENCHANT) {
|
|
_oldCharacter = c;
|
|
}
|
|
|
|
events.setCursor(0);
|
|
windows[29].open();
|
|
windows[30].open();
|
|
|
|
Common::String buttonsText;
|
|
#ifdef USE_TTS
|
|
uint buttonTextCount = 0;
|
|
#endif
|
|
|
|
enum { REDRAW_NONE, REDRAW_TEXT, REDRAW_FULL } redrawFlag = REDRAW_FULL;
|
|
for (;;) {
|
|
if (redrawFlag == REDRAW_FULL) {
|
|
// Write text for the dialog
|
|
Common::String msg;
|
|
if (mode != ITEMMODE_CHAR_INFO && mode != ITEMMODE_8 && mode != ITEMMODE_ENCHANT
|
|
&& mode != ITEMMODE_RECHARGE && mode != ITEMMODE_TO_GOLD) {
|
|
msg = Common::String::format(Res.ITEMS_DIALOG_TEXT1,
|
|
Res.BTN_BUY, Res.BTN_SELL, Res.BTN_IDENTIFY, Res.BTN_FIX);
|
|
} else if (mode != ITEMMODE_ENCHANT && mode != ITEMMODE_RECHARGE && mode != ITEMMODE_TO_GOLD) {
|
|
msg = Common::String::format(Res.ITEMS_DIALOG_TEXT1,
|
|
category == 3 ? Res.BTN_USE : Res.BTN_EQUIP,
|
|
Res.BTN_REMOVE, Res.BTN_DISCARD, Res.BTN_QUEST);
|
|
} else if (mode == ITEMMODE_ENCHANT) {
|
|
msg = Common::String::format(Res.ITEMS_DIALOG_TEXT2, Res.BTN_ENCHANT);
|
|
} else if (mode == ITEMMODE_RECHARGE) {
|
|
msg = Common::String::format(Res.ITEMS_DIALOG_TEXT2, Res.BTN_RECHARGE);
|
|
} else {
|
|
msg = Common::String::format(Res.ITEMS_DIALOG_TEXT2, Res.BTN_GOLD);
|
|
}
|
|
|
|
buttonsText.clear();
|
|
windows[29].writeString(msg, false, &buttonsText);
|
|
|
|
Common::fill(&arr[0], &arr[40], 0);
|
|
itemIndex = -1;
|
|
priorMode = ITEMMODE_INVALID;
|
|
}
|
|
|
|
if (mode != priorMode) {
|
|
// Set up the buttons for the dialog
|
|
loadButtons(mode, c, category);
|
|
#ifdef USE_TTS
|
|
setButtonTexts(buttonsText);
|
|
buttonTextCount = _buttonTexts.size();
|
|
#endif
|
|
priorMode = mode;
|
|
drawButtons(&windows[0]);
|
|
}
|
|
|
|
if (redrawFlag == REDRAW_TEXT || redrawFlag == REDRAW_FULL) {
|
|
lines.clear();
|
|
|
|
for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
|
|
DrawStruct &ds = _itemsDrawList[idx];
|
|
XeenItem &i = c->_items[category][idx];
|
|
|
|
ds._sprites = nullptr;
|
|
ds._x = 8;
|
|
ds._y = 18 + idx * 9;
|
|
|
|
switch (category) {
|
|
case CATEGORY_WEAPON:
|
|
case CATEGORY_ARMOR:
|
|
case CATEGORY_ACCESSORY:
|
|
if (i._id) {
|
|
if ((mode == ITEMMODE_CHAR_INFO && !g_vm->_extOptions._showItemCosts)
|
|
|| mode == ITEMMODE_8 || mode == ITEMMODE_ENCHANT || mode == ITEMMODE_RECHARGE) {
|
|
lines.push_back(Common::String::format(Res.ITEMS_DIALOG_LINE1,
|
|
arr[idx], idx + 1,
|
|
c->_items[category].getFullDescription(idx, arr[idx]).c_str()));
|
|
} else {
|
|
lines.push_back(Common::String::format(Res.ITEMS_DIALOG_LINE2,
|
|
arr[idx], idx + 1,
|
|
c->_items[category].getFullDescription(idx, arr[idx]).c_str(),
|
|
calcItemCost(c, idx,
|
|
(mode == ITEMMODE_CHAR_INFO) ? ITEMMODE_BUY : mode,
|
|
mode == ITEMMODE_TO_GOLD ? 1 : startingChar->_skills[MERCHANT],
|
|
category)
|
|
));
|
|
}
|
|
|
|
ds._sprites = &_equipSprites;
|
|
if (c->_items[category].passRestrictions(i._id, true))
|
|
ds._frame = i._frame;
|
|
else
|
|
ds._frame = 14;
|
|
} else if (ds._sprites == nullptr && idx == 0) {
|
|
lines.push_back(Res.NO_ITEMS_AVAILABLE);
|
|
}
|
|
break;
|
|
|
|
case CATEGORY_MISC:
|
|
if (i._material == 0) {
|
|
// No item
|
|
if (idx == 0) {
|
|
lines.push_back(Res.NO_ITEMS_AVAILABLE);
|
|
}
|
|
} else {
|
|
ItemsMode tempMode = mode;
|
|
int skill = startingChar->_skills[MERCHANT];
|
|
|
|
if (mode == ITEMMODE_CHAR_INFO || mode == ITEMMODE_8
|
|
|| mode == ITEMMODE_ENCHANT || mode == ITEMMODE_RECHARGE) {
|
|
tempMode = ITEMMODE_ENCHANT;
|
|
} else if (mode == ITEMMODE_TO_GOLD) {
|
|
skill = 1;
|
|
}
|
|
|
|
lines.push_back(Common::String::format(Res.ITEMS_DIALOG_LINE2,
|
|
arr[idx], idx + 1,
|
|
c->_items[category].getFullDescription(idx, arr[idx]).c_str(),
|
|
calcItemCost(c, idx, tempMode, skill, category)
|
|
));
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
#ifdef USE_TTS
|
|
uint8 lineCount = lines.size();
|
|
// Make space for spells
|
|
_buttonTexts.resize(lines.size() + buttonTextCount - 1);
|
|
#endif
|
|
|
|
while (lines.size() < INV_ITEMS_TOTAL)
|
|
lines.push_back("");
|
|
|
|
Common::String ttsMessage;
|
|
#ifdef USE_TTS
|
|
uint8 headerCount = 0;
|
|
#endif
|
|
// Draw out overall text and the list of items
|
|
switch (mode) {
|
|
case ITEMMODE_CHAR_INFO:
|
|
case ITEMMODE_8:
|
|
windows[30].writeString(Common::String::format(Res.X_FOR_THE_Y,
|
|
category == CATEGORY_MISC ? "\x3l" : "\x3""c",
|
|
Res.CATEGORY_NAMES[category], c->_name.c_str(), Res.CLASS_NAMES[c->_class],
|
|
category == CATEGORY_MISC ? Res.FMT_CHARGES : " ",
|
|
lines[0].c_str(), lines[1].c_str(), lines[2].c_str(), lines[3].c_str(),
|
|
lines[4].c_str(), lines[5].c_str(), lines[6].c_str(), lines[7].c_str(),
|
|
lines[8].c_str()
|
|
), false, &ttsMessage);
|
|
#ifdef USE_TTS
|
|
// Misc category lists charges as well
|
|
headerCount = category == CATEGORY_MISC ? 2 : 1;
|
|
#endif
|
|
break;
|
|
|
|
case ITEMMODE_BUY:
|
|
windows[30].writeString(Common::String::format(Res.AVAILABLE_GOLD_COST,
|
|
Res.CATEGORY_NAMES[category], party._gold,
|
|
lines[0].c_str(), lines[1].c_str(), lines[2].c_str(), lines[3].c_str(),
|
|
lines[4].c_str(), lines[5].c_str(), lines[6].c_str(), lines[7].c_str(),
|
|
lines[8].c_str()
|
|
), false, &ttsMessage);
|
|
#ifdef USE_TTS
|
|
headerCount = 3;
|
|
#endif
|
|
break;
|
|
|
|
case ITEMMODE_SELL:
|
|
case ITEMMODE_RECHARGE:
|
|
case ITEMMODE_ENCHANT:
|
|
case ITEMMODE_REPAIR:
|
|
case ITEMMODE_IDENTIFY:
|
|
case ITEMMODE_TO_GOLD:
|
|
windows[30].writeString(Common::String::format(Res.X_FOR_Y,
|
|
Res.CATEGORY_NAMES[category], startingChar->_name.c_str(),
|
|
(mode == ITEMMODE_RECHARGE || mode == ITEMMODE_ENCHANT) ? Res.CHARGES : Res.COST,
|
|
lines[0].c_str(), lines[1].c_str(), lines[2].c_str(), lines[3].c_str(),
|
|
lines[4].c_str(), lines[5].c_str(), lines[6].c_str(), lines[7].c_str(),
|
|
lines[8].c_str()
|
|
), false, &ttsMessage);
|
|
#ifdef USE_TTS
|
|
headerCount = 2;
|
|
#endif
|
|
break;
|
|
|
|
case ITEMMODE_3:
|
|
case ITEMMODE_5:
|
|
windows[30].writeString(Common::String::format(Res.X_FOR_Y_GOLD,
|
|
Res.CATEGORY_NAMES[category], c->_name.c_str(), party._gold, Res.CHARGES,
|
|
lines[0].c_str(), lines[1].c_str(), lines[2].c_str(), lines[3].c_str(),
|
|
lines[4].c_str(), lines[5].c_str(), lines[6].c_str(), lines[7].c_str(),
|
|
lines[8].c_str()
|
|
), false, &ttsMessage);
|
|
#ifdef USE_TTS
|
|
headerCount = 2;
|
|
#endif
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
#ifdef USE_TTS
|
|
if (lines[0] == Res.NO_ITEMS_AVAILABLE) {
|
|
// Speak headers and the "no items" message
|
|
uint index = 0;
|
|
_vm->sayText(getNextTextSection(ttsMessage, index, headerCount + 1));
|
|
} else {
|
|
speakText(ttsMessage, headerCount, lineCount);
|
|
}
|
|
#endif
|
|
|
|
// Draw the glyphs for the items
|
|
windows[0].drawList(_itemsDrawList, INV_ITEMS_TOTAL);
|
|
windows[0].update();
|
|
}
|
|
|
|
redrawFlag = REDRAW_NONE;
|
|
|
|
if (itemIndex != -1) {
|
|
switch (mode) {
|
|
case ITEMMODE_BUY:
|
|
actionIndex = 0;
|
|
break;
|
|
case ITEMMODE_SELL:
|
|
actionIndex = 1;
|
|
break;
|
|
case ITEMMODE_REPAIR:
|
|
actionIndex = 3;
|
|
break;
|
|
case ITEMMODE_IDENTIFY:
|
|
actionIndex = 2;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
// If it's time to do an item action, take care of it
|
|
if (actionIndex >= 0) {
|
|
int result = doItemOptions(*c, actionIndex, itemIndex, category, mode);
|
|
if (result == 1) {
|
|
// Finish dialog with no selected character
|
|
c = nullptr;
|
|
break;
|
|
} else if (result == 2) {
|
|
// Close dialogs and finish dialog with original starting character
|
|
windows[30].close();
|
|
windows[29].close();
|
|
c = startingChar;
|
|
break;
|
|
}
|
|
|
|
// Otherwise, result and continue showing dialog
|
|
actionIndex = -1;
|
|
redrawFlag = REDRAW_FULL;
|
|
continue;
|
|
}
|
|
|
|
#ifdef USE_TTS
|
|
_vm->sayText(buttonsText);
|
|
#endif
|
|
|
|
// Wait for a selection
|
|
_buttonValue = 0;
|
|
while (!_vm->shouldExit() && !_buttonValue) {
|
|
events.pollEventsAndWait();
|
|
checkEvents(_vm);
|
|
}
|
|
if (_vm->shouldExit())
|
|
return nullptr;
|
|
|
|
// Handle escaping out of dialog
|
|
if (_buttonValue == Common::KEYCODE_ESCAPE) {
|
|
if (mode == ITEMMODE_8)
|
|
continue;
|
|
c = startingChar;
|
|
break;
|
|
}
|
|
|
|
// Handle other selections
|
|
if (Common::KEYCODE_F1 == _buttonValue ||
|
|
Common::KEYCODE_F2 == _buttonValue ||
|
|
Common::KEYCODE_F3 == _buttonValue ||
|
|
Common::KEYCODE_F4 == _buttonValue ||
|
|
Common::KEYCODE_F5 == _buttonValue ||
|
|
Common::KEYCODE_F6 == _buttonValue) {
|
|
if (!varA && mode != ITEMMODE_3 && mode != ITEMMODE_ENCHANT && mode != ITEMMODE_RECHARGE && mode != ITEMMODE_TO_GOLD && party._mazeId != 0) {
|
|
_buttonValue -= Common::KEYCODE_F1;
|
|
|
|
if (_buttonValue < (int)(_vm->_mode == MODE_COMBAT ? combat._combatParty.size() : party._activeParty.size())) {
|
|
// Character number is valid
|
|
#ifdef USE_TTS
|
|
_vm->stopTextToSpeech();
|
|
#endif
|
|
redrawFlag = REDRAW_FULL;
|
|
Character *newChar = _vm->_mode == MODE_COMBAT ? combat._combatParty[_buttonValue] : &party._activeParty[_buttonValue];
|
|
|
|
if (mode == ITEMMODE_BUY) {
|
|
_oldCharacter = newChar;
|
|
startingChar = newChar;
|
|
c = &_itemsCharacter;
|
|
_itemsCharacter._class = _oldCharacter->_class;
|
|
} else if (mode == ITEMMODE_SELL || mode == ITEMMODE_REPAIR || mode == ITEMMODE_IDENTIFY) {
|
|
_oldCharacter = newChar;
|
|
startingChar = newChar;
|
|
c = newChar;
|
|
} else if (itemIndex != -1) {
|
|
// Switching item to another character
|
|
InventoryItems &destItems = newChar->_items[category];
|
|
InventoryItems &srcItems = c->_items[category];
|
|
XeenItem &srcItem = srcItems[itemIndex];
|
|
|
|
if (srcItem._state._cursed)
|
|
ErrorScroll::show(_vm, Res.CANNOT_REMOVE_CURSED_ITEM);
|
|
else if (destItems.isFull())
|
|
ErrorScroll::show(_vm, Common::String::format(
|
|
Res.CATEGORY_BACKPACK_IS_FULL[category], newChar->_name.c_str()));
|
|
else {
|
|
XeenItem &destItem = destItems[INV_ITEMS_TOTAL - 1];
|
|
destItem = srcItem;
|
|
srcItem.clear();
|
|
destItem._frame = 0;
|
|
|
|
srcItems.sort();
|
|
destItems.sort();
|
|
continue;
|
|
}
|
|
} else {
|
|
c = newChar;
|
|
startingChar = newChar;
|
|
}
|
|
|
|
intf.highlightChar(_buttonValue);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
} else if (Common::KEYCODE_1 == _buttonValue ||
|
|
Common::KEYCODE_2 == _buttonValue ||
|
|
Common::KEYCODE_3 == _buttonValue ||
|
|
Common::KEYCODE_4 == _buttonValue ||
|
|
Common::KEYCODE_5 == _buttonValue ||
|
|
Common::KEYCODE_6 == _buttonValue ||
|
|
Common::KEYCODE_7 == _buttonValue ||
|
|
Common::KEYCODE_8 == _buttonValue ||
|
|
Common::KEYCODE_9 == _buttonValue) {
|
|
// Select an item
|
|
if (mode != ITEMMODE_3) {
|
|
_buttonValue -= Common::KEYCODE_1;
|
|
if (_buttonValue != itemIndex) {
|
|
// Check whether the new selection has an associated item
|
|
if (!c->_items[category][_buttonValue].empty()) {
|
|
itemIndex = _buttonValue;
|
|
Common::fill(&arr[0], &arr[40], 0);
|
|
arr[itemIndex] = 15;
|
|
}
|
|
} else {
|
|
Common::fill(&arr[0], &arr[40], 0);
|
|
itemIndex = -1;
|
|
}
|
|
|
|
redrawFlag = REDRAW_TEXT;
|
|
}
|
|
|
|
} else if (Res.KeyConstants.DialogsItems.KEY_WEAPONS == _buttonValue) {
|
|
// Weapons category
|
|
category = CATEGORY_WEAPON;
|
|
redrawFlag = REDRAW_FULL;
|
|
|
|
} else if (Res.KeyConstants.DialogsItems.KEY_ARMOR == _buttonValue) {
|
|
// Armor category
|
|
category = CATEGORY_ARMOR;
|
|
redrawFlag = REDRAW_FULL;
|
|
|
|
} else if (Res.KeyConstants.DialogsItems.KEY_ACCESSORY == _buttonValue) {
|
|
// Accessories category
|
|
category = CATEGORY_ACCESSORY;
|
|
redrawFlag = REDRAW_FULL;
|
|
|
|
} else if (Res.KeyConstants.DialogsItems.KEY_MISC == _buttonValue) {
|
|
// Misc
|
|
category = CATEGORY_MISC;
|
|
redrawFlag = REDRAW_FULL;
|
|
|
|
} else if (mode == ITEMMODE_ENCHANT ||
|
|
mode == ITEMMODE_RECHARGE ||
|
|
mode == ITEMMODE_TO_GOLD) {
|
|
if (Res.KeyConstants.DialogsItems.KEY_USE == _buttonValue) {
|
|
|
|
} else if (mode == ITEMMODE_ENCHANT &&
|
|
Res.KeyConstants.DialogsItems.KEY_ENCHANT == _buttonValue) {
|
|
actionIndex = 4;
|
|
} else if (mode == ITEMMODE_RECHARGE &&
|
|
Res.KeyConstants.DialogsItems.KEY_RECHRG == _buttonValue) {
|
|
actionIndex = 5;
|
|
} else if (mode == ITEMMODE_TO_GOLD &&
|
|
Res.KeyConstants.DialogsItems.KEY_GOLD == _buttonValue) {
|
|
actionIndex = 6;
|
|
} else if (mode == ITEMMODE_TO_GOLD &&
|
|
Res.KeyConstants.DialogsItems.KEY_EQUIP == _buttonValue) {
|
|
if (category != CATEGORY_MISC)
|
|
actionIndex = 0;
|
|
}
|
|
|
|
} else if (ITEMMODE_BUY == mode ||
|
|
ITEMMODE_SELL == mode ||
|
|
ITEMMODE_IDENTIFY == mode ||
|
|
ITEMMODE_REPAIR == mode) {
|
|
if (Res.KeyConstants.DialogsItems.KEY_BUY == _buttonValue) {
|
|
mode = ITEMMODE_BUY;
|
|
c = &_itemsCharacter;
|
|
redrawFlag = REDRAW_FULL;
|
|
} else if (Res.KeyConstants.DialogsItems.KEY_SELL == _buttonValue) {
|
|
mode = ITEMMODE_SELL;
|
|
c = startingChar;
|
|
redrawFlag = REDRAW_TEXT;
|
|
} else if (Res.KeyConstants.DialogsItems.KEY_IDENTIFY == _buttonValue) {
|
|
mode = ITEMMODE_IDENTIFY;
|
|
c = startingChar;
|
|
redrawFlag = REDRAW_TEXT;
|
|
} else if (Res.KeyConstants.DialogsItems.KEY_FIX == _buttonValue) {
|
|
mode = ITEMMODE_REPAIR;
|
|
c = startingChar;
|
|
redrawFlag = REDRAW_TEXT;
|
|
}
|
|
} else if (ITEMMODE_CHAR_INFO == mode) {
|
|
if (Res.KeyConstants.DialogsItems.KEY_EQUIP == _buttonValue) {
|
|
if (category != CATEGORY_MISC)
|
|
actionIndex = 0;
|
|
} else if (Res.KeyConstants.DialogsItems.KEY_USE == _buttonValue) {
|
|
if (category == CATEGORY_MISC)
|
|
actionIndex = 2;
|
|
} else if (Res.KeyConstants.DialogsItems.KEY_REM == _buttonValue) {
|
|
actionIndex = 1;
|
|
} else if (Res.KeyConstants.DialogsItems.KEY_DISC == _buttonValue) {
|
|
actionIndex = 3;
|
|
} else if (Res.KeyConstants.DialogsItems.KEY_QUEST == _buttonValue) {
|
|
// Quests
|
|
Quests::show(_vm);
|
|
redrawFlag = REDRAW_FULL;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
windows[30].close();
|
|
windows[29].close();
|
|
|
|
intf.drawParty(true);
|
|
if (updateStock)
|
|
party._blacksmithWares.charData2BlackData(_itemsCharacter);
|
|
|
|
return c;
|
|
}
|
|
|
|
void ItemsDialog::loadButtons(ItemsMode mode, Character *&c, ItemCategory category) {
|
|
if (_iconSprites.empty())
|
|
_iconSprites.load(Common::Path(Common::String::format("%s.icn", (mode == ITEMMODE_CHAR_INFO) ? "items" : "buy")));
|
|
if (_equipSprites.empty())
|
|
_equipSprites.load("equip.icn");
|
|
|
|
clearButtons();
|
|
if (mode == ITEMMODE_ENCHANT || mode == ITEMMODE_RECHARGE || mode == ITEMMODE_TO_GOLD) {
|
|
// Enchant button list
|
|
addButton(Common::Rect(12, 109, 36, 129), Res.KeyConstants.DialogsItems.KEY_WEAPONS, &_iconSprites, kItemsEnchantWeapons);
|
|
addButton(Common::Rect(46, 109, 70, 129), Res.KeyConstants.DialogsItems.KEY_ARMOR, &_iconSprites, kItemsEnchantArmor);
|
|
addButton(Common::Rect(80, 109, 104, 129), Res.KeyConstants.DialogsItems.KEY_ACCESSORY, &_iconSprites, kItemsEnchantAccessories);
|
|
addButton(Common::Rect(114, 109, 138, 129), Res.KeyConstants.DialogsItems.KEY_MISC, &_iconSprites, kItemsEnchantMisc);
|
|
addButton(Common::Rect(148, 109, 172, 129), Res.KeyConstants.DialogsItems.KEY_ENCHANT, &_iconSprites, kItemsEnchantEnchant);
|
|
addButton(Common::Rect(284, 109, 308, 129), Common::KEYCODE_ESCAPE, &_iconSprites, kItemsEnchantExit);
|
|
addButton(Common::Rect(148, 109, 172, 129), Res.KeyConstants.DialogsItems.KEY_USE, &_iconSprites, kItemsEnchantUse);
|
|
addButton(Common::Rect(8, 20, 263, 28), Common::KEYCODE_1, nullptr, kItemsEnchantItem1);
|
|
addButton(Common::Rect(8, 29, 263, 37), Common::KEYCODE_2, nullptr, kItemsEnchantItem2);
|
|
addButton(Common::Rect(8, 38, 263, 46), Common::KEYCODE_3, nullptr, kItemsEnchantItem3);
|
|
addButton(Common::Rect(8, 47, 263, 55), Common::KEYCODE_4, nullptr, kItemsEnchantItem4);
|
|
addButton(Common::Rect(8, 56, 263, 64), Common::KEYCODE_5, nullptr, kItemsEnchantItem5);
|
|
addButton(Common::Rect(8, 65, 263, 73), Common::KEYCODE_6, nullptr, kItemsEnchantItem6);
|
|
addButton(Common::Rect(8, 74, 263, 82), Common::KEYCODE_7, nullptr, kItemsEnchantItem7);
|
|
addButton(Common::Rect(8, 83, 263, 91), Common::KEYCODE_8, nullptr, kItemsEnchantItem8);
|
|
addButton(Common::Rect(8, 92, 263, 100), Common::KEYCODE_9, nullptr, kItemsEnchantItem9);
|
|
} else {
|
|
bool flag = mode == ITEMMODE_BUY || mode == ITEMMODE_SELL || mode == ITEMMODE_IDENTIFY
|
|
|| mode == ITEMMODE_REPAIR;
|
|
addButton(Common::Rect(12, 109, 36, 129), Res.KeyConstants.DialogsItems.KEY_WEAPONS, &_iconSprites, kItemsWeapons);
|
|
addButton(Common::Rect(46, 109, 70, 129), Res.KeyConstants.DialogsItems.KEY_ARMOR, &_iconSprites, kItemsArmor);
|
|
addButton(Common::Rect(80, 109, 104, 129), Res.KeyConstants.DialogsItems.KEY_ACCESSORY, &_iconSprites, kItemsAccessories);
|
|
addButton(Common::Rect(114, 109, 138, 129), Res.KeyConstants.DialogsItems.KEY_MISC, &_iconSprites, kItemsMisc);
|
|
addButton(Common::Rect(148, 109, 172, 129), flag ? Res.KeyConstants.DialogsItems.KEY_BUY : Res.KeyConstants.DialogsItems.KEY_EQUIP, &_iconSprites, kItemsBuyOrEquip);
|
|
addButton(Common::Rect(182, 109, 206, 129), flag ? Res.KeyConstants.DialogsItems.KEY_SELL : Res.KeyConstants.DialogsItems.KEY_REM, &_iconSprites, kItemsSellOrRemove);
|
|
addButton(Common::Rect(216, 109, 240, 129), flag ? Res.KeyConstants.DialogsItems.KEY_IDENTIFY : Res.KeyConstants.DialogsItems.KEY_DISC, &_iconSprites, kItemsIdentifyOrDiscard);
|
|
addButton(Common::Rect(250, 109, 274, 129), flag ? Res.KeyConstants.DialogsItems.KEY_FIX : Res.KeyConstants.DialogsItems.KEY_QUEST, &_iconSprites, kItemsFixOrQuest);
|
|
addButton(Common::Rect(284, 109, 308, 129), Common::KEYCODE_ESCAPE, &_iconSprites, kItemsExit);
|
|
addButton(Common::Rect(8, 20, 263, 28), Common::KEYCODE_1, nullptr, kItemsItem1);
|
|
addButton(Common::Rect(8, 29, 263, 37), Common::KEYCODE_2, nullptr, kItemsItem2);
|
|
addButton(Common::Rect(8, 38, 263, 46), Common::KEYCODE_3, nullptr, kItemsItem3);
|
|
addButton(Common::Rect(8, 47, 263, 55), Common::KEYCODE_4, nullptr, kItemsItem4);
|
|
addButton(Common::Rect(8, 56, 263, 64), Common::KEYCODE_5, nullptr, kItemsItem5);
|
|
addButton(Common::Rect(8, 65, 263, 73), Common::KEYCODE_6, nullptr, kItemsItem6);
|
|
addButton(Common::Rect(8, 74, 263, 82), Common::KEYCODE_7, nullptr, kItemsItem7);
|
|
addButton(Common::Rect(8, 83, 263, 91), Common::KEYCODE_8, nullptr, kItemsItem8);
|
|
addButton(Common::Rect(8, 92, 263, 100), Common::KEYCODE_9, nullptr, kItemsItem9);
|
|
addPartyButtons(_vm);
|
|
}
|
|
|
|
if (mode == ITEMMODE_CHAR_INFO && category == CATEGORY_MISC) {
|
|
_buttons[4].setFrame(18);
|
|
_buttons[4]._value = Res.KeyConstants.DialogsItems.KEY_USE;
|
|
}
|
|
if (mode != ITEMMODE_ENCHANT && mode != ITEMMODE_RECHARGE && mode != ITEMMODE_TO_GOLD) {
|
|
_buttons[5].setFrame(10);
|
|
_buttons[6].setFrame(12);
|
|
_buttons[7].setFrame(14);
|
|
}
|
|
|
|
// Set button as depressed depending on which mode the dialog is currently in
|
|
switch (mode) {
|
|
case ITEMMODE_BUY:
|
|
_buttons[4].setFrame(9);
|
|
break;
|
|
case ITEMMODE_SELL:
|
|
_buttons[5].setFrame(11);
|
|
break;
|
|
case ITEMMODE_IDENTIFY:
|
|
_buttons[6].setFrame(13);
|
|
break;
|
|
case ITEMMODE_REPAIR:
|
|
_buttons[7].setFrame(15);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if ((mode != ITEMMODE_CHAR_INFO || category != CATEGORY_MISC) && mode != ITEMMODE_ENCHANT
|
|
&& mode != ITEMMODE_RECHARGE && mode != ITEMMODE_TO_GOLD) {
|
|
_buttons[4]._bounds.moveTo(148, _buttons[4]._bounds.top);
|
|
_buttons[9]._draw = false;
|
|
} else if (mode == ITEMMODE_RECHARGE) {
|
|
_buttons[4]._value = Res.KeyConstants.DialogsItems.KEY_RECHRG;
|
|
} else if (mode == ITEMMODE_ENCHANT) {
|
|
_buttons[4]._value = Res.KeyConstants.DialogsItems.KEY_ENCHANT;
|
|
} else if (mode == ITEMMODE_TO_GOLD) {
|
|
_buttons[4]._value = Res.KeyConstants.DialogsItems.KEY_GOLD;
|
|
}
|
|
}
|
|
|
|
void ItemsDialog::setEquipmentIcons() {
|
|
for (int typeIndex = 0; typeIndex < 4; ++typeIndex) {
|
|
for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) {
|
|
switch (typeIndex) {
|
|
case CATEGORY_WEAPON: {
|
|
XeenItem &i = _itemsCharacter._weapons[idx];
|
|
if (i._id <= 17)
|
|
i._frame = 1;
|
|
else if (i._id <= 29 || i._id > 33)
|
|
i._frame = 13;
|
|
else
|
|
i._frame = 4;
|
|
break;
|
|
}
|
|
|
|
case CATEGORY_ARMOR: {
|
|
XeenItem &i = _itemsCharacter._armor[idx];
|
|
if (i._id <= 7)
|
|
i._frame = 3;
|
|
else if (i._id == 8)
|
|
i._frame = 2;
|
|
else if (i._id == 9)
|
|
i._frame = 5;
|
|
else if (i._id == 10)
|
|
i._frame = 9;
|
|
else if (i._id <= 12)
|
|
i._frame = 10;
|
|
else
|
|
i._frame = 6;
|
|
break;
|
|
}
|
|
|
|
case CATEGORY_ACCESSORY: {
|
|
XeenItem &i = _itemsCharacter._accessories[idx];
|
|
if (i._id == 1)
|
|
i._id = 8;
|
|
else if (i._id == 2)
|
|
i._frame = 12;
|
|
else if (i._id <= 7)
|
|
i._frame = 7;
|
|
else
|
|
i._frame = 11;
|
|
break;
|
|
}
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
int ItemsDialog::calcItemCost(Character *c, int itemIndex, ItemsMode mode,
|
|
int skillLevel, ItemCategory category) {
|
|
int amount1 = 0, amount2 = 0, amount3 = 0, amount4 = 0;
|
|
int result = 0;
|
|
int level = skillLevel & 0x7f;
|
|
XeenItem &i = c->_items[category][itemIndex];
|
|
|
|
const int *BASE_COSTS[4] = {
|
|
Res.WEAPON_BASE_COSTS, Res.ARMOR_BASE_COSTS, Res.ACCESSORY_BASE_COSTS, Res.MISC_BASE_COSTS
|
|
};
|
|
|
|
switch (mode) {
|
|
case ITEMMODE_BUY:
|
|
level = 0;
|
|
break;
|
|
case ITEMMODE_SELL:
|
|
case ITEMMODE_TO_GOLD:
|
|
level = level == 0 ? 1 : 0;
|
|
break;
|
|
case ITEMMODE_IDENTIFY:
|
|
level = 2;
|
|
break;
|
|
case ITEMMODE_REPAIR:
|
|
level = 3;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
switch (category) {
|
|
case CATEGORY_WEAPON:
|
|
case CATEGORY_ARMOR:
|
|
case CATEGORY_ACCESSORY:
|
|
amount1 = (BASE_COSTS[category])[i._id];
|
|
|
|
if (i._material > 36 && i._material < 59) {
|
|
switch (i._material) {
|
|
case 37:
|
|
amount1 /= 10;
|
|
break;
|
|
case 38:
|
|
amount1 /= 4;
|
|
break;
|
|
case 39:
|
|
amount1 /= 2;
|
|
break;
|
|
case 40:
|
|
amount1 /= 4;
|
|
break;
|
|
default:
|
|
amount1 *= Res.METAL_BASE_MULTIPLIERS[i._material - 37];
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i._material < 37)
|
|
amount2 = Res.ELEMENTAL_DAMAGE[i._material] * 100;
|
|
else if (i._material > 58)
|
|
amount3 = Res.ELEMENTAL_DAMAGE[i._material - 59 + 7] * 100;
|
|
|
|
switch (mode) {
|
|
case ITEMMODE_BUY:
|
|
case ITEMMODE_SELL:
|
|
case ITEMMODE_REPAIR:
|
|
case ITEMMODE_IDENTIFY:
|
|
case ITEMMODE_TO_GOLD:
|
|
result = (amount1 + amount2 + amount3 + amount4) / Res.ITEM_SKILL_DIVISORS[level];
|
|
if (!result)
|
|
result = 1;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case CATEGORY_MISC:
|
|
// Misc
|
|
amount1 = Res.MISC_MATERIAL_COSTS[i._material];
|
|
amount4 = Res.MISC_BASE_COSTS[i._id];
|
|
|
|
switch (mode) {
|
|
case ITEMMODE_BUY:
|
|
case ITEMMODE_SELL:
|
|
case ITEMMODE_REPAIR:
|
|
case ITEMMODE_IDENTIFY:
|
|
case ITEMMODE_TO_GOLD:
|
|
result = (amount1 + amount2 + amount3 + amount4) / Res.ITEM_SKILL_DIVISORS[level];
|
|
if (!result)
|
|
result = 1;
|
|
break;
|
|
|
|
case ITEMMODE_3:
|
|
case ITEMMODE_RECHARGE:
|
|
case ITEMMODE_5:
|
|
case ITEMMODE_ENCHANT:
|
|
// Show number of charges
|
|
result = i._state._counter;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return (mode == ITEMMODE_CHAR_INFO) ? 0 : result;
|
|
}
|
|
|
|
const char *ItemsDialog::getGoldPlurals(int cost) {
|
|
if (Common::RU_RUS == g_vm->getLanguage())
|
|
return Res.GOLDS[cost % 10 == 1 ? 0 : 1];
|
|
return Res.GOLDS[0];
|
|
}
|
|
|
|
int ItemsDialog::doItemOptions(Character &c, int actionIndex, int itemIndex, ItemCategory category,
|
|
ItemsMode mode) {
|
|
Combat &combat = *_vm->_combat;
|
|
EventsManager &events = *_vm->_events;
|
|
Interface &intf = *_vm->_interface;
|
|
Party &party = *_vm->_party;
|
|
Sound &sound = *_vm->_sound;
|
|
Spells &spells = *_vm->_spells;
|
|
Windows &windows = *_vm->_windows;
|
|
int ccNum = _vm->_files->_ccNum;
|
|
|
|
InventoryItems &items = c._items[category];
|
|
if (items[0].empty())
|
|
// Inventory is empty
|
|
return category == CATEGORY_MISC ? 0 : 2;
|
|
|
|
if (itemIndex < 0 || itemIndex > 8) {
|
|
// Populate item button texts. Text for items starts at keycode 1 and ends at keycode 9
|
|
Common::StringArray ttsItemButtonTexts;
|
|
#ifdef USE_TTS
|
|
for (uint i = 0; i < _buttons.size(); ++i) {
|
|
if (_buttons[i]._value == Common::KeyCode::KEYCODE_1) {
|
|
if (_buttons[i]._ttsIndex >= _buttonTexts.size()) {
|
|
break;
|
|
}
|
|
|
|
ttsItemButtonTexts.assign(_buttonTexts.begin() + _buttons[i]._ttsIndex, _buttonTexts.end());
|
|
break;
|
|
}
|
|
}
|
|
#endif
|
|
itemIndex = ItemSelectionDialog::show(actionIndex, items, ttsItemButtonTexts);
|
|
}
|
|
|
|
if (itemIndex != -1) {
|
|
XeenItem &item = items[itemIndex];
|
|
|
|
switch (mode) {
|
|
case ITEMMODE_CHAR_INFO:
|
|
case ITEMMODE_8:
|
|
switch (actionIndex) {
|
|
case 0:
|
|
c._items[category].equipItem(itemIndex);
|
|
break;
|
|
case 1:
|
|
c._items[category].removeItem(itemIndex);
|
|
break;
|
|
case 2:
|
|
if (!party._mazeId) {
|
|
ErrorScroll::show(_vm, Res.WHATS_YOUR_HURRY);
|
|
} else {
|
|
XeenItem &i = c._misc[itemIndex];
|
|
|
|
Condition condition = c.worstCondition();
|
|
switch (condition) {
|
|
case ASLEEP:
|
|
case PARALYZED:
|
|
case UNCONSCIOUS:
|
|
case DEAD:
|
|
case STONED:
|
|
case ERADICATED:
|
|
ErrorScroll::show(_vm, Common::String::format(Res.IN_NO_CONDITION, c._name.c_str()));
|
|
break;
|
|
default:
|
|
if (combat._itemFlag) {
|
|
ErrorScroll::show(_vm, Res.USE_ITEM_IN_COMBAT);
|
|
} else if (i._id && !i.isBad() && i._state._counter > 0) {
|
|
--i._state._counter;
|
|
|
|
_oldCharacter = &c;
|
|
combat._oldCharacter = _oldCharacter;
|
|
|
|
windows[30].close();
|
|
windows[29].close();
|
|
windows[24].close();
|
|
|
|
spells.castItemSpell(i._id);
|
|
|
|
if (!i._state._counter) {
|
|
// Ran out of charges, so make item disappear
|
|
c._items[category][itemIndex].clear();
|
|
c._items[category].sort();
|
|
}
|
|
|
|
intf._charsShooting = false;
|
|
combat.moveMonsters();
|
|
combat._whosTurn = -1;
|
|
return 1;
|
|
} else {
|
|
ErrorScroll::show(_vm, Common::String::format(Res.NO_SPECIAL_ABILITIES,
|
|
c._items[category].getFullDescription(itemIndex).c_str()
|
|
));
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case 3:
|
|
if (c._items[category].discardItem(itemIndex) && mode == ITEMMODE_8)
|
|
return 2;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case ITEMMODE_BUY: {
|
|
InventoryItems &invItems = _oldCharacter->_items[category];
|
|
if (invItems.isFull()) {
|
|
// Character's inventory for that category is already full
|
|
ErrorScroll::show(_vm, Common::String::format(Res.BACKPACK_IS_FULL,
|
|
_oldCharacter->_name.c_str()));
|
|
} else {
|
|
int cost = calcItemCost(&c, itemIndex, mode, 0, category);
|
|
Common::String desc = c._items[category].getFullDescription(itemIndex);
|
|
if (Confirm::show(_vm, Common::String::format(Res.BUY_X_FOR_Y_GOLD,
|
|
desc.c_str(), cost, getGoldPlurals(cost)))) {
|
|
if (party.subtract(CONS_GOLD, cost, WHERE_PARTY, WT_FREEZE_WAIT)) {
|
|
if (ccNum) {
|
|
sound.stopSound();
|
|
sound.playSound("choice2.voc");
|
|
}
|
|
|
|
// Add entry to the end of the list
|
|
XeenItem &srcItem = c._items[category][itemIndex];
|
|
XeenItem &destItem = _oldCharacter->_items[category][INV_ITEMS_TOTAL - 1];
|
|
destItem = srcItem;
|
|
destItem._frame = 0;
|
|
|
|
srcItem.clear();
|
|
c._items[category].sort();
|
|
_oldCharacter->_items[category].sort();
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
case ITEMMODE_SELL: {
|
|
bool noNeed;
|
|
switch (category) {
|
|
case CATEGORY_WEAPON:
|
|
noNeed = (item._state._cursed) || item._id >= XEEN_SLAYER_SWORD;
|
|
break;
|
|
default:
|
|
noNeed = item._state._cursed;
|
|
break;
|
|
}
|
|
|
|
if (noNeed) {
|
|
ErrorScroll::show(_vm, Common::String::format(Res.NO_NEED_OF_THIS,
|
|
c._items[category].getFullDescription(itemIndex).c_str()));
|
|
} else {
|
|
int cost = calcItemCost(&c, itemIndex, mode, c._skills[MERCHANT], category);
|
|
Common::String desc = c._items[category].getFullDescription(itemIndex);
|
|
Common::String msg = Common::String::format(Res.SELL_X_FOR_Y_GOLD,
|
|
desc.c_str(), cost, getGoldPlurals(cost));
|
|
|
|
if (Confirm::show(_vm, msg)) {
|
|
// Remove the sold item and add gold to the party's total
|
|
item.clear();
|
|
c._items[category].sort();
|
|
|
|
party._gold += cost;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
case ITEMMODE_RECHARGE:
|
|
if (category != CATEGORY_MISC || item.empty() || item._material > 9 || item._id == 53) {
|
|
sound.playFX(21);
|
|
ErrorScroll::show(_vm, Common::String::format(Res.NOT_RECHARGABLE, Res.SPELL_FAILED));
|
|
} else {
|
|
item._state._counter = MIN(63, _vm->getRandomNumber(1, 6) + item._state._counter);
|
|
sound.playFX(20);
|
|
}
|
|
return 2;
|
|
|
|
case ITEMMODE_ENCHANT: {
|
|
int amount = _vm->getRandomNumber(1, _oldCharacter->getCurrentLevel() / 5 + 1);
|
|
amount = MIN(amount, 5);
|
|
_oldCharacter->_items[category].enchantItem(itemIndex, amount);
|
|
return 2;
|
|
}
|
|
|
|
case ITEMMODE_REPAIR:
|
|
if (!item._state._broken) {
|
|
ErrorScroll::show(_vm, Res.ITEM_NOT_BROKEN);
|
|
} else {
|
|
int cost = calcItemCost(&c, itemIndex, mode, actionIndex, category);
|
|
Common::String msg = Common::String::format(Res.FIX_IDENTIFY_GOLD,
|
|
Res.FIX_IDENTIFY[0],
|
|
c._items[category].getFullDescription(itemIndex).c_str(),
|
|
cost, getGoldPlurals(cost));
|
|
|
|
if (Confirm::show(_vm, msg) && party.subtract(CONS_GOLD, cost, WHERE_PARTY)) {
|
|
item._state._broken = false;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case ITEMMODE_IDENTIFY: {
|
|
int cost = calcItemCost(&c, itemIndex, mode, actionIndex, category);
|
|
Common::String msg = Common::String::format(Res.FIX_IDENTIFY_GOLD,
|
|
Res.FIX_IDENTIFY[1],
|
|
c._items[category].getFullDescription(itemIndex).c_str(),
|
|
cost, getGoldPlurals(cost));
|
|
|
|
if (Confirm::show(_vm, msg) && party.subtract(CONS_GOLD, cost, WHERE_PARTY)) {
|
|
Common::String details = c._items[category].getIdentifiedDetails(itemIndex);
|
|
Common::String desc = c._items[category].getFullDescription(itemIndex);
|
|
Common::String str = Common::String::format(Res.IDENTIFY_ITEM_MSG,
|
|
desc.c_str(), details.c_str());
|
|
|
|
Window &win = windows[14];
|
|
win.open();
|
|
win.writeString(str);
|
|
win.update();
|
|
|
|
saveButtons();
|
|
clearButtons();
|
|
|
|
while (!_vm->shouldExit() && !events.isKeyMousePressed())
|
|
events.pollEventsAndWait();
|
|
events.clearEvents();
|
|
|
|
restoreButtons();
|
|
win.close();
|
|
}
|
|
break;
|
|
}
|
|
|
|
case ITEMMODE_TO_GOLD:
|
|
// Convert item in inventory to gold
|
|
itemToGold(c, itemIndex, category, mode);
|
|
return 2;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void ItemsDialog::itemToGold(Character &c, int itemIndex, ItemCategory category,
|
|
ItemsMode mode) {
|
|
XeenItem &item = c._items[category][itemIndex];
|
|
Party &party = *_vm->_party;
|
|
Sound &sound = *_vm->_sound;
|
|
|
|
if (category == CATEGORY_WEAPON && item._id >= XEEN_SLAYER_SWORD) {
|
|
sound.playFX(21);
|
|
ErrorScroll::show(_vm, Common::String::format("\v012\t000\x03""c%s",
|
|
Res.SPELL_FAILED));
|
|
} else if (!item.empty()) {
|
|
// There is a valid item present
|
|
// Calculate cost of item and add it to the party's total
|
|
int cost = calcItemCost(&c, itemIndex, mode, 1, category);
|
|
party._gold += cost;
|
|
|
|
// Remove the item from the inventory
|
|
item.clear();
|
|
c._items[category].sort();
|
|
}
|
|
}
|
|
|
|
#ifdef USE_TTS
|
|
|
|
void ItemsDialog::speakText(const Common::String &text, uint8 headerCount, uint8 lineCount) {
|
|
uint index = 0;
|
|
_vm->sayText(getNextTextSection(text, index, headerCount));
|
|
|
|
uint startingIndex = 0;
|
|
|
|
for (uint i = 0; i < _buttonTexts.size(); ++i) {
|
|
if (_buttonTexts[i].empty()) {
|
|
startingIndex = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// In some cases, each item has 3 fields: number, name, and cost. In others, it only has the number and name
|
|
// This generally corresponds to the number of fields in the header (i.e. "Weapons for Character" and "Cost" is 2 headers
|
|
// and 2 fields, versus just "Weapons for Character" that's 1 header with 1 field)
|
|
uint fieldsPerSection = (headerCount >= 2 || g_vm->_extOptions._showItemCosts) ? 3 : 2;
|
|
for (uint i = 0; i < lineCount; ++i) {
|
|
Common::String itemInfo = getNextTextSection(text, index, fieldsPerSection, ", ");
|
|
_vm->sayText(itemInfo);
|
|
|
|
if (startingIndex != 0 && i + startingIndex < _buttonTexts.size()) {
|
|
_buttonTexts[i + startingIndex] = itemInfo;
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
int ItemSelectionDialog::show(int actionIndex, InventoryItems &items, const Common::StringArray &ttsItemButtonTexts) {
|
|
ItemSelectionDialog *dlg = new ItemSelectionDialog(g_vm, actionIndex, items, ttsItemButtonTexts);
|
|
int result = dlg->execute();
|
|
delete dlg;
|
|
|
|
return result;
|
|
}
|
|
|
|
void ItemSelectionDialog::loadButtons() {
|
|
_icons.load("esc.icn");
|
|
addButton(Common::Rect(235, 111, 259, 131), Common::KEYCODE_ESCAPE, &_icons);
|
|
addButton(Common::Rect(8, 20, 263, 28), Common::KEYCODE_1, nullptr, kItemSelectionItem1);
|
|
addButton(Common::Rect(8, 29, 263, 37), Common::KEYCODE_2, nullptr, kItemSelectionItem2);
|
|
addButton(Common::Rect(8, 38, 263, 46), Common::KEYCODE_3, nullptr, kItemSelectionItem3);
|
|
addButton(Common::Rect(8, 47, 263, 55), Common::KEYCODE_4, nullptr, kItemSelectionItem4);
|
|
addButton(Common::Rect(8, 56, 263, 64), Common::KEYCODE_5, nullptr, kItemSelectionItem5);
|
|
addButton(Common::Rect(8, 65, 263, 73), Common::KEYCODE_6, nullptr, kItemSelectionItem6);
|
|
addButton(Common::Rect(8, 74, 263, 82), Common::KEYCODE_7, nullptr, kItemSelectionItem7);
|
|
addButton(Common::Rect(8, 83, 263, 91), Common::KEYCODE_8, nullptr, kItemSelectionItem8);
|
|
addButton(Common::Rect(8, 92, 263, 100), Common::KEYCODE_9, nullptr, kItemSelectionItem9);
|
|
}
|
|
|
|
int ItemSelectionDialog::execute() {
|
|
EventsManager &events = *g_vm->_events;
|
|
Windows &windows = *g_vm->_windows;
|
|
Window &w = windows[13];
|
|
|
|
w.open();
|
|
w.writeString(Common::String::format(Res.WHICH_ITEM, Res.ITEM_ACTIONS[_actionIndex]));
|
|
_icons.draw(0, 0, Common::Point(235, 111));
|
|
w.update();
|
|
|
|
#ifdef USE_TTS
|
|
for (uint i = 0; i < _buttonTexts.size(); ++i) {
|
|
_vm->sayText(_buttonTexts[i]);
|
|
}
|
|
#endif
|
|
|
|
int itemIndex = -1;
|
|
while (!_vm->shouldExit()) {
|
|
_buttonValue = 0;
|
|
while (!_buttonValue) {
|
|
events.pollEventsAndWait();
|
|
checkEvents(_vm);
|
|
if (_vm->shouldExit())
|
|
return false;
|
|
}
|
|
|
|
if (_buttonValue == Common::KEYCODE_ESCAPE) {
|
|
itemIndex = -1;
|
|
break;
|
|
}
|
|
else if (_buttonValue >= Common::KEYCODE_1 && _buttonValue <= Common::KEYCODE_9) {
|
|
// Check whether there's an item at the selected index
|
|
int selectedIndex = _buttonValue - Common::KEYCODE_1;
|
|
if (!_items[selectedIndex]._id)
|
|
continue;
|
|
|
|
itemIndex = selectedIndex;
|
|
break;
|
|
}
|
|
}
|
|
|
|
w.close();
|
|
return itemIndex;
|
|
}
|
|
|
|
} // End of namespace Xeen
|
|
} // End of namespace MM
|