Esempio n. 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);
}
Esempio n. 2
0
void ScummEngine::setCameraFollows(Actor *a, bool setCamera) {

	int t, i;

	camera._mode = kFollowActorCameraMode;
	camera._follows = a->_number;

	if (!a->isInCurrentRoom()) {
		startScene(a->getRoom(), 0, 0);
		camera._mode = kFollowActorCameraMode;
		camera._cur.x = a->_pos.x;
		setCameraAt(camera._cur.x, 0);
	}

	t = a->_pos.x / 8 - _screenStartStrip;

	if (t < camera._leftTrigger || t  > camera._rightTrigger || setCamera == true)
		setCameraAt(a->_pos.x, 0);

	for (i = 1; i < _numActors; i++) {
		if (_actors[i].isInCurrentRoom())
			_actors[i]._needRedraw = true;
	}
	runInventoryScript(0);
}
Esempio n. 3
0
void ScummEngine::actorFollowCamera(int act) {
	if (!(_game.features & GF_NEW_CAMERA)) {
		int old;

		old = camera._follows;
		setCameraFollows(derefActor(act, "actorFollowCamera"));
		if (camera._follows != old)
			runInventoryScript(0);

		camera._movingToActor = false;
	}
}
Esempio n. 4
0
void ScummEngine_v0::o_pickupObject() {
	int obj = fetchScriptByte();
	if (!obj)
		obj = _cmdObject;

	/* Don't take an object twice */
	if (whereIsObject(obj) == WIO_INVENTORY)
		return;

	addObjectToInventory(obj, _roomResource);
	markObjectRectAsDirty(obj);
	putOwner(obj, VAR(VAR_EGO));
	putState(obj, getState(obj) | kObjectState_08 | kObjectStateUntouchable);
	clearDrawObjectQueue();

	runInventoryScript(1);
}
Esempio n. 5
0
void ScummEngine_v70he::o70_pickupObject() {
	int obj, room;

	room = pop();
	obj = pop();
	if (room == 0)
		room = getObjectRoom(obj);

	addObjectToInventory(obj, room);
	putOwner(obj, VAR(VAR_EGO));
	if (_game.heversion <= 70) {
		putClass(obj, kObjectClassUntouchable, 1);
		putState(obj, 1);
		markObjectRectAsDirty(obj);
		clearDrawObjectQueue();
	}
	runInventoryScript(obj);									/* Difference */
}
Esempio n. 6
0
void ScummEngine_v4::o4_pickupObject() {
	int obj = getVarOrDirectWord(PARAM_1);

	if (obj < 1) {
		error("pickupObjectOld received invalid index %d (script %d)", obj, vm.slot[_currentScript].number);
	}

	if (getObjectIndex(obj) == -1)
		return;

	if (whereIsObject(obj) == WIO_INVENTORY)	// Don't take an object twice
		return;

	// debug(0, "adding %d from %d to inventoryOld", obj, _currentRoom);
	addObjectToInventory(obj, _roomResource);
	markObjectRectAsDirty(obj);
	putOwner(obj, VAR(VAR_EGO));
	putClass(obj, kObjectClassUntouchable, 1);
	putState(obj, 1);
	clearDrawObjectQueue();
	runInventoryScript(1);
}
Esempio n. 7
0
void ScummEngine_v7::setCameraFollows(Actor *a, bool setCamera) {

	byte oldfollow = camera._follows;
	int ax, ay;

	camera._follows = a->_number;
	VAR(VAR_CAMERA_FOLLOWED_ACTOR) = a->_number;

	if (!a->isInCurrentRoom()) {
		startScene(a->getRoom(), 0, 0);
	}

	ax = ABS(a->_pos.x - camera._cur.x);
	ay = ABS(a->_pos.y - camera._cur.y);

	if (ax > VAR(VAR_CAMERA_THRESHOLD_X) || ay > VAR(VAR_CAMERA_THRESHOLD_Y) || ax > (_screenWidth / 2) || ay > (_screenHeight / 2)) {
		setCameraAt(a->_pos.x, a->_pos.y);
	}

	if (a->_number != oldfollow)
		runInventoryScript(0);
}