diff options
Diffstat (limited to 'engines/agos/items.cpp')
-rw-r--r-- | engines/agos/items.cpp | 418 |
1 files changed, 418 insertions, 0 deletions
diff --git a/engines/agos/items.cpp b/engines/agos/items.cpp new file mode 100644 index 0000000000..b0ebabe0ae --- /dev/null +++ b/engines/agos/items.cpp @@ -0,0 +1,418 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2001 Ludvig Strigeus + * Copyright (C) 2001-2006 The ScummVM project + * + * 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 "common/stdafx.h" + +#include "common/file.h" + +#include "agos/intern.h" +#include "agos/agos.h" +#include "agos/vga.h" + +namespace AGOS { + +Child *AGOSEngine::allocateChildBlock(Item *i, uint type, uint size) { + Child *child = (Child *)allocateItem(size); + child->next = i->children; + i->children = child; + child->type = type; + return child; +} + +byte *AGOSEngine::allocateItem(uint size) { + byte *org = _itemHeapPtr; + size = (size + sizeof(void*) - 1) & ~(sizeof(void*) - 1); + + _itemHeapPtr += size; + _itemHeapCurPos += size; + + if (_itemHeapCurPos > _itemHeapSize) + error("allocateItem: Itemheap overflow"); + + return org; +} + +void AGOSEngine::allocItemHeap() { + _itemHeapSize = _itemMemSize; + _itemHeapCurPos = 0; + _itemHeapPtr = (byte *)calloc(_itemMemSize, 1); + if (!_itemHeapPtr) + error("Out Of Memory - Items"); +} + +uint AGOSEngine::itemGetIconNumber(Item *item) { + if (getGameType() == GType_ELVIRA1) { + return getUserFlag(item, 7); + } else { + SubObject *child = (SubObject *)findChildOfType(item, 2); + uint offs; + + if (child == NULL || !(child->objectFlags & kOFIcon)) + return 0; + + offs = getOffsetOfChild2Param(child, 0x10); + return child->objectFlagValue[offs]; + } +} + +void AGOSEngine::setItemState(Item *item, int value) { + item->state = value; +} + +void AGOSEngine::createPlayer() { + SubPlayer *p; + + _currentPlayer = _itemArrayPtr[1]; + _currentPlayer->adjective = -1; + _currentPlayer->noun = 10000; + + p = (SubPlayer *)allocateChildBlock(_currentPlayer, 3, sizeof(SubPlayer)); + if (p == NULL) + error("createPlayer: player create failure"); + + p->size = 0; + p->weight = 0; + p->strength = 6000; + //p->flag = xxx; + p->level = 1; + p->score = 0; + + setUserFlag(_currentPlayer, 0, 0); +} + +Child *AGOSEngine::findChildOfType(Item *i, uint type) { + Child *child = i->children; + for (; child; child = child->next) + if (child->type == type) + return child; + return NULL; +} + +int AGOSEngine::getUserFlag(Item *item, int a) { + SubUserFlag *subUserFlag; + + subUserFlag = (SubUserFlag *) findChildOfType(item, 9); + if (subUserFlag == NULL) + return 0; + + if (a < 0 || a > 7) + return 0; + + return subUserFlag->userFlags[a]; +} + +void AGOSEngine::setUserFlag(Item *item, int a, int b) { + SubUserFlag *subUserFlag; + + subUserFlag = (SubUserFlag *) findChildOfType(item, 9); + if (subUserFlag == NULL) { + subUserFlag = (SubUserFlag *) allocateChildBlock(item, 9, sizeof(SubUserFlag)); + } + + if (a < 0 || a > 7) + return; + + subUserFlag->userFlags[a] = b; +} + +int AGOSEngine::getUserItem(Item *item, int n) { + SubUserFlag *subUserFlag; + + subUserFlag = (SubUserFlag *) findChildOfType(item, 9); + if (subUserFlag == NULL) + return 0; + + if (n < 0 || n > 0) + return 0; + + return subUserFlag->userItems[n]; +} + +void AGOSEngine::setUserItem(Item *item, int n, int m) { + SubUserFlag *subUserFlag; + + subUserFlag = (SubUserFlag *) findChildOfType(item, 9); + if (subUserFlag == NULL) { + subUserFlag = (SubUserFlag *) allocateChildBlock(item, 9, sizeof(SubUserFlag)); + } + + if (n == 0) + subUserFlag->userItems[n] = m; +} + +bool AGOSEngine::isRoom(Item *item) { + return findChildOfType(item, 1) != NULL; +} + +bool AGOSEngine::isObject(Item *item) { + return findChildOfType(item, 2) != NULL; +} + +bool AGOSEngine::isPlayer(Item *item) { + return findChildOfType(item, 3) != NULL; +} + +uint AGOSEngine::getOffsetOfChild2Param(SubObject *child, uint prop) { + uint m = 1; + uint offset = 0; + while (m != prop) { + if (child->objectFlags & m) + offset++; + m *= 2; + } + return offset; +} + +Item *AGOSEngine::me() { + if (_currentPlayer) + return _currentPlayer; + return _dummyItem1; +} + +Item *AGOSEngine::actor() { + error("actor: is this code ever used?"); + //if (_actorPlayer) + // return _actorPlayer; + return _dummyItem1; +} + +Item *AGOSEngine::getNextItemPtr() { + int a = getNextWord(); + switch (a) { + case -1: + return _subjectItem; + case -3: + return _objectItem; + case -5: + return me(); + case -7: + return actor(); + case -9: + return derefItem(me()->parent); + default: + return derefItem(a); + } +} + +Item *AGOSEngine::getNextItemPtrStrange() { + int a = getNextWord(); + switch (a) { + case -1: + return _subjectItem; + case -3: + return _objectItem; + case -5: + return _dummyItem2; + case -7: + return NULL; + case -9: + return _dummyItem3; + default: + return derefItem(a); + } +} + +uint AGOSEngine::getNextItemID() { + int a = getNextWord(); + switch (a) { + case -1: + return itemPtrToID(_subjectItem); + case -3: + return itemPtrToID(_objectItem); + case -5: + return getItem1ID(); + case -7: + return 0; + case -9: + return me()->parent; + default: + return a; + } +} + +void AGOSEngine::setItemParent(Item *item, Item *parent) { + Item *old_parent = derefItem(item->parent); + + if (item == parent) + error("setItemParent: Trying to set item as its own parent"); + + // unlink it if it has a parent + if (old_parent) + unlinkItem(item); + itemChildrenChanged(old_parent); + linkItem(item, parent); + itemChildrenChanged(parent); +} + +void AGOSEngine::itemChildrenChanged(Item *item) { + int i; + WindowBlock *window; + + if (_noParentNotify) + return; + + mouseOff(); + + for (i = 0; i != 8; i++) { + window = _windowArray[i]; + if (window && window->iconPtr && window->iconPtr->itemRef == item) { + if (_fcsData1[i]) { + _fcsData2[i] = true; + } else { + _fcsData2[i] = false; + drawIconArray(i, item, window->iconPtr->line, window->iconPtr->classMask); + } + } + } + + mouseOn(); +} + +void AGOSEngine::unlinkItem(Item *item) { + Item *first, *parent, *next; + + // can't unlink item without parent + if (item->parent == 0) + return; + + // get parent and first child of parent + parent = derefItem(item->parent); + first = derefItem(parent->child); + + // the node to remove is first in the parent's children? + if (first == item) { + parent->child = item->next; + item->parent = 0; + item->next = 0; + return; + } + + for (;;) { + if (!first) + error("unlinkItem: parent empty"); + if (first->next == 0) + error("unlinkItem: parent does not contain child"); + + next = derefItem(first->next); + if (next == item) { + first->next = next->next; + item->parent = 0; + item->next = 0; + return; + } + first = next; + } +} + +void AGOSEngine::linkItem(Item *item, Item *parent) { + uint id; + // Don't allow that an item that is already linked is relinked + if (item->parent) + return; + + id = itemPtrToID(parent); + item->parent = id; + + if (parent != 0) { + item->next = parent->child; + parent->child = itemPtrToID(item); + } else { + item->next = 0; + } +} + +bool AGOSEngine::has_item_childflag_0x10(Item *item) { + SubObject *child = (SubObject *)findChildOfType(item, 2); + return child && (child->objectFlags & kOFIcon) != 0; +} + +int AGOSEngine::wordMatch(Item *item, int16 a, int16 n) { + if ((a == -1) && (n == item->noun)) + return 1; + if ((a == item->adjective) && (n == item->noun)) + return 1 ; + + return 0; +} + +Item *AGOSEngine::derefItem(uint item) { + if (item >= _itemArraySize) { + debug(1, "derefItem: invalid item %d", item); + return 0; + } + return _itemArrayPtr[item]; +} + +Item *AGOSEngine::findInByClass(Item *i, int16 m) { + i = derefItem(i->child); + + while (i) { + if (i->classFlags & m) { + //_findNextPtr = derefItem(i->next); + return i; + } + if (m == 0) { + //_findNextPtr = derefItem(i->next); + return i; + } + i = derefItem(i->next); + } + + return NULL; +} + +Item *AGOSEngine::findMaster(int16 a, int16 n) { + uint j; + + for (j = 1; j < _itemArraySize; j++) { + Item *item = derefItem(j); + if (wordMatch(item, a, n)) + return item; + } + + return NULL; +} + +Item *AGOSEngine::nextMaster(Item *i, int16 a, int16 n) { + uint j; + uint first = itemPtrToID(i) + 1; + + for (j = first; j < _itemArraySize; j++) { + Item *item = derefItem(j); + if (wordMatch(item, a, n)) + return item; + } + + return NULL; +} + +uint AGOSEngine::itemPtrToID(Item *id) { + uint i; + for (i = 0; i != _itemArraySize; i++) + if (_itemArrayPtr[i] == id) + return i; + error("itemPtrToID: not found"); + return 0; +} + +} // End of namespace AGOS |