aboutsummaryrefslogtreecommitdiff
path: root/engines/agos/items.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/agos/items.cpp')
-rw-r--r--engines/agos/items.cpp418
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