scummvm/engines/efh/menu.cpp

1441 lines
46 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 "efh/efh.h"
namespace Efh {
int16 EfhEngine::displayBoxWithText(Common::String str, int16 menuType, int16 displayOption, bool displayTeamWindowFl) {
debugC(3, kDebugEngine, "displayBoxWithText %s %d %d %s", str.c_str(), menuType, displayOption, displayTeamWindowFl ? "True" : "False");
int16 retVal = 0xFF;
int16 minX, maxX, minY, maxY;
switch (menuType) {
case 0:
minX = 129;
minY = 9;
maxX = 302;
maxY = 18;
break;
case 1:
minX = 129;
minY = 9;
maxX = 302;
maxY = 110;
break;
case 2:
minX = 129;
minY = 112;
maxX = 302;
maxY = 132;
break;
case 3:
minX = 129;
minY = 79;
maxX = 303;
maxY = 107;
break;
default:
minX = minY = 0;
maxX = 320;
maxY = 200;
break;
}
drawColoredRect(minX, minY, maxX, maxY, 0);
if (!str.empty())
retVal = script_parse(str, minX, minY, maxX, maxY, true);
if (displayTeamWindowFl)
displayLowStatusScreen(false);
if (displayOption != 0) {
displayFctFullScreen();
if (_textBoxDisabledByScriptFl)
_textBoxDisabledByScriptFl = false;
else {
drawColoredRect(minX, minY, maxX, maxY, 0);
if (!str.empty())
script_parse(str, minX, minY, maxX, maxY, false);
}
if (displayTeamWindowFl)
displayLowStatusScreen(false);
if (displayOption >= 2)
getLastCharAfterAnimCount(_guessAnimationAmount);
if (displayOption == 3)
drawColoredRect(minX, minY, maxX, maxY, 0);
}
return retVal;
}
bool EfhEngine::handleDeathMenu() {
debugC(3, kDebugEngine, "handleDeathMenu");
_saveAuthorized = false;
displayAnimFrames(20, true);
_imageSetSubFilesIdx = 213;
drawScreen();
for (uint counter = 0; counter < 2; ++counter) {
clearBottomTextZone(0);
displayCenteredString("Darkness Prevails...Death Has Taken You!", 24, 296, 153);
setTextPos(100, 162);
setTextColorWhite();
displayCharAtTextPos('L');
setTextColorRed();
displayStringAtTextPos("oad last saved game");
setTextPos(100, 171);
setTextColorWhite();
displayCharAtTextPos('R');
setTextColorRed();
displayStringAtTextPos("estart from beginning");
setTextPos(100, 180);
setTextColorWhite();
displayCharAtTextPos('Q');
setTextColorRed();
displayStringAtTextPos("uit for now");
if (counter == 0)
displayFctFullScreen();
}
for (bool found = false; !found && !shouldQuitGame();) {
Common::KeyCode input = waitForKey();
switch (input) {
case Common::KEYCODE_l:
// If the user actually loads a savegame, it'll get _saveAuthorized from the savegame (always true) and will set 'found' to true.
// If 'found' remains false, it means the user cancelled the loading and still needs to take a decision
// Original is calling loadEfhGame() because there's only one savegame, so it's not ambiguous
loadGameDialog();
found = _saveAuthorized;
break;
case Common::KEYCODE_q:
_shouldQuit = true;
return true;
break;
case Common::KEYCODE_r:
loadEfhGame();
resetGame();
found = true;
_saveAuthorized = true;
break;
case Common::KEYCODE_x: // mysterious and unexpected keycode ?
found = true;
break;
default:
break;
}
}
displayAnimFrames(0xFE, true);
return false;
}
void EfhEngine::displayCombatMenu(int16 charId) {
debugC(6, kDebugEngine, "displayCombatMenu %d", charId);
Common::String buffer = Common::String::format("%s:", _npcBuf[charId]._name);
setTextColorWhite();
setTextPos(144, 7);
displayStringAtTextPos(buffer);
setTextPos(152, 79);
displayStringAtTextPos("A");
setTextColorRed();
displayStringAtTextPos("ttack");
setTextPos(195, 79);
setTextColorWhite();
displayStringAtTextPos("H");
setTextColorRed();
displayStringAtTextPos("ide");
setTextPos(152, 88);
setTextColorWhite();
displayStringAtTextPos("D");
setTextColorRed();
displayStringAtTextPos("efend");
setTextPos(195, 88);
setTextColorWhite();
displayStringAtTextPos("R");
setTextColorRed();
displayStringAtTextPos("un");
setTextPos(152, 97);
setTextColorWhite();
displayStringAtTextPos("S");
setTextColorRed();
displayStringAtTextPos("tatus");
}
void EfhEngine::displayMenuItemString(int16 menuBoxId, int16 thisBoxId, int16 minX, int16 maxX, int16 minY, const char *str) {
debugC(6, kDebugEngine, "displayMenuItemString %d %d %d->%d %d %s", menuBoxId, thisBoxId, minX, maxX, minY, str);
if (menuBoxId == thisBoxId) {
if (_menuDepth == 0)
setTextColorWhite();
else
setTextColorGrey();
Common::String buffer = Common::String::format("> %s <", str);
displayCenteredString(buffer, minX, maxX, minY);
setTextColorRed();
} else {
if (_menuDepth == 0)
setTextColorRed();
else
setTextColorGrey();
displayCenteredString(str, minX, maxX, minY);
}
}
void EfhEngine::displayStatusMenu(int16 windowId) {
debugC(3, kDebugEngine, "displayStatusMenu %d", windowId);
for (uint counter = 0; counter < 9; ++counter) {
drawColoredRect(80, 39 + 14 * counter, 134, 47 + 14 * counter, 0);
}
if (_menuDepth != 0)
setTextColorGrey();
displayMenuItemString(windowId, 0, 80, 134, 39, "EQUIP");
displayMenuItemString(windowId, 1, 80, 134, 53, "USE");
displayMenuItemString(windowId, 2, 80, 134, 67, "GIVE");
displayMenuItemString(windowId, 3, 80, 134, 81, "TRADE");
displayMenuItemString(windowId, 4, 80, 134, 95, "DROP");
displayMenuItemString(windowId, 5, 80, 134, 109, "INFO.");
displayMenuItemString(windowId, 6, 80, 134, 123, "PASSIVE");
displayMenuItemString(windowId, 7, 80, 134, 137, "ACTIVE");
displayMenuItemString(windowId, 8, 80, 134, 151, "LEAVE");
setTextColorRed();
}
void EfhEngine::prepareStatusRightWindowIndexes(int16 menuId, int16 charId) {
debugC(6, kDebugEngine, "prepareStatusRightWindowIndexes %d %d", menuId, charId);
_menuItemCounter = 0;
switch (menuId) {
case kEfhMenuInfo:
for (int16 counter = 0; counter <= 10; ++counter) {
if (_npcBuf[charId]._infoScore[counter] != 0) {
_menuStatItemArr[_menuItemCounter++] = counter + 26;
}
}
break;
case kEfhMenuPassive:
for (int16 counter = 0; counter <= 10; ++counter) {
if (_npcBuf[charId]._passiveScore[counter] != 0) {
_menuStatItemArr[_menuItemCounter++] = counter + 15;
}
}
break;
case kEfhMenuActive:
for (int16 counter = 0; counter <= 14; ++counter) {
if (_npcBuf[charId]._activeScore[counter] != 0) {
_menuStatItemArr[_menuItemCounter++] = counter;
}
}
break;
default:
for (uint counter = 0; counter < 10; ++counter) {
if (_npcBuf[charId]._inventory[counter]._ref != 0x7FFF) {
_menuStatItemArr[_menuItemCounter++] = counter;
}
}
break;
}
}
void EfhEngine::displayCharacterSummary(int16 curMenuLine, int16 npcId) {
debugC(3, kDebugEngine, "displayCharacterSummary %d %d", curMenuLine, npcId);
setTextColorRed();
Common::String buffer1 = _npcBuf[npcId]._name;
setTextPos(146, 27);
displayStringAtTextPos("Name: ");
displayStringAtTextPos(buffer1);
buffer1 = Common::String::format("Level: %d", getXPLevel(_npcBuf[npcId]._xp));
setTextPos(146, 36);
displayStringAtTextPos(buffer1);
buffer1 = Common::String::format("XP: %u", _npcBuf[npcId]._xp);
setTextPos(227, 36);
displayStringAtTextPos(buffer1);
buffer1 = Common::String::format("Speed: %d", _npcBuf[npcId]._speed);
setTextPos(146, 45);
displayStringAtTextPos(buffer1);
buffer1 = Common::String::format("Defense: %d", getEquipmentDefense(npcId));
setTextPos(146, 54);
displayStringAtTextPos(buffer1);
buffer1 = Common::String::format("Hit Points: %d", _npcBuf[npcId]._hitPoints);
setTextPos(146, 63);
displayStringAtTextPos(buffer1);
buffer1 = Common::String::format("Max HP: %d", _npcBuf[npcId]._maxHP);
setTextPos(227, 63);
displayStringAtTextPos(buffer1);
displayCenteredString("Inventory", 144, 310, 72);
if (_menuItemCounter == 0) {
if (curMenuLine != -1)
setTextColorWhite();
displayCenteredString("Nothing Carried", 144, 310, 117);
setTextColorRed();
return;
}
for (int counter = 0; counter < _menuItemCounter; ++counter) {
if (_menuDepth == 0)
setTextColorGrey();
else {
if (counter == curMenuLine)
setTextColorWhite();
}
int16 textPosY = 81 + counter * 9;
int16 itemId = _npcBuf[npcId]._inventory[_menuStatItemArr[counter]]._ref;
if (itemId != 0x7FFF) {
if (_npcBuf[npcId]._inventory[_menuStatItemArr[counter]].isEquipped()) {
setTextPos(146, textPosY);
displayCharAtTextPos('E');
}
}
setTextPos(152, textPosY);
if (counter == curMenuLine) {
buffer1 = Common::String::format("%c>", 'A' + counter);
} else {
buffer1 = Common::String::format("%c)", 'A' + counter);
}
displayStringAtTextPos(buffer1);
if (itemId != 0x7FFF) {
setTextPos(168, textPosY);
buffer1 = Common::String::format(" %s", _items[itemId]._name);
displayStringAtTextPos(buffer1);
setTextPos(262, textPosY);
if (_items[itemId]._defense > 0) {
int16 curHitPoints = _npcBuf[npcId]._inventory[_menuStatItemArr[counter]]._curHitPoints;
if (curHitPoints != 0xFF) {
buffer1 = Common::String::format("%d", 1 + curHitPoints / 8);
displayStringAtTextPos(buffer1);
setTextPos(286, textPosY);
displayStringAtTextPos("Def");
}
// useless code removed.
// else {
// var54 = _items[_npcBuf[npcId]._inventory[_menuStatItemArr[counter]]._ref]._defense;
// {
} else if (_items[itemId]._uses != 0x7F) {
int16 stat1 = _npcBuf[npcId]._inventory[_menuStatItemArr[counter]].getUsesLeft();
if (stat1 != 0x7F) {
buffer1 = Common::String::format("%d", stat1);
displayStringAtTextPos(buffer1);
setTextPos(286, textPosY);
if (stat1 == 1)
displayStringAtTextPos("Use");
else
displayStringAtTextPos("Uses");
}
}
}
setTextColorRed();
}
}
void EfhEngine::displayCharacterInformationOrSkills(int16 curMenuLine, int16 charId) {
debugC(3, kDebugEngine, "displayCharacterInformationOrSkills %d %d", curMenuLine, charId);
setTextColorRed();
Common::String buffer = _npcBuf[charId]._name;
setTextPos(146, 27);
displayStringAtTextPos("Name: ");
displayStringAtTextPos(buffer);
if (_menuItemCounter <= 0) {
if (curMenuLine != -1)
setTextColorWhite();
displayCenteredString("No Skills To Select", 144, 310, 96);
setTextColorRed();
return;
}
for (int counter = 0; counter < _menuItemCounter; ++counter) {
if (counter == curMenuLine)
setTextColorWhite();
int16 textPosY = 38 + counter * 9;
setTextPos(146, textPosY);
if (counter == curMenuLine) {
buffer = Common::String::format("%c>", 'A' + counter);
} else {
buffer = Common::String::format("%c)", 'A' + counter);
}
displayStringAtTextPos(buffer);
setTextPos(163, textPosY);
int16 scoreId = _menuStatItemArr[counter];
displayStringAtTextPos(kSkillArray[scoreId]);
if (scoreId < 15)
buffer = Common::String::format("%d", _npcBuf[charId]._activeScore[_menuStatItemArr[counter]]);
else if (scoreId < 26)
buffer = Common::String::format("%d", _npcBuf[charId]._passiveScore[_menuStatItemArr[counter] - 15]);
else if (scoreId < 37)
buffer = Common::String::format("%d", _npcBuf[charId]._infoScore[_menuStatItemArr[counter] - 26]);
setTextPos(278, textPosY);
displayStringAtTextPos(buffer);
setTextColorRed();
}
}
void EfhEngine::displayStatusMenuActions(int16 menuId, int16 curMenuLine, int16 npcId) {
debugC(6, kDebugEngine, "displayStatusMenuActions %d %d %d", menuId, curMenuLine, npcId);
drawColoredRect(144, 15, 310, 184, 0);
displayCenteredString("(ESCape Aborts)", 144, 310, 175);
_textColor = 0x0E;
switch (menuId) {
case kEfhMenuEquip:
displayCenteredString("Select Item to Equip", 144, 310, 15);
displayCharacterSummary(curMenuLine, npcId);
break;
case kEfhMenuUse:
displayCenteredString("Select Item to Use", 144, 310, 15);
displayCharacterSummary(curMenuLine, npcId);
break;
case kEfhMenuGive:
displayCenteredString("Select Item to Give", 144, 310, 15);
displayCharacterSummary(curMenuLine, npcId);
break;
case kEfhMenuTrade:
displayCenteredString("Select Item to Trade", 144, 310, 15);
displayCharacterSummary(curMenuLine, npcId);
break;
case kEfhMenuDrop:
displayCenteredString("Select Item to Drop", 144, 310, 15);
displayCharacterSummary(curMenuLine, npcId);
break;
case kEfhMenuInfo:
displayCenteredString("Character Information", 144, 310, 15);
displayCharacterInformationOrSkills(curMenuLine, npcId);
break;
case kEfhMenuPassive:
displayCenteredString("Passive Skills", 144, 310, 15);
displayCharacterInformationOrSkills(curMenuLine, npcId);
break;
case kEfhMenuActive:
displayCenteredString("Active Skills", 144, 310, 15);
displayCharacterInformationOrSkills(curMenuLine, npcId);
break;
case kEfhMenuLeave:
case kEfhMenuInvalid:
displayCenteredString("Character Summary", 144, 310, 15);
displayCharacterSummary(curMenuLine, npcId);
break;
default:
break;
}
}
void EfhEngine::prepareStatusMenu(int16 windowId, int16 menuId, int16 curMenuLine, int16 charId, bool refreshFl) {
debugC(6, kDebugEngine, "prepareStatusMenu %d %d %d %d %s", windowId, menuId, curMenuLine, charId, refreshFl ? "True" : "False");
displayStatusMenu(windowId);
prepareStatusRightWindowIndexes(menuId, charId);
displayStatusMenuActions(menuId, curMenuLine, charId);
if (refreshFl)
displayFctFullScreen();
}
void EfhEngine::displayWindowAndStatusMenu(int16 charId, int16 windowId, int16 menuId, int16 curMenuLine) {
debugC(6, kDebugEngine, "displayWindowAndStatusMenu %d %d %d %d", charId, windowId, menuId, curMenuLine);
for (int counter = 0; counter < 2; ++counter) {
displayWindow(_menuBuf, 0, 0, _decompBuf);
prepareStatusMenu(windowId, menuId, curMenuLine, charId, false);
if (counter == 0)
displayFctFullScreen();
}
}
int16 EfhEngine::displayStringInSmallWindowWithBorder(Common::String str, bool delayFl, int16 charId, int16 windowId, int16 menuId, int16 curMenuLine) {
debugC(3, kDebugEngine, "displayStringInSmallWindowWithBorder %s %s %d %d %d %d", str.c_str(), delayFl ? "True" : "False", charId, windowId, menuId, curMenuLine);
int16 retVal = 0;
for (uint counter = 0; counter < 2; ++counter) {
prepareStatusMenu(windowId, menuId, curMenuLine, charId, false);
displayWindow(_windowWithBorderBuf, 19, 113, _decompBuf);
if (counter == 0) {
script_parse(str, 28, 122, 105, 166, false);
} else {
retVal = script_parse(str, 28, 122, 105, 166, true);
}
// The original is only calling displayFctFullScreen when counter = 0, but it's related to the screen buffers which aren't used in ScummVM implementation
// Calling it once fixes the (almost) unreadable text displayed otherwise.
// Maybe a refactoring to remove those 0..1 loop would be useful at some point.
displayFctFullScreen();
}
if (delayFl) {
getLastCharAfterAnimCount(_guessAnimationAmount);
displayWindowAndStatusMenu(charId, windowId, menuId, curMenuLine);
}
return retVal;
}
int16 EfhEngine::handleStatusMenu(int16 gameMode, int16 charId) {
debugC(3, kDebugEngine, "handleStatusMenu %d %d", gameMode, charId);
int16 menuId = kEfhMenuInvalid;
int16 selectedLine = -1;
int16 windowId = -1;
int16 curMenuLine = -1;
bool selectionDoneFl = false;
bool var2 = false;
saveAnimImageSetId();
_statusMenuActive = true;
_menuDepth = 0;
displayWindowAndStatusMenu(charId, windowId, menuId, curMenuLine);
for (;;) {
if (windowId != -1)
prepareStatusMenu(windowId, menuId, curMenuLine, charId, true);
else
windowId = kEfhMenuEquip;
do {
Common::KeyCode var19 = handleAndMapInput(false);
if (_menuDepth == 0) {
switch (var19) {
case Common::KEYCODE_a:
windowId = kEfhMenuActive;
var19 = Common::KEYCODE_RETURN;
break;
case Common::KEYCODE_d:
windowId = kEfhMenuDrop;
var19 = Common::KEYCODE_RETURN;
break;
case Common::KEYCODE_e:
windowId = kEfhMenuEquip;
var19 = Common::KEYCODE_RETURN;
break;
case Common::KEYCODE_g:
windowId = kEfhMenuGive;
var19 = Common::KEYCODE_RETURN;
break;
case Common::KEYCODE_i:
windowId = kEfhMenuInfo;
var19 = Common::KEYCODE_RETURN;
break;
case Common::KEYCODE_ESCAPE:
case Common::KEYCODE_l:
windowId = kEfhMenuLeave;
var19 = Common::KEYCODE_RETURN;
break;
case Common::KEYCODE_p:
windowId = kEfhMenuPassive;
var19 = Common::KEYCODE_RETURN;
break;
case Common::KEYCODE_t:
windowId = kEfhMenuTrade;
var19 = Common::KEYCODE_RETURN;
break;
case Common::KEYCODE_u:
windowId = kEfhMenuUse;
var19 = Common::KEYCODE_RETURN;
break;
default:
debugC(9, kDebugEngine, "handleStatusMenu - unhandled keys");
break;
}
} else if (_menuDepth == 1) {
// in the sub-menus, only a list of selectable items is displayed
if (var19 >= Common::KEYCODE_a && var19 <= Common::KEYCODE_z) {
int16 var8 = var19 - Common::KEYCODE_a;
if (var8 < _menuItemCounter) {
curMenuLine = var8;
var19 = Common::KEYCODE_RETURN;
}
}
}
switch (var19) {
case Common::KEYCODE_RETURN:
// case 0xFA: Joystick button 1
if (_menuDepth == 0) {
menuId = windowId;
if (menuId >= kEfhMenuLeave)
selectionDoneFl = true;
else {
_menuDepth = 1;
curMenuLine = 0;
}
} else if (_menuDepth == 1) {
if (_menuItemCounter == 0) {
_menuDepth = 0;
curMenuLine = -1;
menuId = kEfhMenuInvalid;
prepareStatusMenu(windowId, menuId, curMenuLine, charId, true);
} else {
selectedLine = curMenuLine;
selectionDoneFl = true;
}
}
break;
case Common::KEYCODE_ESCAPE:
_menuDepth = 0;
curMenuLine = -1;
menuId = kEfhMenuInvalid;
prepareStatusMenu(windowId, menuId, curMenuLine, charId, true);
break;
case Common::KEYCODE_2:
case Common::KEYCODE_6:
// Added for ScummVM
case Common::KEYCODE_DOWN:
case Common::KEYCODE_RIGHT:
case Common::KEYCODE_KP2:
case Common::KEYCODE_KP6:
// Original checks joystick axis: case 0xCC, 0xCF
if (_menuDepth == 0) {
if (++windowId > kEfhMenuLeave)
windowId = kEfhMenuEquip;
} else if (_menuDepth == 1) {
if (_menuItemCounter != 0) {
++curMenuLine;
if (curMenuLine > _menuItemCounter - 1)
curMenuLine = 0;
}
}
break;
case Common::KEYCODE_4:
case Common::KEYCODE_8:
// Added for ScummVM
case Common::KEYCODE_LEFT:
case Common::KEYCODE_UP:
case Common::KEYCODE_KP4:
case Common::KEYCODE_KP8:
// Original checks joystick axis: case 0xC7, 0xCA
if (_menuDepth == 0) {
if (--windowId < kEfhMenuEquip)
windowId = kEfhMenuLeave;
} else if (_menuDepth == 1) {
if (_menuItemCounter != 0) {
--curMenuLine;
if (curMenuLine < 0)
curMenuLine = _menuItemCounter - 1;
}
}
break;
default:
break;
}
prepareStatusMenu(windowId, menuId, curMenuLine, charId, true);
} while (!selectionDoneFl && !shouldQuitGame()); // Loop until a menu entry is confirmed by the user by pressing the enter key
bool validationFl = true;
int16 objectId;
int16 itemId;
switch (menuId) {
case kEfhMenuEquip:
objectId = _menuStatItemArr[selectedLine];
itemId = _npcBuf[charId]._inventory[objectId]._ref; // CHECKME: Useless?
tryToggleEquipped(charId, objectId, windowId, menuId, curMenuLine);
if (gameMode == 2) {
restoreAnimImageSetId();
_statusMenuActive = false;
return 0x7D00;
}
break;
case kEfhMenuUse:
objectId = _menuStatItemArr[selectedLine];
itemId = _npcBuf[charId]._inventory[objectId]._ref;
if (gameMode == 2) {
restoreAnimImageSetId();
_statusMenuActive = false;
return objectId;
}
if (handleInteractionText(_mapPosX, _mapPosY, charId, itemId, 2, -1)) {
_statusMenuActive = false;
return -1;
}
useObject(charId, objectId, windowId, menuId, curMenuLine, 2);
break;
case kEfhMenuGive:
objectId = _menuStatItemArr[selectedLine];
itemId = _npcBuf[charId]._inventory[objectId]._ref;
if (hasObjectEquipped(charId, objectId) && isItemCursed(itemId)) {
displayStringInSmallWindowWithBorder("The item is cursed! IT IS EVIL!!!!!!!!", true, charId, windowId, menuId, curMenuLine);
} else if (hasObjectEquipped(charId, objectId)) {
displayStringInSmallWindowWithBorder("Item is Equipped! Give anyway?", false, charId, windowId, menuId, curMenuLine);
if (!getValidationFromUser())
validationFl = false;
displayWindowAndStatusMenu(charId, windowId, menuId, curMenuLine);
if (validationFl) {
if (gameMode == 2) {
displayStringInSmallWindowWithBorder("Not a Combat Option !", true, charId, windowId, menuId, curMenuLine);
} else {
removeObject(charId, objectId);
if (handleInteractionText(_mapPosX, _mapPosY, charId, itemId, 3, -1)) {
_statusMenuActive = false;
return -1;
}
}
}
}
break;
case kEfhMenuTrade:
objectId = _menuStatItemArr[selectedLine];
itemId = _npcBuf[charId]._inventory[objectId]._ref;
if (hasObjectEquipped(charId, objectId) && isItemCursed(itemId)) {
displayStringInSmallWindowWithBorder("The item is cursed! IT IS EVIL!!!!!!!!", true, charId, windowId, menuId, curMenuLine);
break;
}
if (hasObjectEquipped(charId, objectId)) {
displayStringInSmallWindowWithBorder("Item is Equipped! Trade anyway?", false, charId, windowId, menuId, curMenuLine);
if (!getValidationFromUser())
validationFl = false;
displayWindowAndStatusMenu(charId, windowId, menuId, curMenuLine);
}
if (validationFl) {
bool givenFl;
int16 destCharId;
do {
if (_teamChar[2]._id != -1) {
displayStringInSmallWindowWithBorder("Who will you give the item to?", false, charId, windowId, menuId, curMenuLine);
destCharId = selectOtherCharFromTeam();
var2 = false;
} else if (_teamChar[1]._id == -1) {
destCharId = 0x1A;
var2 = false;
} else {
var2 = true;
if (_teamChar[0]._id == charId)
destCharId = 1;
else
destCharId = 0;
}
if (destCharId != 0x1A && destCharId != 0x1B) {
givenFl = giveItemTo(_teamChar[destCharId]._id, objectId, charId);
if (!givenFl) {
displayStringInSmallWindowWithBorder("That character cannot carry anymore!", false, charId, windowId, menuId, curMenuLine);
getLastCharAfterAnimCount(_guessAnimationAmount);
}
} else {
if (destCharId == 0x1A) {
displayStringInSmallWindowWithBorder("No one to trade with!", false, charId, windowId, menuId, curMenuLine);
getLastCharAfterAnimCount(_guessAnimationAmount);
destCharId = 0x1B;
}
givenFl = false;
}
} while (!givenFl && !var2 && destCharId != 0x1B && !shouldQuitGame());
if (givenFl) {
removeObject(charId, objectId);
if (gameMode == 2) {
restoreAnimImageSetId();
_statusMenuActive = false;
return 0x7D00;
}
}
displayWindowAndStatusMenu(charId, windowId, menuId, curMenuLine);
}
break;
case kEfhMenuDrop:
objectId = _menuStatItemArr[selectedLine];
itemId = _npcBuf[charId]._inventory[objectId]._ref;
if (hasObjectEquipped(charId, objectId) && isItemCursed(itemId)) {
displayStringInSmallWindowWithBorder("The item is cursed! IT IS EVIL!!!!!!!!", true, charId, windowId, menuId, curMenuLine);
} else if (hasObjectEquipped(charId, objectId)) {
displayStringInSmallWindowWithBorder("Item Is Equipped! Drop Anyway?", false, charId, windowId, menuId, curMenuLine);
if (!getValidationFromUser())
validationFl = false;
displayWindowAndStatusMenu(charId, windowId, menuId, curMenuLine);
if (validationFl) {
removeObject(charId, objectId);
if (gameMode == 2) {
restoreAnimImageSetId();
_statusMenuActive = false;
return 0x7D00;
}
if (handleInteractionText(_mapPosX, _mapPosY, charId, itemId, 1, -1)) {
_statusMenuActive = false;
return -1;
}
}
}
break;
case kEfhMenuInfo:
case kEfhMenuPassive:
case kEfhMenuActive:
objectId = _menuStatItemArr[selectedLine];
if (gameMode == 2) {
displayStringInSmallWindowWithBorder("Not a Combat Option!", true, charId, windowId, menuId, curMenuLine);
} else if (handleInteractionText(_mapPosX, _mapPosY, charId, objectId, 4, -1)) {
_statusMenuActive = false;
return -1;
}
break;
default:
break;
}
if (menuId != kEfhMenuLeave) {
selectionDoneFl = false;
_menuDepth = 0;
menuId = kEfhMenuInvalid;
selectedLine = -1;
curMenuLine = -1;
}
if (menuId == kEfhMenuLeave) {
restoreAnimImageSetId();
_statusMenuActive = false;
return 0x7FFF;
}
}
return 0;
}
void EfhEngine::unequipItem(int16 charId, int16 objectId, int16 windowId, int16 menuId, int16 curMenuLine) {
debugC(6,kDebugEngine, "unequipItem %d %d %d %d %d", charId, objectId, windowId, menuId, curMenuLine);
int16 itemId = _npcBuf[charId]._inventory[objectId]._ref;
if (!isItemCursed(itemId)) {
_npcBuf[charId]._inventory[objectId]._stat1 &= 0x7F;
} else {
// Original message. "Cursed item can't be unequipped" would make more sense, imho
displayStringInSmallWindowWithBorder("Cursed Item Already Equipped!", true, charId, windowId, menuId, curMenuLine);
}
}
void EfhEngine::tryToggleEquipped(int16 charId, int16 objectId, int16 windowId, int16 menuId, int16 curMenuLine) {
debugC(3, kDebugEngine, "tryToggleEquipped %d %d %d %d %d", charId, objectId, windowId, menuId, curMenuLine);
int16 itemId = _npcBuf[charId]._inventory[objectId]._ref;
if (hasObjectEquipped(charId, objectId)) {
unequipItem(charId, objectId, windowId, menuId, curMenuLine);
} else {
int16 curType = _items[itemId]._exclusiveType;
if (curType != 4) {
for (uint counter = 0; counter < 10; ++counter) {
int16 curItemId = _npcBuf[charId]._inventory[counter]._ref;
if (curItemId == 0x7FFF) {
warning("CHECKME : hack");
continue;
}
if (curType == _items[curItemId]._exclusiveType)
unequipItem(charId, counter, windowId, menuId, curMenuLine);
}
}
if (curType != 0) {
// Set item as Equipped
_npcBuf[charId]._inventory[objectId]._stat1 |= 0x80;
}
}
}
int16 EfhEngine::useObject(int16 charId, int16 objectId, int16 teamMonsterId, int16 menuId, int16 curMenuLine, int16 gameMode) {
debugC(3, kDebugEngine, "useObject %d %d %d %d %d %s", charId, objectId, teamMonsterId, menuId, curMenuLine, gameMode == 3 ? "Combat" : "Normal");
Common::String buffer1 = "";
bool objectUsedFl = false;
bool retVal = false;
int16 itemId = _npcBuf[charId]._inventory[objectId]._ref;
switch (_items[itemId]._specialEffect - 1) {
case 0: // "Demonic Powers", "MindDomination", "Guilt Trip", "Sleep Grenade", "SleepGrenader"
if (gameMode == 2) {
displayStringInSmallWindowWithBorder("The item emits a low droning hum...", false, charId, teamMonsterId, menuId, curMenuLine);
} else {
int16 victims = 0;
_messageToBePrinted += " The item emits a low droning hum...";
if (getRandom(100) < 50) {
for (uint ctrMobsterId = 0; ctrMobsterId < 9; ++ctrMobsterId) {
if (isMonsterActive(teamMonsterId, ctrMobsterId)) {
++victims;
_teamMonster[teamMonsterId]._mobsterStatus[ctrMobsterId]._type = kEfhStatusSleeping;
_teamMonster[teamMonsterId]._mobsterStatus[ctrMobsterId]._duration = getRandom(8);
}
}
} else {
int16 NumberOfTargets = getRandom(9);
for (uint ctrMobsterId = 0; ctrMobsterId < 9; ++ctrMobsterId) {
if (NumberOfTargets == 0)
break;
if (isMonsterActive(teamMonsterId, ctrMobsterId)) {
++victims;
--NumberOfTargets;
_teamMonster[teamMonsterId]._mobsterStatus[ctrMobsterId]._type = kEfhStatusSleeping;
_teamMonster[teamMonsterId]._mobsterStatus[ctrMobsterId]._duration = getRandom(8);
}
}
}
// The original was duplicating this code in each branch of the previous random check.
if (victims > 1) {
buffer1 = Common::String::format("%d %ss fall asleep!", victims, kEncounters[_mapMonsters[_techId][_teamMonster[teamMonsterId]._id]._monsterRef]._name);
} else {
buffer1 = Common::String::format("%d %s falls asleep!", victims, kEncounters[_mapMonsters[_techId][_teamMonster[teamMonsterId]._id]._monsterRef]._name);
}
_messageToBePrinted += buffer1;
}
objectUsedFl = true;
break;
case 1: // "Chilling Touch", "Guilt", "Petrify Rod", "Elmer's Gun"
if (gameMode == 2) {
displayStringInSmallWindowWithBorder("The item grows very cold for a moment...", false, charId, teamMonsterId, menuId, curMenuLine);
} else {
_messageToBePrinted += " The item emits a blue beam...";
int16 victim = 0;
if (getRandom(100) < 50) {
for (uint ctrEffectId = 0; ctrEffectId < 9; ++ctrEffectId) {
if (isMonsterActive(teamMonsterId, ctrEffectId)) {
++victim;
_teamMonster[teamMonsterId]._mobsterStatus[ctrEffectId]._type = kEfhStatusFrozen;
_teamMonster[teamMonsterId]._mobsterStatus[ctrEffectId]._duration = getRandom(8);
}
}
} else {
int16 varAC = getRandom(9);
for (uint ctrMobsterId = 0; ctrMobsterId < 9; ++ctrMobsterId) {
if (varAC == 0)
break;
if (isMonsterActive(teamMonsterId, ctrMobsterId)) {
++victim;
--varAC;
_teamMonster[teamMonsterId]._mobsterStatus[ctrMobsterId]._type = kEfhStatusFrozen;
_teamMonster[teamMonsterId]._mobsterStatus[ctrMobsterId]._duration = getRandom(8);
}
}
}
// <CHECKME>: This part is only present in the original in the case < 50, but for me
// it's missing in the other case as there's an effect (frozen enemies) but no feedback to the player
if (victim > 1) {
buffer1 = Common::String::format("%d %ss are frozen in place!", victim, kEncounters[_mapMonsters[_techId][_teamMonster[teamMonsterId]._id]._monsterRef]._name);
} else {
buffer1 = Common::String::format("%d %s is frozen in place!", victim, kEncounters[_mapMonsters[_techId][_teamMonster[teamMonsterId]._id]._monsterRef]._name);
}
_messageToBePrinted += buffer1;
// </CHECKME>
}
objectUsedFl = true;
break;
case 2:
if (gameMode == 2) {
displayStringInSmallWindowWithBorder("A serene feeling passes through the air...", false, charId, teamMonsterId, menuId, curMenuLine);
} else {
_messageToBePrinted += " The combat pauses...as there is a moment of forgiveness...";
_alertDelay = 0;
}
objectUsedFl = true;
break;
case 4: // "Unholy Sinwave", "Holy Water"
if (gameMode == 2) {
displayStringInSmallWindowWithBorder("A dark sense fills your soul...then fades!", false, charId, teamMonsterId, menuId, curMenuLine);
} else {
_messageToBePrinted += " A dark gray fiery whirlwind surrounds the poor victim...the power fades and death abounds!";
if (getRandom(100) < 50) {
for (uint counter = 0; counter < 9; ++counter) {
if (getRandom(100) < 50) {
_mapMonsters[_techId][_teamMonster[teamMonsterId]._id]._hitPoints[counter] = 0;
}
}
} else {
for (uint counter = 0; counter < 9; ++counter) {
if (isMonsterActive(teamMonsterId, counter)) {
if (getRandom(100) < 50) {
_mapMonsters[_techId][_teamMonster[teamMonsterId]._id]._hitPoints[counter] = 0;
}
break;
}
}
}
}
objectUsedFl = true;
break;
case 5: // "Lucifer'sTouch", "Book of Death", "Holy Cross"
if (gameMode == 2) {
displayStringInSmallWindowWithBorder("A dark sense fills your soul...then fades!", false, charId, teamMonsterId, menuId, curMenuLine);
} else {
if (getRandom(100) < 50) {
_messageToBePrinted += " A dark fiery whirlwind surrounds the poor victim...the power fades and all targeted die!";
for (uint counter = 0; counter < 9; ++counter) {
_mapMonsters[_techId][_teamMonster[teamMonsterId]._id]._hitPoints[counter] = 0;
}
} else {
_messageToBePrinted += " A dark fiery whirlwind surrounds the poor victim...the power fades and one victim dies!";
for (uint counter = 0; counter < 9; ++counter) {
if (isMonsterActive(teamMonsterId, counter)) {
_mapMonsters[_techId][_teamMonster[teamMonsterId]._id]._hitPoints[counter] = 0;
}
}
}
}
objectUsedFl = true;
break;
case 12: // "Terror Gaze", "Servitude Rod", "Despair Ankh", "ConfusionPrism", "Pipe of Peace", "Red Cape", "Peace Symbol", "Hell Badge"
if (gameMode == 2) {
displayStringInSmallWindowWithBorder("There is no apparent affect!", false, charId, teamMonsterId, menuId, curMenuLine);
} else {
_messageToBePrinted += " The magic sparkles brilliant hues in the air!";
setMapMonsterAggressivenessAndMovementType(teamMonsterId, _items[itemId]._defenseType);
}
objectUsedFl = true;
break;
case 14: { // "Feathered Cap"
int16 teamCharId;
if (gameMode == 2) {
displayStringInSmallWindowWithBorder("Who will use the item?", false, charId, teamMonsterId, menuId, curMenuLine);
teamCharId = selectOtherCharFromTeam();
} else {
teamCharId = teamMonsterId;
}
if (teamCharId != 0x1B) { // Escape code, which means the user cancelled the selection
buffer1 = " The magic makes the user as quick and agile as a bird!";
if (gameMode == 2) {
displayStringInSmallWindowWithBorder(buffer1, false, charId, teamMonsterId, menuId, curMenuLine);
} else {
_messageToBePrinted += buffer1;
}
_teamChar[teamCharId]._pctDodgeMiss -= 50;
if (_teamChar[teamCharId]._pctDodgeMiss < 0)
_teamChar[teamCharId]._pctDodgeMiss = 0;
}
objectUsedFl = true;
} break;
case 15: { // "Regal Crown"
int16 teamCharId;
if (gameMode == 2) {
displayStringInSmallWindowWithBorder("Who will use the item?", false, charId, teamMonsterId, menuId, curMenuLine);
teamCharId = selectOtherCharFromTeam();
} else {
teamCharId = teamMonsterId;
}
if (teamCharId != 0x1B) {
buffer1 = " The magic makes the user invisible!";
if (gameMode == 2) {
displayStringInSmallWindowWithBorder(buffer1, false, charId, teamMonsterId, menuId, curMenuLine);
} else {
_messageToBePrinted += buffer1;
}
_teamChar[teamCharId]._pctVisible -= 50;
if (_teamChar[teamCharId]._pctVisible < 0)
_teamChar[teamCharId]._pctVisible = 0;
}
objectUsedFl = true;
} break;
case 16: { // Fairy Dust
_mapPosX = getRandom(_largeMapFlag ? 63 : 23);
_mapPosY = getRandom(_largeMapFlag ? 63 : 23);
int16 tileFactId = getTileFactId(_mapPosX, _mapPosY);
if (_tileFact[tileFactId]._status == 0) {
totalPartyKill();
buffer1 = "The entire party vanishes in a flash... only to appear in stone !";
if (gameMode == 2) {
displayStringInSmallWindowWithBorder(buffer1, false, charId, teamMonsterId, menuId, curMenuLine);
} else {
_messageToBePrinted += buffer1;
retVal = true;
}
} else {
if (tileFactId == 0 || tileFactId == 0x48) {
buffer1 = "The entire party vanishes in a flash...but re-appears, as if nothing happened!";
if (gameMode == 2) {
displayStringInSmallWindowWithBorder(buffer1, false, charId, teamMonsterId, menuId, curMenuLine);
} else {
_messageToBePrinted += buffer1;
retVal = true;
}
} else {
buffer1 = "The entire party vanishes in a flash...only to appear elsewhere!";
if (gameMode == 2) {
displayStringInSmallWindowWithBorder(buffer1, false, charId, teamMonsterId, menuId, curMenuLine);
} else {
_messageToBePrinted += buffer1;
retVal = true;
}
}
}
objectUsedFl = true;
} break;
case 17: { // "Devil Dust"
_mapPosX = _items[itemId]._field19_mapPosX_or_maxDeltaPoints;
_mapPosY = _items[itemId]._mapPosY;
int16 tileFactId = getTileFactId(_mapPosX, _mapPosY);
if (_tileFact[tileFactId]._status == 0) {
totalPartyKill();
buffer1 = "The entire party vanishes in a flash... only to appear in stone !";
if (gameMode == 2) {
displayStringInSmallWindowWithBorder(buffer1, false, charId, teamMonsterId, menuId, curMenuLine);
} else {
_messageToBePrinted += buffer1;
retVal = true;
}
} else {
if (tileFactId == 0 || tileFactId == 0x48) {
buffer1 = "The entire party vanishes in a flash...but re-appears, as if nothing happened!";
if (gameMode == 2) {
displayStringInSmallWindowWithBorder(buffer1, false, charId, teamMonsterId, menuId, curMenuLine);
} else {
_messageToBePrinted += buffer1;
retVal = true;
}
} else {
buffer1 = "The entire party vanishes in a flash...only to appear elsewhere!";
if (gameMode == 2) {
displayStringInSmallWindowWithBorder(buffer1, false, charId, teamMonsterId, menuId, curMenuLine);
} else {
_messageToBePrinted += buffer1;
retVal = true;
}
}
}
objectUsedFl = true;
} break;
case 18:
if (gameMode == 2) {
displayStringInSmallWindowWithBorder("The item makes a loud noise!", false, charId, teamMonsterId, menuId, curMenuLine);
} else {
int16 teamCharId = teamMonsterId;
if (teamCharId != 0x1B) {
if (_teamChar[teamCharId]._status._type == kEfhStatusFrozen) {
// The message is weird because it's a duplicate of case 28, which is about "curing" sleep... But it's about being frozen.
// We could improve the description, but that's the way the original deals with it
_messageToBePrinted += " The item makes a loud noise, awakening the character!";
_teamChar[teamCharId]._status._type = kEfhStatusNormal;
_teamChar[teamCharId]._status._duration = 0;
} else {
_messageToBePrinted += " The item makes a loud noise, but has no effect!";
}
}
}
objectUsedFl = true;
break;
case 19: // "Junk"
buffer1 = " * The item breaks!";
if (gameMode == 2) {
displayStringInSmallWindowWithBorder(buffer1, false, charId, teamMonsterId, menuId, curMenuLine);
} else {
_messageToBePrinted += buffer1;
}
setCharacterObjectToBroken(charId, objectId);
objectUsedFl = true;
break;
case 23: // "Divining Rod"
buffer1 = Common::String::format("The %s says, '", _items[itemId]._name);
if (_items[itemId]._field19_mapPosX_or_maxDeltaPoints < _mapPosX) {
if (_items[itemId]._mapPosY < _mapPosY) {
buffer1 += "North West!";
} else if (_items[itemId]._mapPosY > _mapPosY) {
buffer1 += "South West!";
} else {
buffer1 += "West!";
}
} else if (_items[itemId]._field19_mapPosX_or_maxDeltaPoints > _mapPosX) {
if (_items[itemId]._mapPosY < _mapPosY) {
buffer1 += "North East!";
} else if (_items[itemId]._mapPosY > _mapPosY) {
buffer1 += "South East!";
} else {
buffer1 += "East!";
}
} else { // equals _mapPosX
if (_items[itemId]._mapPosY < _mapPosY) {
buffer1 += "North!";
} else if (_items[itemId]._mapPosY > _mapPosY) {
buffer1 += "South!";
} else {
buffer1 += "Here!!!";
}
}
buffer1 += "'";
if (gameMode == 2) {
displayStringInSmallWindowWithBorder(buffer1, false, charId, teamMonsterId, menuId, curMenuLine);
} else {
_messageToBePrinted += buffer1;
retVal = true;
}
objectUsedFl = true;
break;
case 24: {
int16 teamCharId;
if (gameMode == 2) {
displayStringInSmallWindowWithBorder("Who will use this item?", false, charId, teamMonsterId, menuId, curMenuLine);
teamCharId = selectOtherCharFromTeam();
} else
teamCharId = teamMonsterId;
if (teamCharId != 0x1B) {
uint8 varAE = _items[itemId]._defenseType;
uint8 effectPoints = getRandom(_items[itemId]._field19_mapPosX_or_maxDeltaPoints);
_npcBuf[_teamChar[teamCharId]._id]._activeScore[varAE] += effectPoints;
if (_npcBuf[_teamChar[teamCharId]._id]._activeScore[varAE] > 20) {
_npcBuf[_teamChar[teamCharId]._id]._activeScore[varAE] = 20;
}
if (effectPoints > 1)
buffer1 = Common::String::format("%s increased %d points!", kSkillArray[varAE], effectPoints);
else
buffer1 = Common::String::format("%s increased 1 point!", kSkillArray[varAE]);
if (gameMode == 2) {
displayStringInSmallWindowWithBorder(buffer1, false, charId, teamMonsterId, menuId, curMenuLine);
} else {
_messageToBePrinted += buffer1;
retVal = true;
}
}
objectUsedFl = true;
} break;
case 25: {
int16 teamCharId;
if (gameMode == 2) {
displayStringInSmallWindowWithBorder("Who will use this item?", false, charId, teamMonsterId, menuId, curMenuLine);
teamCharId = selectOtherCharFromTeam();
} else
teamCharId = teamMonsterId;
if (teamCharId != 0x1B) {
uint8 varAE = _items[itemId]._defenseType;
uint8 effectPoints = getRandom(_items[itemId]._field19_mapPosX_or_maxDeltaPoints);
_npcBuf[_teamChar[teamCharId]._id]._activeScore[varAE] -= effectPoints;
if (_npcBuf[_teamChar[teamCharId]._id]._activeScore[varAE] > 20) {
_npcBuf[_teamChar[teamCharId]._id]._activeScore[varAE] = 1;
}
if (effectPoints > 1)
buffer1 = Common::String::format("%s lowered %d points!", kSkillArray[varAE], effectPoints);
else
buffer1 = Common::String::format("%s lowered 1 point!", kSkillArray[varAE]);
if (gameMode == 2) {
displayStringInSmallWindowWithBorder(buffer1, false, charId, teamMonsterId, menuId, curMenuLine);
} else {
_messageToBePrinted += buffer1;
retVal = true;
}
}
objectUsedFl = true;
} break;
case 26: // "Black Sphere"
buffer1 = "The entire party collapses, dead!!!";
if (gameMode == 2) {
displayStringInSmallWindowWithBorder(buffer1, false, charId, teamMonsterId, menuId, curMenuLine);
} else {
_messageToBePrinted += buffer1;
retVal = true;
}
totalPartyKill();
objectUsedFl = true;
break;
case 27: { // "Magic Pyramid", "Razor Blade"
int16 teamCharId;
if (gameMode == 2) {
displayStringInSmallWindowWithBorder("Who will use the item?", false, charId, teamMonsterId, menuId, curMenuLine);
teamCharId = selectOtherCharFromTeam();
} else {
teamCharId = teamMonsterId;
}
if (teamCharId != 0x1B) {
_npcBuf[_teamChar[teamCharId]._id]._hitPoints = 0;
buffer1 = Common::String::format("%s collapses, dead!!!", _npcBuf[_teamChar[teamCharId]._id]._name);
if (gameMode == 2) {
displayStringInSmallWindowWithBorder(buffer1, false, charId, teamMonsterId, menuId, curMenuLine);
} else {
_messageToBePrinted += buffer1;
retVal = true;
}
}
objectUsedFl = true;
} break;
case 28: // "Bugle"
if (gameMode == 2) {
displayStringInSmallWindowWithBorder("The item makes a loud noise!", false, charId, teamMonsterId, menuId, curMenuLine);
} else {
int16 teamCharId = teamMonsterId;
if (teamCharId != 0x1B) {
if (_teamChar[teamCharId]._status._type == kEfhStatusSleeping) {
_messageToBePrinted += " The item makes a loud noise, awakening the character!";
_teamChar[teamCharId]._status._type = kEfhStatusNormal;
_teamChar[teamCharId]._status._duration = 0;
} else {
_messageToBePrinted += " The item makes a loud noise, but has no effect!";
}
}
}
objectUsedFl = true;
break;
case 29: { // "Healing Spray", "Healing Elixir", "Curing Potion", "Magic Potion"
int16 teamCharId;
if (gameMode == 2) {
displayStringInSmallWindowWithBorder("Who will use the item?", false, charId, teamMonsterId, menuId, curMenuLine);
teamCharId = selectOtherCharFromTeam();
} else {
teamCharId = teamMonsterId;
}
if (teamCharId != 0x1B) {
int16 effectPoints = getRandom(_items[itemId]._defenseType);
_npcBuf[_teamChar[teamCharId]._id]._hitPoints += effectPoints;
if (_npcBuf[_teamChar[teamCharId]._id]._hitPoints > _npcBuf[_teamChar[teamCharId]._id]._maxHP)
_npcBuf[_teamChar[teamCharId]._id]._hitPoints = _npcBuf[_teamChar[teamCharId]._id]._maxHP;
if (effectPoints > 1)
buffer1 = Common::String::format("%s is healed %d points!", _npcBuf[_teamChar[teamCharId]._id]._name, effectPoints);
else
buffer1 = Common::String::format("%s is healed 1 point!", _npcBuf[_teamChar[teamCharId]._id]._name);
}
if (gameMode == 2) {
displayStringInSmallWindowWithBorder(buffer1, false, charId, teamMonsterId, menuId, curMenuLine);
} else {
_messageToBePrinted += buffer1;
retVal = true;
}
objectUsedFl = true;
} break;
case 30: {
int16 teamCharId;
if (gameMode == 2) {
displayStringInSmallWindowWithBorder("Who will use the item?", false, charId, teamMonsterId, menuId, curMenuLine);
teamCharId = selectOtherCharFromTeam();
} else {
teamCharId = teamMonsterId;
}
if (teamCharId != 0x1B) {
int16 effectPoints = getRandom(_items[itemId]._defenseType);
_npcBuf[_teamChar[teamCharId]._id]._hitPoints -= effectPoints;
if (_npcBuf[_teamChar[teamCharId]._id]._hitPoints < 0)
_npcBuf[_teamChar[teamCharId]._id]._hitPoints = 0;
if (effectPoints > 1)
buffer1 = Common::String::format("%s is harmed for %d points!", _npcBuf[_teamChar[teamCharId]._id]._name, effectPoints);
else
buffer1 = Common::String::format("%s is harmed for 1 point!", _npcBuf[_teamChar[teamCharId]._id]._name);
}
if (gameMode == 2) {
displayStringInSmallWindowWithBorder(buffer1, false, charId, teamMonsterId, menuId, curMenuLine);
} else {
_messageToBePrinted += buffer1;
retVal = true;
}
objectUsedFl = true;
} break;
case 3:
case 6:
case 7:
case 8:
case 9:
case 10:
case 11:
case 13:
case 20:
case 21:
case 22:
default:
break;
}
if (objectUsedFl) {
int16 usesLeft = _npcBuf[charId]._inventory[objectId].getUsesLeft();
if (usesLeft != 0x7F) {
--usesLeft;
if (usesLeft <= 0) {
buffer1 = " * The item breaks!";
if (gameMode == 2) {
getLastCharAfterAnimCount(_guessAnimationAmount);
displayStringInSmallWindowWithBorder(buffer1, false, charId, teamMonsterId, menuId, curMenuLine);
} else {
_messageToBePrinted += buffer1;
}
setCharacterObjectToBroken(charId, objectId);
} else {
// Keep the Equipped bit and set the new number of uses
_npcBuf[charId]._inventory[objectId]._stat1 &= 0x80;
_npcBuf[charId]._inventory[objectId]._stat1 |= usesLeft;
}
}
if (gameMode == 2) {
getLastCharAfterAnimCount(_guessAnimationAmount);
displayWindowAndStatusMenu(charId, teamMonsterId, menuId, curMenuLine);
}
}
return retVal;
}
} // End of namespace Efh