[Scummvm-cvs-logs] scummvm master -> b56f8f2212d50ac959e00136d093b313a1fb2ea2

bluegr bluegr at gmail.com
Sat Feb 22 19:35:39 CET 2014


This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
b56f8f2212 BBVS: Move some code out of bbvs.cpp


Commit: b56f8f2212d50ac959e00136d093b313a1fb2ea2
    https://github.com/scummvm/scummvm/commit/b56f8f2212d50ac959e00136d093b313a1fb2ea2
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2014-02-22T10:34:52-08:00

Commit Message:
BBVS: Move some code out of bbvs.cpp

Changed paths:
  A engines/bbvs/logic.cpp
  A engines/bbvs/scene.cpp
  A engines/bbvs/walk.cpp
    engines/bbvs/bbvs.cpp
    engines/bbvs/bbvs.h
    engines/bbvs/module.mk



diff --git a/engines/bbvs/bbvs.cpp b/engines/bbvs/bbvs.cpp
index d7e6606..3da9e8b 100644
--- a/engines/bbvs/bbvs.cpp
+++ b/engines/bbvs/bbvs.cpp
@@ -66,41 +66,11 @@ static const BBRect kVerbRects[6] = {
 	{ 13, -33, 19, 27}, {-10,   8, 19, 27}, {-11, -49, 19, 27}
 };
 
-static const int8 kWalkTurnTbl[] = {
-	7, 9, 4, 8, 6, 10, 5, 11
-};
-
-static const int8 kWalkAnimTbl[32] = {
-	 3,  0,  0,  0,  2,  1,  1,  1,
-	15, 12, 14, 13,  0,  0,  0,  0,
-	 7,  9,  4,  8,  6, 10,  5, 11,
-	 3,  0,  2,  1, 15, 12, 14, 13
-};
-
-static const int8 kTurnInfo[8][8] = {
-	{ 0,  1,  1,  1,  1, -1, -1, -1},
-	{-1,  0,  1,  1,  1,  1, -1, -1},
-	{-1, -1,  0,  1,  1,  1,  1, -1},
-	{-1, -1, -1,  0,  1,  1,  1,  1},
-	{ 1, -1, -1, -1,  0,  1,  1,  1},
-	{ 1,  1, -1, -1, -1,  0,  1,  1},
-	{ 1,  1,  1, -1, -1, -1,  0,  1},
-	{ 1,  1,  1,  1, -1, -1, -1,  0}
-};
-
 static const byte kTurnTbl[] = {
 	2, 6, 4, 0, 2, 6, 4, 0,
 	3, 1, 5, 7, 0, 0, 0, 0
 };
 
-static const int kAfterVideoSceneNum[] = {
-	 0, 43, 23, 12,  4, 44,  2,
-	16,  4,  4,  4, 44, 12, 44
-};
-
-const int kMainMenu = 44;
-const int kCredits  = 45;
-
 bool WalkArea::contains(const Common::Point &pt) const {
 	return Common::Rect(x, y, x + width, y + height).contains(pt);
 }
@@ -312,243 +282,6 @@ void BbvsEngine::updateGame() {
 
 }
 
