Initial commit
This commit is contained in:
260
engines/agi/inv.cpp
Normal file
260
engines/agi/inv.cpp
Normal file
@@ -0,0 +1,260 @@
|
||||
/* 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 "agi/agi.h"
|
||||
#include "agi/graphics.h"
|
||||
#include "agi/inv.h"
|
||||
#include "agi/text.h"
|
||||
#include "agi/keyboard.h"
|
||||
#include "agi/systemui.h"
|
||||
|
||||
namespace Agi {
|
||||
|
||||
InventoryMgr::InventoryMgr(AgiEngine *agi, GfxMgr *gfx, TextMgr *text, SystemUI *systemUI) {
|
||||
_vm = agi;
|
||||
_gfx = gfx;
|
||||
_text = text;
|
||||
_systemUI = systemUI;
|
||||
|
||||
_activeItemNr = -1;
|
||||
}
|
||||
|
||||
InventoryMgr::~InventoryMgr() {
|
||||
}
|
||||
|
||||
void InventoryMgr::getPlayerInventory() {
|
||||
AgiGame game = _vm->_game;
|
||||
int16 selectedInventoryItem = _vm->getVar(VM_VAR_SELECTED_INVENTORY_ITEM);
|
||||
int16 curRow = 2; // starting at position 2,1
|
||||
int16 curColumn = 1;
|
||||
|
||||
_array.clear();
|
||||
_activeItemNr = 0;
|
||||
|
||||
for (uint16 objectNr = 0; objectNr < game.numObjects; objectNr++) {
|
||||
if (_vm->objectGetLocation(objectNr) == EGO_OWNED) {
|
||||
// item is in the possession of ego, so add it to our internal list
|
||||
if (objectNr == selectedInventoryItem) {
|
||||
// it's the currently selected inventory item, remember that
|
||||
_activeItemNr = _array.size();
|
||||
}
|
||||
|
||||
InventoryEntry inventoryEntry;
|
||||
|
||||
inventoryEntry.objectNr = objectNr;
|
||||
inventoryEntry.name = _vm->objectName(objectNr);
|
||||
inventoryEntry.row = curRow;
|
||||
inventoryEntry.column = curColumn;
|
||||
if (!_vm->isLanguageRTL()) {
|
||||
if (inventoryEntry.column > 1) {
|
||||
// right side, adjust column accordingly
|
||||
inventoryEntry.column -= Common::strnlen(inventoryEntry.name, FONT_COLUMN_CHARACTERS);
|
||||
}
|
||||
} else {
|
||||
// mirror the sides
|
||||
if (inventoryEntry.column == 1) {
|
||||
// right side, adjust column accordingly
|
||||
inventoryEntry.column = FONT_COLUMN_CHARACTERS - 1 - Common::strnlen(inventoryEntry.name, FONT_COLUMN_CHARACTERS);
|
||||
} else {
|
||||
// left side, adjust column accordingly
|
||||
inventoryEntry.column = 1;
|
||||
}
|
||||
}
|
||||
_array.push_back(inventoryEntry);
|
||||
|
||||
// go to next position
|
||||
if (curColumn == 1) {
|
||||
// current position is left side, go to right side
|
||||
curColumn = 39;
|
||||
} else {
|
||||
// current position is right side, so go to left side again and new row
|
||||
curColumn = 1;
|
||||
curRow++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_array.size() == 0) {
|
||||
// empty inventory
|
||||
InventoryEntry inventoryEntry;
|
||||
|
||||
inventoryEntry.objectNr = 0;
|
||||
inventoryEntry.name = _systemUI->getInventoryTextNothing();
|
||||
inventoryEntry.row = 2;
|
||||
inventoryEntry.column = 19 - (strlen(inventoryEntry.name) / 2);
|
||||
_array.push_back(inventoryEntry);
|
||||
}
|
||||
}
|
||||
|
||||
void InventoryMgr::drawAll() {
|
||||
int16 inventoryCount = _array.size();
|
||||
|
||||
_text->charPos_Set(0, 11);
|
||||
_text->displayText(_systemUI->getInventoryTextYouAreCarrying());
|
||||
#ifdef USE_TTS
|
||||
_vm->sayText(_systemUI->getInventoryTextYouAreCarrying(), Common::TextToSpeechManager::INTERRUPT, false);
|
||||
#endif
|
||||
|
||||
for (int16 inventoryNr = 0; inventoryNr < inventoryCount; inventoryNr++) {
|
||||
drawItem(inventoryNr);
|
||||
}
|
||||
}
|
||||
|
||||
void InventoryMgr::drawItem(int16 itemNr) {
|
||||
if (itemNr == _activeItemNr) {
|
||||
_text->charAttrib_Set(15, 0);
|
||||
|
||||
#ifdef USE_TTS
|
||||
if (_vm->_queueNextText) {
|
||||
_vm->sayText(_array[itemNr].name, Common::TextToSpeechManager::QUEUE, false);
|
||||
_vm->_queueNextText = false;
|
||||
} else {
|
||||
_vm->sayText(_array[itemNr].name, Common::TextToSpeechManager::INTERRUPT, false);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
_text->charAttrib_Set(0, 15);
|
||||
|
||||
#ifdef USE_TTS
|
||||
if (_activeItemNr == -1) {
|
||||
_vm->sayText(_array[itemNr].name, Common::TextToSpeechManager::QUEUE, false);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
_text->charPos_Set(_array[itemNr].row, _array[itemNr].column);
|
||||
// original interpreter used printf here
|
||||
// this doesn't really make sense, because for length calculation it's using strlen without printf
|
||||
// which means right-aligned inventory items on the right side would not be displayed properly
|
||||
// in case printf-formatting was actually used
|
||||
// I have to assume that no game uses this, because behavior in original interpreter would have been buggy.
|
||||
_text->displayText(_array[itemNr].name);
|
||||
}
|
||||
|
||||
void InventoryMgr::show() {
|
||||
bool selectItems = false;
|
||||
|
||||
// figure out current inventory of the player
|
||||
getPlayerInventory();
|
||||
|
||||
if (_vm->getFlag(VM_FLAG_STATUS_SELECTS_ITEMS)) {
|
||||
selectItems = true;
|
||||
} else {
|
||||
_activeItemNr = -1; // so that none is shown as active
|
||||
}
|
||||
|
||||
#ifdef USE_TTS
|
||||
_vm->_queueNextText = true;
|
||||
#endif
|
||||
drawAll();
|
||||
|
||||
_text->charAttrib_Set(0, 15);
|
||||
if (selectItems) {
|
||||
_text->charPos_Set(24, 2);
|
||||
_text->displayText(_systemUI->getInventoryTextSelectItems());
|
||||
#ifdef USE_TTS
|
||||
_vm->sayText(_systemUI->getInventoryTextSelectItems());
|
||||
#endif
|
||||
} else {
|
||||
_text->charPos_Set(24, 4);
|
||||
_text->displayText(_systemUI->getInventoryTextReturnToGame());
|
||||
#ifdef USE_TTS
|
||||
_vm->sayText(_systemUI->getInventoryTextReturnToGame());
|
||||
#endif
|
||||
}
|
||||
|
||||
if (selectItems) {
|
||||
_vm->cycleInnerLoopActive(CYCLE_INNERLOOP_INVENTORY);
|
||||
|
||||
do {
|
||||
_vm->processAGIEvents();
|
||||
} while (_vm->cycleInnerLoopIsActive() && !(_vm->shouldQuit() || _vm->_restartGame));
|
||||
|
||||
if (_activeItemNr >= 0) {
|
||||
// pass selected object number
|
||||
_vm->setVar(VM_VAR_SELECTED_INVENTORY_ITEM, _array[_activeItemNr].objectNr);
|
||||
} else {
|
||||
// nothing was selected
|
||||
_vm->setVar(VM_VAR_SELECTED_INVENTORY_ITEM, 0xff);
|
||||
}
|
||||
#ifdef USE_TTS
|
||||
_vm->stopTextToSpeech();
|
||||
#endif
|
||||
|
||||
} else {
|
||||
// no selection is supposed to be possible, just wait for key and exit
|
||||
_vm->waitAnyKey();
|
||||
}
|
||||
}
|
||||
|
||||
void InventoryMgr::keyPress(uint16 newKey) {
|
||||
switch (newKey) {
|
||||
case AGI_KEY_ENTER: {
|
||||
_vm->cycleInnerLoopInactive(); // exit show-loop
|
||||
break;
|
||||
}
|
||||
|
||||
case AGI_KEY_ESCAPE: {
|
||||
_vm->cycleInnerLoopInactive(); // exit show-loop
|
||||
_activeItemNr = -1; // no item selected
|
||||
break;
|
||||
}
|
||||
|
||||
case AGI_KEY_UP:
|
||||
changeActiveItem(-2);
|
||||
break;
|
||||
case AGI_KEY_DOWN:
|
||||
changeActiveItem(+2);
|
||||
break;
|
||||
case AGI_KEY_LEFT:
|
||||
if (!_vm->isLanguageRTL())
|
||||
changeActiveItem(-1);
|
||||
else
|
||||
changeActiveItem(+1);
|
||||
break;
|
||||
case AGI_KEY_RIGHT:
|
||||
if (!_vm->isLanguageRTL())
|
||||
changeActiveItem(+1);
|
||||
else
|
||||
changeActiveItem(-1);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void InventoryMgr::changeActiveItem(int16 direction) {
|
||||
int16 orgItemNr = _activeItemNr;
|
||||
|
||||
_activeItemNr += direction;
|
||||
|
||||
if ((_activeItemNr >= 0) && (_activeItemNr < (int16)_array.size())) {
|
||||
// within bounds
|
||||
drawItem(orgItemNr);
|
||||
drawItem(_activeItemNr);
|
||||
} else {
|
||||
// out of bounds, revert change
|
||||
_activeItemNr = orgItemNr;
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Agi
|
||||
Reference in New Issue
Block a user