Beispiel #1
0
void ScummEngine::setOwnerOf(int obj, int owner) {
	ScriptSlot *ss;

	// In Sam & Max this is necessary, or you won't get your stuff back
	// from the Lost and Found tent after riding the Cone of Tragedy. But
	// it probably applies to all V6+ games. See bugs #493153 and #907113.
	// FT disassembly is checked, behaviour is correct. [sev]

	int arg = (_game.version >= 6) ? obj : 0;

	// WORKAROUND for bug #1917981: Game crash when finishing Indy3 demo.
	// Script 94 tries to empty the inventory but does so in a bogus way.
	// This causes it to try to remove object 0 from the inventory.
	if (_game.id == GID_PASS && obj == 0 && vm.slot[_currentScript].number == 94)
		return;
	assert(obj > 0);

	if (owner == 0) {
		clearOwnerOf(obj);

		// FIXME: See bug #1535358 and many others. Essentially, the following
		// code, while matching disasm of various versions of the SCUMM engine,
		// is total bullocks, and leads to odd crashes due to out-of-bounds
		// array (read) access. Three "famous" crashes were caused by this:
		//   Monkey Island 1: Using meat with flower
		//   FOA: Using ribcage with another item
		//   DOTT: Using stamp with contract
		//
		// The bad code:
		//   if (ss->where == WIO_INVENTORY && _inventory[ss->number] == obj) {
		// That check makes no sense at all: _inventory only contains 80 items,
		// which are in the order the player picked up items. We can only
		// guess that the SCUMM coders meant to write
		//   if (ss->where == WIO_INVENTORY && ss->number == obj) {
		// which would ensure that an object script that nukes itself gets
		// stopped. Alas, we can't just make that change, since it could
		// lead to new regressions.
		// Another fix would be to completely remove this check, which should
		// not cause much problems, since it'll only succeed by pure chance.
		//
		// For now we follow a more defensive route: We perform the check
		// if ss->number is small enough.

		ss = &vm.slot[_currentScript];
		if (ss->where == WIO_INVENTORY) {
			if (ss->number < _numInventory && _inventory[ss->number] == obj) {
				error("Odd setOwnerOf case #1: Please report to Fingolfin where you encountered this");
				putOwner(obj, 0);
				runInventoryScript(arg);
				stopObjectCode();
				return;
			}
			if (ss->number == obj)
				error("Odd setOwnerOf case #2: Please report to Fingolfin where you encountered this");
		}
	}

	putOwner(obj, owner);
	runInventoryScript(arg);
}
Beispiel #2
0
void ScummEngine_v0::o_loadRoomWithEgo() {
	Actor_v0 *a;
	int obj, room, x, y, dir;

	obj = fetchScriptByte();
	room = fetchScriptByte();

	a = (Actor_v0 *)derefActor(VAR(VAR_EGO), "o_loadRoomWithEgo");

	//0x634F
	if (a->_miscflags & kActorMiscFlagFreeze) {
		stopObjectCode();
		return;
	}

	// The original interpreter sets the actors new room X/Y to the last rooms X/Y
	// This fixes a problem with MM: script 158 in room 12, the 'Oomph!' script
	// This scripts runs before the actor position is set to the correct room entry location
	a->putActor(a->getPos().x, a->getPos().y, room);
	_egoPositioned = false;

	startScene(a->_room, a, obj);

	getObjectXYPos(obj, x, y, dir);
	AdjustBoxResult r = a->adjustXYToBeInBox(x, y);
	x = r.x;
	y = r.y;
	a->putActor(x, y, _currentRoom);

	camera._dest.x = camera._cur.x = a->getPos().x;
	setCameraAt(a->getPos().x, a->getPos().y);
	setCameraFollows(a);

	_fullRedraw = true;

	resetSentence();

	if (x >= 0 && y >= 0) {
		a->startWalkActor(x, y, -1);
	}
}