-bool BbvsEngine::evalCondition(Conditions &conditions) {
-	bool result = true;
-	for (int i = 0; i < 8 && result; ++i) {
-		const Condition &condition = conditions.conditions[i];
-		switch (condition.cond) {
-		case kCondSceneObjectVerb:
-			result = _activeItemType == KITSceneObject &&
-				condition.value1 == _currVerbNum &&
-				condition.value2 == _activeItemIndex;
-			break;
-		case kCondBgObjectVerb:
-			result = _activeItemType == kITBgObject &&
-				condition.value1 == _currVerbNum &&
-				condition.value2 == _activeItemIndex;
-			break;
-		case kCondSceneObjectInventory:
-			result = _activeItemType == KITSceneObject &&
-				_currVerbNum == kVerbInvItem &&
-				condition.value1 == _currInventoryItem &&
-				condition.value2 == _activeItemIndex;
-			break;
-		case kCondBgObjectInventory:
-			result = _activeItemType == kITBgObject &&
-				_currVerbNum == kVerbInvItem &&
-				condition.value1 == _currInventoryItem &&
-				condition.value2 == _activeItemIndex;
-			break;
-		case kCondHasInventoryItem:
-			result = _inventoryItemStatus[condition.value1] != 0;
-			break;
-		case kCondHasNotInventoryItem:
-			result = _inventoryItemStatus[condition.value1] == 0;
-			break;
-		case kCondIsGameVar:
-			result = _gameVars[condition.value2] != 0;
-			break;
-		case kCondIsNotGameVar:
-			result = _gameVars[condition.value2] == 0;
-			break;
-		case kCondIsPrevSceneNum:
-			result = condition.value2 == _prevSceneNum;
-			break;
-		case kCondIsCurrTalkObject:
-			result = condition.value2 == _currTalkObjectIndex;
-			break;
-		case kCondIsDialogItem:
-			result = _activeItemType == kITDialog &&
-				condition.value1 == _activeItemIndex;
-			break;
-		case kCondIsCameraNum:
-			result = condition.value1 == _currCameraNum;
-			break;
-		case kCondIsNotPrevSceneNum:
-			result = condition.value2 != _prevSceneNum;
-			break;
-		case kCondIsButtheadAtBgObject:
-			result = _buttheadObject &&
-				_gameModule->getBgObject(condition.value2)->rect.contains(_buttheadObject->x >> 16, _buttheadObject->y >> 16);
-			break;
-		case kCondIsNotSceneVisited:
-			result = _sceneVisited[_currSceneNum] == 0;
-			break;
-		case kCondIsSceneVisited:
-			result = _sceneVisited[_currSceneNum] != 0;
-			break;
-		case kCondUnused:
-		case kCondDialogItem0:
-		case kCondIsCameraNumTransition:
-			result = false;
-			break;
-		}
-	}
-	return result;
-}
-
-bool BbvsEngine::evalCameraCondition(Conditions &conditions, int value) {
-	bool result = true;
-	for (int i = 0; i < 8 && result; ++i) {
-		const Condition &condition = conditions.conditions[i];
-		switch (condition.cond) {
-		case kCondHasInventoryItem:
-			result =  _inventoryItemStatus[condition.value1] != 0;
-			break;
-		case kCondHasNotInventoryItem:
-			result = _inventoryItemStatus[condition.value1] == 0;
-			break;
-		case kCondIsGameVar:
-			result = _gameVars[condition.value2] != 0;
-			break;
-		case kCondIsNotGameVar:
-			result = _gameVars[condition.value2] == 0;
-			break;
-		case kCondIsPrevSceneNum:
-			result = condition.value2 == _prevSceneNum;
-			break;
-		case kCondIsNotPrevSceneNum:
-			result = condition.value2 != _prevSceneNum;
-			break;
-		case kCondIsNotSceneVisited:
-			result = _sceneVisited[_currSceneNum] == 0;
-			break;
-		case kCondIsSceneVisited:
-			result = _sceneVisited[_currSceneNum] != 0;
-			break;
-		case kCondIsCameraNumTransition:
-			result = condition.value1 == _currCameraNum &&
-				condition.value2 == value;
-			break;
-		case kCondUnused:
-		case kCondSceneObjectVerb:
-		case kCondBgObjectVerb:
-		case kCondSceneObjectInventory:
-		case kCondBgObjectInventory:
-		case kCondIsCurrTalkObject:
-		case kCondIsDialogItem:
-		case kCondIsCameraNum:
-		case kCondDialogItem0:
-		case kCondIsButtheadAtBgObject:
-			result = false;
-			break;
-		default:
-			break;
-		}
-	}
-	return result;
-}
-
-int BbvsEngine::evalDialogCondition(Conditions &conditions) {
-	int result = -1;
-	bool success = false;
-	for (int i = 0; i < 8; ++i) {
-		const Condition &condition = conditions.conditions[i];
-		switch (condition.cond) {
-		case kCondSceneObjectVerb:
-			success = _activeItemType == KITSceneObject &&
-				condition.value1 == _currVerbNum &&
-				condition.value2 == _activeItemIndex;
-			break;
-		case kCondBgObjectVerb:
-			success = _activeItemType == kITBgObject &&
-				condition.value1 == _currVerbNum &&
-				condition.value2 == _activeItemIndex;
-			break;
-		case kCondSceneObjectInventory:
-			success = _activeItemType == KITSceneObject &&
-				_currVerbNum == kVerbInvItem &&
-				condition.value1 == _currInventoryItem &&
-				condition.value2 == _activeItemIndex;
-			break;
-		case kCondBgObjectInventory:
-			success = _activeItemType == kITBgObject &&
-				_currVerbNum == kVerbInvItem &&
-				condition.value1 == _currInventoryItem &&
-				condition.value2 == _activeItemIndex;
-			break;
-		case kCondHasInventoryItem:
-			success = _inventoryItemStatus[condition.value1] != 0;
-			break;
-		case kCondHasNotInventoryItem:
-			success = _inventoryItemStatus[condition.value1] == 0;
-			break;
-		case kCondIsGameVar:
-			success = _gameVars[condition.value2] != 0;
-			break;
-		case kCondIsNotGameVar:
-			success = _gameVars[condition.value2] == 0;
-			break;
-		case kCondIsPrevSceneNum:
-			success = condition.value2 == _prevSceneNum;
-			break;
-		case kCondIsCurrTalkObject:
-			success = condition.value2 == _currTalkObjectIndex;
-			break;
-		case kCondIsDialogItem:
-			result = condition.value1;
-			break;
-		case kCondIsCameraNum:
-			success = condition.value1 == _currCameraNum;
-			break;
-		case kCondIsNotPrevSceneNum:
-			success = condition.value2 != _prevSceneNum;
-			break;
-		case kCondIsButtheadAtBgObject:
-			success = _buttheadObject &&
-				_gameModule->getBgObject(condition.value2)->rect.contains(_buttheadObject->x >> 16, _buttheadObject->y >> 16);
-			break;
-		case kCondIsNotSceneVisited:
-			success = _sceneVisited[_currSceneNum] == 0;
-			break;
-		case kCondIsSceneVisited:
-			success = _sceneVisited[_currSceneNum] != 0;
-			break;
-		case kCondDialogItem0:
-			return 0;
-		case kCondUnused:
-		case kCondIsCameraNumTransition:
-			success = false;
-			break;
-		}
-		if (!success)
-			return -1;
-	}
-	return result;
-}
-
-void BbvsEngine::evalActionResults(ActionResults &results) {
-	for (int i = 0; i < 8; ++i) {
-		const ActionResult &result = results.actionResults[i];
-		switch (result.kind) {
-		case kActResAddInventoryItem:
-			_inventoryItemStatus[result.value1] = 1;
-			_currVerbNum = kVerbInvItem;
-			_currInventoryItem = result.value1;
-			break;
-		case kActResRemoveInventoryItem:
-			_inventoryItemStatus[result.value1] = 0;
-			if (result.value1 == _currInventoryItem)
-				_currInventoryItem = -1;
-			if (_currVerbNum == kVerbInvItem)
-				_currVerbNum = kVerbLook;
-			break;
-		case kActResSetGameVar:
-			_gameVars[result.value2] = 1;
-			break;
-		case kActResUnsetGameVar:
-			_gameVars[result.value2] = 0;
-			break;
-		case kActResStartDialog:
-			_gameState = kGSDialog;
-			break;
-		case kActResChangeScene:
-			_newSceneNum = result.value2;
-			break;
-		}
-	}
-}
-
 void BbvsEngine::updateBackgroundSounds() {
 	for (int i = 0; i < _gameModule->getSceneSoundsCount(); ++i) {
 		SceneSound *sceneSound = _gameModule->getSceneSound(i);
@@ -564,198 +297,6 @@ void BbvsEngine::updateBackgroundSounds() {
 	}
 } 
 
-void BbvsEngine::loadScene(int sceneNum) {
-	debug(0, "BbvsEngine::loadScene() sceneNum: %d", sceneNum);
-	
-	Common::String sprFilename = Common::String::format("vnm/vspr%04d.vnm", sceneNum);
-	Common::String gamFilename = Common::String::format("vnm/game%04d.vnm", sceneNum);
-
-	_screen->clear();
-
-	_spriteModule->load(sprFilename.c_str());
-	_gameModule->load(gamFilename.c_str());
-	
-	Palette palette = _spriteModule->getPalette();
-	_screen->setPalette(palette);
-
-	// Preload sounds
-	for (uint i = 0; i < _gameModule->getPreloadSoundsCount(); ++i) {
-		Common::String filename = Common::String::format("snd/snd%05d.aif", _gameModule->getPreloadSound(i));
-		_sound->loadSound(filename);
-	}
-
-	if (sceneNum >= kMainMenu) {
-		DrawList drawList;
-		drawList.add(_gameModule->getBgSpriteIndex(0), 0, 0, 0);
-		_screen->drawDrawList(drawList, _spriteModule);
-		drawScreen();
-	}
-
-}
-
-void BbvsEngine::initScene(bool sounds) {
-
-	stopSpeech();
-	stopSounds();
-	_sound->unloadSounds();
-
-	_gameState = kGSScene;
-	_prevSceneNum = _currSceneNum;
-	_sceneVisited[_currSceneNum] = 1;
-	_mouseCursorSpriteIndex = 0;
-	_verbPos.x = -1;
-	_verbPos.y = -1;
-	_activeItemType = kITEmpty;
-	_activeItemIndex = 0;
-	_cameraPos.x = 0;
-	_cameraPos.y = 0;
-	_newCameraPos.x = 0;
-	_newCameraPos.y = 0;
-	_inventoryButtonIndex = -1;
-	_currTalkObjectIndex = -1;
-	_currCameraNum = 0;
-	_walkMousePos.x = -1;
-	_walkMousePos.y = -1;
-	_currAction = 0;
-	_currActionCommandIndex = -1;
-	_currActionCommandTimeStamp = 0;
-	_dialogSlotCount = 0;
-	_buttheadObject = 0;
-	_beavisObject = 0;
-
-	memset(_backgroundSoundsActive, 0, sizeof(_backgroundSoundsActive));
-
-	memset(_sceneObjects, 0, sizeof(_sceneObjects));
-	for (int i = 0; i < kSceneObjectsCount; ++i) {
-		_sceneObjects[i].walkDestPt.x = -1;
-		_sceneObjects[i].walkDestPt.y = -1;
-	}
-
-	memset(_dialogItemStatus, 0, sizeof(_dialogItemStatus));
-
-	_sceneObjectActions.clear();
-
-	loadScene(_newSceneNum);
-	_currSceneNum = _newSceneNum;
-	_newSceneNum = 0;
-	
-	for (int i = 0; i < _gameModule->getSceneObjectDefsCount(); ++i)
-		_sceneObjects[i].sceneObjectDef = _gameModule->getSceneObjectDef(i);
-		
-	for (int i = 0; i < _gameModule->getSceneObjectInitsCount(); ++i) {
-		SceneObjectInit *soInit = _gameModule->getSceneObjectInit(i);
-		if (evalCondition(soInit->conditions)) {
-			SceneObject *sceneObject = &_sceneObjects[soInit->sceneObjectIndex];
-			sceneObject->anim = _gameModule->getAnimation(soInit->animIndex);
-			sceneObject->animIndex = soInit->animIndex;
-			sceneObject->frameIndex = sceneObject->anim->frameCount - 1;
-			sceneObject->frameTicks = 1;
-			sceneObject->x = soInit->x << 16;
-			sceneObject->y = soInit->y << 16;
-		}
-	}
-
-	if (_gameModule->getButtheadObjectIndex() >= 0) {
-		_buttheadObject = &_sceneObjects[_gameModule->getButtheadObjectIndex()];
-		// Search for the Beavis object
-		for (int i = 0; i < _gameModule->getSceneObjectDefsCount(); ++i)
-			if (!strcmp(_sceneObjects[i].sceneObjectDef->name, "Beavis")) {
-				_beavisObject = &_sceneObjects[i];
-				break;
-			}
-	}
-
-	updateSceneObjectsTurnValue();
-
-	updateWalkableRects();
-
-	_currCameraNum = 0;
-	if (_buttheadObject) {
-		int minDistance = 0xFFFFFF;
-		for (int cameraNum = 0; cameraNum < 4; ++cameraNum) {
-			CameraInit *cameraInit = _gameModule->getCameraInit(cameraNum);
-			int curDistance = ABS(cameraInit->cameraPos.x - (int)(_buttheadObject->x >> 16) + 160);
-			if (curDistance < minDistance) {
-				minDistance = curDistance;
-				_currCameraNum = cameraNum;
-			}
-		}
-	}
-	
-	_cameraPos = _gameModule->getCameraInit(_currCameraNum)->cameraPos;
-	_newCameraPos = _cameraPos;
-	
-	_walkAreaActions.clear();
-	for (int i = 0; i < _gameModule->getActionsCount(); ++i) {
-		Action *action = _gameModule->getAction(i);
-		for (int j = 0; j < 8; ++j)
-			if (action->conditions.conditions[j].cond == kCondIsButtheadAtBgObject)
-				_walkAreaActions.push_back(action);
-	}
-
-	_mouseCursorSpriteIndex = 0;
-
-	_activeItemIndex = 0;
-	_activeItemType = kITEmpty;
-	
-	for (int i = 0; i < _gameModule->getActionsCount(); ++i) {
-		Action *action = _gameModule->getAction(i);
-		if (evalCondition(action->conditions)) {
-			_gameState = kGSWait;
-			_currAction = action;
-			for (uint j = 0; j < action->actionCommands.size(); ++j) {
-				ActionCommand *actionCommand = &action->actionCommands[j];
-				if (actionCommand->cmd == kActionCmdSetCameraPos) {
-					_currCameraNum = actionCommand->param;
-					_cameraPos = _gameModule->getCameraInit(_currCameraNum)->cameraPos;
-					_newCameraPos = _cameraPos;
-					break;
-				}
-			}
-			break;
-		}
-	}
-	
-	if (sounds)
-		updateBackgroundSounds();
-
-}
-
-bool BbvsEngine::changeScene() {
-
-	writeContinueSavegame();
-	
-	if (_newSceneNum >= 27 && _newSceneNum <= 30) {
-		// Run minigames
-		stopSpeech();
-		stopSounds();
-		_sceneVisited[_currSceneNum] = 1;
-		if (runMinigame(_newSceneNum - 27)) {
-			SWAP(_currSceneNum, _newSceneNum);
-		}
-	} else if (_newSceneNum >= 31 && _newSceneNum <= 43) {
-		// Play video
-		stopSpeech();
-		stopSounds();
-		_sceneVisited[_currSceneNum] = 1;
-		_playVideoNumber = _newSceneNum - 30;
-		_currSceneNum = _newSceneNum;
-		_newSceneNum = kAfterVideoSceneNum[_playVideoNumber];
-	} else if (_newSceneNum >= 100 && _currSceneNum == kCredits) {
-		// Play secret video
-		stopSounds();
-		_playVideoNumber = _newSceneNum;
-		_currSceneNum = 49;
-		_newSceneNum = kCredits;
-	} else {
-		// Normal scene
-		initScene(true);
-	}
-
-	return true;
-	
-}
-
 bool BbvsEngine::update(int mouseX, int mouseY, uint mouseButtons, Common::KeyCode keyCode) {
 
 	if (_bootSaveSlot >= 0) {
@@ -1676,426 +1217,6 @@ void BbvsEngine::updateCommon() {
 
 }
 
-void BbvsEngine::startWalkObject(SceneObject *sceneObject) {
-	const int kMaxDistance = 0xFFFFFF;
-
-	if (_buttheadObject != sceneObject && _beavisObject != sceneObject)
-		return;
-	
-	initWalkAreas(sceneObject);
-	_sourceWalkAreaPt.x = sceneObject->x >> 16;
-	_sourceWalkAreaPt.y = sceneObject->y >> 16;
-
-	_sourceWalkArea = getWalkAreaAtPos(_sourceWalkAreaPt);
-	if (!_sourceWalkArea)
-		return;
-
-	_destWalkAreaPt = sceneObject->walkDestPt;
-
-	_destWalkArea = getWalkAreaAtPos(_destWalkAreaPt);
-	if (!_destWalkArea)
-		return;
-		
-	if (_sourceWalkArea != _destWalkArea) {
-		_currWalkDistance = kMaxDistance;
-		walkFindPath(_sourceWalkArea, 0);
-		_destWalkAreaPt = _currWalkDistance == kMaxDistance ? _sourceWalkAreaPt : _finalWalkPt;
-	}
-
-	walkObject(sceneObject, _destWalkAreaPt, sceneObject->sceneObjectDef->walkSpeed);
-	
-}
-
-void BbvsEngine::updateWalkObject(SceneObject *sceneObject) {
-	int animIndex;
-	
-	if (sceneObject->walkCount > 0 && (sceneObject->xIncr != 0 || sceneObject->yIncr != 0)) {
-		if (ABS(sceneObject->xIncr) <= ABS(sceneObject->yIncr))
-			sceneObject->turnValue = sceneObject->yIncr >= 0 ? 0 : 4;
-		else
-			sceneObject->turnValue = sceneObject->xIncr >= 0 ? 6 : 2;
-		animIndex = sceneObject->sceneObjectDef->animIndices[kWalkAnimTbl[sceneObject->turnValue]];
-		sceneObject->turnCount = 0;
-		sceneObject->turnTicks = 0;
-	} else {
-		animIndex = sceneObject->sceneObjectDef->animIndices[kWalkTurnTbl[sceneObject->turnValue]];
-	}
-
-	Animation *anim = 0;
-	if (animIndex > 0)
-		anim = _gameModule->getAnimation(animIndex);
-	
-	if (sceneObject->anim != anim) {
-		if (anim) {
-			sceneObject->anim = anim;
-			sceneObject->animIndex = animIndex;
-			sceneObject->frameTicks = 1;
-			sceneObject->frameIndex = anim->frameCount - 1;
-		} else {
-			sceneObject->anim = 0;
-			sceneObject->animIndex = 0;
-			sceneObject->frameTicks = 0;
-			sceneObject->frameIndex = 0;
-		}
-	}
-
-}
-
-void BbvsEngine::walkObject(SceneObject *sceneObject, const Common::Point &destPt, int walkSpeed) {
-	int deltaX = destPt.x - (sceneObject->x >> 16);
-	int deltaY = destPt.y - (sceneObject->y >> 16);
-	float distance = sqrt((double)(deltaX * deltaX + deltaY * deltaY));
-	// NOTE The original doesn't have this check but without it the whole pathfinding breaks
-	if (distance > 0.0) {
-		sceneObject->walkCount = distance / ((((float)ABS(deltaX) / distance) + 1.0) * ((float)walkSpeed / 120));
-		sceneObject->xIncr = ((float)deltaX / sceneObject->walkCount) * 65536.0;
-		sceneObject->yIncr = ((float)deltaY / sceneObject->walkCount) * 65536.0;
-		sceneObject->x = (sceneObject->x & 0xFFFF0000) | 0x8000;
-		sceneObject->y = (sceneObject->y & 0xFFFF0000) | 0x8000;
-	} else
-		sceneObject->walkCount = 0;
-}
-
-void BbvsEngine::turnObject(SceneObject *sceneObject) {
-	if (sceneObject->turnTicks > 0) {
-		--sceneObject->turnTicks;
-	} else {
-		int turnDir = kTurnInfo[sceneObject->turnValue][sceneObject->turnCount & 0x7F];
-		if (turnDir) {
-			sceneObject->turnValue = (sceneObject->turnValue + turnDir) & 7;
-			int turnAnimIndex = sceneObject->sceneObjectDef->animIndices[kWalkTurnTbl[sceneObject->turnValue]];
-			if (turnAnimIndex) {
-				Animation *anim = _gameModule->getAnimation(turnAnimIndex);
-				if (anim) {
-					sceneObject->anim = anim;
-					sceneObject->animIndex = turnAnimIndex;
-					sceneObject->turnTicks = 4;
-					sceneObject->frameTicks = 1;
-					sceneObject->frameIndex = anim->frameCount - 1;
-				}
-			}
-		} else {
-			sceneObject->turnCount = 0;
-		}
-	}
-}
-
-int BbvsEngine::rectSubtract(const Common::Rect &rect1, const Common::Rect &rect2, Common::Rect *outRects) {
-	int count = 0;
-	Common::Rect workRect = rect1.findIntersectingRect(rect2);
-	if (!workRect.isEmpty()) {
-		count = 0;
-		outRects[count] = Common::Rect(rect2.width(), workRect.top - rect2.top);
-		if (!outRects[count].isEmpty()) {
-			outRects[count].translate(rect2.left, rect2.top);
-			++count;
-		}
-		outRects[count] = Common::Rect(workRect.left - rect2.left, workRect.height());
-		if (!outRects[count].isEmpty()) {
-			outRects[count].translate(rect2.left, workRect.top);
-			++count;
-		}
-		outRects[count] = Common::Rect(rect2.right - workRect.right, workRect.height());
-		if (!outRects[count].isEmpty()) {
-			outRects[count].translate(workRect.right, workRect.top);
-			++count;
-		}
-		outRects[count] = Common::Rect(rect2.width(), rect2.bottom - workRect.bottom);
-		if (!outRects[count].isEmpty()) {
-			outRects[count].translate(rect2.left, workRect.bottom);
-			++count;
-		}
-	} else {
-		outRects[0] = rect2;
-		count = 1;
-	}
-	return count;
-}
-
-WalkInfo *BbvsEngine::addWalkInfo(int16 x, int16 y, int delta, int direction, int16 midPtX, int16 midPtY, int walkAreaIndex) {
-	WalkInfo *walkInfo = &_walkInfos[_walkInfosCount++];
-	walkInfo->walkAreaIndex = walkAreaIndex;
-	walkInfo->direction = direction;
-	walkInfo->x = x;
-	walkInfo->y = y;
-	walkInfo->delta = delta;
-	walkInfo->midPt.x = midPtX;
-	walkInfo->midPt.y = midPtY;
-	return walkInfo;
-}
-
-void BbvsEngine::initWalkAreas(SceneObject *sceneObject) {
-	int16 objX = sceneObject->x >> 16;
-	int16 objY = sceneObject->y >> 16;
-	Common::Rect rect;
-	bool doRect = false;
-	Common::Rect *workWalkableRects;
-
-	if (_buttheadObject == sceneObject && _beavisObject->anim) {
-		rect = _beavisObject->anim->frameRects2[_beavisObject->frameIndex];
-		rect.translate(_beavisObject->x >> 16, 1 + (_beavisObject->y >> 16));
-		doRect = !rect.isEmpty();
-	} else if (_buttheadObject->anim) {
-		rect = _buttheadObject->anim->frameRects2[_buttheadObject->frameIndex];
-		rect.translate(_buttheadObject->x >> 16, 1 + (_buttheadObject->y >> 16));
-		doRect = !rect.isEmpty();
-	}
-
-	workWalkableRects = _walkableRects;
-
-	_walkAreasCount = _walkableRectsCount;
-
-	if (doRect && !rect.contains(objX, objY)) {
-		_walkAreasCount = 0;
-		for (int i = 0; i < _walkableRectsCount; ++i)
-			_walkAreasCount += rectSubtract(rect, _walkableRects[i], &_tempWalkableRects1[_walkAreasCount]);
-		workWalkableRects = _tempWalkableRects1;
-	}
-
-	for (int i = 0; i < _walkAreasCount; ++i) {
-		_walkAreas[i].x = workWalkableRects[i].left;
-		_walkAreas[i].y = workWalkableRects[i].top;
-		_walkAreas[i].width = workWalkableRects[i].width();
-		_walkAreas[i].height = workWalkableRects[i].height();
-		_walkAreas[i].checked = false;
-		_walkAreas[i].linksCount = 0;
-	}
-
-	_walkInfosCount = 0;
-
-	// Find connections between the walkRects
-
-	for (int i = 0; i < _walkAreasCount; ++i) {
-		WalkArea *walkArea1 = &_walkAreas[i];
-		int xIter = walkArea1->x + walkArea1->width;
-		int yIter = walkArea1->y + walkArea1->height;
-
-		for (int j = 0; j < _walkAreasCount; ++j) {
-			WalkArea *walkArea2 = &_walkAreas[j];
-
-			if (i == j)
-				continue;
-
-			if (walkArea2->y == yIter) {
-				int wa1x = MAX(walkArea1->x, walkArea2->x);
-				int wa2x = MIN(walkArea2->x + walkArea2->width, xIter);
-				if (wa2x > wa1x) {
-					debug(5, "WalkArea %d connected to %d by Y", i, j);
-					WalkInfo *walkInfo1 = addWalkInfo(wa1x, yIter - 1, wa2x - wa1x, 0, wa1x + (wa2x - wa1x) / 2, yIter - 1, i);
-					WalkInfo *walkInfo2 = addWalkInfo(wa1x, yIter, wa2x - wa1x, 0, wa1x + (wa2x - wa1x) / 2, yIter, j);
-					walkArea1->linksD1[walkArea1->linksCount] = walkInfo1;
-					walkArea1->linksD2[walkArea1->linksCount] = walkInfo2;
-					walkArea1->links[walkArea1->linksCount++] = walkArea2;
-					walkArea2->linksD1[walkArea2->linksCount] = walkInfo2;
-					walkArea2->linksD2[walkArea2->linksCount] = walkInfo1;
-					walkArea2->links[walkArea2->linksCount++] = walkArea1;
-				}
-			}
-
-			if (walkArea2->x == xIter) {
-				int wa1y = MAX(walkArea1->y, walkArea2->y);
-				int wa2y = MIN(walkArea2->y + walkArea2->height, yIter);
-				if (wa2y > wa1y) {
-					debug(5, "WalkArea %d connected to %d by X", i, j);
-					WalkInfo *walkInfo1 = addWalkInfo(xIter - 1, wa1y, wa2y - wa1y, 1, xIter - 1, wa1y + (wa2y - wa1y) / 2, i);
-					WalkInfo *walkInfo2 = addWalkInfo(xIter, wa1y, wa2y - wa1y, 1, xIter, wa1y + (wa2y - wa1y) / 2, j);
-					walkArea1->linksD1[walkArea1->linksCount] = walkInfo1;
-					walkArea1->linksD2[walkArea1->linksCount] = walkInfo2;
-					walkArea1->links[walkArea1->linksCount++] = walkArea2;
-					walkArea2->linksD1[walkArea2->linksCount] = walkInfo2;
-					walkArea2->linksD2[walkArea2->linksCount] = walkInfo1;
-					walkArea2->links[walkArea2->linksCount++] = walkArea1;
-				}
-			}
-
-		}
-
-	}
-
-}
-
-WalkArea *BbvsEngine::getWalkAreaAtPos(const Common::Point &pt) {
-	for (int i = 0; i < _walkAreasCount; ++i) {
-		WalkArea *walkArea = &_walkAreas[i];
-		if (walkArea->contains(pt))
-			return walkArea;
-	}
-	return 0;
-}
-
-bool BbvsEngine::canButtheadWalkToDest(const Common::Point &destPt) {
-	Common::Point srcPt;
-
-	_walkReachedDestArea = false;
-	initWalkAreas(_buttheadObject);
-	srcPt.x = _buttheadObject->x >> 16;
-	srcPt.y = _buttheadObject->y >> 16;
-	_sourceWalkArea = getWalkAreaAtPos(srcPt);
-	if (_sourceWalkArea) {
-		_destWalkArea = getWalkAreaAtPos(destPt);
-		if (_destWalkArea)
-			canWalkToDest(_sourceWalkArea, 0);
-	}
-	return _walkReachedDestArea;
-}
-
-void BbvsEngine::canWalkToDest(WalkArea *walkArea, int infoCount) {
-	
-	if (_destWalkArea == walkArea) {
-		_walkReachedDestArea = true;
-		return;
-	}
-	
-	if (_gameModule->getFieldC() <= 320 || infoCount <= 20) {
-		walkArea->checked = true;
-		for (int linkIndex = 0; linkIndex < walkArea->linksCount; ++linkIndex) {
-			if (!walkArea->links[linkIndex]->checked) {
-				canWalkToDest(walkArea->links[linkIndex], infoCount + 2);
-				if (_walkReachedDestArea)
-					break;
-			}
-		}
-		walkArea->checked = false;
-	}
-
-}
-
-bool BbvsEngine::walkTestLineWalkable(const Common::Point &sourcePt, const Common::Point &destPt, WalkInfo *walkInfo) {
-	const float ptDeltaX = destPt.x - sourcePt.x;
-	const float ptDeltaY = destPt.y - sourcePt.y;
-	const float wDeltaX = walkInfo->x - sourcePt.x;
-	const float wDeltaY = walkInfo->y - sourcePt.y;
-	if (destPt.x == sourcePt.x)
-		return true;
-	if (walkInfo->direction) {
-		const float nDeltaY = wDeltaX * ptDeltaY / ptDeltaX + (float)sourcePt.y - (float)walkInfo->y;
-		return (nDeltaY >= 0.0) && (nDeltaY < (float)walkInfo->delta);
-	} else {
-		const float nDeltaX = wDeltaY / ptDeltaX * ptDeltaY + (float)sourcePt.x - (float)walkInfo->x;
-		return (nDeltaX >= 0.0) && (nDeltaX < (float)walkInfo->delta);
-	}
-	return false;
-}
-
-void BbvsEngine::walkFindPath(WalkArea *sourceWalkArea, int infoCount) {
-	if (_destWalkArea == sourceWalkArea) {
-		walkFoundPath(infoCount);
-	} else if (_gameModule->getFieldC() <= 320 || infoCount <= 20) {
-		sourceWalkArea->checked = true;
-		for (int linkIndex = 0; linkIndex < sourceWalkArea->linksCount; ++linkIndex) {
-			if (!sourceWalkArea->links[linkIndex]->checked) {
-				_walkInfoPtrs[infoCount + 0] = sourceWalkArea->linksD1[linkIndex];
-				_walkInfoPtrs[infoCount + 1] = sourceWalkArea->linksD2[linkIndex];
-				walkFindPath(sourceWalkArea->links[linkIndex], infoCount + 2);
-			}
-		}
-		sourceWalkArea->checked = false;
-	}
-}
-
-int BbvsEngine::calcDistance(const Common::Point &pt1, const Common::Point &pt2) {
-	return (int)sqrt((double)(pt1.x - pt2.x) * (pt1.x - pt2.x) + (pt1.y - pt2.y) * (pt1.y - pt2.y));
-}
-
-void BbvsEngine::walkFoundPath(int count) {
-	debug(5, "BbvsEngine::walkFoundPath(%d)", count);
-	
-	Common::Point midPt = _sourceWalkAreaPt;
-	int totalMidPtDistance = 0;
-	
-	if (count > 0) {
-		Common::Point lastMidPt;
-		int halfCount = (count + 1) >> 1;
-		for (int i = 0; i < halfCount; ++i) {
-			lastMidPt = midPt;
-			midPt = _walkInfoPtrs[i * 2]->midPt;
-			totalMidPtDistance += calcDistance(midPt, lastMidPt);
-		}
-	}
-
-	int distance = calcDistance(midPt, _destWalkAreaPt) + totalMidPtDistance;
-
-	debug(5, "BbvsEngine::walkFoundPath() distance: %d; _currWalkDistance: %d", distance, _currWalkDistance);
-
-	if (distance >= _currWalkDistance)
-		return;
-		
-	debug(5, "BbvsEngine::walkFoundPath() distance smaller");
-
-	_currWalkDistance = distance;
-
-	Common::Point destPt = _destWalkAreaPt, newDestPt;
-	
-	while (1) {
-
-		int index = 0;
-		if (count > 0) {
-			do {
-				if (!walkTestLineWalkable(_sourceWalkAreaPt, destPt, _walkInfoPtrs[index]))
-					break;
-				++index;
-			} while (index < count);
-		}
-
-		if (index == count)
-			break;
-
-		WalkInfo *walkInfo = _walkInfoPtrs[--count];
-		destPt.x = walkInfo->x;
-		destPt.y = walkInfo->y;
-		
-		if (walkInfo->direction) {
-			newDestPt.x = walkInfo->x;
-			newDestPt.y = walkInfo->y + walkInfo->delta - 1;
-		} else {
-			newDestPt.x = walkInfo->x + walkInfo->delta - 1;
-			newDestPt.y = walkInfo->y;
-		}
-
-		if ((newDestPt.x - _destWalkAreaPt.x) * (newDestPt.x - _destWalkAreaPt.x) +
-			(newDestPt.y - _destWalkAreaPt.y) * (newDestPt.y - _destWalkAreaPt.y) <
-			(destPt.x - _destWalkAreaPt.x) * (destPt.x - _destWalkAreaPt.x) +
-			(destPt.y - _destWalkAreaPt.y) * (destPt.y - _destWalkAreaPt.y))
-			destPt = newDestPt;
-
-	}
-
-	debug(5, "BbvsEngine::walkFoundPath() destPt: (%d, %d)", destPt.x, destPt.y);
-
-	_finalWalkPt = destPt;
-
-	debug(5, "BbvsEngine::walkFoundPath() OK");
-
-}
-
-void BbvsEngine::updateWalkableRects() {
-	// Go through all walkable rects and subtract all scene object rects
-	Common::Rect *rectsList1 = _tempWalkableRects1;
-	Common::Rect *rectsList2 = _gameModule->getWalkRects();
-	_walkableRectsCount = _gameModule->getWalkRectsCount();
-	for (int i = 0; i < _gameModule->getSceneObjectDefsCount(); ++i) {
-		SceneObject *sceneObject = &_sceneObjects[i];
-		Animation *anim = sceneObject->anim;
-		if (anim && _buttheadObject != sceneObject && _beavisObject != sceneObject) {
-			Common::Rect rect = sceneObject->anim->frameRects2[sceneObject->frameIndex];
-			rect.translate(sceneObject->x >> 16, sceneObject->y >> 16);
-			int count = _walkableRectsCount;
-			_walkableRectsCount = 0;
-			for (int j = 0; j < count; ++j)
-				_walkableRectsCount += rectSubtract(rect, rectsList2[j], &rectsList1[_walkableRectsCount]);
-			if (rectsList1 == _tempWalkableRects1) {
-				rectsList1 = _tempWalkableRects2;
-				rectsList2 = _tempWalkableRects1;
-			} else {
-				rectsList1 = _tempWalkableRects1;
-				rectsList2 = _tempWalkableRects2;
-			}
-		}
-	}
-	for (int i = 0; i < _walkableRectsCount; ++i)
-		_walkableRects[i] = rectsList2[i];
-}
-
 void BbvsEngine::updateSceneObjectsTurnValue() {
 	for (int i = 0; i < _gameModule->getSceneObjectDefsCount(); ++i) {
 		SceneObject *sceneObject = &_sceneObjects[i];
diff --git a/engines/bbvs/bbvs.h b/engines/bbvs/bbvs.h
index b429c31..8136184 100644
--- a/engines/bbvs/bbvs.h
+++ b/engines/bbvs/bbvs.h
@@ -206,6 +206,13 @@ const int kDialogItemStatusCount = 50;
 const int kGameVarsCount = 2000;
 const int kSceneVisitedCount = 64;
 
+const int kMainMenu = 44;
+const int kCredits  = 45;
+
+static const int8 kWalkTurnTbl[] = {
+	7, 9, 4, 8, 6, 10, 5, 11
+};
+
 class BbvsEngine : public Engine {
 protected:
 	Common::Error run();
diff --git a/engines/bbvs/logic.cpp b/engines/bbvs/logic.cpp
new file mode 100644
index 0000000..06792e2
--- /dev/null
+++ b/engines/bbvs/logic.cpp
@@ -0,0 +1,265 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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.
+ *
+ */
+
+#include "bbvs/bbvs.h"
+#include "bbvs/gamemodule.h"
+
+namespace Bbvs {
+
+bool BbvsEngine::evalCondition(Conditions &conditions) {
+	bool result = true;
+	for (int i = 0; i < 8 && result; ++i) {
+		const Condition &condition = conditions.conditions[i];
+		switch (condition.cond) {
+		case kCondSceneObjectVerb:
+			result = _activeItemType == KITSceneObject &&
+				condition.value1 == _currVerbNum &&
+				condition.value2 == _activeItemIndex;
+			break;
+		case kCondBgObjectVerb:
+			result = _activeItemType == kITBgObject &&
+				condition.value1 == _currVerbNum &&
+				condition.value2 == _activeItemIndex;
+			break;
+		case kCondSceneObjectInventory:
+			result = _activeItemType == KITSceneObject &&
+				_currVerbNum == kVerbInvItem &&
+				condition.value1 == _currInventoryItem &&
+				condition.value2 == _activeItemIndex;
+			break;
+		case kCondBgObjectInventory:
+			result = _activeItemType == kITBgObject &&
+				_currVerbNum == kVerbInvItem &&
+				condition.value1 == _currInventoryItem &&
+				condition.value2 == _activeItemIndex;
+			break;
+		case kCondHasInventoryItem:
+			result = _inventoryItemStatus[condition.value1] != 0;
+			break;
+		case kCondHasNotInventoryItem:
+			result = _inventoryItemStatus[condition.value1] == 0;
+			break;
+		case kCondIsGameVar:
+			result = _gameVars[condition.value2] != 0;
+			break;
+		case kCondIsNotGameVar:
+			result = _gameVars[condition.value2] == 0;
+			break;
+		case kCondIsPrevSceneNum:
+			result = condition.value2 == _prevSceneNum;
+			break;
+		case kCondIsCurrTalkObject:
+			result = condition.value2 == _currTalkObjectIndex;
+			break;
+		case kCondIsDialogItem:
+			result = _activeItemType == kITDialog &&
+				condition.value1 == _activeItemIndex;
+			break;
+		case kCondIsCameraNum:
+			result = condition.value1 == _currCameraNum;
+			break;
+		case kCondIsNotPrevSceneNum:
+			result = condition.value2 != _prevSceneNum;
+			break;
+		case kCondIsButtheadAtBgObject:
+			result = _buttheadObject &&
+				_gameModule->getBgObject(condition.value2)->rect.contains(_buttheadObject->x >> 16, _buttheadObject->y >> 16);
+			break;
+		case kCondIsNotSceneVisited:
+			result = _sceneVisited[_currSceneNum] == 0;
+			break;
+		case kCondIsSceneVisited:
+			result = _sceneVisited[_currSceneNum] != 0;
+			break;
+		case kCondUnused:
+		case kCondDialogItem0:
+		case kCondIsCameraNumTransition:
+			result = false;
+			break;
+		}
+	}
+	return result;
+}
+
+bool BbvsEngine::evalCameraCondition(Conditions &conditions, int value) {
+	bool result = true;
+	for (int i = 0; i < 8 && result; ++i) {
+		const Condition &condition = conditions.conditions[i];
+		switch (condition.cond) {
+		case kCondHasInventoryItem:
+			result =  _inventoryItemStatus[condition.value1] != 0;
+			break;
+		case kCondHasNotInventoryItem:
+			result = _inventoryItemStatus[condition.value1] == 0;
+			break;
+		case kCondIsGameVar:
+			result = _gameVars[condition.value2] != 0;
+			break;
+		case kCondIsNotGameVar:
+			result = _gameVars[condition.value2] == 0;
+			break;
+		case kCondIsPrevSceneNum:
+			result = condition.value2 == _prevSceneNum;
+			break;
+		case kCondIsNotPrevSceneNum:
+			result = condition.value2 != _prevSceneNum;
+			break;
+		case kCondIsNotSceneVisited:
+			result = _sceneVisited[_currSceneNum] == 0;
+			break;
+		case kCondIsSceneVisited:
+			result = _sceneVisited[_currSceneNum] != 0;
+			break;
+		case kCondIsCameraNumTransition:
+			result = condition.value1 == _currCameraNum &&
+				condition.value2 == value;
+			break;
+		case kCondUnused:
+		case kCondSceneObjectVerb:
+		case kCondBgObjectVerb:
+		case kCondSceneObjectInventory:
+		case kCondBgObjectInventory:
+		case kCondIsCurrTalkObject:
+		case kCondIsDialogItem:
+		case kCondIsCameraNum:
+		case kCondDialogItem0:
+		case kCondIsButtheadAtBgObject:
+			result = false;
+			break;
+		default:
+			break;
+		}
+	}
+	return result;
+}
+
+int BbvsEngine::evalDialogCondition(Conditions &conditions) {
+	int result = -1;
+	bool success = false;
+	for (int i = 0; i < 8; ++i) {
+		const Condition &condition = conditions.conditions[i];
+		switch (condition.cond) {
+		case kCondSceneObjectVerb:
+			success = _activeItemType == KITSceneObject &&
+				condition.value1 == _currVerbNum &&
+				condition.value2 == _activeItemIndex;
+			break;
+		case kCondBgObjectVerb:
+			success = _activeItemType == kITBgObject &&
+				condition.value1 == _currVerbNum &&
+				condition.value2 == _activeItemIndex;
+			break;
+		case kCondSceneObjectInventory:
+			success = _activeItemType == KITSceneObject &&
+				_currVerbNum == kVerbInvItem &&
+				condition.value1 == _currInventoryItem &&
+				condition.value2 == _activeItemIndex;
+			break;
+		case kCondBgObjectInventory:
+			success = _activeItemType == kITBgObject &&
+				_currVerbNum == kVerbInvItem &&
+				condition.value1 == _currInventoryItem &&
+				condition.value2 == _activeItemIndex;
+			break;
+		case kCondHasInventoryItem:
+			success = _inventoryItemStatus[condition.value1] != 0;
+			break;
+		case kCondHasNotInventoryItem:
+			success = _inventoryItemStatus[condition.value1] == 0;
+			break;
+		case kCondIsGameVar:
+			success = _gameVars[condition.value2] != 0;
+			break;
+		case kCondIsNotGameVar:
+			success = _gameVars[condition.value2] == 0;
+			break;
+		case kCondIsPrevSceneNum:
+			success = condition.value2 == _prevSceneNum;
+			break;
+		case kCondIsCurrTalkObject:
+			success = condition.value2 == _currTalkObjectIndex;
+			break;
+		case kCondIsDialogItem:
+			result = condition.value1;
+			break;
+		case kCondIsCameraNum:
+			success = condition.value1 == _currCameraNum;
+			break;
+		case kCondIsNotPrevSceneNum:
+			success = condition.value2 != _prevSceneNum;
+			break;
+		case kCondIsButtheadAtBgObject:
+			success = _buttheadObject &&
+				_gameModule->getBgObject(condition.value2)->rect.contains(_buttheadObject->x >> 16, _buttheadObject->y >> 16);
+			break;
+		case kCondIsNotSceneVisited:
+			success = _sceneVisited[_currSceneNum] == 0;
+			break;
+		case kCondIsSceneVisited:
+			success = _sceneVisited[_currSceneNum] != 0;
+			break;
+		case kCondDialogItem0:
+			return 0;
+		case kCondUnused:
+		case kCondIsCameraNumTransition:
+			success = false;
+			break;
+		}
+		if (!success)
+			return -1;
+	}
+	return result;
+}
+
+void BbvsEngine::evalActionResults(ActionResults &results) {
+	for (int i = 0; i < 8; ++i) {
+		const ActionResult &result = results.actionResults[i];
+		switch (result.kind) {
+		case kActResAddInventoryItem:
+			_inventoryItemStatus[result.value1] = 1;
+			_currVerbNum = kVerbInvItem;
+			_currInventoryItem = result.value1;
+			break;
+		case kActResRemoveInventoryItem:
+			_inventoryItemStatus[result.value1] = 0;
+			if (result.value1 == _currInventoryItem)
+				_currInventoryItem = -1;
+			if (_currVerbNum == kVerbInvItem)
+				_currVerbNum = kVerbLook;
+			break;
+		case kActResSetGameVar:
+			_gameVars[result.value2] = 1;
+			break;
+		case kActResUnsetGameVar:
+			_gameVars[result.value2] = 0;
+			break;
+		case kActResStartDialog:
+			_gameState = kGSDialog;
+			break;
+		case kActResChangeScene:
+			_newSceneNum = result.value2;
+			break;
+		}
+	}
+}
+
+} // End of namespace Bbvs
diff --git a/engines/bbvs/module.mk b/engines/bbvs/module.mk
index eb6dc86..90c62d0 100644
--- a/engines/bbvs/module.mk
+++ b/engines/bbvs/module.mk
@@ -6,10 +6,13 @@ MODULE_OBJS := \
 	dialogs.o \
 	gamemodule.o \
 	graphics.o \
+	logic.o \
 	saveload.o \
+	scene.o \
 	sound.o \
 	spritemodule.o \
 	videoplayer.o \
+	walk.o \
 	minigames/bbairguitar.o \
 	minigames/bbairguitar_anims.o \
 	minigames/bbant.o \
diff --git a/engines/bbvs/scene.cpp b/engines/bbvs/scene.cpp
new file mode 100644
index 0000000..0d86eb4
--- /dev/null
+++ b/engines/bbvs/scene.cpp
@@ -0,0 +1,227 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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.
+ *
+ */
+
+#include "bbvs/bbvs.h"
+#include "bbvs/gamemodule.h"
+#include "bbvs/graphics.h"
+#include "bbvs/sound.h"
+
+namespace Bbvs {
+
+static const int kAfterVideoSceneNum[] = {
+	 0, 43, 23, 12,  4, 44,  2,
+	16,  4,  4,  4, 44, 12, 44
+};
+
+void BbvsEngine::loadScene(int sceneNum) {
+	debug(0, "BbvsEngine::loadScene() sceneNum: %d", sceneNum);
+	
+	Common::String sprFilename = Common::String::format("vnm/vspr%04d.vnm", sceneNum);
+	Common::String gamFilename = Common::String::format("vnm/game%04d.vnm", sceneNum);
+
+	_screen->clear();
+
+	_spriteModule->load(sprFilename.c_str());
+	_gameModule->load(gamFilename.c_str());
+	
+	Palette palette = _spriteModule->getPalette();
+	_screen->setPalette(palette);
+
+	// Preload sounds
+	for (uint i = 0; i < _gameModule->getPreloadSoundsCount(); ++i) {
+		Common::String filename = Common::String::format("snd/snd%05d.aif", _gameModule->getPreloadSound(i));
+		_sound->loadSound(filename);
+	}
+
+	if (sceneNum >= kMainMenu) {
+		DrawList drawList;
+		drawList.add(_gameModule->getBgSpriteIndex(0), 0, 0, 0);
+		_screen->drawDrawList(drawList, _spriteModule);
+		drawScreen();
+	}
+
+}
+
+void BbvsEngine::initScene(bool sounds) {
+
+	stopSpeech();
+	stopSounds();
+	_sound->unloadSounds();
+
+	_gameState = kGSScene;
+	_prevSceneNum = _currSceneNum;
+	_sceneVisited[_currSceneNum] = 1;
+	_mouseCursorSpriteIndex = 0;
+	_verbPos.x = -1;
+	_verbPos.y = -1;
+	_activeItemType = kITEmpty;
+	_activeItemIndex = 0;
+	_cameraPos.x = 0;
+	_cameraPos.y = 0;
+	_newCameraPos.x = 0;
+	_newCameraPos.y = 0;
+	_inventoryButtonIndex = -1;
+	_currTalkObjectIndex = -1;
+	_currCameraNum = 0;
+	_walkMousePos.x = -1;
+	_walkMousePos.y = -1;
+	_currAction = 0;
+	_currActionCommandIndex = -1;
+	_currActionCommandTimeStamp = 0;
+	_dialogSlotCount = 0;
+	_buttheadObject = 0;
+	_beavisObject = 0;
+
+	memset(_backgroundSoundsActive, 0, sizeof(_backgroundSoundsActive));
+
+	memset(_sceneObjects, 0, sizeof(_sceneObjects));
+	for (int i = 0; i < kSceneObjectsCount; ++i) {
+		_sceneObjects[i].walkDestPt.x = -1;
+		_sceneObjects[i].walkDestPt.y = -1;
+	}
+
+	memset(_dialogItemStatus, 0, sizeof(_dialogItemStatus));
+
+	_sceneObjectActions.clear();
+
+	loadScene(_newSceneNum);
+	_currSceneNum = _newSceneNum;
+	_newSceneNum = 0;
+	
+	for (int i = 0; i < _gameModule->getSceneObjectDefsCount(); ++i)
+		_sceneObjects[i].sceneObjectDef = _gameModule->getSceneObjectDef(i);
+		
+	for (int i = 0; i < _gameModule->getSceneObjectInitsCount(); ++i) {
+		SceneObjectInit *soInit = _gameModule->getSceneObjectInit(i);
+		if (evalCondition(soInit->conditions)) {
+			SceneObject *sceneObject = &_sceneObjects[soInit->sceneObjectIndex];
+			sceneObject->anim = _gameModule->getAnimation(soInit->animIndex);
+			sceneObject->animIndex = soInit->animIndex;
+			sceneObject->frameIndex = sceneObject->anim->frameCount - 1;
+			sceneObject->frameTicks = 1;
+			sceneObject->x = soInit->x << 16;
+			sceneObject->y = soInit->y << 16;
+		}
+	}
+
+	if (_gameModule->getButtheadObjectIndex() >= 0) {
+		_buttheadObject = &_sceneObjects[_gameModule->getButtheadObjectIndex()];
+		// Search for the Beavis object
+		for (int i = 0; i < _gameModule->getSceneObjectDefsCount(); ++i)
+			if (!strcmp(_sceneObjects[i].sceneObjectDef->name, "Beavis")) {
+				_beavisObject = &_sceneObjects[i];
+				break;
+			}
+	}
+
+	updateSceneObjectsTurnValue();
+
+	updateWalkableRects();
+
+	_currCameraNum = 0;
+	if (_buttheadObject) {
+		int minDistance = 0xFFFFFF;
+		for (int cameraNum = 0; cameraNum < 4; ++cameraNum) {
+			CameraInit *cameraInit = _gameModule->getCameraInit(cameraNum);
+			int curDistance = ABS(cameraInit->cameraPos.x - (int)(_buttheadObject->x >> 16) + 160);
+			if (curDistance < minDistance) {
+				minDistance = curDistance;
+				_currCameraNum = cameraNum;
+			}
+		}
+	}
+	
+	_cameraPos = _gameModule->getCameraInit(_currCameraNum)->cameraPos;
+	_newCameraPos = _cameraPos;
+	
+	_walkAreaActions.clear();
+	for (int i = 0; i < _gameModule->getActionsCount(); ++i) {
+		Action *action = _gameModule->getAction(i);
+		for (int j = 0; j < 8; ++j)
+			if (action->conditions.conditions[j].cond == kCondIsButtheadAtBgObject)
+				_walkAreaActions.push_back(action);
+	}
+
+	_mouseCursorSpriteIndex = 0;
+
+	_activeItemIndex = 0;
+	_activeItemType = kITEmpty;
+	
+	for (int i = 0; i < _gameModule->getActionsCount(); ++i) {
+		Action *action = _gameModule->getAction(i);
+		if (evalCondition(action->conditions)) {
+			_gameState = kGSWait;
+			_currAction = action;
+			for (uint j = 0; j < action->actionCommands.size(); ++j) {
+				ActionCommand *actionCommand = &action->actionCommands[j];
+				if (actionCommand->cmd == kActionCmdSetCameraPos) {
+					_currCameraNum = actionCommand->param;
+					_cameraPos = _gameModule->getCameraInit(_currCameraNum)->cameraPos;
+					_newCameraPos = _cameraPos;
+					break;
+				}
+			}
+			break;
+		}
+	}
+	
+	if (sounds)
+		updateBackgroundSounds();
+
+}
+
+bool BbvsEngine::changeScene() {
+
+	writeContinueSavegame();
+	
+	if (_newSceneNum >= 27 && _newSceneNum <= 30) {
+		// Run minigames
+		stopSpeech();
+		stopSounds();
+		_sceneVisited[_currSceneNum] = 1;
+		if (runMinigame(_newSceneNum - 27)) {
+			SWAP(_currSceneNum, _newSceneNum);
+		}
+	} else if (_newSceneNum >= 31 && _newSceneNum <= 43) {
+		// Play video
+		stopSpeech();
+		stopSounds();
+		_sceneVisited[_currSceneNum] = 1;
+		_playVideoNumber = _newSceneNum - 30;
+		_currSceneNum = _newSceneNum;
+		_newSceneNum = kAfterVideoSceneNum[_playVideoNumber];
+	} else if (_newSceneNum >= 100 && _currSceneNum == kCredits) {
+		// Play secret video
+		stopSounds();
+		_playVideoNumber = _newSceneNum;
+		_currSceneNum = 49;
+		_newSceneNum = kCredits;
+	} else {
+		// Normal scene
+		initScene(true);
+	}
+
+	return true;
+	
+}
+
+} // End of namespace Bbvs
diff --git a/engines/bbvs/walk.cpp b/engines/bbvs/walk.cpp
new file mode 100644
index 0000000..cabe402
--- /dev/null
+++ b/engines/bbvs/walk.cpp
@@ -0,0 +1,466 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * 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.
+ *
+ */
+
+#include "bbvs/bbvs.h"
+#include "bbvs/gamemodule.h"
+
+namespace Bbvs {
+
+static const int8 kTurnInfo[8][8] = {
+	{ 0,  1,  1,  1,  1, -1, -1, -1},
+	{-1,  0,  1,  1,  1,  1, -1, -1},
+	{-1, -1,  0,  1,  1,  1,  1, -1},
+	{-1, -1, -1,  0,  1,  1,  1,  1},
+	{ 1, -1, -1, -1,  0,  1,  1,  1},
+	{ 1,  1, -1, -1, -1,  0,  1,  1},
+	{ 1,  1,  1, -1, -1, -1,  0,  1},
+	{ 1,  1,  1,  1, -1, -1, -1,  0}
+};
+
+static const int8 kWalkAnimTbl[32] = {
+	 3,  0,  0,  0,  2,  1,  1,  1,
+	15, 12, 14, 13,  0,  0,  0,  0,
+	 7,  9,  4,  8,  6, 10,  5, 11,
+	 3,  0,  2,  1, 15, 12, 14, 13
+};
+
+void BbvsEngine::startWalkObject(SceneObject *sceneObject) {
+	const int kMaxDistance = 0xFFFFFF;
+
+	if (_buttheadObject != sceneObject && _beavisObject != sceneObject)
+		return;
+	
+	initWalkAreas(sceneObject);
+	_sourceWalkAreaPt.x = sceneObject->x >> 16;
+	_sourceWalkAreaPt.y = sceneObject->y >> 16;
+
+	_sourceWalkArea = getWalkAreaAtPos(_sourceWalkAreaPt);
+	if (!_sourceWalkArea)
+		return;
+
+	_destWalkAreaPt = sceneObject->walkDestPt;
+
+	_destWalkArea = getWalkAreaAtPos(_destWalkAreaPt);
+	if (!_destWalkArea)
+		return;
+		
+	if (_sourceWalkArea != _destWalkArea) {
+		_currWalkDistance = kMaxDistance;
+		walkFindPath(_sourceWalkArea, 0);
+		_destWalkAreaPt = _currWalkDistance == kMaxDistance ? _sourceWalkAreaPt : _finalWalkPt;
+	}
+
+	walkObject(sceneObject, _destWalkAreaPt, sceneObject->sceneObjectDef->walkSpeed);
+	
+}
+
+void BbvsEngine::updateWalkObject(SceneObject *sceneObject) {
+	int animIndex;
+	
+	if (sceneObject->walkCount > 0 && (sceneObject->xIncr != 0 || sceneObject->yIncr != 0)) {
+		if (ABS(sceneObject->xIncr) <= ABS(sceneObject->yIncr))
+			sceneObject->turnValue = sceneObject->yIncr >= 0 ? 0 : 4;
+		else
+			sceneObject->turnValue = sceneObject->xIncr >= 0 ? 6 : 2;
+		animIndex = sceneObject->sceneObjectDef->animIndices[kWalkAnimTbl[sceneObject->turnValue]];
+		sceneObject->turnCount = 0;
+		sceneObject->turnTicks = 0;
+	} else {
+		animIndex = sceneObject->sceneObjectDef->animIndices[kWalkTurnTbl[sceneObject->turnValue]];
+	}
+
+	Animation *anim = 0;
+	if (animIndex > 0)
+		anim = _gameModule->getAnimation(animIndex);
+	
+	if (sceneObject->anim != anim) {
+		if (anim) {
+			sceneObject->anim = anim;
+			sceneObject->animIndex = animIndex;
+			sceneObject->frameTicks = 1;
+			sceneObject->frameIndex = anim->frameCount - 1;
+		} else {
+			sceneObject->anim = 0;
+			sceneObject->animIndex = 0;
+			sceneObject->frameTicks = 0;
+			sceneObject->frameIndex = 0;
+		}
+	}
+
+}
+
+void BbvsEngine::walkObject(SceneObject *sceneObject, const Common::Point &destPt, int walkSpeed) {
+	int deltaX = destPt.x - (sceneObject->x >> 16);
+	int deltaY = destPt.y - (sceneObject->y >> 16);
+	float distance = sqrt((double)(deltaX * deltaX + deltaY * deltaY));
+	// NOTE The original doesn't have this check but without it the whole pathfinding breaks
+	if (distance > 0.0) {
+		sceneObject->walkCount = distance / ((((float)ABS(deltaX) / distance) + 1.0) * ((float)walkSpeed / 120));
+		sceneObject->xIncr = ((float)deltaX / sceneObject->walkCount) * 65536.0;
+		sceneObject->yIncr = ((float)deltaY / sceneObject->walkCount) * 65536.0;
+		sceneObject->x = (sceneObject->x & 0xFFFF0000) | 0x8000;
+		sceneObject->y = (sceneObject->y & 0xFFFF0000) | 0x8000;
+	} else
+		sceneObject->walkCount = 0;
+}
+
+void BbvsEngine::turnObject(SceneObject *sceneObject) {
+	if (sceneObject->turnTicks > 0) {
+		--sceneObject->turnTicks;
+	} else {
+		int turnDir = kTurnInfo[sceneObject->turnValue][sceneObject->turnCount & 0x7F];
+		if (turnDir) {
+			sceneObject->turnValue = (sceneObject->turnValue + turnDir) & 7;
+			int turnAnimIndex = sceneObject->sceneObjectDef->animIndices[kWalkTurnTbl[sceneObject->turnValue]];
+			if (turnAnimIndex) {
+				Animation *anim = _gameModule->getAnimation(turnAnimIndex);
+				if (anim) {
+					sceneObject->anim = anim;
+					sceneObject->animIndex = turnAnimIndex;
+					sceneObject->turnTicks = 4;
+					sceneObject->frameTicks = 1;
+					sceneObject->frameIndex = anim->frameCount - 1;
+				}
+			}
+		} else {
+			sceneObject->turnCount = 0;
+		}
+	}
+}
+
+int BbvsEngine::rectSubtract(const Common::Rect &rect1, const Common::Rect &rect2, Common::Rect *outRects) {
+	int count = 0;
+	Common::Rect workRect = rect1.findIntersectingRect(rect2);
+	if (!workRect.isEmpty()) {
+		count = 0;
+		outRects[count] = Common::Rect(rect2.width(), workRect.top - rect2.top);
+		if (!outRects[count].isEmpty()) {
+			outRects[count].translate(rect2.left, rect2.top);
+			++count;
+		}
+		outRects[count] = Common::Rect(workRect.left - rect2.left, workRect.height());
+		if (!outRects[count].isEmpty()) {
+			outRects[count].translate(rect2.left, workRect.top);
+			++count;
+		}
+		outRects[count] = Common::Rect(rect2.right - workRect.right, workRect.height());
+		if (!outRects[count].isEmpty()) {
+			outRects[count].translate(workRect.right, workRect.top);
+			++count;
+		}
+		outRects[count] = Common::Rect(rect2.width(), rect2.bottom - workRect.bottom);
+		if (!outRects[count].isEmpty()) {
+			outRects[count].translate(rect2.left, workRect.bottom);
+			++count;
+		}
+	} else {
+		outRects[0] = rect2;
+		count = 1;
+	}
+	return count;
+}
+
+WalkInfo *BbvsEngine::addWalkInfo(int16 x, int16 y, int delta, int direction, int16 midPtX, int16 midPtY, int walkAreaIndex) {
+	WalkInfo *walkInfo = &_walkInfos[_walkInfosCount++];
+	walkInfo->walkAreaIndex = walkAreaIndex;
+	walkInfo->direction = direction;
+	walkInfo->x = x;
+	walkInfo->y = y;
+	walkInfo->delta = delta;
+	walkInfo->midPt.x = midPtX;
+	walkInfo->midPt.y = midPtY;
+	return walkInfo;
+}
+
+void BbvsEngine::initWalkAreas(SceneObject *sceneObject) {
+	int16 objX = sceneObject->x >> 16;
+	int16 objY = sceneObject->y >> 16;
+	Common::Rect rect;
+	bool doRect = false;
+	Common::Rect *workWalkableRects;
+
+	if (_buttheadObject == sceneObject && _beavisObject->anim) {
+		rect = _beavisObject->anim->frameRects2[_beavisObject->frameIndex];
+		rect.translate(_beavisObject->x >> 16, 1 + (_beavisObject->y >> 16));
+		doRect = !rect.isEmpty();
+	} else if (_buttheadObject->anim) {
+		rect = _buttheadObject->anim->frameRects2[_buttheadObject->frameIndex];
+		rect.translate(_buttheadObject->x >> 16, 1 + (_buttheadObject->y >> 16));
+		doRect = !rect.isEmpty();
+	}
+
+	workWalkableRects = _walkableRects;
+
+	_walkAreasCount = _walkableRectsCount;
+
+	if (doRect && !rect.contains(objX, objY)) {
+		_walkAreasCount = 0;
+		for (int i = 0; i < _walkableRectsCount; ++i)
+			_walkAreasCount += rectSubtract(rect, _walkableRects[i], &_tempWalkableRects1[_walkAreasCount]);
+		workWalkableRects = _tempWalkableRects1;
+	}
+
+	for (int i = 0; i < _walkAreasCount; ++i) {
+		_walkAreas[i].x = workWalkableRects[i].left;
+		_walkAreas[i].y = workWalkableRects[i].top;
+		_walkAreas[i].width = workWalkableRects[i].width();
+		_walkAreas[i].height = workWalkableRects[i].height();
+		_walkAreas[i].checked = false;
+		_walkAreas[i].linksCount = 0;
+	}
+
+	_walkInfosCount = 0;
+
+	// Find connections between the walkRects
+
+	for (int i = 0; i < _walkAreasCount; ++i) {
+		WalkArea *walkArea1 = &_walkAreas[i];
+		int xIter = walkArea1->x + walkArea1->width;
+		int yIter = walkArea1->y + walkArea1->height;
+
+		for (int j = 0; j < _walkAreasCount; ++j) {
+			WalkArea *walkArea2 = &_walkAreas[j];
+
+			if (i == j)
+				continue;
+
+			if (walkArea2->y == yIter) {
+				int wa1x = MAX(walkArea1->x, walkArea2->x);
+				int wa2x = MIN(walkArea2->x + walkArea2->width, xIter);
+				if (wa2x > wa1x) {
+					debug(5, "WalkArea %d connected to %d by Y", i, j);
+					WalkInfo *walkInfo1 = addWalkInfo(wa1x, yIter - 1, wa2x - wa1x, 0, wa1x + (wa2x - wa1x) / 2, yIter - 1, i);
+					WalkInfo *walkInfo2 = addWalkInfo(wa1x, yIter, wa2x - wa1x, 0, wa1x + (wa2x - wa1x) / 2, yIter, j);
+					walkArea1->linksD1[walkArea1->linksCount] = walkInfo1;
+					walkArea1->linksD2[walkArea1->linksCount] = walkInfo2;
+					walkArea1->links[walkArea1->linksCount++] = walkArea2;
+					walkArea2->linksD1[walkArea2->linksCount] = walkInfo2;
+					walkArea2->linksD2[walkArea2->linksCount] = walkInfo1;
+					walkArea2->links[walkArea2->linksCount++] = walkArea1;
+				}
+			}
+
+			if (walkArea2->x == xIter) {
+				int wa1y = MAX(walkArea1->y, walkArea2->y);
+				int wa2y = MIN(walkArea2->y + walkArea2->height, yIter);
+				if (wa2y > wa1y) {
+					debug(5, "WalkArea %d connected to %d by X", i, j);
+					WalkInfo *walkInfo1 = addWalkInfo(xIter - 1, wa1y, wa2y - wa1y, 1, xIter - 1, wa1y + (wa2y - wa1y) / 2, i);
+					WalkInfo *walkInfo2 = addWalkInfo(xIter, wa1y, wa2y - wa1y, 1, xIter, wa1y + (wa2y - wa1y) / 2, j);
+					walkArea1->linksD1[walkArea1->linksCount] = walkInfo1;
+					walkArea1->linksD2[walkArea1->linksCount] = walkInfo2;
+					walkArea1->links[walkArea1->linksCount++] = walkArea2;
+					walkArea2->linksD1[walkArea2->linksCount] = walkInfo2;
+					walkArea2->linksD2[walkArea2->linksCount] = walkInfo1;
+					walkArea2->links[walkArea2->linksCount++] = walkArea1;
+				}
+			}
+
+		}
+
+	}
+
+}
+
+WalkArea *BbvsEngine::getWalkAreaAtPos(const Common::Point &pt) {
+	for (int i = 0; i < _walkAreasCount; ++i) {
+		WalkArea *walkArea = &_walkAreas[i];
+		if (walkArea->contains(pt))
+			return walkArea;
+	}
+	return 0;
+}
+
+bool BbvsEngine::canButtheadWalkToDest(const Common::Point &destPt) {
+	Common::Point srcPt;
+
+	_walkReachedDestArea = false;
+	initWalkAreas(_buttheadObject);
+	srcPt.x = _buttheadObject->x >> 16;
+	srcPt.y = _buttheadObject->y >> 16;
+	_sourceWalkArea = getWalkAreaAtPos(srcPt);
+	if (_sourceWalkArea) {
+		_destWalkArea = getWalkAreaAtPos(destPt);
+		if (_destWalkArea)
+			canWalkToDest(_sourceWalkArea, 0);
+	}
+	return _walkReachedDestArea;
+}
+
+void BbvsEngine::canWalkToDest(WalkArea *walkArea, int infoCount) {
+	
+	if (_destWalkArea == walkArea) {
+		_walkReachedDestArea = true;
+		return;
+	}
+	
+	if (_gameModule->getFieldC() <= 320 || infoCount <= 20) {
+		walkArea->checked = true;
+		for (int linkIndex = 0; linkIndex < walkArea->linksCount; ++linkIndex) {
+			if (!walkArea->links[linkIndex]->checked) {
+				canWalkToDest(walkArea->links[linkIndex], infoCount + 2);
+				if (_walkReachedDestArea)
+					break;
+			}
+		}
+		walkArea->checked = false;
+	}
+
+}
+
+bool BbvsEngine::walkTestLineWalkable(const Common::Point &sourcePt, const Common::Point &destPt, WalkInfo *walkInfo) {
+	const float ptDeltaX = destPt.x - sourcePt.x;
+	const float ptDeltaY = destPt.y - sourcePt.y;
+	const float wDeltaX = walkInfo->x - sourcePt.x;
+	const float wDeltaY = walkInfo->y - sourcePt.y;
+	if (destPt.x == sourcePt.x)
+		return true;
+	if (walkInfo->direction) {
+		const float nDeltaY = wDeltaX * ptDeltaY / ptDeltaX + (float)sourcePt.y - (float)walkInfo->y;
+		return (nDeltaY >= 0.0) && (nDeltaY < (float)walkInfo->delta);
+	} else {
+		const float nDeltaX = wDeltaY / ptDeltaX * ptDeltaY + (float)sourcePt.x - (float)walkInfo->x;
+		return (nDeltaX >= 0.0) && (nDeltaX < (float)walkInfo->delta);
+	}
+	return false;
+}
+
+void BbvsEngine::walkFindPath(WalkArea *sourceWalkArea, int infoCount) {
+	if (_destWalkArea == sourceWalkArea) {
+		walkFoundPath(infoCount);
+	} else if (_gameModule->getFieldC() <= 320 || infoCount <= 20) {
+		sourceWalkArea->checked = true;
+		for (int linkIndex = 0; linkIndex < sourceWalkArea->linksCount; ++linkIndex) {
+			if (!sourceWalkArea->links[linkIndex]->checked) {
+				_walkInfoPtrs[infoCount + 0] = sourceWalkArea->linksD1[linkIndex];
+				_walkInfoPtrs[infoCount + 1] = sourceWalkArea->linksD2[linkIndex];
+				walkFindPath(sourceWalkArea->links[linkIndex], infoCount + 2);
+			}
+		}
+		sourceWalkArea->checked = false;
+	}
+}
+
+int BbvsEngine::calcDistance(const Common::Point &pt1, const Common::Point &pt2) {
+	return (int)sqrt((double)(pt1.x - pt2.x) * (pt1.x - pt2.x) + (pt1.y - pt2.y) * (pt1.y - pt2.y));
+}
+
+void BbvsEngine::walkFoundPath(int count) {
+	debug(5, "BbvsEngine::walkFoundPath(%d)", count);
+	
+	Common::Point midPt = _sourceWalkAreaPt;
+	int totalMidPtDistance = 0;
+	
+	if (count > 0) {
+		Common::Point lastMidPt;
+		int halfCount = (count + 1) >> 1;
+		for (int i = 0; i < halfCount; ++i) {
+			lastMidPt = midPt;
+			midPt = _walkInfoPtrs[i * 2]->midPt;
+			totalMidPtDistance += calcDistance(midPt, lastMidPt);
+		}
+	}
+
+	int distance = calcDistance(midPt, _destWalkAreaPt) + totalMidPtDistance;
+
+	debug(5, "BbvsEngine::walkFoundPath() distance: %d; _currWalkDistance: %d", distance, _currWalkDistance);
+
+	if (distance >= _currWalkDistance)
+		return;
+		
+	debug(5, "BbvsEngine::walkFoundPath() distance smaller");
+
+	_currWalkDistance = distance;
+
+	Common::Point destPt = _destWalkAreaPt, newDestPt;
+	
+	while (1) {
+
+		int index = 0;
+		if (count > 0) {
+			do {
+				if (!walkTestLineWalkable(_sourceWalkAreaPt, destPt, _walkInfoPtrs[index]))
+					break;
+				++index;
+			} while (index < count);
+		}
+
+		if (index == count)
+			break;
+
+		WalkInfo *walkInfo = _walkInfoPtrs[--count];
+		destPt.x = walkInfo->x;
+		destPt.y = walkInfo->y;
+		
+		if (walkInfo->direction) {
+			newDestPt.x = walkInfo->x;
+			newDestPt.y = walkInfo->y + walkInfo->delta - 1;
+		} else {
+			newDestPt.x = walkInfo->x + walkInfo->delta - 1;
+			newDestPt.y = walkInfo->y;
+		}
+
+		if ((newDestPt.x - _destWalkAreaPt.x) * (newDestPt.x - _destWalkAreaPt.x) +
+			(newDestPt.y - _destWalkAreaPt.y) * (newDestPt.y - _destWalkAreaPt.y) <
+			(destPt.x - _destWalkAreaPt.x) * (destPt.x - _destWalkAreaPt.x) +
+			(destPt.y - _destWalkAreaPt.y) * (destPt.y - _destWalkAreaPt.y))
+			destPt = newDestPt;
+
+	}
+
+	debug(5, "BbvsEngine::walkFoundPath() destPt: (%d, %d)", destPt.x, destPt.y);
+
+	_finalWalkPt = destPt;
+
+	debug(5, "BbvsEngine::walkFoundPath() OK");
+
+}
+
+void BbvsEngine::updateWalkableRects() {
+	// Go through all walkable rects and subtract all scene object rects
+	Common::Rect *rectsList1 = _tempWalkableRects1;
+	Common::Rect *rectsList2 = _gameModule->getWalkRects();
+	_walkableRectsCount = _gameModule->getWalkRectsCount();
+	for (int i = 0; i < _gameModule->getSceneObjectDefsCount(); ++i) {
+		SceneObject *sceneObject = &_sceneObjects[i];
+		Animation *anim = sceneObject->anim;
+		if (anim && _buttheadObject != sceneObject && _beavisObject != sceneObject) {
+			Common::Rect rect = sceneObject->anim->frameRects2[sceneObject->frameIndex];
+			rect.translate(sceneObject->x >> 16, sceneObject->y >> 16);
+			int count = _walkableRectsCount;
+			_walkableRectsCount = 0;
+			for (int j = 0; j < count; ++j)
+				_walkableRectsCount += rectSubtract(rect, rectsList2[j], &rectsList1[_walkableRectsCount]);
+			if (rectsList1 == _tempWalkableRects1) {
+				rectsList1 = _tempWalkableRects2;
+				rectsList2 = _tempWalkableRects1;
+			} else {
+				rectsList1 = _tempWalkableRects1;
+				rectsList2 = _tempWalkableRects2;
+			}
+		}
+	}
+	for (int i = 0; i < _walkableRectsCount; ++i)
+		_walkableRects[i] = rectsList2[i];
+}
+
+} // End of namespace Bbvs






More information about the Scummvm-git-logs mailing list