2007-05-30 21:56:52 +00:00
|
|
|
/* 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.
|
2007-01-14 21:29:12 +00:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
* $URL$
|
|
|
|
* $Id$
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#include "parallaction/parallaction.h"
|
2007-05-13 14:38:05 +00:00
|
|
|
|
2007-01-14 21:29:12 +00:00
|
|
|
|
|
|
|
|
|
|
|
namespace Parallaction {
|
|
|
|
|
|
|
|
//
|
2007-03-13 20:41:40 +00:00
|
|
|
// inventory is a grid made of (at most) 30 cells, 24x24 pixels each,
|
2007-01-14 21:29:12 +00:00
|
|
|
// arranged in 6 lines
|
|
|
|
//
|
|
|
|
// inventory items are stored in cnv files in a 32x24 grid
|
|
|
|
// but only 24x24 pixels are actually copied to graphic memory
|
|
|
|
//
|
|
|
|
|
|
|
|
#define INVENTORY_MAX_ITEMS 30
|
2007-05-13 14:56:44 +00:00
|
|
|
#define INVENTORY_FIRST_ITEM 4 // first four entries are used up by verbs
|
2007-01-14 21:29:12 +00:00
|
|
|
|
|
|
|
#define INVENTORY_ITEMS_PER_LINE 5
|
|
|
|
#define INVENTORY_LINES 6
|
|
|
|
|
|
|
|
#define INVENTORY_WIDTH (INVENTORY_ITEMS_PER_LINE*INVENTORYITEM_WIDTH)
|
|
|
|
#define INVENTORY_HEIGHT (INVENTORY_LINES*INVENTORYITEM_HEIGHT)
|
|
|
|
|
2007-09-23 20:17:50 +00:00
|
|
|
Inventory *_inv = 0;
|
|
|
|
InventoryRenderer *_re = 0;
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-09-25 15:58:44 +00:00
|
|
|
|
2007-01-14 21:29:12 +00:00
|
|
|
int16 Parallaction::getHoverInventoryItem(int16 x, int16 y) {
|
2007-09-23 20:17:50 +00:00
|
|
|
return _re->hitTest(Common::Point(x,y));
|
|
|
|
}
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-09-25 15:58:44 +00:00
|
|
|
void highlightInventoryItem(ItemPosition pos, byte color) {
|
|
|
|
_re->highlightItem(pos, color);
|
|
|
|
}
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-09-23 20:17:50 +00:00
|
|
|
int Parallaction::addInventoryItem(ItemName item) {
|
|
|
|
return _inv->addItem(item);
|
|
|
|
}
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-09-23 20:17:50 +00:00
|
|
|
int Parallaction::addInventoryItem(ItemName item, uint32 value) {
|
|
|
|
return _inv->addItem(item, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Parallaction::dropItem(uint16 v) {
|
|
|
|
_inv->removeItem(v);
|
|
|
|
}
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-09-23 20:17:50 +00:00
|
|
|
bool Parallaction::isItemInInventory(int32 v) {
|
|
|
|
return (_inv->findItem(v) != -1);
|
2007-01-14 21:29:12 +00:00
|
|
|
}
|
|
|
|
|
2007-09-23 20:17:50 +00:00
|
|
|
const InventoryItem* getInventoryItem(int16 pos) {
|
|
|
|
return _inv->getItem(pos);
|
|
|
|
}
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-09-23 20:17:50 +00:00
|
|
|
int16 getInventoryItemIndex(int16 pos) {
|
|
|
|
return _inv->getItemName(pos);
|
|
|
|
}
|
|
|
|
|
|
|
|
void initInventory() {
|
|
|
|
_inv = new Inventory(INVENTORY_MAX_ITEMS);
|
|
|
|
_re = new InventoryRenderer(_vm);
|
|
|
|
_re->bindInventory(_inv);
|
|
|
|
}
|
2007-07-08 20:15:43 +00:00
|
|
|
|
2007-09-23 20:17:50 +00:00
|
|
|
void destroyInventory() {
|
|
|
|
delete _inv;
|
|
|
|
delete _re;
|
|
|
|
}
|
|
|
|
|
|
|
|
void cleanInventory(bool keepVerbs) {
|
|
|
|
_inv->clear(keepVerbs);
|
|
|
|
}
|
|
|
|
|
2007-09-25 15:58:44 +00:00
|
|
|
void openInventory() {
|
|
|
|
_re->showInventory();
|
|
|
|
}
|
|
|
|
|
|
|
|
void closeInventory() {
|
|
|
|
_re->hideInventory();
|
|
|
|
}
|
2007-09-23 20:17:50 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void Parallaction_ns::jobShowInventory(void *parm, Job *j) {
|
2007-08-25 20:34:10 +00:00
|
|
|
Common::Rect r;
|
2007-09-23 20:17:50 +00:00
|
|
|
_re->getRect(r);
|
|
|
|
_gfx->copyRect(Gfx::kBitBack, r, _re->getData(), INVENTORY_WIDTH);
|
|
|
|
}
|
2007-08-25 20:34:10 +00:00
|
|
|
|
2007-09-23 20:17:50 +00:00
|
|
|
void Parallaction_ns::jobHideInventory(void *parm, Job *j) {
|
|
|
|
static uint16 count = 0;
|
|
|
|
_engineFlags |= kEngineBlockInput;
|
2007-07-08 20:15:43 +00:00
|
|
|
|
2007-09-23 20:17:50 +00:00
|
|
|
count++;
|
|
|
|
if (count == 2) {
|
|
|
|
count = 0;
|
|
|
|
j->_finished = 1;
|
|
|
|
_engineFlags &= ~kEngineBlockInput;
|
2007-05-13 14:38:05 +00:00
|
|
|
}
|
2007-07-08 20:15:43 +00:00
|
|
|
|
2007-09-23 20:17:50 +00:00
|
|
|
Common::Rect r;
|
|
|
|
_re->getRect(r);
|
|
|
|
_gfx->restoreBackground(r);
|
2007-05-13 14:38:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-07-08 20:15:43 +00:00
|
|
|
|
|
|
|
|
2007-09-23 20:17:50 +00:00
|
|
|
|
|
|
|
InventoryRenderer::InventoryRenderer(Parallaction *vm) : _vm(vm) {
|
2007-09-25 15:58:44 +00:00
|
|
|
_surf.create(INVENTORY_WIDTH, INVENTORY_HEIGHT, 1);
|
2007-05-13 14:38:05 +00:00
|
|
|
}
|
|
|
|
|
2007-09-23 20:17:50 +00:00
|
|
|
InventoryRenderer::~InventoryRenderer() {
|
2007-09-25 15:58:44 +00:00
|
|
|
_surf.free();
|
2007-09-23 20:17:50 +00:00
|
|
|
}
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-09-23 20:17:50 +00:00
|
|
|
void InventoryRenderer::showInventory() {
|
|
|
|
if (!_inv)
|
|
|
|
error("InventoryRenderer not bound to inventory");
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-09-23 20:17:50 +00:00
|
|
|
_engineFlags |= kEngineInventory;
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-09-23 20:17:50 +00:00
|
|
|
uint16 lines = getNumLines();
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-09-23 20:17:50 +00:00
|
|
|
_pos.x = CLIP(_vm->_mousePos.x - (INVENTORY_WIDTH / 2), 0, (int)(_vm->_screenWidth - INVENTORY_WIDTH));
|
|
|
|
_pos.y = CLIP(_vm->_mousePos.y - 2 - (lines * INVENTORYITEM_HEIGHT), 0, (int)(_vm->_screenHeight - lines * INVENTORYITEM_HEIGHT));
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-09-23 20:17:50 +00:00
|
|
|
refresh();
|
|
|
|
}
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-09-23 20:17:50 +00:00
|
|
|
void InventoryRenderer::hideInventory() {
|
|
|
|
if (!_inv)
|
|
|
|
error("InventoryRenderer not bound to inventory");
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-09-23 20:17:50 +00:00
|
|
|
_engineFlags &= ~kEngineInventory;
|
|
|
|
}
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-09-23 20:17:50 +00:00
|
|
|
void InventoryRenderer::getRect(Common::Rect& r) const {
|
|
|
|
r.setWidth(INVENTORY_WIDTH);
|
|
|
|
r.setHeight(INVENTORYITEM_HEIGHT * getNumLines());
|
|
|
|
r.moveTo(_pos);
|
|
|
|
}
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-09-23 20:17:50 +00:00
|
|
|
ItemPosition InventoryRenderer::hitTest(const Common::Point &p) const {
|
|
|
|
Common::Rect r;
|
|
|
|
getRect(r);
|
|
|
|
if (!r.contains(p))
|
|
|
|
return -1;
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-09-23 20:17:50 +00:00
|
|
|
return ((p.x - _pos.x) / INVENTORYITEM_WIDTH) + (INVENTORY_ITEMS_PER_LINE * ((p.y - _pos.y) / INVENTORYITEM_HEIGHT));
|
2007-01-14 21:29:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-09-23 20:17:50 +00:00
|
|
|
void InventoryRenderer::drawItem(ItemPosition pos, ItemName name) {
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-09-23 20:17:50 +00:00
|
|
|
Common::Rect r;
|
2007-09-25 15:58:44 +00:00
|
|
|
getItemRect(pos, r);
|
2007-09-23 20:17:50 +00:00
|
|
|
|
|
|
|
// FIXME: this will end up in a general blit function
|
|
|
|
|
|
|
|
byte* s = _vm->_char._objs->getData(name);
|
2007-09-25 15:58:44 +00:00
|
|
|
byte* d = (byte*)_surf.getBasePtr(r.left, r.top);
|
2007-09-23 20:17:50 +00:00
|
|
|
for (uint32 i = 0; i < INVENTORYITEM_HEIGHT; i++) {
|
|
|
|
memcpy(d, s, INVENTORYITEM_WIDTH);
|
|
|
|
|
|
|
|
d += INVENTORY_WIDTH;
|
|
|
|
s += INVENTORYITEM_PITCH;
|
2007-01-14 21:29:12 +00:00
|
|
|
}
|
2007-09-23 20:17:50 +00:00
|
|
|
}
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-09-23 20:17:50 +00:00
|
|
|
int16 InventoryRenderer::getNumLines() const {
|
|
|
|
int16 num = _inv->getNumItems();
|
|
|
|
return (num / INVENTORY_ITEMS_PER_LINE) + ((num % INVENTORY_ITEMS_PER_LINE) > 0 ? 1 : 0);
|
2007-01-14 21:29:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-09-23 20:17:50 +00:00
|
|
|
void InventoryRenderer::refresh() {
|
|
|
|
for (uint16 i = 0; i < INVENTORY_MAX_ITEMS; i++) {
|
|
|
|
ItemName name = _inv->getItemName(i);
|
|
|
|
drawItem(i, name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-09-25 15:58:44 +00:00
|
|
|
void InventoryRenderer::highlightItem(ItemPosition pos, byte color) {
|
|
|
|
if (pos == -1)
|
|
|
|
return;
|
2007-03-13 20:41:40 +00:00
|
|
|
|
2007-09-25 15:58:44 +00:00
|
|
|
Common::Rect r;
|
|
|
|
getItemRect(pos, r);
|
2007-03-13 20:41:40 +00:00
|
|
|
|
2007-09-25 15:58:44 +00:00
|
|
|
if (color != 12)
|
|
|
|
color = 19;
|
2007-03-13 20:41:40 +00:00
|
|
|
|
2007-09-25 15:58:44 +00:00
|
|
|
_surf.frameRect(r, color);
|
2007-03-13 20:41:40 +00:00
|
|
|
}
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-09-25 15:58:44 +00:00
|
|
|
void InventoryRenderer::getItemRect(ItemPosition pos, Common::Rect &r) {
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-09-25 15:58:44 +00:00
|
|
|
r.setHeight(INVENTORYITEM_HEIGHT);
|
|
|
|
r.setWidth(INVENTORYITEM_WIDTH);
|
2007-01-14 21:29:12 +00:00
|
|
|
|
|
|
|
uint16 line = pos / INVENTORY_ITEMS_PER_LINE;
|
|
|
|
uint16 col = pos % INVENTORY_ITEMS_PER_LINE;
|
|
|
|
|
2007-09-25 15:58:44 +00:00
|
|
|
r.moveTo(col * INVENTORYITEM_WIDTH, line * INVENTORYITEM_HEIGHT);
|
2007-01-14 21:29:12 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2007-03-13 23:30:36 +00:00
|
|
|
|
2007-01-14 21:29:12 +00:00
|
|
|
|
|
|
|
|
2007-09-25 15:58:44 +00:00
|
|
|
|
|
|
|
|
2007-09-23 20:17:50 +00:00
|
|
|
Inventory::Inventory(uint16 maxItems) : _maxItems(maxItems), _numItems(0) {
|
|
|
|
_items = (InventoryItem*)calloc(_maxItems, sizeof(InventoryItem));
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-09-23 20:17:50 +00:00
|
|
|
addItem(1, kZoneDoor);
|
|
|
|
addItem(3, kZoneExamine);
|
|
|
|
addItem(2, kZoneGet);
|
|
|
|
addItem(4, kZoneSpeak);
|
|
|
|
}
|
2007-01-14 21:29:12 +00:00
|
|
|
|
|
|
|
|
2007-09-23 20:17:50 +00:00
|
|
|
Inventory::~Inventory() {
|
|
|
|
free(_items);
|
|
|
|
}
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-09-23 20:17:50 +00:00
|
|
|
ItemPosition Inventory::addItem(ItemName name, uint32 value) {
|
|
|
|
if (_numItems == INVENTORY_MAX_ITEMS)
|
|
|
|
return -1;
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-10-06 20:56:17 +00:00
|
|
|
// NOTE: items whose name == 0 aren't really inventory items,
|
|
|
|
// but the engine expects the inventory to accept them as valid.
|
|
|
|
// This nasty trick has been discovered because of regression
|
|
|
|
// after r29060.
|
2007-09-23 20:17:50 +00:00
|
|
|
if (name == 0)
|
2007-10-06 20:56:17 +00:00
|
|
|
return 0;
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-09-23 20:17:50 +00:00
|
|
|
_items[_numItems]._id = value;
|
|
|
|
_items[_numItems]._index = name;
|
2007-03-13 20:47:59 +00:00
|
|
|
|
2007-09-23 20:17:50 +00:00
|
|
|
_numItems++;
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-09-23 20:17:50 +00:00
|
|
|
return _numItems;
|
2007-01-14 21:29:12 +00:00
|
|
|
}
|
|
|
|
|
2007-09-23 20:17:50 +00:00
|
|
|
ItemPosition Inventory::addItem(ItemName name) {
|
|
|
|
return addItem(name, MAKE_INVENTORY_ID(name));
|
|
|
|
}
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-09-23 20:17:50 +00:00
|
|
|
ItemPosition Inventory::findItem(ItemName name) const {
|
|
|
|
for (ItemPosition slot = 0; slot < _numItems; slot++) {
|
|
|
|
if (name == _items[slot]._index)
|
|
|
|
return slot;
|
|
|
|
}
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-09-23 20:17:50 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-09-23 20:17:50 +00:00
|
|
|
void Inventory::removeItem(ItemName name) {
|
|
|
|
ItemPosition pos = findItem(name);
|
|
|
|
if (pos == -1) {
|
|
|
|
return;
|
|
|
|
}
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-09-23 20:17:50 +00:00
|
|
|
_numItems--;
|
2007-07-08 20:15:43 +00:00
|
|
|
|
2007-09-23 20:17:50 +00:00
|
|
|
if (_numItems != pos) {
|
|
|
|
memcpy(&_items[pos], &_items[pos+1], (_numItems - pos) * sizeof(InventoryItem));
|
|
|
|
}
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-09-23 20:17:50 +00:00
|
|
|
_items[_numItems]._id = 0;
|
|
|
|
_items[_numItems]._index = 0;
|
2007-01-14 21:29:12 +00:00
|
|
|
}
|
|
|
|
|
2007-09-23 20:17:50 +00:00
|
|
|
void Inventory::clear(bool keepVerbs) {
|
|
|
|
uint first = (keepVerbs ? INVENTORY_FIRST_ITEM : 0);
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-09-23 20:17:50 +00:00
|
|
|
for (uint16 slot = first; slot < _maxItems; slot++) {
|
|
|
|
_items[slot]._id = 0;
|
|
|
|
_items[slot]._index = 0;
|
|
|
|
}
|
2007-01-14 21:29:12 +00:00
|
|
|
|
2007-09-23 20:17:50 +00:00
|
|
|
_numItems = first;
|
2007-01-14 21:29:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-09-23 20:17:50 +00:00
|
|
|
ItemName Inventory::getItemName(ItemPosition pos) const {
|
2007-09-24 19:45:18 +00:00
|
|
|
return (pos >= 0 && pos < INVENTORY_MAX_ITEMS) ? _items[pos]._index : 0;
|
2007-05-21 21:06:30 +00:00
|
|
|
}
|
|
|
|
|
2007-09-23 20:17:50 +00:00
|
|
|
const InventoryItem* Inventory::getItem(ItemPosition pos) const {
|
|
|
|
return &_items[pos];
|
|
|
|
}
|
2007-01-14 21:29:12 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} // namespace Parallaction
|