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 | 
