[Scummvm-git-logs] scummvm master -> 7090841ccc43c64d5a1d9058071ebccaf6b52fc2

peterkohaut peterkohaut at users.noreply.github.com
Sun Feb 18 22:21:26 CET 2018


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:
7090841ccc BLADERUNNER: Support for running


Commit: 7090841ccc43c64d5a1d9058071ebccaf6b52fc2
    https://github.com/scummvm/scummvm/commit/7090841ccc43c64d5a1d9058071ebccaf6b52fc2
Author: Peter Kohaut (peter.kohaut at gmail.com)
Date: 2018-02-18T22:20:16+01:00

Commit Message:
BLADERUNNER: Support for running

Fixed Runciter idle state
Fixed movement track delay
Basic combat support

Changed paths:
    engines/bladerunner/actor.cpp
    engines/bladerunner/actor.h
    engines/bladerunner/actor_walk.cpp
    engines/bladerunner/actor_walk.h
    engines/bladerunner/bladerunner.cpp
    engines/bladerunner/bladerunner.h
    engines/bladerunner/boundingbox.cpp
    engines/bladerunner/boundingbox.h
    engines/bladerunner/combat.cpp
    engines/bladerunner/combat.h
    engines/bladerunner/game_constants.h
    engines/bladerunner/item.cpp
    engines/bladerunner/item.h
    engines/bladerunner/items.cpp
    engines/bladerunner/items.h
    engines/bladerunner/mouse.cpp
    engines/bladerunner/mouse.h
    engines/bladerunner/movement_track.cpp
    engines/bladerunner/movement_track.h
    engines/bladerunner/scene.cpp
    engines/bladerunner/scene_objects.cpp
    engines/bladerunner/scene_objects.h
    engines/bladerunner/script/ai/leon.cpp
    engines/bladerunner/script/ai/maggie.cpp
    engines/bladerunner/script/ai/mccoy.cpp
    engines/bladerunner/script/ai/officer_leary.cpp
    engines/bladerunner/script/ai/runciter.cpp
    engines/bladerunner/script/ai_script.cpp
    engines/bladerunner/script/ai_script.h
    engines/bladerunner/script/scene_script.cpp
    engines/bladerunner/script/scene_script.h
    engines/bladerunner/script/script.cpp
    engines/bladerunner/set.cpp
    engines/bladerunner/settings.cpp
    engines/bladerunner/settings.h
    engines/bladerunner/ui/kia.cpp
    engines/bladerunner/vector.h


diff --git a/engines/bladerunner/actor.cpp b/engines/bladerunner/actor.cpp
index 4d66d74..14c8ef9 100644
--- a/engines/bladerunner/actor.cpp
+++ b/engines/bladerunner/actor.cpp
@@ -82,10 +82,10 @@ void Actor::setup(int actorId) {
 	_animationId    = 0;
 	_animationFrame = 0;
 	_fps            = 15;
-	_frame_ms       = 1000 / _fps;
+	_frameMs       = 1000 / _fps;
 
 	_isMoving            = false;
-	_isTargetable        = false;
+	_isTarget            = false;
 	_inCombat            = false;
 	_isInvisible         = false;
 	_isImmuneToObstacles = false;
@@ -101,8 +101,8 @@ void Actor::setup(int actorId) {
 	_movementTrackDelayOnNextWaypoint = -1;
 
 	for (int i = 0; i != 7; ++i) {
-		_timersRemain[i] = 0;
-		_timersStart[i] = _vm->getTotalPlayTime();
+		_timersLeft[i] = 0;
+		_timersLast[i] = _vm->getTotalPlayTime();
 	}
 
 	_honesty              = 50;
@@ -120,7 +120,9 @@ void Actor::setup(int actorId) {
 	_movementTrackNextAngle      = -1;
 	_movementTrackNextRunning    = false;
 
-	_timersRemain[4] = 60000;
+	// Timer for exchanging clues
+	_timersLeft[4]   = 60000;
+
 	_animationMode   = -1;
 	_screenRectangle = Common::Rect(-1, -1, -1, -1);
 
@@ -154,73 +156,76 @@ void Actor::setFPS(int fps) {
 	_fps = fps;
 
 	if (fps == 0) {
-		_frame_ms = 0;
+		_frameMs = 0;
 	} else if (fps == -1) {
-		_frame_ms = -1000;
+		_frameMs = -1000;
 	} else if (fps == -2) {
 		_fps = _vm->_sliceAnimations->getFPS(_animationId);
-		_frame_ms = 1000 / _fps;
+		_frameMs = 1000 / _fps;
 	} else {
-		_frame_ms = 1000 / fps;
+		_frameMs = 1000 / fps;
 	}
 }
 
-void Actor::countdownTimerStart(int timerId, int interval) {
+void Actor::increaseFPS() {
+	int fps = MIN(_fps + 3, 30);
+	setFPS(fps);
+}
+
+void Actor::timerStart(int timerId, int interval) {
 	assert(timerId >= 0 && timerId < 7);
-	_timersRemain[timerId] = interval;
-	_timersStart[timerId] = _vm->getTotalPlayTime();
+	_timersLeft[timerId] = interval;
+	_timersLast[timerId] = _vm->getTotalPlayTime();
 }
 
-void Actor::countdownTimerReset(int timerId) {
+void Actor::timerReset(int timerId) {
 	assert(timerId >= 0 && timerId < 7);
-	_timersRemain[timerId] = 0;
+	_timersLeft[timerId] = 0;
 }
 
-int Actor::countdownTimerGetRemainingTime(int timerId) {
+int Actor::timerLeft(int timerId) {
 	assert(timerId >= 0 && timerId < 7);
-	return _timersRemain[timerId];
+	return _timersLeft[timerId];
 }
 
-void Actor::countdownTimersUpdate() {
+void Actor::timersUpdate() {
 	for (int i = 0; i <= 6; i++) {
-		countdownTimerUpdate(i);
+		timerUpdate(i);
 	}
 }
 
-void Actor::countdownTimerUpdate(int timerId) {
-	if (_timersRemain[timerId] == 0) {
+void Actor::timerUpdate(int timerId) {
+	if (_timersLeft[timerId] == 0) {
 		return;
 	}
 
-	uint32 now = _vm->getTotalPlayTime();
-	int tickInterval = now - _timersStart[timerId];
-	_timersStart[timerId] = now;
+	uint32 timeNow = _vm->getTotalPlayTime();
+	int timeDiff = timeNow - _timersLast[timerId];
+	_timersLast[timerId] = timeNow;
+	_timersLeft[timerId] -= timeDiff;
 
-	//warning("tickInterval: %d", tickInterval);
-	_timersRemain[timerId] -= tickInterval;
-
-	if (_timersRemain[timerId] <= 0) {
+	if (_timersLeft[timerId] <= 0) {
 		switch (timerId) {
 		case 0:
 		case 1:
 		case 2:
 			if (!_vm->_aiScripts->isInsideScript() && !_vm->_sceneScript->isInsideScript()) {
-				_vm->_aiScripts->timerExpired(this->_id, timerId);
-				this->_timersRemain[timerId] = 0;
+				_vm->_aiScripts->timerExpired(_id, timerId);
+				_timersLeft[timerId] = 0;
 			} else {
-				this->_timersRemain[timerId] = 1;
+				_timersLeft[timerId] = 1;
 			}
 			break;
 		case 3:
-			_timersRemain[3] = 0;
+			_timersLeft[3] = 0;
 			if (_movementTrack->isPaused()) {
-				_timersRemain[3] = 1;
+				_timersLeft[3] = 1;
 			} else {
 				movementTrackNext(false);
 			}
 			break;
 		case 4:
-			// Something timer
+			// Exchange clues between actors
 			break;
 		case 5:
 			// Actor animation frame timer
@@ -235,7 +240,7 @@ void Actor::countdownTimerUpdate(int timerId) {
 					setFPS(newFps);
 				}
 			}
-			_timersRemain[6] = 200;
+			_timersLeft[6] = 200;
 			break;
 		}
 	}
@@ -244,18 +249,18 @@ void Actor::countdownTimerUpdate(int timerId) {
 void Actor::movementTrackNext(bool omitAiScript) {
 	bool hasNextMovement;
 	int waypointSetId;
-	int running;
+	bool run;
 	int angle;
 	int delay;
 	int waypointId;
 	Vector3 waypointPosition;
 	bool arrived;
 
-	hasNextMovement = _movementTrack->next(&waypointId, &delay, &angle, &running);
+	hasNextMovement = _movementTrack->next(&waypointId, &delay, &angle, &run);
 	_movementTrackNextWaypointId = waypointId;
 	_movementTrackNextDelay = delay;
 	_movementTrackNextAngle = angle;
-	_movementTrackNextRunning = running;
+	_movementTrackNextRunning = run;
 	if (hasNextMovement) {
 		if (angle == -1) {
 			angle = 0;
@@ -264,7 +269,7 @@ void Actor::movementTrackNext(bool omitAiScript) {
 		_vm->_waypoints->getXYZ(waypointId, &waypointPosition.x, &waypointPosition.y, &waypointPosition.z);
 		if (_setId == waypointSetId && waypointSetId == _vm->_actors[0]->_setId) {
 			stopWalking(false);
-			_walkInfo->setup(_id, running, _position, waypointPosition, false, &arrived);
+			_walkInfo->setup(_id, run, _position, waypointPosition, false, &arrived);
 
 			_movementTrackWalkingToWaypointId = waypointId;
 			_movementTrackDelayOnNextWaypoint = delay;
@@ -281,7 +286,7 @@ void Actor::movementTrackNext(bool omitAiScript) {
 			if (delay > 1) {
 				changeAnimationMode(kAnimationModeIdle, false);
 			}
-			countdownTimerStart(3, delay);
+			timerStart(3, delay);
 		}
 		//return true;
 	} else {
@@ -315,19 +320,18 @@ void Actor::movementTrackUnpause() {
 }
 
 void Actor::movementTrackWaypointReached() {
-	int seconds;
 	if (!_movementTrack->isPaused() && _id != kActorMcCoy) {
-		if (_movementTrackWalkingToWaypointId >= 0 && _movementTrackDelayOnNextWaypoint) {
+		if (_movementTrackWalkingToWaypointId >= 0 && _movementTrackDelayOnNextWaypoint >= 0) {
 			if (!_movementTrackDelayOnNextWaypoint) {
 				_movementTrackDelayOnNextWaypoint = 1;
 			}
 			if (_vm->_aiScripts->reachedMovementTrackWaypoint(_id, _movementTrackWalkingToWaypointId)) {
-				seconds = _movementTrackDelayOnNextWaypoint;
-				if (seconds > 1) {
+				int delay = _movementTrackDelayOnNextWaypoint;
+				if (delay > 1) {
 					changeAnimationMode(kAnimationModeIdle, false);
-					seconds = _movementTrackDelayOnNextWaypoint; // todo: analyze if movement is changed in some aiscript->ChangeAnimationMode?
+					delay = _movementTrackDelayOnNextWaypoint; // todo: analyze if movement is changed in some aiscript->ChangeAnimationMode?
 				}
-				countdownTimerStart(3, seconds);
+				timerStart(3, delay);
 			}
 		}
 		_movementTrackWalkingToWaypointId = -1;
@@ -350,7 +354,7 @@ void Actor::setAtXYZ(const Vector3 &position, int facing, bool snapFacing, bool
 	_vm->_sceneObjects->remove(_id + kSceneObjectOffsetActors);
 
 	if (_vm->_scene->getSetId() == _setId) {
-		_vm->_sceneObjects->addActor(_id + kSceneObjectOffsetActors, _bbox, &_screenRectangle, 1, moving, _isTargetable, retired);
+		_vm->_sceneObjects->addActor(_id + kSceneObjectOffsetActors, _bbox, &_screenRectangle, 1, moving, _isTarget, retired);
 	}
 }
 
@@ -360,8 +364,8 @@ void Actor::setAtWaypoint(int waypointId, int angle, int moving, bool retired) {
 	setAtXYZ(waypointPosition, angle, true, moving, retired);
 }
 
-bool Actor::loopWalk(const Vector3 &destination, int destinationOffset, bool interruptible, bool run, const Vector3 &start, float targetWidth, float targetSize, bool a8, bool *flagIsRunning, bool async) {
-	*flagIsRunning = false;
+bool Actor::loopWalk(const Vector3 &destination, int destinationOffset, bool interruptible, bool run, const Vector3 &start, float targetWidth, float targetSize, bool a8, bool *isRunning, bool async) {
+	*isRunning = false;
 
 	if (destinationOffset > 0) {
 		float dist = distance(_position, destination);
@@ -397,7 +401,7 @@ bool Actor::loopWalk(const Vector3 &destination, int destinationOffset, bool int
 	}
 
 	if (!walking) {
-		faceXYZ(destination.x, destination.y, destination.z, false);
+		faceXYZ(destination, false);
 		return false;
 	}
 
@@ -406,8 +410,8 @@ bool Actor::loopWalk(const Vector3 &destination, int destinationOffset, bool int
 	}
 
 	if (interruptible) {
-		_vm->_isWalkingInterruptible = 1;
-		_vm->_interruptWalking = 0;
+		_vm->_isWalkingInterruptible = true;
+		_vm->_interruptWalking = false;
 	} else {
 		_vm->playerLosesControl();
 	}
@@ -419,7 +423,7 @@ bool Actor::loopWalk(const Vector3 &destination, int destinationOffset, bool int
 	bool wasInterrupted = false;
 	while (_walkInfo->isWalking() && _vm->_gameIsRunning) {
 		if (_walkInfo->isRunning()) {
-			*flagIsRunning = true;
+			*isRunning = true;
 		}
 		_vm->gameTick();
 		if (_id == kActorMcCoy && interruptible && _vm->_interruptWalking) {
@@ -450,21 +454,21 @@ bool Actor::walkTo(bool run, const Vector3 &destination, bool a3) {
 	return _walkInfo->setup(_id, run, _position, destination, a3, &arrived);
 }
 
-bool Actor::loopWalkToActor(int otherActorId, int destinationOffset, int interruptible, bool run, bool a5, bool *flagIsRunning) {
-	return loopWalk(_vm->_actors[otherActorId]->_position, destinationOffset, interruptible, run, _position, 24.0f, 24.0f, a5, flagIsRunning, false);
+bool Actor::loopWalkToActor(int otherActorId, int destinationOffset, int interruptible, bool run, bool a5, bool *isRunning) {
+	return loopWalk(_vm->_actors[otherActorId]->_position, destinationOffset, interruptible, run, _position, 24.0f, 24.0f, a5, isRunning, false);
 }
 
-bool Actor::loopWalkToItem(int itemId, int destinationOffset, int interruptible, bool run, bool a5, bool *flagIsRunning) {
+bool Actor::loopWalkToItem(int itemId, int destinationOffset, int interruptible, bool run, bool a5, bool *isRunning) {
 	float x, y, z;
 	int width, height;
 	_vm->_items->getXYZ(itemId, &x, &y, &z);
 	_vm->_items->getWidthHeight(itemId, &width, &height);
 	Vector3 itemPosition(x, y, z);
 
-	return loopWalk(itemPosition, destinationOffset, interruptible, run, _position, width, 24.0f, a5, flagIsRunning, false);
+	return loopWalk(itemPosition, destinationOffset, interruptible, run, _position, width, 24.0f, a5, isRunning, false);
 }
 
-bool Actor::loopWalkToSceneObject(const char *objectName, int destinationOffset, bool interruptible, bool run, bool a5, bool *flagIsRunning) {
+bool Actor::loopWalkToSceneObject(const char *objectName, int destinationOffset, bool interruptible, bool run, bool a5, bool *isRunning) {
 	int sceneObject = _vm->_scene->_set->findObject(objectName);
 	if (sceneObject < 0) {
 		return true;
@@ -506,41 +510,45 @@ bool Actor::loopWalkToSceneObject(const char *objectName, int destinationOffset,
 	float y = _vm->_scene->_set->getAltitudeAtXZ(closestX, closestZ, &inWalkbox);
 	Vector3 destination(closestX, y, closestZ);
 
-	return loopWalk(destination, destinationOffset, interruptible, run, _position, 0.0f, 24.0f, a5, flagIsRunning, false);
+	return loopWalk(destination, destinationOffset, interruptible, run, _position, 0.0f, 24.0f, a5, isRunning, false);
 }
 
-bool Actor::loopWalkToWaypoint(int waypointId, int destinationOffset, int interruptible, bool run, bool a5, bool *flagIsRunning) {
+bool Actor::loopWalkToWaypoint(int waypointId, int destinationOffset, int interruptible, bool run, bool a5, bool *isRunning) {
 	Vector3 waypointPosition;
 	_vm->_waypoints->getXYZ(waypointId, &waypointPosition.x, &waypointPosition.y, &waypointPosition.z);
-	return loopWalk(waypointPosition, destinationOffset, interruptible, run, _position, 0.0f, 24.0f, a5, flagIsRunning, false);
+	return loopWalk(waypointPosition, destinationOffset, interruptible, run, _position, 0.0f, 24.0f, a5, isRunning, false);
 }
 
-bool Actor::loopWalkToXYZ(const Vector3 &destination, int destinationOffset, bool interruptible, bool run, bool a5, bool *flagIsRunning) {
-	return loopWalk(destination, destinationOffset, interruptible, run, _position, 0.0f, 24.0f, a5, flagIsRunning, false);
+bool Actor::loopWalkToXYZ(const Vector3 &destination, int destinationOffset, bool interruptible, bool run, bool a5, bool *isRunning) {
+	return loopWalk(destination, destinationOffset, interruptible, run, _position, 0.0f, 24.0f, a5, isRunning, false);
 }
 
 bool Actor::asyncWalkToWaypoint(int waypointId, int destinationOffset, bool run, bool a5) {
-	bool flagIsRunning;
+	bool isRunning;
 	Vector3 waypointPosition;
 	_vm->_waypoints->getXYZ(waypointId, &waypointPosition.x, &waypointPosition.y, &waypointPosition.z);
-	return loopWalk(waypointPosition, destinationOffset, false, run, _position, 0.0f, 24.0f, a5, &flagIsRunning, true);
+	return loopWalk(waypointPosition, destinationOffset, false, run, _position, 0.0f, 24.0f, a5, &isRunning, true);
 }
 
 void Actor::asyncWalkToXYZ(const Vector3 &destination, int destinationOffset, bool run, int a6) {
-	bool flagIsRunning;
-	loopWalk(destination, destinationOffset, false, run, _position, 0.0f, 24.0f, a6, &flagIsRunning, true);
+	bool isRunning;
+	loopWalk(destination, destinationOffset, false, run, _position, 0.0f, 24.0f, a6, &isRunning, true);
+}
+
+void Actor::run() {
+	_walkInfo->run(_id);
 }
 
 bool Actor::tick(bool forceDraw, Common::Rect *screenRect) {
-	int remain = 0;
+	int timeLeft = 0;
 	bool needsUpdate = false;
 	if (_fps > 0) {
-		countdownTimerUpdate(5);
-		remain = countdownTimerGetRemainingTime(5);
-		needsUpdate = remain <= 0;
+		timerUpdate(5);
+		timeLeft = timerLeft(5);
+		needsUpdate = timeLeft <= 0;
 	} else if (forceDraw) {
 		needsUpdate = true;
-		remain = 0;
+		timeLeft = 0;
 	}
 
 	if (needsUpdate) {
@@ -570,68 +578,68 @@ bool Actor::tick(bool forceDraw, Common::Rect *screenRect) {
 				positionChange.y = -4.0f;
 			}
 
-			this->_targetFacing = -1;
+			_targetFacing = -1;
 
 			bool walked = _walkInfo->tick(_id, -positionChange.y, false);
 
 			Vector3 pos;
 			int facing;
 			_walkInfo->getCurrentPosition(_id, &pos, &facing);
-			setAtXYZ(pos, facing, false, this->_isMoving, false);
+			setAtXYZ(pos, facing, false, _isMoving, false);
 			if (walked) {
 				_vm->_actors[_id]->changeAnimationMode(kAnimationModeIdle);
 
-				this->movementTrackWaypointReached();
-				if (this->inCombat()) {
-					this->changeAnimationMode(this->_animationModeCombatIdle, false);
+				movementTrackWaypointReached();
+				if (inCombat()) {
+					changeAnimationMode(_animationModeCombatIdle, false);
 				} else {
-					this->changeAnimationMode(kAnimationModeIdle, false);
+					changeAnimationMode(kAnimationModeIdle, false);
 				}
 			}
 		} else {
 			if (angleChange != 0.0f) {
 				int facingChange = angleChange * (512.0f / M_PI);
 				if (facingChange != 0) {
-					this->_facing = this->_facing - facingChange;
-					if (this->_facing < 0) {
-						this->_facing += 1024;
+					_facing = _facing - facingChange;
+					if (_facing < 0) {
+						_facing += 1024;
 					}
 
-					if (this->_facing >= 1024) {
-						this->_facing = this->_facing - 1024;
+					if (_facing >= 1024) {
+						_facing = _facing - 1024;
 					}
 				}
 			}
 
 			if (0.0f != positionChange.x || 0.0f != positionChange.y || 0.0f != positionChange.z) {
-				if (this->_actorSpeed.x != 0.0f) {
-					positionChange.x = positionChange.x * this->_actorSpeed.x;
+				if (_actorSpeed.x != 0.0f) {
+					positionChange.x = positionChange.x * _actorSpeed.x;
 				}
-				if (this->_actorSpeed.y != 0.0f) {
-					positionChange.y = positionChange.y * this->_actorSpeed.y;
+				if (_actorSpeed.y != 0.0f) {
+					positionChange.y = positionChange.y * _actorSpeed.y;
 				}
-				if (this->_actorSpeed.z != 0.0f) {
-					positionChange.z = positionChange.z * this->_actorSpeed.z;
+				if (_actorSpeed.z != 0.0f) {
+					positionChange.z = positionChange.z * _actorSpeed.z;
 				}
 
 				float angle = _facing * (M_PI / 512.0f);
 				float sinx = sin(angle);
 				float cosx = cos(angle);
 
-				float originalX = this->_position.x;
-				float originalY = this->_position.y;
-				float originalZ = this->_position.z;
+				float originalX = _position.x;
+				float originalY = _position.y;
+				float originalZ = _position.z;
 
-				this->_position.x = this->_position.x + positionChange.x * cosx - positionChange.y * sinx;
-				this->_position.z = this->_position.z + positionChange.x * sinx + positionChange.y * cosx;
-				this->_position.y = this->_position.y + positionChange.z;
+				_position.x = _position.x + positionChange.x * cosx - positionChange.y * sinx;
+				_position.z = _position.z + positionChange.x * sinx + positionChange.y * cosx;
+				_position.y = _position.y + positionChange.z;
 
-				if (_vm->_sceneObjects->existsOnXZ(this->_id + kSceneObjectOffsetActors, this->_position.x, this->_position.z, false, false) == 1 && !this->_isImmuneToObstacles) {
-					this->_position.x = originalX;
-					this->_position.y = originalY;
-					this->_position.z = originalZ;
+				if (_vm->_sceneObjects->existsOnXZ(_id + kSceneObjectOffsetActors, _position.x, _position.z, false, false) == 1 && !_isImmuneToObstacles) {
+					_position.x = originalX;
+					_position.y = originalY;
+					_position.z = originalZ;
 				}
-				setAtXYZ(this->_position, this->_facing, true, this->_isMoving, this->_isRetired);
+				setAtXYZ(_position, _facing, true, _isMoving, _isRetired);
 			}
 		}
 	}
@@ -645,16 +653,17 @@ bool Actor::tick(bool forceDraw, Common::Rect *screenRect) {
 	}
 
 	if (needsUpdate) {
-		int nextFrameTime = remain + _frame_ms;
-		if (nextFrameTime <= 0)
+		int nextFrameTime = timeLeft + _frameMs;
+		if (nextFrameTime <= 0) {
 			nextFrameTime = 1;
-		countdownTimerStart(5, nextFrameTime);
+		}
+		timerStart(5, nextFrameTime);
 	}
-	if (this->_targetFacing >= 0) {
-		if (this->_targetFacing == this->_facing) {
-			this->_targetFacing = -1;
+	if (_targetFacing >= 0) {
+		if (_targetFacing == _facing) {
+			_targetFacing = -1;
 		} else {
-			this->setFacing(this->_targetFacing, false);
+			setFacing(_targetFacing, false);
 		}
 	}
 	return isVisible;
@@ -761,8 +770,8 @@ void Actor::setBoundingBox(const Vector3 &position, bool retired) {
 }
 
 float Actor::distanceFromView(View *view) const{
-	float xDist = this->_position.x - view->_cameraPosition.x;
-	float zDist = this->_position.z + view->_cameraPosition.z;
+	float xDist = _position.x - view->_cameraPosition.x;
+	float zDist = _position.z + view->_cameraPosition.z;
 	return sqrt(xDist * xDist + zDist * zDist);
 }
 
@@ -799,7 +808,7 @@ void Actor::faceActor(int otherActorId, bool animate) {
 		return;
 	}
 
-	faceXYZ(otherActor->_position.x, otherActor->_position.y, otherActor->_position.z, animate);
+	faceXYZ(otherActor->_position, animate);
 }
 
 void Actor::faceObject(const char *objectName, bool animate) {
@@ -843,6 +852,10 @@ void Actor::faceXYZ(float x, float y, float z, bool animate) {
 	faceHeading(heading, animate);
 }
 
+void Actor::faceXYZ(const Vector3 &pos, bool animate) {
+	faceXYZ(pos.x, pos.y, pos.z, animate);
+}
+
 void Actor::faceCurrentCamera(bool animate) {
 	faceXYZ(_vm->_view->_cameraPosition.x, _vm->_view->_cameraPosition.y, -_vm->_view->_cameraPosition.z, animate);
 }
@@ -936,8 +949,8 @@ void Actor::retire(bool retired, int width, int height, int retiredByActorId) {
 	}
 }
 
-void Actor::setTargetable(bool targetable) {
-	_isTargetable = targetable;
+void Actor::setTarget(bool target) {
+	_isTarget = target;
 }
 
 void Actor::setHealth(int hp, int maxHp) {
@@ -1095,6 +1108,22 @@ int Actor::soundBalance() const {
 	return 35.0f * (CLIP(screenPosition.x / 640.0f, 0.0f, 1.0f) * 2.0f - 1.0f);
 }
 
+bool Actor::isObstacleBetween(float targetX, float targetZ) {
+	return _vm->_sceneObjects->isObstacleBetween(_position.x, _position.z, targetX, targetZ, _position.y, -1);
+}
+
+int Actor::findTargetUnderMouse(BladeRunnerEngine *vm, int mouseX, int mouseY) {
+	int setId = vm->_scene->getSetId();
+	for (int i = 0; i < (int)vm->_gameInfo->getActorCount(); ++i) {
+		if (vm->_actors[i]->isTarget() && vm->_actors[i]->getSetId() == setId) {
+			if (vm->_actors[i]->_screenRectangle.contains(mouseX, mouseY)) {
+				return i;
+			}
+		}
+	}
+	return -1;
+}
+
 bool Actor::walkFindU1(const Vector3 &startPosition, const Vector3 &targetPosition, float size, Vector3 *newDestination) {
 	newDestination->x = 0.0f;
 	newDestination->y = 0.0f;
@@ -1163,9 +1192,9 @@ bool Actor::walkFindU2(Vector3 *newDestination, float targetWidth, int destinati
 
 bool Actor::walkToNearestPoint(const Vector3 &destination, float distance) {
 	Vector3 out;
-	bool flagIsRunning;
+	bool isRunning;
 	if (_walkInfo->findNearestEmptyPosition(_id, destination, distance, out)) {
-		loopWalk(out, 0, false, false, _position, 0.0f, 24.0f, false, &flagIsRunning, false);
+		loopWalk(out, 0, false, false, _position, 0.0f, 24.0f, false, &isRunning, false);
 		return true;
 	}
 	return false;
diff --git a/engines/bladerunner/actor.h b/engines/bladerunner/actor.h
index b160ca3..6bbcf93 100644
--- a/engines/bladerunner/actor.h
+++ b/engines/bladerunner/actor.h
@@ -71,7 +71,7 @@ private:
 	int     _walkboxId;
 
 	// Flags
-	bool _isTargetable;
+	bool _isTarget;
 	bool _isInvisible;
 	bool _isImmuneToObstacles;
 	bool _inWalkLoop;
@@ -98,15 +98,15 @@ private:
 	int _animationModeCombatWalk;
 	int _animationModeCombatRun;
 	int _fps;
-	int _frame_ms;
+	int _frameMs;
 	int _animationId;
 	int _animationFrame;
 
 	int _retiredWidth;
 	int _retiredHeight;
 
-	int _timersRemain[7];
-	int _timersStart[7];
+	int _timersLeft[7];
+	int _timersLast[7];
 
 	float _scale;
 
@@ -132,25 +132,29 @@ public:
 
 	void changeAnimationMode(int animationMode, bool force = false);
 	void setFPS(int fps);
+	void increaseFPS();
 
-	void countdownTimerStart(int timerId, int interval);
-	void countdownTimerReset(int timerId);
-	int  countdownTimerGetRemainingTime(int timerId);
-	void countdownTimersUpdate();
-	void countdownTimerUpdate(int timerId);
+	void timerStart(int timerId, int interval);
+	void timerReset(int timerId);
+	int  timerLeft(int timerId);
+	void timersUpdate();
+	void timerUpdate(int timerId);
 
 	void movementTrackNext(bool omitAiScript);
 	void movementTrackPause();
 	void movementTrackUnpause();
 	void movementTrackWaypointReached();
 
-	bool loopWalkToActor(int otherActorId, int destinationOffset, int interruptible, bool run, bool a5, bool *flagIsRunning);
-	bool loopWalkToItem(int itemId, int destinationOffset, int interruptible, bool run, bool a5, bool *flagIsRunning);
-	bool loopWalkToSceneObject(const char *objectName, int destinationOffset, bool interruptible, bool run, bool a5, bool *flagIsRunning);
-	bool loopWalkToWaypoint(int waypointId, int destinationOffset, int interruptible, bool run, bool a5, bool *flagIsRunning);
-	bool loopWalkToXYZ(const Vector3 &destination, int destinationOffset, bool interruptible, bool run, bool a5, bool *flagIsRunning);
+	bool loopWalk(const Vector3 &destination, int destinationOffset, bool interruptible, bool run, const Vector3 &start, float a6, float a7, bool a8, bool *isRunning, bool async);
+	bool walkTo(bool run, const Vector3 &destination, bool a3);
+	bool loopWalkToActor(int otherActorId, int destinationOffset, int interruptible, bool run, bool a5, bool *isRunning);
+	bool loopWalkToItem(int itemId, int destinationOffset, int interruptible, bool run, bool a5, bool *isRunning);
+	bool loopWalkToSceneObject(const char *objectName, int destinationOffset, bool interruptible, bool run, bool a5, bool *isRunning);
+	bool loopWalkToWaypoint(int waypointId, int destinationOffset, int interruptible, bool run, bool a5, bool *isRunning);
+	bool loopWalkToXYZ(const Vector3 &destination, int destinationOffset, bool interruptible, bool run, bool a5, bool *isRunning);
 	bool asyncWalkToWaypoint(int waypointId, int destinationOffset, bool run, bool a5);
 	void asyncWalkToXYZ(const Vector3 &destination, int destinationOffset, bool run, int a6);
+	void run();
 
 	bool tick(bool forceUpdate, Common::Rect *screenRect);
 	bool draw(Common::Rect *screenRect);
@@ -161,8 +165,8 @@ public:
 	Common::Rect *getScreenRectangle() { return &_screenRectangle; }
 	int getWalkbox() const { return _walkboxId; }
 	bool isRetired() const { return _isRetired; }
-	bool isTargetable() const { return _isTargetable; }
-	void setTargetable(bool targetable);
+	bool isTarget() const { return _isTarget; }
+	void setTarget(bool targetable);
 	bool isImmuneToObstacles() const { return _isImmuneToObstacles; }
 	bool inCombat() const { return _inCombat; }
 	bool isMoving() const { return _isMoving; }
@@ -177,6 +181,7 @@ public:
 	void faceItem(int itemId, bool animate);
 	void faceWaypoint(int waypointId, bool animate);
 	void faceXYZ(float x, float y, float z, bool animate);
+	void faceXYZ(const Vector3 &pos, bool animate);
 	void faceCurrentCamera(bool animate);
 	void faceHeading(int heading, bool animate);
 	void modifyFriendlinessToOther(int otherActorId, signed int change);
@@ -203,7 +208,7 @@ public:
 	void combatModeOff();
 
 	void setGoal(int goalNumber);
-	int getGoal()  const;
+	int getGoal() const;
 
 	float distanceFromActor(int otherActorId);
 
@@ -220,14 +225,14 @@ public:
 	int soundVolume() const;
 	int soundBalance() const;
 
+	bool isObstacleBetween(float targetX, float targetZ);
+
+	static int findTargetUnderMouse(BladeRunnerEngine *vm, int mouseX, int mouseY);
 private:
 	void setFacing(int facing, bool halfOrSet = true);
 	void setBoundingBox(const Vector3 &position, bool retired);
 	float distanceFromView(View *view) const;
 
-	bool loopWalk(const Vector3 &destination, int destinationOffset, bool interruptible, bool run, const Vector3 &start, float a6, float a7, bool a8, bool *isRunning, bool async);
-	bool walkTo(bool run, const Vector3 &destination, bool a3);
-
 	bool walkFindU1(const Vector3 &startPosition, const Vector3 &targetPosition, float a3, Vector3 *newDestination);
 	bool walkFindU2(Vector3 *newDestination, float targetWidth, int destinationOffset, float targetSize, const Vector3 &startPosition, const Vector3 &targetPosition);
 	bool walkToNearestPoint(const Vector3 &destination, float distance);
diff --git a/engines/bladerunner/actor_walk.cpp b/engines/bladerunner/actor_walk.cpp
index fccc8e2..3a2327a 100644
--- a/engines/bladerunner/actor_walk.cpp
+++ b/engines/bladerunner/actor_walk.cpp
@@ -37,8 +37,8 @@ namespace BladeRunner {
 ActorWalk::ActorWalk(BladeRunnerEngine *vm) {
 	_vm = vm;
 
-	_walking = 0;
-	_running = 0;
+	_walking = false;
+	_running = false;
 	_facing = -1;
 	_status = 0;
 
@@ -228,6 +228,16 @@ void ActorWalk::stop(int actorId, bool immediately, int combatAnimationMode, int
 	}
 }
 
+void ActorWalk::run(int actorId) {
+	_running = true;
+
+	int animationMode = kAnimationModeRun;
+	if (_vm->_actors[actorId]->inCombat()) {
+		animationMode = kAnimationModeCombatRun;
+	}
+	_vm->_actors[actorId]->changeAnimationMode(animationMode, false);
+}
+
 bool ActorWalk::isXYZEmpty(float x, float y, float z, int actorId) const {
 	if (_vm->_scene->_set->findWalkbox(x, z) == -1) {
 		return true;
diff --git a/engines/bladerunner/actor_walk.h b/engines/bladerunner/actor_walk.h
index 07e383a..e3e48b8 100644
--- a/engines/bladerunner/actor_walk.h
+++ b/engines/bladerunner/actor_walk.h
@@ -58,6 +58,7 @@ public:
 	bool findNearestEmptyPosition(int actorId, const Vector3 &from, int distance, Vector3 &out) const;
 
 	void stop(int actorId, bool immediately, int combatAnimationMode, int animationMode);
+	void run(int actorId);
 
 private:
 	int nextOnPath(int actorId, const Vector3 &from, const Vector3 &to, Vector3 &next) const;
diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp
index 5f565d9..a45c0e6 100644
--- a/engines/bladerunner/bladerunner.cpp
+++ b/engines/bladerunner/bladerunner.cpp
@@ -97,7 +97,7 @@ BladeRunnerEngine::BladeRunnerEngine(OSystem *syst, const ADGameDescription *des
 	_gameIsLoading   = false;
 	_sceneIsLoading  = false;
 
-	_walkingActorId         = -1;
+	_runningActorId         = -1;
 	_isWalkingInterruptible = false;
 	_interruptWalking       = false;
 
@@ -178,6 +178,7 @@ BladeRunnerEngine::BladeRunnerEngine(OSystem *syst, const ADGameDescription *des
 	for (int i = 0; i != kActorCount; ++i) {
 		_actors[i] = nullptr;
 	}
+	walkingReset();
 }
 
 BladeRunnerEngine::~BladeRunnerEngine() {
@@ -341,8 +342,7 @@ bool BladeRunnerEngine::startup(bool hasSavegames) {
 	_playerActor = _actors[_gameInfo->getPlayerId()];
 
 	_playerActor->setFPS(15);
-
-	// TODO: set _playerActor countdown timer 6
+	_playerActor->timerStart(6, 200);
 
 	// TODO: Set actor ids (redundant?)
 
@@ -863,16 +863,16 @@ void BladeRunnerEngine::gameTick() {
 					Vector3 pos = _view->calculateScreenPosition(0.5 * (a + b));
 					int color;
 
-					switch (sceneObject->sceneObjectType) {
+					switch (sceneObject->type) {
 					case kSceneObjectTypeActor:
 						color = 0b111110000000000;
 						drawBBox(a, b, _view, &_surfaceFront, color);
-						_mainFont->drawColor(_textActorNames->getText(sceneObject->sceneObjectId - kSceneObjectOffsetActors), _surfaceFront, pos.x, pos.y, color);
+						_mainFont->drawColor(_textActorNames->getText(sceneObject->id - kSceneObjectOffsetActors), _surfaceFront, pos.x, pos.y, color);
 						break;
 					case kSceneObjectTypeItem:
 						char itemText[40];
 						drawBBox(a, b, _view, &_surfaceFront, color);
-						sprintf(itemText, "item %i", sceneObject->sceneObjectId - kSceneObjectOffsetItems);
+						sprintf(itemText, "item %i", sceneObject->id - kSceneObjectOffsetItems);
 						_mainFont->drawColor(itemText, _surfaceFront, pos.x, pos.y, color);
 						break;
 					case kSceneObjectTypeObject:
@@ -883,10 +883,10 @@ void BladeRunnerEngine::gameTick() {
 							color = 0b000001111100000;
 						}
 						drawBBox(a, b, _view, &_surfaceFront, color);
-						_mainFont->drawColor(_scene->objectGetName(sceneObject->sceneObjectId - kSceneObjectOffsetObjects), _surfaceFront, pos.x, pos.y, color);
+						_mainFont->drawColor(_scene->objectGetName(sceneObject->id - kSceneObjectOffsetObjects), _surfaceFront, pos.x, pos.y, color);
 						break;
 					}
-					_surfaceFront.frameRect(sceneObject->screenRectangle, color);
+					_surfaceFront.frameRect(*sceneObject->screenRectangle, color);
 				}
 			}
 
@@ -1001,12 +1001,31 @@ void BladeRunnerEngine::actorsUpdate() {
 			Actor *actor = _actors[i];
 			if (actor->getSetId() == setId) {
 				_aiScripts->update(i);
-				actor->countdownTimersUpdate();
+				actor->timersUpdate();
 			}
 		}
 	}
 }
 
+void BladeRunnerEngine::walkingReset() {
+	_mouseClickTimeLast   = 0;
+	_mouseClickTimeDiff   = 0;
+	_walkingToExitId      = -1;
+	_isInsideScriptExit   = false;
+	_walkingToRegionId    = -1;
+	_isInsideScriptRegion = false;
+	_walkingToObjectId    = -1;
+	_isInsideScriptObject = false;
+	_walkingToItemId      = -1;
+	_isInsideScriptItem   = false;
+	_walkingToEmpty       = false;
+	_walkingToEmptyX      = 0;
+	_walkingToEmptyY      = 0;
+	_isInsideScriptEmpty  = false;
+	_walkingToActorId     = -1;
+	_isInsideScriptActor  = false;
+}
+
 void BladeRunnerEngine::handleEvents() {
 	if (shouldQuit()) {
 		_gameIsRunning = false;
@@ -1149,16 +1168,23 @@ void BladeRunnerEngine::handleKeyDown(Common::Event &event) {
 	}
 }
 
-void BladeRunnerEngine::handleMouseAction(int x, int y, bool buttonLeft, bool buttonDown) {
+void BladeRunnerEngine::handleMouseAction(int x, int y, bool mainButton, bool buttonDown) {
+	int timeNow = getTotalPlayTime();
+
+	if (buttonDown) {
+		_mouseClickTimeDiff = timeNow - _mouseClickTimeLast;
+		_mouseClickTimeLast = timeNow;
+	}
+
 	if (!playerHasControl() || _mouse->isDisabled()) {
 		return;
 	}
 
 	if (_kia->isOpen()) {
 		if (buttonDown) {
-			_kia->handleMouseDown(x, y, buttonLeft);
+			_kia->handleMouseDown(x, y, mainButton);
 		} else {
-			_kia->handleMouseUp(x, y, buttonLeft);
+			_kia->handleMouseUp(x, y, mainButton);
 		}
 		return;
 	}
@@ -1174,18 +1200,18 @@ void BladeRunnerEngine::handleMouseAction(int x, int y, bool buttonLeft, bool bu
 
 	if (_esper->isOpen()) {
 		if (buttonDown) {
-			_esper->handleMouseDown(x, y, buttonLeft);
+			_esper->handleMouseDown(x, y, mainButton);
 		} else {
-			_esper->handleMouseUp(x, y, buttonLeft);
+			_esper->handleMouseUp(x, y, mainButton);
 		}
 		return;
 	}
 
 	if (_vk->isOpen()) {
 		if (buttonDown) {
-			_vk->handleMouseDown(x, y, buttonLeft);
+			_vk->handleMouseDown(x, y, mainButton);
 		} else {
-			_vk->handleMouseUp(x, y, buttonLeft);
+			_vk->handleMouseUp(x, y, mainButton);
 		}
 		return;
 	}
@@ -1200,91 +1226,379 @@ void BladeRunnerEngine::handleMouseAction(int x, int y, bool buttonLeft, bool bu
 	}
 
 	if (_dialogueMenu->waitingForInput()) {
-		if (buttonLeft && !buttonDown) {
+		if (mainButton && !buttonDown) {
 			_dialogueMenu->mouseUp();
 		}
 		return;
 	}
 
-	if (buttonLeft && !buttonDown) {
+	if (mainButton) {
 		Vector3 scenePosition = _mouse->getXYZ(x, y);
 
 		bool isClickable;
 		bool isObstacle;
 		bool isTarget;
 
-		int sceneObjectId = _sceneObjects->findByXYZ(&isClickable, &isObstacle, &isTarget, scenePosition.x, scenePosition.y, scenePosition.z, true, false, true);
+		int sceneObjectId = _sceneObjects->findByXYZ(&isClickable, &isObstacle, &isTarget, scenePosition, true, false, true);
 		int exitIndex = _scene->_exits->getRegionAtXY(x, y);
+		int regionIndex = _scene->_regions->getRegionAtXY(x, y);
 
-		if ((sceneObjectId < 0 || sceneObjectId > 73) && exitIndex >= 0) {
-			handleMouseClickExit(x, y, exitIndex);
-			return;
+		if ((sceneObjectId < kSceneObjectOffsetActors || sceneObjectId >= kSceneObjectOffsetActors) && exitIndex >= 0) {
+			handleMouseClickExit(exitIndex, x, y, buttonDown);
+		} else if (regionIndex >= 0) {
+			handleMouseClickRegion(regionIndex, x, y, buttonDown);
+		} else if (sceneObjectId == -1) {
+			handleMouseClickEmpty(x, y, scenePosition, buttonDown);
+		} else if (sceneObjectId >= kSceneObjectOffsetActors && sceneObjectId < kSceneObjectOffsetItems) {
+			handleMouseClickActor(sceneObjectId - kSceneObjectOffsetActors, mainButton, buttonDown, scenePosition, x, y);
+		} else if (sceneObjectId >= kSceneObjectOffsetItems && sceneObjectId < kSceneObjectOffsetObjects) {
+			handleMouseClickItem(sceneObjectId - kSceneObjectOffsetItems, buttonDown);
+		} else if (sceneObjectId >= kSceneObjectOffsetObjects && sceneObjectId <= 293) {
+			handleMouseClick3DObject(sceneObjectId - kSceneObjectOffsetObjects, buttonDown, isClickable, isTarget);
 		}
-
-		int regionIndex = _scene->_regions->getRegionAtXY(x, y);
-		if (regionIndex >= 0) {
-			handleMouseClickRegion(x, y, regionIndex);
-			return;
+	} else if (buttonDown) {
+		if (_playerActor->inWalkLoop()) {
+			_playerActor->stopWalking(false);
 		}
+		_combat->change();
+	}
+}
 
-		if (sceneObjectId == -1) {
-			handleMouseClickEmpty(x, y, scenePosition);
-			return;
-		} else if (sceneObjectId >= 0 && sceneObjectId <= 73) {
-			handleMouseClickActor(x, y, sceneObjectId);
-			return;
-		} else if (sceneObjectId >= 74 && sceneObjectId <= 197) {
-			handleMouseClickItem(x, y, sceneObjectId - 74);
-			return;
-		} else if (sceneObjectId >= 198 && sceneObjectId <= 293) {
-			handleMouseClick3DObject(x, y, sceneObjectId - 198, isClickable, isTarget);
-			return;
-		}
+void BladeRunnerEngine::handleMouseClickExit(int exitId, int x, int y, bool buttonDown) {
+	debug("clicked on exit %d %d %d", exitId, x, y);
+
+	if (_isWalkingInterruptible && exitId != _walkingToExitId) {
+		_isWalkingInterruptible = false;
+		_interruptWalking = true;
+		walkingReset();
+		_walkingToExitId = exitId;
+		return;
 	}
-	if (!buttonLeft && buttonDown) {
-		// TODO: stop walking && switch combat mode
+
+	if (buttonDown) {
+		return;
 	}
 
+	if (_isInsideScriptExit && exitId == _walkingToExitId) {
+		_playerActor->run();
+		if (_mouseClickTimeDiff <= 10000) {
+			_playerActor->increaseFPS();
+		}
+	} else {
+		_walkingToExitId   = exitId;
+		_walkingToRegionId = -1;
+		_walkingToObjectId = -1;
+		_walkingToItemId   = -1;
+		_walkingToEmpty    = false;
+		_walkingToActorId  = -1;
+
+		_isInsideScriptExit = true;
+		_sceneScript->clickedOnExit(exitId);
+		_isInsideScriptExit = false;
+	}
 }
 
-void BladeRunnerEngine::handleMouseClickExit(int x, int y, int exitIndex) {
-	debug("clicked on exit %d %d %d", exitIndex, x, y);
-	_sceneScript->clickedOnExit(exitIndex);
-}
+void BladeRunnerEngine::handleMouseClickRegion(int regionId, int x, int y, bool buttonDown) {
+	debug("clicked on region %d %d %d", regionId, x, y);
+
+	if (_isWalkingInterruptible && regionId != _walkingToRegionId) {
+		_isWalkingInterruptible = false;
+		_interruptWalking = true;
+		walkingReset();
+		_walkingToRegionId = regionId;
+		return;
+	}
 
-void BladeRunnerEngine::handleMouseClickRegion(int x, int y, int regionIndex) {
-	debug("clicked on region %d %d %d", regionIndex, x, y);
-	_sceneScript->clickedOn2DRegion(regionIndex);
+	if (buttonDown || _mouse->isInactive()) {
+		return;
+	}
+
+	if (_isInsideScriptRegion && regionId == _walkingToRegionId) {
+		_playerActor->run();
+		if (_mouseClickTimeDiff <= 10000) {
+			_playerActor->increaseFPS();
+		}
+	} else {
+		_walkingToExitId   = -1;
+		_walkingToRegionId = regionId;
+		_walkingToObjectId = -1;
+		_walkingToItemId   = -1;
+		_walkingToEmpty    = false;
+		_walkingToActorId  = -1;
+
+		_isInsideScriptRegion = true;
+		_sceneScript->clickedOn2DRegion(regionId);
+		_isInsideScriptRegion = false;
+	}
 }
 
-void BladeRunnerEngine::handleMouseClick3DObject(int x, int y, int objectId, bool isClickable, bool isTarget) {
+void BladeRunnerEngine::handleMouseClick3DObject(int objectId, bool buttonDown, bool isClickable, bool isTarget) {
 	const char *objectName = _scene->objectGetName(objectId);
 	debug("Clicked on object %s", objectName);
-	_sceneScript->clickedOn3DObject(objectName, false);
+
+	if (_isWalkingInterruptible && objectId != _walkingToObjectId) {
+		_isWalkingInterruptible = false;
+		_interruptWalking = true;
+		walkingReset();
+		_walkingToObjectId = objectId;
+		return;
+	}
+
+	if (_mouse->isInactive()) {
+		return;
+	}
+
+	if (!_combat->isActive()) {
+		if (buttonDown || !isClickable) {
+			return;
+		}
+
+		if (_isInsideScriptObject && objectId == _walkingToObjectId) {
+			_playerActor->run();
+			if (_mouseClickTimeDiff <= 10000) {
+				_playerActor->increaseFPS();
+			}
+		} else {
+			_walkingToExitId   = -1;
+			_walkingToRegionId = -1;
+			_walkingToObjectId = objectId;
+			_walkingToItemId   = -1;
+			_walkingToEmpty    = false;
+			_walkingToActorId  = -1;
+
+			_isInsideScriptObject = true;
+			_sceneScript->clickedOn3DObject(objectName, false);
+			_isInsideScriptObject = false;
+		}
+	} else {
+		if (!buttonDown || !isTarget) {
+			return;
+		}
+		_playerActor->stopWalking(false);
+		_playerActor->faceObject(objectName, false);
+		_playerActor->changeAnimationMode(kAnimationModeCombatShoot, false);
+		_settings->decreaseAmmo();
+		_audioPlayer->playAud(_gameInfo->getSfxTrack(_combat->getHitSound()), 100, 0, 0, 90, 0);
+
+		//TODO mouse::randomize(Mouse);
+
+		_isInsideScriptObject = true;
+		_sceneScript->clickedOn3DObject(objectName, true);
+		_isInsideScriptObject = false;
+	}
 }
 
-void BladeRunnerEngine::handleMouseClickEmpty(int x, int y, Vector3 &mousePosition) {
+void BladeRunnerEngine::handleMouseClickEmpty(int x, int y, Vector3 &scenePosition, bool buttonDown) {
+	debug("Clicked on nothing %f, %f, %f", scenePosition.x, scenePosition.y, scenePosition.z);
+
+	if (_isWalkingInterruptible) {
+		_isWalkingInterruptible = false;
+		_interruptWalking = true;
+		walkingReset();
+		_walkingToEmpty = false;
+		return;
+	}
+
+	_isInsideScriptEmpty = true;
 	bool sceneMouseClick = _sceneScript->mouseClick(x, y);
+	_isInsideScriptEmpty = false;
 
 	if (sceneMouseClick) {
 		return;
 	}
 
-	bool isRunning;
-	debug("Clicked on nothing %f, %f, %f", mousePosition.x, mousePosition.y, mousePosition.z);
-	_playerActor->loopWalkToXYZ(mousePosition, 0, false, false, false, &isRunning);
+	int actorId = Actor::findTargetUnderMouse(this, x, y);
+	int itemId = _items->findTargetUnderMouse(x, y);
+
+	if (_combat->isActive() && buttonDown && actorId > 0 && itemId > 0) {
+		_playerActor->stopWalking(false);
+		if (actorId > 0) {
+			_playerActor->faceActor(actorId, false);
+		} else {
+			_playerActor->faceItem(itemId, false);
+		}
+		_playerActor->changeAnimationMode(kAnimationModeCombatShoot, false);
+		_settings->decreaseAmmo();
+		_audioPlayer->playAud(_gameInfo->getSfxTrack(_combat->getMissSound()), 100, 0, 0, 90, 0);
+
+		//TODO mouse::randomize(Mouse);
+
+		if (actorId) {
+			_aiScripts->shotAtAndMissed(actorId);
+		}
+	} else {
+		if (buttonDown) {
+			return;
+		}
+
+		_walkingToExitId   = -1;
+		_walkingToRegionId = -1;
+		_walkingToObjectId = -1;
+		_walkingToItemId   = -1;
+		_walkingToEmpty    = true;
+		_walkingToActorId  = -1;
+
+		if (_combat->isActive() && (actorId > 0 || itemId > 0)) {
+			return;
+		}
+
+		int xDist = abs(_walkingToEmptyX - x);
+		int yDist = abs(_walkingToEmptyY - y);
+
+		_walkingToEmptyX = x;
+		_walkingToEmptyY = y;
+
+		bool inWalkbox = false;
+		float altitude = _scene->_set->getAltitudeAtXZ(scenePosition.x, scenePosition.z, &inWalkbox);
+
+		if (!inWalkbox || scenePosition.y >= altitude + 6.0f) {
+			return;
+		}
+
+		bool run = _playerActor->isRunning();;
+		if (_mouseClickTimeDiff <= 10000 && xDist < 10 && yDist < 10) {
+			run = true;
+		}
+
+		_playerActor->walkTo(run, scenePosition, false);
+
+		if (run && _playerActor->isWalking()) {
+			_playerActor->increaseFPS();
+		}
+	}
 }
 
-void BladeRunnerEngine::handleMouseClickItem(int x, int y, int itemId) {
+void BladeRunnerEngine::handleMouseClickItem(int itemId, bool buttonDown) {
 	debug("Clicked on item %d", itemId);
-	_sceneScript->clickedOnItem(itemId, false);
+
+	if (_isWalkingInterruptible && itemId != _walkingToItemId) {
+		_isWalkingInterruptible = false;
+		_interruptWalking = true;
+		walkingReset();
+		_walkingToItemId = itemId;
+		return;
+	}
+
+	if (_mouse->isInactive()) {
+		return;
+	}
+
+	if (!_combat->isActive()) {
+		if (buttonDown) {
+			return;
+		}
+
+		if (_isInsideScriptItem && itemId == _walkingToItemId) {
+			_playerActor->run();
+			if (_mouseClickTimeDiff <= 10000) {
+				_playerActor->increaseFPS();
+			}
+		} else {
+			_walkingToExitId = -1;
+			_walkingToRegionId = -1;
+			_walkingToObjectId = -1;
+			_walkingToItemId = itemId;
+			_walkingToEmpty = false;
+			_walkingToActorId = -1;
+
+			_isInsideScriptItem = true;
+			_sceneScript->clickedOnItem(itemId, false);
+			_isInsideScriptItem = false;
+		}
+	} else {
+		if (!buttonDown || !_items->isTarget(itemId) /* || _mouse->isRandomized() */) {
+			return;
+		}
+
+		_playerActor->stopWalking(false);
+		_playerActor->faceItem(itemId, false);
+		_playerActor->changeAnimationMode(kAnimationModeCombatShoot, false);
+		_settings->decreaseAmmo();
+		_audioPlayer->playAud(_gameInfo->getSfxTrack(_combat->getHitSound()), 100, 0, 0, 90, 0);
+
+		//TODO mouse::randomize(Mouse);
+		_isInsideScriptItem = true;
+		_sceneScript->clickedOnItem(itemId, true);
+		_isInsideScriptItem = false;
+	}
 }
 
-void BladeRunnerEngine::handleMouseClickActor(int x, int y, int actorId) {
+void BladeRunnerEngine::handleMouseClickActor(int actorId, bool mainButton, bool buttonDown, Vector3 &scenePosition, int x, int y) {
 	debug("Clicked on actor %d", actorId);
-	bool t = _sceneScript->clickedOnActor(actorId);
-	if (!_combat->isActive() && !t) {
-		_aiScripts->clickedByPlayer(actorId);
+
+	if (_isWalkingInterruptible && actorId != _walkingToActorId) {
+		_isWalkingInterruptible = false;
+		_interruptWalking = true;
+		walkingReset();
+		_walkingToActorId = actorId;
+		return;
+	}
+
+	if (_mouse->isInactive()) {
+		return;
+	}
+
+	if (!buttonDown) {
+		if (actorId == kActorMcCoy) {
+			if (mainButton) {
+				if (!_combat->isActive()) {
+					_kia->openLastOpened();
+				}
+			} else if (!_playerActor->inWalkLoop()) {
+				_combat->change();
+			}
+			return;
+		}
+
+		if (_isInsideScriptActor && actorId == _walkingToActorId) {
+			_playerActor->run();
+			if (_mouseClickTimeDiff <= 10000) {
+				_playerActor->increaseFPS();
+			}
+		} else {
+			_walkingToExitId = -1;
+			_walkingToRegionId = -1;
+			_walkingToObjectId = -1;
+			_walkingToItemId = -1;
+			_walkingToEmpty = false;
+			_walkingToActorId = actorId;
+
+			_isInsideScriptActor = true;
+			bool processedBySceneScript = _sceneScript->clickedOnActor(actorId);
+			_isInsideScriptActor = false;
+
+			if (!_combat->isActive() && !processedBySceneScript) {
+				_aiScripts->clickedByPlayer(actorId);
+			}
+		}
+	} else {
+		if (!_combat->isActive() || actorId == kActorMcCoy || !_actors[actorId]->isTarget() || _actors[actorId]->isRetired() /*|| _mouse->isRandomized()*/) {
+			return;
+		}
+		_playerActor->stopWalking(false);
+		_playerActor->faceActor(actorId, false);
+		_playerActor->changeAnimationMode(kAnimationModeCombatShoot, false);
+		_settings->decreaseAmmo();
+
+		float targetX = _actors[actorId]->getX();
+		float targetZ = _actors[actorId]->getZ();
+
+		bool missed = _playerActor->isObstacleBetween(targetX, targetZ);
+
+		_audioPlayer->playAud(_gameInfo->getSfxTrack(missed ? _combat->getMissSound() : _combat->getHitSound()), 100, 0, 0, 90, 0);
+
+		//TODO mouse::randomize(Mouse);
+
+		if (missed) {
+			_aiScripts->shotAtAndMissed(actorId);
+		} else {
+			_isInsideScriptActor = true;
+			bool canShoot = _aiScripts->shotAtAndHit(actorId);
+			_isInsideScriptActor = false;
+			if (!canShoot) {
+				_combat->shoot(actorId, scenePosition, x);
+			}
+		}
 	}
 }
 
diff --git a/engines/bladerunner/bladerunner.h b/engines/bladerunner/bladerunner.h
index 07e52de..373974f 100644
--- a/engines/bladerunner/bladerunner.h
+++ b/engines/bladerunner/bladerunner.h
@@ -174,7 +174,25 @@ public:
 	int _walkSoundId;
 	int _walkSoundVolume;
 	int _walkSoundBalance;
-	int _walkingActorId;
+	int _runningActorId;
+
+	int _mouseClickTimeLast;
+	int _mouseClickTimeDiff;
+
+	int  _walkingToExitId;
+	bool _isInsideScriptExit;
+	int  _walkingToRegionId;
+	bool _isInsideScriptRegion;
+	int  _walkingToObjectId;
+	bool _isInsideScriptObject;
+	int  _walkingToItemId;
+	bool _isInsideScriptItem;
+	bool _walkingToEmpty;
+	int _walkingToEmptyX;
+	int _walkingToEmptyY;
+	bool _isInsideScriptEmpty;
+	int _walkingToActorId;
+	bool _isInsideScriptActor;
 
 private:
 	MIXArchive _archives[kArchiveCount];
@@ -199,17 +217,22 @@ public:
 
 	void gameLoop();
 	void gameTick();
+
 	void actorsUpdate();
+
+	void walkingReset();
+
 	void handleEvents();
 	void handleKeyUp(Common::Event &event);
 	void handleKeyDown(Common::Event &event);
-	void handleMouseAction(int x, int y, bool buttonLeft, bool buttonDown);
-	void handleMouseClickExit(int x, int y, int exitIndex);
-	void handleMouseClickRegion(int x, int y, int regionIndex);
-	void handleMouseClickItem(int x, int y, int itemId);
-	void handleMouseClickActor(int x, int y, int actorId);
-	void handleMouseClick3DObject(int x, int y, int objectId, bool isClickable, bool isTarget);
-	void handleMouseClickEmpty(int x, int y, Vector3 &mousePosition);
+	void handleMouseAction(int x, int y, bool mainButton, bool buttonDown);
+	void handleMouseClickExit(int exitId, int x, int y, bool buttonDown);
+	void handleMouseClickRegion(int regionId, int x, int y, bool buttonDown);
+	void handleMouseClickItem(int itemId, bool buttonDown);
+	void handleMouseClickActor(int actorId, bool mainButton, bool buttonDown, Vector3 &scenePosition, int x, int y);
+	void handleMouseClick3DObject(int objectId, bool buttonDown, bool isClickable, bool isTarget);
+	void handleMouseClickEmpty(int x, int y, Vector3 &scenePosition, bool buttonDown);
+
 	void gameWaitForActive();
 	void loopActorSpeaking();
 
diff --git a/engines/bladerunner/boundingbox.cpp b/engines/bladerunner/boundingbox.cpp
index f7e7eca..a1c79a1 100644
--- a/engines/bladerunner/boundingbox.cpp
+++ b/engines/bladerunner/boundingbox.cpp
@@ -50,6 +50,10 @@ bool BoundingBox::inside(float x, float y, float z) const {
 	    && z >= _vertices[0].z && z <= _vertices[1].z;
 }
 
+bool BoundingBox::inside(Vector3 &position) const {
+	return inside(position.x, position.y, position.z);
+}
+
 void BoundingBox::setXYZ(float x0, float y0, float z0, float x1, float y1, float z1) {
 	_vertices[0].x = x0;
 	_vertices[0].y = y0;
diff --git a/engines/bladerunner/boundingbox.h b/engines/bladerunner/boundingbox.h
index 3f42318..11922cb 100644
--- a/engines/bladerunner/boundingbox.h
+++ b/engines/bladerunner/boundingbox.h
@@ -36,6 +36,7 @@ public:
 
 	void expand(float x0, float y0, float z0, float x1, float y1, float z1);
 	bool inside(float x, float y, float z) const;
+	bool inside(Vector3 &position) const;
 
 	void setXYZ(float x0, float y0, float z0, float x1, float y1, float z1);
 	void getXYZ(float *x0, float *y0, float *z0, float *x1, float *y1, float *z1) const;
diff --git a/engines/bladerunner/combat.cpp b/engines/bladerunner/combat.cpp
index 26b8b5d..c371f7b 100644
--- a/engines/bladerunner/combat.cpp
+++ b/engines/bladerunner/combat.cpp
@@ -33,6 +33,13 @@ namespace BladeRunner {
 Combat::Combat(BladeRunnerEngine *vm) {
 	_vm = vm;
 
+	reset();
+}
+
+Combat::~Combat() {
+}
+
+void Combat::reset() {
 	_active = false;
 	_enabled = true;
 
@@ -40,15 +47,12 @@ Combat::Combat(BladeRunnerEngine *vm) {
 	_ammoDamage[1] = 20;
 	_ammoDamage[2] = 30;
 
-	for (int i = 0; i < 9; i++) {
+	for (int i = 0; i < kSoundCount; i++) {
 		_hitSoundId[i] = -1;
 		_missSoundId[i] = -1;
 	}
 }
 
-Combat::~Combat() {
-}
-
 void Combat::activate() {
 	if(_enabled) {
 		_vm->_playerActor->combatModeOn(-1, -1, -1, -1, kAnimationModeCombatIdle, kAnimationModeCombatWalk, kAnimationModeCombatRun, -1, -1, -1, _vm->_combat->_ammoDamage[_vm->_settings->getAmmoType()], 0, 0);
@@ -63,7 +67,17 @@ void Combat::deactivate() {
 	}
 }
 
-bool Combat::isActive() {
+void Combat::change() {
+	if (!_vm->_playerActor->inWalkLoop() && _enabled) {
+		if (_active) {
+			deactivate();
+		} else {
+			activate();
+		}
+	}
+}
+
+bool Combat::isActive() const{
 	return _active;
 }
 
@@ -91,4 +105,8 @@ int Combat::getMissSound() {
 	return _hitSoundId[3 * _vm->_settings->getAmmoType() + _vm->_rnd.getRandomNumber(2)];
 }
 
+void Combat::shoot(int actorId, Vector3 &to, int screenX) {
+
+}
+
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/combat.h b/engines/bladerunner/combat.h
index 8f0119a..21989da 100644
--- a/engines/bladerunner/combat.h
+++ b/engines/bladerunner/combat.h
@@ -25,15 +25,19 @@
 
 namespace BladeRunner {
 
+class Vector3;
+
 class BladeRunnerEngine;
 
 class Combat {
+	static const int kSoundCount = 9;
+
 	BladeRunnerEngine *_vm;
 
 	bool _active;
 	bool _enabled;
-	int _hitSoundId[9];
-	int _missSoundId[9];
+	int _hitSoundId[kSoundCount];
+	int _missSoundId[kSoundCount];
 //	int _random1;
 //	int _random2;
 
@@ -44,9 +48,12 @@ public:
 	Combat(BladeRunnerEngine *vm);
 	~Combat();
 
+	void reset();
+
 	void activate();
 	void deactivate();
-	bool isActive();
+	void change();
+	bool isActive() const;
 
 	void enable();
 	void disable();
@@ -55,6 +62,8 @@ public:
 	void setMissSound(int ammoType, int column, int soundId);
 	int getHitSound();
 	int getMissSound();
+
+	void shoot(int actorId, Vector3 &to, int screenX);
 };
 
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/game_constants.h b/engines/bladerunner/game_constants.h
index 30b28de..54f5fed 100644
--- a/engines/bladerunner/game_constants.h
+++ b/engines/bladerunner/game_constants.h
@@ -559,8 +559,11 @@ enum AnimationModes {
 	kAnimationModeWalk = 1,
 	kAnimationModeRun = 2,
 	kAnimationModeCombatIdle = 4,
+	kAnimationModeCombatAim = 5,
+	kAnimationModeCombatShoot = 6,
 	kAnimationModeCombatWalk = 7,
-	kAnimationModeCombatRun = 8
+	kAnimationModeCombatRun = 8,
+	kAnimationModeFeeding = 52
 };
 
 enum SceneLoopMode {
@@ -804,6 +807,21 @@ enum Elevators {
 	kElevatorPS = 2
 };
 
+// enum SceneObjectOffset {
+// 	kSceneObjectActorIdStart  = 0,
+// 	kSceneObjectActorIdEnd    = kSceneObjectActorIdStart  +  73,
+// 	kSceneObjectItemIdStart   = kSceneObjectActorIdEnd    +   1,
+// 	kSceneObjectItemIdEnd     = kSceneObjectItemIdStart   + 123,
+// 	kSceneObjectObjectIdStart = kSceneObjectItemIdEnd     +   1,
+// 	kSceneObjectObjectIdEnd   = kSceneObjectObjectIdStart +  95
+// };
+
+enum SceneObjectOffset {
+	kSceneObjectOffsetActors  = 0,
+	kSceneObjectOffsetItems   = 74,
+	kSceneObjectOffsetObjects = 198
+};
+
 } // End of namespace BladeRunner
 
 #endif
diff --git a/engines/bladerunner/item.cpp b/engines/bladerunner/item.cpp
index eafc99c..1d2de92 100644
--- a/engines/bladerunner/item.cpp
+++ b/engines/bladerunner/item.cpp
@@ -47,7 +47,7 @@ Item::Item(BladeRunnerEngine *vm) {
 	_screenX = 0;
 	_screenY = 0;
 	_depth = 0.0f;
-	_isTargetable = false;
+	_isTarget = false;
 	_isSpinning = false;
 	_facingChange = 0;
 	_isVisible = true;
@@ -69,8 +69,8 @@ void Item::getWidthHeight(int *width, int *height) const {
 	*height = _height;
 }
 
-bool Item::isTargetable() const {
-	return _isTargetable;
+bool Item::isTarget() const {
+	return _isTarget;
 }
 
 bool Item::tick(Common::Rect *screenRect, bool special) {
@@ -134,7 +134,7 @@ void Item::setXYZ(Vector3 position) {
 	_depth = screenPosition.z * 25.5f;
 }
 
-void Item::setup(int itemId, int setId, int animationId, Vector3 position, int facing, int height, int width, bool isTargetableFlag, bool isVisibleFlag, bool isPoliceMazeEnemyFlag) {
+void Item::setup(int itemId, int setId, int animationId, Vector3 position, int facing, int height, int width, bool isTarget, bool isVisible, bool isPoliceMazeEnemy) {
 	_itemId = itemId;
 	_setId = setId;
 	_animationId = animationId;
@@ -142,9 +142,9 @@ void Item::setup(int itemId, int setId, int animationId, Vector3 position, int f
 	_angle = facing * (M_PI / 512.0f);
 	_width = width;
 	_height = height;
-	_isTargetable = isTargetableFlag;
-	_isVisible = isVisibleFlag;
-	_isPoliceMazeEnemy = isPoliceMazeEnemyFlag;
+	_isTarget = isTarget;
+	_isVisible = isVisible;
+	_isPoliceMazeEnemy = isPoliceMazeEnemy;
 	setXYZ(position);
 	_screenRectangle.bottom = -1;
 	_screenRectangle.right = -1;
@@ -152,4 +152,12 @@ void Item::setup(int itemId, int setId, int animationId, Vector3 position, int f
 	_screenRectangle.left = -1;
 }
 
+bool Item::isUnderMouse(int mouseX, int mouseY) const {
+	return _isVisible
+	    && mouseX >= _screenRectangle.left   - 10
+	    && mouseX <= _screenRectangle.right  + 10
+	    && mouseY >= _screenRectangle.top    - 10
+	    && mouseY <= _screenRectangle.bottom + 10;
+}
+
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/item.h b/engines/bladerunner/item.h
index e14aaa5..09f5ae6 100644
--- a/engines/bladerunner/item.h
+++ b/engines/bladerunner/item.h
@@ -52,7 +52,7 @@ class Item {
 	int          _screenX;
 	int          _screenY;
 	float        _depth;
-	bool         _isTargetable;
+	bool         _isTarget;
 	bool         _isSpinning;
 	int          _facingChange;
 	bool         _isVisible;
@@ -65,10 +65,12 @@ public:
 	void setXYZ(Vector3 position);
 	void getWidthHeight(int *width, int *height) const;
 
-	bool isTargetable() const;
+	bool isTarget() const;
 	bool tick(Common::Rect *screenRect, bool special);
 
-	void setup(int itemId, int setId, int animationId, Vector3 position, int facing, int height, int width, bool isTargetableFlag, bool isVisibleFlag, bool isPoliceMazeEnemyFlag);
+	void setup(int itemId, int setId, int animationId, Vector3 position, int facing, int height, int width, bool isTarget, bool isVisible, bool isPoliceMazeEnemy);
+
+	bool isUnderMouse(int mouseX, int mouseY) const;
 };
 
 }
diff --git a/engines/bladerunner/items.cpp b/engines/bladerunner/items.cpp
index e85366e..5e79f7a 100644
--- a/engines/bladerunner/items.cpp
+++ b/engines/bladerunner/items.cpp
@@ -59,15 +59,15 @@ void Items::tick() {
 		if (_items[i]->_setId != setId) {
 			continue;
 		}
-		bool set14NotTarget = setId == kSetPS10_PS11_PS12_PS13 && !_items[i]->isTargetable();
+		bool notPoliceMazeTarget = setId == kSetPS10_PS11_PS12_PS13 && !_items[i]->isTarget();
 		Common::Rect screenRect;
-		if (_items[i]->tick(&screenRect, set14NotTarget)) {
+		if (_items[i]->tick(&screenRect, notPoliceMazeTarget)) {
 			_vm->_zbuffer->mark(screenRect);
 		}
 	}
 }
 
-bool Items::addToWorld(int itemId, int animationId, int setId, Vector3 position, int facing, int height, int width, bool isTargetableFlag, bool isVisibleFlag, bool isPoliceMazeEnemyFlag, bool addToSetFlag) {
+bool Items::addToWorld(int itemId, int animationId, int setId, Vector3 position, int facing, int height, int width, bool isTarget, bool isVisible, bool isPoliceMazeEnemy, bool addToSet) {
 	if (_items.size() >= 100) {
 		return false;
 	}
@@ -77,11 +77,11 @@ bool Items::addToWorld(int itemId, int animationId, int setId, Vector3 position,
 	}
 
 	Item *item = new Item(_vm);
-	item->setup(itemId, setId, animationId, position, facing, height, width, isTargetableFlag, isVisibleFlag, isPoliceMazeEnemyFlag);
+	item->setup(itemId, setId, animationId, position, facing, height, width, isTarget, isVisible, isPoliceMazeEnemy);
 	_items.push_back(item);
 
-	if (addToSetFlag && setId == _vm->_scene->getSetId()) {
-		return _vm->_sceneObjects->addItem(itemId + kSceneObjectOffsetItems, &item->_boundingBox, &item->_screenRectangle, isTargetableFlag, isVisibleFlag);
+	if (addToSet && setId == _vm->_scene->getSetId()) {
+		return _vm->_sceneObjects->addItem(itemId + kSceneObjectOffsetItems, &item->_boundingBox, &item->_screenRectangle, isTarget, isVisible);
 	}
 	return true;
 }
@@ -94,7 +94,7 @@ bool Items::addToSet(int setId) {
 	for (int i = 0; i < itemCount; i++) {
 		Item *item = _vm->_items->_items[i];
 		if (item->_setId == setId) {
-			_vm->_sceneObjects->addItem(item->_itemId + kSceneObjectOffsetItems, &item->_boundingBox, &item->_screenRectangle, item->isTargetable(), item->_isVisible);
+			_vm->_sceneObjects->addItem(item->_itemId + kSceneObjectOffsetItems, &item->_boundingBox, &item->_screenRectangle, item->isTarget(), item->_isVisible);
 		}
 	}
 	return true;
@@ -116,10 +116,29 @@ bool Items::remove(int itemId) {
 	return true;
 }
 
+bool Items::isTarget(int itemId) const {
+	int itemIndex = findItem(itemId);
+	if (itemIndex == -1) {
+		return false;
+	}
+	return _items[itemIndex]->isTarget();
+}
+
+int Items::findTargetUnderMouse(int mouseX, int mouseY) const {
+	int setId = _vm->_scene->getSetId();
+	for (int i = 0 ; i < (int)_items.size(); ++i) {
+		if (_items[i]->_setId == setId && _items[i]->isTarget() && _items[i]->isUnderMouse(mouseX, mouseY)) {
+			return _items[i]->_itemId;
+		}
+	}
+	return -1;
+}
+
 int Items::findItem(int itemId) const {
 	for (int i = 0; i < (int)_items.size(); i++) {
-		if (_items[i]->_itemId == itemId)
+		if (_items[i]->_itemId == itemId) {
 			return i;
+		}
 	}
 	return -1;
 }
diff --git a/engines/bladerunner/items.h b/engines/bladerunner/items.h
index c49231f..711abc6 100644
--- a/engines/bladerunner/items.h
+++ b/engines/bladerunner/items.h
@@ -43,10 +43,13 @@ public:
 	void getWidthHeight(int itemId, int *width, int *height) const;
 
 	void tick();
-	bool addToWorld(int itemId, int animationId, int setId, Vector3 position, int facing, int height, int width, bool isTargetableFlag, bool isVisibleFlag, bool isPoliceMazeEnemyFlag, bool addToSetFlag);
+	bool addToWorld(int itemId, int animationId, int setId, Vector3 position, int facing, int height, int width, bool isTarget, bool isVisible, bool isPoliceMazeEnemy, bool addToSet);
 	bool addToSet(int itemId);
 	bool remove(int itemId);
 
+	bool isTarget(int itemId) const;
+	int findTargetUnderMouse(int mouseX, int mouseY) const;
+
 private:
 	int findItem(int itemId) const;
 };
diff --git a/engines/bladerunner/mouse.cpp b/engines/bladerunner/mouse.cpp
index 3dfd1fe..7d67e98 100644
--- a/engines/bladerunner/mouse.cpp
+++ b/engines/bladerunner/mouse.cpp
@@ -22,11 +22,16 @@
 
 #include "bladerunner/mouse.h"
 
+#include "bladerunner/actor.h"
 #include "bladerunner/bladerunner.h"
+#include "bladerunner/combat.h"
 #include "bladerunner/dialogue_menu.h"
+#include "bladerunner/game_constants.h"
+#include "bladerunner/items.h"
 #include "bladerunner/regions.h"
 #include "bladerunner/scene.h"
 #include "bladerunner/scene_objects.h"
+#include "bladerunner/settings.h"
 #include "bladerunner/shape.h"
 #include "bladerunner/view.h"
 #include "bladerunner/zbuffer.h"
@@ -267,22 +272,25 @@ void Mouse::tick(int x, int y) {
 		return;
 	}
 
-	Vector3 mousePosition = getXYZ(x, y);
+	Vector3 scenePosition = getXYZ(x, y);
 	int cursorId = 0;
 
 	bool isClickable = false;
 	bool isObstacle  = false;
 	bool isTarget    = false;
 
-	int sceneObjectId = _vm->_sceneObjects->findByXYZ(&isClickable, &isObstacle, &isTarget, mousePosition.x, mousePosition.y, mousePosition.z, 1, 0, 1);
+	int sceneObjectId = _vm->_sceneObjects->findByXYZ(&isClickable, &isObstacle, &isTarget, scenePosition, true, false, true);
 	int exitType = _vm->_scene->_exits->getTypeAtXY(x, y);
 
-	if (sceneObjectId >= 0 && sceneObjectId <= 74) {
+	if (sceneObjectId >= kSceneObjectOffsetActors && sceneObjectId < kSceneObjectOffsetItems) {
 		exitType = -1;
 	}
 
 	if (exitType != -1) {
 		switch (exitType) {
+		case 0:
+			cursorId = 12;
+			break;
 		case 1:
 			cursorId = 13;
 			break;
@@ -292,26 +300,76 @@ void Mouse::tick(int x, int y) {
 		case 3:
 			cursorId = 15;
 			break;
-		default:
-			cursorId = 12;
 		}
 		setCursor(cursorId);
 		return;
 	}
 
-	if (true /* not in combat */) {
-		if (sceneObjectId == 0
-		 || (sceneObjectId >= 0 && isClickable)
-		 || _vm->_scene->_regions->getRegionAtXY(x, y) >= 0) {
+	if (!_vm->_combat->isActive()) {
+		if (sceneObjectId == kActorMcCoy + kSceneObjectOffsetActors
+		|| (sceneObjectId > 0 && isClickable)
+		|| _vm->_scene->_regions->getRegionAtXY(x, y) >= 0) {
 			cursorId = 1;
 		}
 		setCursor(cursorId);
 		return;
 	}
 
+	int animationMode = _vm->_playerActor->getAnimationMode();
+	int actorId = Actor::findTargetUnderMouse(_vm, x, y);
+	int itemId = _vm->_items->findTargetUnderMouse(x, y);
+
+	bool isObject = isTarget && sceneObjectId >= kSceneObjectOffsetObjects && sceneObjectId <= 293;
+
+	if (!_vm->_playerActor->isMoving()) {
+		if (actorId >= 0) {
+			_vm->_playerActor->faceActor(actorId, false);
+		} else if (itemId >= 0) {
+			_vm->_playerActor->faceItem(itemId, false);
+		} else if (isObject) {
+			_vm->_playerActor->faceXYZ(scenePosition, false);
+		}
+	}
+
+	if (actorId >= 0 || itemId >= 0 || isObject) {
+		switch (_vm->_settings->getAmmoType()) {
+		case 0:
+			cursorId = 7;
+			break;
+		case 1:
+			cursorId = 9;
+			break;
+		case 2:
+			cursorId = 11;
+			break;
+		}
+
+		if (!_vm->_playerActor->isMoving() && animationMode != kAnimationModeCombatAim && animationMode != 22 && animationMode != 49) {
+			_vm->_playerActor->changeAnimationMode(kAnimationModeCombatAim, false);
+		}
+	} else {
+		switch (_vm->_settings->getAmmoType()) {
+		case 0:
+			cursorId = 6;
+			break;
+		case 1:
+			cursorId = 8;
+			break;
+		case 2:
+			cursorId = 10;
+			break;
+		}
+		if (!_vm->_playerActor->isMoving() && animationMode != kAnimationModeCombatIdle && animationMode != 22 && animationMode != 49) {
+			_vm->_playerActor->changeAnimationMode(kAnimationModeCombatIdle, false);
+		}
+	}
 	setCursor(cursorId);
 }
 
+bool Mouse::isInactive() const {
+	return _cursor == 6 || _cursor == 8 || _cursor == 10;
+}
+
 // TEST: RC01 after intro: [290, 216] -> [-204.589249 51.450668 7.659241]
 Vector3 Mouse::getXYZ(int x, int y) const {
 	if (_vm->_scene->getSetId() == -1)
diff --git a/engines/bladerunner/mouse.h b/engines/bladerunner/mouse.h
index 64b0199..2f33d72 100644
--- a/engines/bladerunner/mouse.h
+++ b/engines/bladerunner/mouse.h
@@ -62,6 +62,7 @@ public:
 	void updateCursorFrame();
 
 	void tick(int x, int y);
+	bool isInactive() const;
 
 // private:
 	Vector3 getXYZ(int x, int y) const;
diff --git a/engines/bladerunner/movement_track.cpp b/engines/bladerunner/movement_track.cpp
index 13b60d1..47eb56a 100644
--- a/engines/bladerunner/movement_track.cpp
+++ b/engines/bladerunner/movement_track.cpp
@@ -41,15 +41,15 @@ void MovementTrack::reset() {
 		_entries[i].waypointId = -1;
 		_entries[i].delay = -1;
 		_entries[i].angle = -1;
-		_entries[i].running = 0;
+		_entries[i].run = false;
 	}
 }
 
-int MovementTrack::append(int waypointId, int delay, int running) {
-	return append(waypointId, delay, -1, running);
+int MovementTrack::append(int waypointId, int delay, bool run) {
+	return append(waypointId, delay, -1, run);
 }
 
-int MovementTrack::append(int waypointId, int delay, int angle, int running) {	
+int MovementTrack::append(int waypointId, int delay, int angle, bool run) {
 	if (_lastIndex >= kSize) {
 		return 0;
 	}
@@ -57,7 +57,7 @@ int MovementTrack::append(int waypointId, int delay, int angle, int running) {
 	_entries[_lastIndex].waypointId = waypointId;
 	_entries[_lastIndex].delay = delay;
 	_entries[_lastIndex].angle = angle;
-	_entries[_lastIndex].running = running;
+	_entries[_lastIndex].run = run;
 
 	_lastIndex++;
 	_hasNext = true;
@@ -90,18 +90,18 @@ bool MovementTrack::hasNext() const {
 	return _hasNext;
 }
 
-bool MovementTrack::next(int *waypointId, int *delay, int *angle, int *running) {
+bool MovementTrack::next(int *waypointId, int *delay, int *angle, bool *run) {
 	if (_currentIndex < _lastIndex && _hasNext) {
 		*waypointId = _entries[_currentIndex].waypointId;
 		*delay = _entries[_currentIndex].delay;
 		*angle = _entries[_currentIndex].angle;
-		*running = _entries[_currentIndex++].running;
+		*run = _entries[_currentIndex++].run;
 		return true;
 	} else {
 		*waypointId = -1;
 		*delay = -1;
 		*angle = -1;
-		*running = 0;
+		*run = false;
 		_hasNext = false;
 		return false;
 	}
diff --git a/engines/bladerunner/movement_track.h b/engines/bladerunner/movement_track.h
index 174b222..cba9b69 100644
--- a/engines/bladerunner/movement_track.h
+++ b/engines/bladerunner/movement_track.h
@@ -34,10 +34,10 @@ class MovementTrack {
 	static const int kSize = 100;
 
 	struct Entry {
-		int waypointId;
-		int delay;
-		int angle;
-		int running;
+		int  waypointId;
+		int  delay;
+		int  angle;
+		bool run;
 	};
 
 	int   _currentIndex;
@@ -49,15 +49,15 @@ class MovementTrack {
 public:
 	MovementTrack();
 	~MovementTrack();
-	int append(int waypointId, int delay, int running);
-	int append(int waypointId, int delay, int angle, int running);
+	int append(int waypointId, int delay, bool run);
+	int append(int waypointId, int delay, int angle, bool run);
 	void flush();
 	void repeat();
 	void pause();
 	void unpause();
 	bool isPaused() const;
 	bool hasNext() const;
-	bool next(int *waypointId, int *delay, int *angle, int *running);
+	bool next(int *waypointId, int *delay, int *angle, bool *run);
 
 	//int saveGame();
 
diff --git a/engines/bladerunner/scene.cpp b/engines/bladerunner/scene.cpp
index f20c0be..c327e80 100644
--- a/engines/bladerunner/scene.cpp
+++ b/engines/bladerunner/scene.cpp
@@ -76,13 +76,15 @@ bool Scene::open(int setId, int sceneId, bool isLoadingGame) {
 		_vm->_actorDialogueQueue->flush(1, false);
 	}
 
+	_vm->walkingReset();
+
 	_setId = setId;
 	_sceneId = sceneId;
 
 	const Common::String sceneName = _vm->_gameInfo->getSceneName(_sceneId);
 
 	if (isLoadingGame) {
-		// TODO: Set up overlays
+		// TODO: _vm->overlays->resume()
 	} else {
 		_regions->clear();
 		_exits->clear();
@@ -162,7 +164,7 @@ bool Scene::open(int setId, int sceneId, bool isLoadingGame) {
 				   actor->getScreenRectangle(),
 				   1,
 				   0,
-				   actor->isTargetable(),
+				   actor->isTarget(),
 				   actor->isRetired());
 		}
 	}
diff --git a/engines/bladerunner/scene_objects.cpp b/engines/bladerunner/scene_objects.cpp
index 9f4adb5..5d22be4 100644
--- a/engines/bladerunner/scene_objects.cpp
+++ b/engines/bladerunner/scene_objects.cpp
@@ -48,9 +48,9 @@ SceneObjects::~SceneObjects() {
 
 void SceneObjects::clear() {
 	for (int i = 0; i < kSceneObjectCount; ++i) {
-		_sceneObjects[i].sceneObjectId    = -1;
-		_sceneObjects[i].sceneObjectType  = kSceneObjectTypeUnknown;
-		_sceneObjects[i].distanceToCamera = 0;
+		_sceneObjects[i].id               = -1;
+		_sceneObjects[i].type             = kSceneObjectTypeUnknown;
+		_sceneObjects[i].distanceToCamera = 0.0f;
 		_sceneObjects[i].isPresent        = false;
 		_sceneObjects[i].isClickable      = false;
 		_sceneObjects[i].isObstacle       = false;
@@ -95,7 +95,7 @@ bool SceneObjects::remove(int sceneObjectId) {
 	return true;
 }
 
-int SceneObjects::findByXYZ(bool *isClickable, bool *isObstacle, bool *isTarget, float x, float y, float z, bool findClickables, bool findObstacles, bool findTargets) const {
+int SceneObjects::findByXYZ(bool *isClickable, bool *isObstacle, bool *isTarget, Vector3 &position, bool findClickables, bool findObstacles, bool findTargets) const {
 	*isClickable = false;
 	*isObstacle  = false;
 	*isTarget    = false;
@@ -110,16 +110,16 @@ int SceneObjects::findByXYZ(bool *isClickable, bool *isObstacle, bool *isTarget,
 			(findTargets    && sceneObject->isTarget)) {
 			BoundingBox boundingBox = sceneObject->boundingBox;
 
-			if (sceneObject->sceneObjectType == kSceneObjectTypeObject || sceneObject->sceneObjectType == kSceneObjectTypeItem) {
+			if (sceneObject->type == kSceneObjectTypeObject || sceneObject->type == kSceneObjectTypeItem) {
 				boundingBox.expand(-4.0, 0.0, -4.0, 4.0, 0.0, 4.0);
 			}
 
-			if (boundingBox.inside(x, y, z)) {
+			if (boundingBox.inside(position)) {
 				*isClickable = sceneObject->isClickable;
 				*isObstacle  = sceneObject->isObstacle;
 				*isTarget    = sceneObject->isTarget;
 
-				return sceneObject->sceneObjectId;
+				return sceneObject->id;
 			}
 		}
 	}
@@ -127,7 +127,7 @@ int SceneObjects::findByXYZ(bool *isClickable, bool *isObstacle, bool *isTarget,
 	return -1;
 }
 
-bool SceneObjects::existsOnXZ(int exceptSceneObjectId, float x, float z, bool a5, bool a6) const {
+bool SceneObjects::existsOnXZ(int exceptSceneObjectId, float x, float z, bool movingActorIsObstacle, bool standingActorIsObstacle) const {
 	float xMin = x - 12.5f;
 	float xMax = x + 12.5f;
 	float zMin = z - 12.5f;
@@ -138,20 +138,20 @@ bool SceneObjects::existsOnXZ(int exceptSceneObjectId, float x, float z, bool a5
 	if (count > 0) {
 		for (int i = 0; i < count; i++) {
 			const SceneObject *sceneObject = &_sceneObjects[_sceneObjectsSortedByDistance[i]];
-			bool v13 = false;
-			if (sceneObject->sceneObjectType == kSceneObjectTypeActor) {
+			bool isObstacle = false;
+			if (sceneObject->type == kSceneObjectTypeActor) {
 				if (sceneObject->isRetired) {
-					v13 = false;
+					isObstacle = false;
 				} else if (sceneObject->isMoving) {
-					v13 = a5 != 0;
+					isObstacle = movingActorIsObstacle != 0;
 				} else {
-					v13 = a6 != 0;
+					isObstacle = standingActorIsObstacle != 0;
 				}
 			} else {
-				v13 = sceneObject->isObstacle;
+				isObstacle = sceneObject->isObstacle;
 			}
 
-			if (v13 && sceneObject->sceneObjectId != exceptSceneObjectId) {
+			if (isObstacle && sceneObject->id != exceptSceneObjectId) {
 				float x1, y1, z1, x2, y2, z2;
 				sceneObject->boundingBox.getXYZ(&x1, &y1, &z1, &x2, &y2, &z2);
 				if (z1 <= zMax && z2 >= zMin && x1 <= xMax && x2 >= xMin) {
@@ -167,7 +167,7 @@ int SceneObjects::findById(int sceneObjectId) const {
 	for (int i = 0; i < _count; ++i) {
 		int j = this->_sceneObjectsSortedByDistance[i];
 
-		if (_sceneObjects[j].isPresent && _sceneObjects[j].sceneObjectId == sceneObjectId) {
+		if (_sceneObjects[j].isPresent && _sceneObjects[j].id == sceneObjectId) {
 			return j;
 		}
 	}
@@ -180,11 +180,11 @@ bool SceneObjects::addSceneObject(int sceneObjectId, SceneObjectType sceneObject
 		return false;
 	}
 
-	_sceneObjects[index].sceneObjectId   = sceneObjectId;
-	_sceneObjects[index].sceneObjectType = sceneObjectType;
+	_sceneObjects[index].id              = sceneObjectId;
+	_sceneObjects[index].type            = sceneObjectType;
 	_sceneObjects[index].isPresent       = true;
 	_sceneObjects[index].boundingBox     = *boundingBox;
-	_sceneObjects[index].screenRectangle = *screenRectangle;
+	_sceneObjects[index].screenRectangle = screenRectangle;
 	_sceneObjects[index].isClickable     = isClickable;
 	_sceneObjects[index].isObstacle      = isObstacle;
 	_sceneObjects[index].unknown1        = unknown1;
@@ -237,7 +237,7 @@ void SceneObjects::setRetired(int sceneObjectId, bool isRetired) {
 	_sceneObjects[i].isRetired = isRetired;
 }
 
-bool SceneObjects::isBetweenTwoXZ(int sceneObjectId, float x1, float z1, float x2, float z2) const {
+bool SceneObjects::isBetween(float sourceX, float sourceZ, float targetX, float targetZ, int sceneObjectId) const {
 	int i = findById(sceneObjectId);
 	if (i == -1) {
 		return false;
@@ -246,15 +246,46 @@ bool SceneObjects::isBetweenTwoXZ(int sceneObjectId, float x1, float z1, float x
 	float objectX1, objectY1, objectZ1, objectX2, objectY2, objectZ2;
 	_sceneObjects[i].boundingBox.getXYZ(&objectX1, &objectY1, &objectZ1, &objectX2, &objectY2, &objectZ2);
 
-	//TODO
-	//		if (!lineIntersectection(sourceX, sourceZ, targetX, targetZ, objectX1, objectZ1, objectX2, objectZ1, &intersectionX, &intersectionY, &v18)
-	//			&& !lineIntersectection(sourceX, sourceZ, targetX, targetZ, objectX2, objectZ1, objectX2, objectZ2, &intersectionX, &intersectionY, &v18)
-	//			&& !lineIntersectection(sourceX, sourceZ, targetX, targetZ, objectX2, objectZ2, objectX1, objectZ2, &intersectionX, &intersectionY, &v18)
-	//			&& !lineIntersectection(sourceX, sourceZ, targetX, targetZ, objectX1, objectZ2, objectX1, objectZ1, &intersectionX, &intersectionY, &v18))
-	//			return false;
-	return true;
+	Vector2 intersection;
+	return lineIntersection(Vector2(sourceX, sourceZ), Vector2(targetX, targetZ), Vector2(objectX1, objectZ1), Vector2(objectX2, objectZ1), &intersection)
+	    || lineIntersection(Vector2(sourceX, sourceZ), Vector2(targetX, targetZ), Vector2(objectX2, objectZ1), Vector2(objectX2, objectZ2), &intersection)
+	    || lineIntersection(Vector2(sourceX, sourceZ), Vector2(targetX, targetZ), Vector2(objectX2, objectZ2), Vector2(objectX1, objectZ2), &intersection)
+	    || lineIntersection(Vector2(sourceX, sourceZ), Vector2(targetX, targetZ), Vector2(objectX1, objectZ2), Vector2(objectX1, objectZ1), &intersection);
 }
 
+bool SceneObjects::isObstacleBetween(float sourceX, float sourceZ, float targetX, float targetZ, float altitude, int exceptSceneObjectId) const {
+	for (int i = 0; i < _count; ++i) {
+		const SceneObject *sceneObject = &_sceneObjects[_sceneObjectsSortedByDistance[i]];
+
+		if (sceneObject->type == kSceneObjectTypeActor || !sceneObject->isObstacle || sceneObject->id == exceptSceneObjectId) {
+			continue;
+		}
+
+		float objectX1, objectY1, objectZ1, objectX2, objectY2, objectZ2;
+		_sceneObjects[i].boundingBox.getXYZ(&objectX1, &objectY1, &objectZ1, &objectX2, &objectY2, &objectZ2);
+
+		if (84.0f <= objectY1 - altitude || 72.0f >= objectY2 - altitude) {
+			continue;
+		}
+
+		float xAdjustement = (objectX2 - objectX1) * 0.1f;
+		float zAdjustement = (objectZ2 - objectZ1) * 0.1f;
+
+		objectX1 = objectX1 + xAdjustement;
+		objectZ1 = objectZ1 + zAdjustement;
+		objectX2 = objectX2 - xAdjustement;
+		objectZ2 = objectZ2 - zAdjustement;
+
+		Vector2 intersection;
+		if (lineIntersection(Vector2(sourceX, sourceZ), Vector2(targetX, targetZ), Vector2(objectX1, objectZ1), Vector2(objectX2, objectZ1), &intersection)
+		 || lineIntersection(Vector2(sourceX, sourceZ), Vector2(targetX, targetZ), Vector2(objectX2, objectZ1), Vector2(objectX2, objectZ2), &intersection)
+		 || lineIntersection(Vector2(sourceX, sourceZ), Vector2(targetX, targetZ), Vector2(objectX2, objectZ2), Vector2(objectX1, objectZ2), &intersection)
+		 || lineIntersection(Vector2(sourceX, sourceZ), Vector2(targetX, targetZ), Vector2(objectX1, objectZ2), Vector2(objectX1, objectZ1), &intersection)) {
+			return true;
+		}
+	}
+	return false;
+}
 
 void SceneObjects::setIsClickable(int sceneObjectId, bool isClickable) {
 	int i = findById(sceneObjectId);
@@ -282,12 +313,12 @@ void SceneObjects::setIsTarget(int sceneObjectId, bool isTarget) {
 
 void SceneObjects::updateObstacles() {
 	_vm->_obstacles->clear();
-	for(int i = 0; i < _count; i++) {
+	for (int i = 0; i < _count; ++i) {
 		int index = _sceneObjectsSortedByDistance[i];
-		SceneObject sceneObject = _sceneObjects[index];
-		if(sceneObject.isObstacle) {
+		const SceneObject *sceneObject = &_sceneObjects[index];
+		if (sceneObject->isObstacle) {
 			float x0, y0, z0, x1, y1, z1;
-			sceneObject.boundingBox.getXYZ(&x0, &y0, &z0, &x1, &y1, &z1);
+			sceneObject->boundingBox.getXYZ(&x0, &y0, &z0, &x1, &y1, &z1);
 			_vm->_obstacles->add(x0, z0, x1, z1);
 		}
 	}
diff --git a/engines/bladerunner/scene_objects.h b/engines/bladerunner/scene_objects.h
index 23f6f98..624deee 100644
--- a/engines/bladerunner/scene_objects.h
+++ b/engines/bladerunner/scene_objects.h
@@ -39,12 +39,6 @@ enum SceneObjectType {
 	kSceneObjectTypeItem    = 2
 };
 
-enum SceneObjectOffset {
-	kSceneObjectOffsetActors  = 0,
-	kSceneObjectOffsetItems   = 74,
-	kSceneObjectOffsetObjects = 198
-};
-
 class SceneObjects {
 #if BLADERUNNER_DEBUG_RENDERING
 	friend class BladeRunnerEngine;
@@ -52,10 +46,10 @@ class SceneObjects {
 	static const int kSceneObjectCount = 115;
 
 	struct SceneObject {
-		int             sceneObjectId;
-		SceneObjectType sceneObjectType;
+		int             id;
+		SceneObjectType type;
 		BoundingBox     boundingBox;
-		Common::Rect    screenRectangle;
+		Common::Rect   *screenRectangle;
 		float           distanceToCamera;
 		bool            isPresent;
 		bool            isClickable;
@@ -82,16 +76,18 @@ public:
 	bool addItem(int sceneObjectId, BoundingBox *boundingBox, Common::Rect *screenRectangle, bool isTarget, bool isObstacle);
 	bool remove(int sceneObjectId);
 	void clear();
-	int findByXYZ(bool *isClickable, bool *isObstacle, bool *isTarget, float x, float y, float z, bool findClickables, bool findObstacles, bool findTargets) const;
-	bool existsOnXZ(int exceptSceneObjectId, float x, float z, bool a5, bool a6) const;
+	int findByXYZ(bool *isClickable, bool *isObstacle, bool *isTarget, Vector3 &position, bool findClickables, bool findObstacles, bool findTargets) const;
+	bool existsOnXZ(int exceptSceneObjectId, float x, float z, bool movingActorIsObstacle, bool standingActorIsObstacle) const;
 	void setMoving(int sceneObjectId, bool isMoving);
 	void setRetired(int sceneObjectId, bool isRetired);
-	bool isBetweenTwoXZ(int sceneObjectId, float x1, float z1, float x2, float z2) const;
+	bool isBetween(float sourceX, float sourceZ, float targetX, float targetZ, int sceneObjectId) const;
+	bool isObstacleBetween(float sourceX, float sourceZ, float targetX, float targetZ, float altitude, int exceptSceneObjectId) const;
 	void setIsClickable(int sceneObjectId, bool isClickable);
 	void setIsObstacle(int sceneObjectId, bool isObstacle);
 	void setIsTarget(int sceneObjectId, bool isTarget);
 	void updateObstacles();
 
+
 private:
 	int findById(int sceneObjectId) const;
 	bool addSceneObject(int sceneObjectId, SceneObjectType sceneObjectType, BoundingBox *boundingBox, Common::Rect *screenRectangle, bool isClickable, bool isObstacle, uint8 unknown1, bool isTarget, bool isMoving, bool isRetired);
diff --git a/engines/bladerunner/script/ai/leon.cpp b/engines/bladerunner/script/ai/leon.cpp
index 9d82464..3d136ee 100644
--- a/engines/bladerunner/script/ai/leon.cpp
+++ b/engines/bladerunner/script/ai/leon.cpp
@@ -128,10 +128,11 @@ void AIScriptLeon::OtherAgentEnteredCombatMode(int otherActorId, int combatMode)
 
 void AIScriptLeon::ShotAtAndMissed() {}
 
-void AIScriptLeon::ShotAtAndHit() {
+bool AIScriptLeon::ShotAtAndHit() {
 	if (Actor_Query_Goal_Number(kActorLeon) != 7) {
 		Actor_Set_Goal_Number(kActorLeon, 7);
 	}
+	return false;
 }
 
 void AIScriptLeon::Retired(int byActorId) {}
@@ -351,7 +352,7 @@ bool AIScriptLeon::UpdateAnimation(int *animation, int *frame) {
 
 bool AIScriptLeon::ChangeAnimationMode(int mode) {
 	switch (mode) {
-	case 0:
+	case kAnimationModeIdle:
 		switch (_animationState) {
 		case 2:
 		case 3:
@@ -370,7 +371,7 @@ bool AIScriptLeon::ChangeAnimationMode(int mode) {
 			break;
 		}
 		break;
-	case 1:
+	case kAnimationModeWalk:
 		_animationState = 1;
 		_animationFrame = 0;
 		break;
@@ -379,7 +380,7 @@ bool AIScriptLeon::ChangeAnimationMode(int mode) {
 		_animationFrame = 0;
 		var_45EDAC = 0;
 		break;
-	case 6:
+	case kAnimationModeCombatShoot:
 		_animationState = 10;
 		_animationFrame = 0;
 		break;
diff --git a/engines/bladerunner/script/ai/maggie.cpp b/engines/bladerunner/script/ai/maggie.cpp
index 3fd213f..89dd651 100644
--- a/engines/bladerunner/script/ai/maggie.cpp
+++ b/engines/bladerunner/script/ai/maggie.cpp
@@ -139,7 +139,7 @@ void AIScriptMaggie::ClickedByPlayer() {
 			Actor_Set_Targetable(kActorMaggie, true);
 			AI_Movement_Track_Flush(kActorMaggie);
 			Actor_Face_Actor(kActorMcCoy, kActorMaggie, true);
-			Actor_Says(kActorMcCoy, 2400, 52);
+			Actor_Says(kActorMcCoy, 2400, kAnimationModeFeeding);
 		}
 		return; // true
 	}
@@ -210,10 +210,11 @@ void AIScriptMaggie::OtherAgentEnteredCombatMode(int otherActorId, int combatMod
 void AIScriptMaggie::ShotAtAndMissed() {
 }
 
-void AIScriptMaggie::ShotAtAndHit() {
+bool AIScriptMaggie::ShotAtAndHit() {
 	AI_Movement_Track_Flush(kActorMaggie);
 	Actor_Set_Goal_Number(kActorMaggie, 414);
 	Actor_Set_Targetable(kActorMaggie, false);
+	return false;
 }
 
 void AIScriptMaggie::Retired(int byActorId) {
@@ -270,7 +271,7 @@ bool AIScriptMaggie::GoalChanged(int currentGoalNumber, int newGoalNumber) {
 		Loop_Actor_Walk_To_Actor(kActorMaggie, kActorMcCoy, 48, false, false);
 		Actor_Face_Actor(kActorMcCoy, kActorMaggie, true);
 		Actor_Face_Actor(kActorMaggie, kActorMcCoy, false);
-		Actor_Says(kActorMcCoy, 2400, 52);
+		Actor_Says(kActorMcCoy, 2400, kAnimationModeFeeding);
 		Actor_Set_Goal_Number(kActorMaggie, 8);
 		Player_Gains_Control();
 		return true;
@@ -593,7 +594,7 @@ bool AIScriptMaggie::ChangeAnimationMode(int mode) {
 			}
 		}
 		break;
-	case 52:
+	case kAnimationModeFeeding:
 		if (Game_Flag_Query(kFlagMaggieIsHurt)) {
 			_animationState = kMaggieStateHurtJumping;
 			_animationFrame = 0;
diff --git a/engines/bladerunner/script/ai/mccoy.cpp b/engines/bladerunner/script/ai/mccoy.cpp
index f84c9a9..3f3888f 100644
--- a/engines/bladerunner/script/ai/mccoy.cpp
+++ b/engines/bladerunner/script/ai/mccoy.cpp
@@ -219,7 +219,8 @@ void AIScriptMcCoy::OtherAgentEnteredCombatMode(int otherActorId, int combatMode
 void AIScriptMcCoy::ShotAtAndMissed() {
 }
 
-void AIScriptMcCoy::ShotAtAndHit() {
+bool AIScriptMcCoy::ShotAtAndHit() {
+	return false;
 }
 
 void AIScriptMcCoy::Retired(int byActorId) {
@@ -633,7 +634,7 @@ bool AIScriptMcCoy::UpdateAnimation(int *animation, int *frame) {
 		*animation = 32;
 		_animationFrame++;
 		if (_animationFrame == 7) {
-			Actor_Change_Animation_Mode(kActorMaggie, 52);
+			Actor_Change_Animation_Mode(kActorMaggie, kAnimationModeFeeding);
 		}
 		if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(*animation)) {
 			*animation = 19;
@@ -1244,7 +1245,7 @@ bool AIScriptMcCoy::ChangeAnimationMode(int mode) {
 			_animationState = 70;
 		}
 		return true;
-	case 52:
+	case kAnimationModeFeeding:
 		_animationState = 55;
 		_animationFrame = 0;
 		return true;
@@ -1488,19 +1489,19 @@ bool AIScriptMcCoy::ChangeAnimationMode(int mode) {
 			dword_45A0F4 = 21;
 		}
 		return true;
-	case 8:
+	case kAnimationModeCombatRun:
 		if (_animationState != 27 && _animationState != 50) {
 			_animationState = 37;
 			_animationFrame = 0;
 		}
 		return true;
-	case 7:
+	case kAnimationModeCombatWalk:
 		if (_animationState != 27 && _animationState != 50) {
 			_animationState = 36;
 			_animationFrame = 0;
 		}
 		return true;
-	case 6:
+	case kAnimationModeCombatShoot:
 		_animationState = 21;
 		_animationFrame = 0;
 		return true;
@@ -1524,7 +1525,7 @@ bool AIScriptMcCoy::ChangeAnimationMode(int mode) {
 			break;
 		}
 		return true;
-	case 4:
+	case kAnimationModeCombatIdle:
 		switch (_animationState) {
 		case 22:
 			_animationState = 19;
@@ -1586,7 +1587,7 @@ bool AIScriptMcCoy::ChangeAnimationMode(int mode) {
 			_animationNext = 20;
 		}
 		return true;
-	case 2:
+	case kAnimationModeRun:
 		if (_animationState == 27 || _animationState == 50) {
 			return true;
 		}
@@ -1598,7 +1599,7 @@ bool AIScriptMcCoy::ChangeAnimationMode(int mode) {
 		_animationState = 58;
 		_animationFrame = 4;
 		return true;
-	case 1:
+	case kAnimationModeWalk:
 		if (_animationState == 27 || _animationState == 50) {
 			return true;
 		}
@@ -1610,7 +1611,7 @@ bool AIScriptMcCoy::ChangeAnimationMode(int mode) {
 		_animationState = 58;
 		_animationFrame = 0;
 		return true;
-	case 0:
+	case kAnimationModeIdle:
 		if (Game_Flag_Query(550)) {
 			if (_animationFrame > 6) {
 				_animationState = 57;
diff --git a/engines/bladerunner/script/ai/officer_leary.cpp b/engines/bladerunner/script/ai/officer_leary.cpp
index 86b3ace..c95ba20 100644
--- a/engines/bladerunner/script/ai/officer_leary.cpp
+++ b/engines/bladerunner/script/ai/officer_leary.cpp
@@ -209,10 +209,11 @@ void AIScriptOfficerLeary::OtherAgentEnteredCombatMode(int otherActorId, int com
 
 void AIScriptOfficerLeary::ShotAtAndMissed() {}
 
-void AIScriptOfficerLeary::ShotAtAndHit() {
+bool AIScriptOfficerLeary::ShotAtAndHit() {
 	if (Actor_Query_Goal_Number(kActorOfficerLeary) == 307) {
 		Actor_Set_Health(kActorOfficerLeary, 50, 50);
 	}
+	return false;
 }
 
 void AIScriptOfficerLeary::Retired(int byActorId) {
diff --git a/engines/bladerunner/script/ai/runciter.cpp b/engines/bladerunner/script/ai/runciter.cpp
index c18dd2d..d1d7a08 100644
--- a/engines/bladerunner/script/ai/runciter.cpp
+++ b/engines/bladerunner/script/ai/runciter.cpp
@@ -139,7 +139,7 @@ void AIScriptRunciter::OtherAgentEnteredCombatMode(int otherActorId, int combatM
 
 void AIScriptRunciter::ShotAtAndMissed() {}
 
-void AIScriptRunciter::ShotAtAndHit() {
+bool AIScriptRunciter::ShotAtAndHit() {
 	Actor_Set_Targetable(kActorRunciter, false);
 	Actor_Change_Animation_Mode(kActorRunciter, 48);
 	Actor_Set_Goal_Number(kActorRunciter, 599);
@@ -153,6 +153,7 @@ void AIScriptRunciter::ShotAtAndHit() {
 		Actor_Voice_Over(2090, kActorVoiceOver);
 	}
 	Actor_Modify_Friendliness_To_Other(kActorClovis, kActorMcCoy, 3);
+	return false;
 }
 
 void AIScriptRunciter::Retired(int byActorId) {}
@@ -472,8 +473,8 @@ bool AIScriptRunciter::UpdateAnimation(int *animation, int *frame) {
 
 bool AIScriptRunciter::ChangeAnimationMode(int mode) {
 	switch (mode) {
-	case kAnimationModeCombatIdle:
-		if (_animationState <= 11) {
+	case kAnimationModeIdle:
+		if (_animationState >= 2 && _animationState <= 11) {
 			var_45CD88 = 1;
 		} else {
 			_animationState = 0;
@@ -485,14 +486,14 @@ bool AIScriptRunciter::ChangeAnimationMode(int mode) {
 		if (_animationState > 1) {
 			_animationState = 1;
 			_animationFrame = 0;
-		} else if (!_animationState) {
+		} else if (_animationState == 0) {
 			_animationState = 13;
 			_animationStateNext = 1;
 			_animationNext = 526;
 		}
 		break;
 	case 3:
-		if (_animationState) {
+		if (_animationState  != 0) {
 			_animationState = 2;
 			_animationFrame = 0;
 		} else {
@@ -503,7 +504,7 @@ bool AIScriptRunciter::ChangeAnimationMode(int mode) {
 		var_45CD88 = 0;
 		break;
 	case 12:
-		if (_animationState) {
+		if (_animationState != 0) {
 			_animationState = 2;
 			_animationFrame = 0;
 		} else {
@@ -514,7 +515,7 @@ bool AIScriptRunciter::ChangeAnimationMode(int mode) {
 		var_45CD88 = 0;
 		break;
 	case 13:
-		if (_animationState) {
+		if (_animationState != 0) {
 			_animationState = 2;
 			_animationFrame = 0;
 		} else {
@@ -525,7 +526,7 @@ bool AIScriptRunciter::ChangeAnimationMode(int mode) {
 		var_45CD88 = 0;
 		break;
 	case 14:
-		if (_animationState) {
+		if (_animationState != 0) {
 			_animationState = 2;
 			_animationFrame = 0;
 		} else {
@@ -536,7 +537,7 @@ bool AIScriptRunciter::ChangeAnimationMode(int mode) {
 		var_45CD88 = 0;
 		break;
 	case 15:
-		if (_animationState) {
+		if (_animationState != 0) {
 			_animationState = 2;
 			_animationFrame = 0;
 		} else {
@@ -547,7 +548,7 @@ bool AIScriptRunciter::ChangeAnimationMode(int mode) {
 		var_45CD88 = 0;
 		break;
 	case 16:
-		if (_animationState) {
+		if (_animationState != 0) {
 			_animationState = 2;
 			_animationFrame = 0;
 		} else {
@@ -558,7 +559,7 @@ bool AIScriptRunciter::ChangeAnimationMode(int mode) {
 		var_45CD88 = 0;
 		break;
 	case 17:
-		if (_animationState) {
+		if (_animationState != 0) {
 			_animationState = 2;
 			_animationFrame = 0;
 		} else {
@@ -569,7 +570,7 @@ bool AIScriptRunciter::ChangeAnimationMode(int mode) {
 		var_45CD88 = 0;
 		break;
 	case 18:
-		if (_animationState) {
+		if (_animationState != 0) {
 			_animationState = 2;
 			_animationFrame = 0;
 		} else {
@@ -580,7 +581,7 @@ bool AIScriptRunciter::ChangeAnimationMode(int mode) {
 		var_45CD88 = 0;
 		break;
 	case 19:
-		if (_animationState) {
+		if (_animationState != 0) {
 			_animationState = 2;
 			_animationFrame = 0;
 		} else {
diff --git a/engines/bladerunner/script/ai_script.cpp b/engines/bladerunner/script/ai_script.cpp
index 503fb73..7b211aa 100644
--- a/engines/bladerunner/script/ai_script.cpp
+++ b/engines/bladerunner/script/ai_script.cpp
@@ -144,6 +144,35 @@ void AIScripts::otherAgentExitedThisScene(int actor, int otherActorId) {
 	_inScriptCounter--;
 }
 
+void AIScripts::otherAgentEnteredCombatMode(int actorId, int otherActorId, int combatMode) {
+	assert(actorId < _actorCount);
+	_inScriptCounter++;
+	if (_AIScripts[actorId]) {
+		_AIScripts[actorId]->OtherAgentEnteredCombatMode(otherActorId, combatMode);
+	}
+	_inScriptCounter--;
+}
+
+void AIScripts::shotAtAndMissed(int actorId) {
+	assert(actorId < _actorCount);
+	_inScriptCounter++;
+	if (_AIScripts[actorId]) {
+		_AIScripts[actorId]->ShotAtAndMissed();
+	}
+	_inScriptCounter--;
+}
+
+bool AIScripts::shotAtAndHit(int actorId) {
+	assert(actorId < _actorCount);
+	bool result = true;
+	_inScriptCounter++;
+	if (_AIScripts[actorId]) {
+		result = _AIScripts[actorId]->ShotAtAndHit();
+	}
+	_inScriptCounter--;
+	return result;
+}
+
 void AIScripts::retired(int actor, int retiredByActorId) {
 	assert(actor < _actorCount);
 	_inScriptCounter++;
diff --git a/engines/bladerunner/script/ai_script.h b/engines/bladerunner/script/ai_script.h
index 40df2fb..4be79c6 100644
--- a/engines/bladerunner/script/ai_script.h
+++ b/engines/bladerunner/script/ai_script.h
@@ -50,7 +50,7 @@ public:
 	virtual void OtherAgentExitedThisScene(int otherActorId) = 0;
 	virtual void OtherAgentEnteredCombatMode(int otherActorId, int combatMode) = 0;
 	virtual void ShotAtAndMissed() = 0;
-	virtual void ShotAtAndHit() = 0;
+	virtual bool ShotAtAndHit() = 0;
 	virtual void Retired(int byActorId) = 0;
 	virtual int GetFriendlinessModifierIfGetsClue(int otherActorId, int clueId) = 0;
 	virtual bool GoalChanged(int currentGoalNumber, int newGoalNumber) = 0;
@@ -79,7 +79,7 @@ public: \
 	void OtherAgentExitedThisScene(int otherActorId); \
 	void OtherAgentEnteredCombatMode(int otherActorId, int combatMode); \
 	void ShotAtAndMissed(); \
-	void ShotAtAndHit(); \
+	bool ShotAtAndHit(); \
 	void Retired(int byActorId); \
 	int GetFriendlinessModifierIfGetsClue(int otherActorId, int clueId); \
 	bool GoalChanged(int currentGoalNumber, int newGoalNumber); \
@@ -176,6 +176,9 @@ public:
 	void enteredScene(int actor, int setId);
 	void otherAgentEnteredThisScene(int actor, int otherActorId);
 	void otherAgentExitedThisScene(int actor, int otherActorId);
+	void otherAgentEnteredCombatMode(int actorId, int otherActorId, int combatMode);
+	void shotAtAndMissed(int actorId);
+	bool shotAtAndHit(int actorId);
 	void retired(int actor, int retiredByActorId);
 	void goalChanged(int actor, int currentGoalNumber, int newGoalNumber);
 	bool reachedMovementTrackWaypoint(int actor, int waypointId);
diff --git a/engines/bladerunner/script/scene_script.cpp b/engines/bladerunner/script/scene_script.cpp
index 639bca8..01fe3e3 100644
--- a/engines/bladerunner/script/scene_script.cpp
+++ b/engines/bladerunner/script/scene_script.cpp
@@ -174,20 +174,21 @@ bool SceneScript::mouseClick(int x, int y) {
 	//MouseX = x;
 	//MouseY = y;
 	bool result = _currentScript->MouseClick(x, y);
-	//SelectedEntity = -1;
+	_vm->_runningActorId = -1;
 	_inScriptCounter--;
 	//MouseX = -1;
 	//MouseY = -1;
 	return result;
 }
 
-bool SceneScript::clickedOn3DObject(const char *objectName, bool a2) {
+bool SceneScript::clickedOn3DObject(const char *objectName, bool attack) {
 	if (_inScriptCounter > 0) {
 		return true;
 	}
 
 	_inScriptCounter++;
-	bool result = _currentScript->ClickedOn3DObject(objectName, a2);
+	bool result = _currentScript->ClickedOn3DObject(objectName, attack);
+	_vm->_runningActorId = -1;
 	_inScriptCounter--;
 	return result;
 }
@@ -199,6 +200,7 @@ bool SceneScript::clickedOnActor(int actorId) {
 
 	_inScriptCounter++;
 	bool result = _currentScript->ClickedOnActor(actorId);
+	_vm->_runningActorId = -1;
 	_inScriptCounter--;
 	return result;
 }
@@ -210,6 +212,7 @@ bool SceneScript::clickedOnItem(int itemId, bool a2) {
 
 	_inScriptCounter++;
 	bool result = _currentScript->ClickedOnItem(itemId, a2);
+	_vm->_runningActorId = -1;
 	_inScriptCounter--;
 	return result;
 }
@@ -221,6 +224,7 @@ bool SceneScript::clickedOnExit(int exitId) {
 
 	_inScriptCounter++;
 	bool result = _currentScript->ClickedOnExit(exitId);
+	_vm->_runningActorId = -1;
 	_inScriptCounter--;
 	return result;
 }
@@ -232,6 +236,7 @@ bool SceneScript::clickedOn2DRegion(int region) {
 
 	_inScriptCounter++;
 	bool result = _currentScript->ClickedOn2DRegion(region);
+	_vm->_runningActorId = -1;
 	_inScriptCounter--;
 	return result;
 }
diff --git a/engines/bladerunner/script/scene_script.h b/engines/bladerunner/script/scene_script.h
index ece9669..086388c 100644
--- a/engines/bladerunner/script/scene_script.h
+++ b/engines/bladerunner/script/scene_script.h
@@ -36,7 +36,7 @@ public:
 	virtual void InitializeScene() = 0;
 	virtual void SceneLoaded() = 0;
 	virtual bool MouseClick(int x, int y) = 0;
-	virtual bool ClickedOn3DObject(const char *objectName, bool a2) = 0;
+	virtual bool ClickedOn3DObject(const char *objectName, bool attack) = 0;
 	virtual bool ClickedOnActor(int actorId) = 0;
 	virtual bool ClickedOnItem(int itemId, bool a2) = 0;
 	virtual bool ClickedOnExit(int exitId) = 0;
@@ -57,7 +57,7 @@ public: \
 	void InitializeScene(); \
 	void SceneLoaded(); \
 	bool MouseClick(int x, int y); \
-	bool ClickedOn3DObject(const char *objectName, bool a2); \
+	bool ClickedOn3DObject(const char *objectName, bool attack); \
 	bool ClickedOnActor(int actorId); \
 	bool ClickedOnItem(int itemId, bool a2); \
 	bool ClickedOnExit(int exitId); \
@@ -536,7 +536,7 @@ public:
 	void initializeScene();
 	void sceneLoaded();
 	bool mouseClick(int x, int y);
-	bool clickedOn3DObject(const char *objectName, bool a2);
+	bool clickedOn3DObject(const char *objectName, bool attack);
 	bool clickedOnActor(int actorId);
 	bool clickedOnItem(int itemId, bool a2);
 	bool clickedOnExit(int exitId);
diff --git a/engines/bladerunner/script/script.cpp b/engines/bladerunner/script/script.cpp
index c4b0de8..f88f330 100644
--- a/engines/bladerunner/script/script.cpp
+++ b/engines/bladerunner/script/script.cpp
@@ -231,7 +231,7 @@ void ScriptBase::Actor_Set_Health(int actorId, int hp, int maxHp) {
 }
 
 void ScriptBase::Actor_Set_Targetable(int actorId, bool targetable) {
-	_vm->_actors[actorId]->setTargetable(targetable);
+	_vm->_actors[actorId]->setTarget(targetable);
 
 }
 
@@ -258,7 +258,7 @@ void ScriptBase::Actor_Says_With_Pause(int actorId, int sentenceId, float pause,
 		if (actorId != kActorMcCoy) {
 			actor->changeAnimationMode(animationMode, false);
 			animationModeChanged = true;
-		} else if (_vm->_combat->isActive()) {
+		} else if (!_vm->_combat->isActive()) {
 			actor->changeAnimationMode(animationMode, false);
 			animationModeChanged = true;
 		}
@@ -364,11 +364,11 @@ bool ScriptBase::Actor_Query_In_Between_Two_Actors(int actorId, int otherActor1I
 	float z1 = _vm->_actors[otherActor1Id]->getZ();
 	float x2 = _vm->_actors[otherActor2Id]->getX();
 	float z2 = _vm->_actors[otherActor2Id]->getZ();
-	return _vm->_sceneObjects->isBetweenTwoXZ(actorId + kSceneObjectOffsetActors, x1, z1, x2, z1)
-		|| _vm->_sceneObjects->isBetweenTwoXZ(actorId + kSceneObjectOffsetActors, x1 - 12.0f, z1 - 12.0f, x2 - 12.0f, z2 - 12.0f)
-		|| _vm->_sceneObjects->isBetweenTwoXZ(actorId + kSceneObjectOffsetActors, x1 + 12.0f, z1 - 12.0f, x2 + 12.0f, z2 - 12.0f)
-		|| _vm->_sceneObjects->isBetweenTwoXZ(actorId + kSceneObjectOffsetActors, x1 + 12.0f, z1 + 12.0f, x2 + 12.0f, z2 + 12.0f)
-		|| _vm->_sceneObjects->isBetweenTwoXZ(actorId + kSceneObjectOffsetActors, x1 - 12.0f, z1 + 12.0f, x2 - 12.0f, z2 + 12.0f);
+	return _vm->_sceneObjects->isBetween(x1,         z1,         x2,         z1,         actorId + kSceneObjectOffsetActors)
+		|| _vm->_sceneObjects->isBetween(x1 - 12.0f, z1 - 12.0f, x2 - 12.0f, z2 - 12.0f, actorId + kSceneObjectOffsetActors)
+		|| _vm->_sceneObjects->isBetween(x1 + 12.0f, z1 - 12.0f, x2 + 12.0f, z2 - 12.0f, actorId + kSceneObjectOffsetActors)
+		|| _vm->_sceneObjects->isBetween(x1 + 12.0f, z1 + 12.0f, x2 + 12.0f, z2 + 12.0f, actorId + kSceneObjectOffsetActors)
+		|| _vm->_sceneObjects->isBetween(x1 - 12.0f, z1 + 12.0f, x2 - 12.0f, z2 + 12.0f, actorId + kSceneObjectOffsetActors);
 }
 
 void ScriptBase::Actor_Set_Goal_Number(int actorId, int goalNumber) {
@@ -408,20 +408,21 @@ int ScriptBase::Actor_Query_Animation_Mode(int actorId) {
 bool ScriptBase::Loop_Actor_Walk_To_Actor(int actorId, int otherActorId, int distance, bool interruptible, bool run) {
 	_vm->gameWaitForActive();
 
-	if (_vm->_walkingActorId == actorId) {
+	if (_vm->_runningActorId == actorId) {
 		run = true;
 	}
+
 	_vm->_playerActorIdle = false;
-	bool isRunning;
 
+	bool isRunning;
 	bool result = _vm->_actors[actorId]->loopWalkToActor(otherActorId, distance, interruptible, run, true, &isRunning);
 
 	if (_vm->_playerActorIdle) {
 		result = true;
 		_vm->_playerActorIdle = false;
 	}
-	if (isRunning == 1) {
-		_vm->_walkingActorId = actorId;
+	if (isRunning) {
+		_vm->_runningActorId = actorId;
 	}
 	Global_Variable_Set(kVariableWalkLoopActor, actorId);
 	Global_Variable_Set(kVariableWalkLoopRun, isRunning);
@@ -431,20 +432,21 @@ bool ScriptBase::Loop_Actor_Walk_To_Actor(int actorId, int otherActorId, int dis
 bool ScriptBase::Loop_Actor_Walk_To_Item(int actorId, int itemId, int destinationOffset, bool interruptible, bool run) {
 	_vm->gameWaitForActive();
 
-	if (_vm->_walkingActorId == actorId) {
+	if (_vm->_runningActorId == actorId) {
 		run = true;
 	}
+
 	_vm->_playerActorIdle = false;
-	bool isRunning;
 
+	bool isRunning;
 	bool result = _vm->_actors[actorId]->loopWalkToItem(itemId, destinationOffset, interruptible, run, true, &isRunning);
 
-	if (_vm->_playerActorIdle == 1) {
+	if (_vm->_playerActorIdle) {
 		result = true;
 		_vm->_playerActorIdle = false;
 	}
-	if (isRunning == 1) {
-		_vm->_walkingActorId = actorId;
+	if (isRunning) {
+		_vm->_runningActorId = actorId;
 	}
 	Global_Variable_Set(kVariableWalkLoopActor, actorId);
 	Global_Variable_Set(kVariableWalkLoopRun, isRunning);
@@ -454,20 +456,21 @@ bool ScriptBase::Loop_Actor_Walk_To_Item(int actorId, int itemId, int destinatio
 bool ScriptBase::Loop_Actor_Walk_To_Scene_Object(int actorId, const char *objectName, int destinationOffset, bool interruptible, bool run) {
 	_vm->gameWaitForActive();
 
-	if (_vm->_walkingActorId == actorId) {
+	if (_vm->_runningActorId == actorId) {
 		run = true;
 	}
+
 	_vm->_playerActorIdle = false;
-	bool isRunning;
 
+	bool isRunning;
 	bool result = _vm->_actors[actorId]->loopWalkToSceneObject(objectName, destinationOffset, interruptible, run, true, &isRunning);
 
 	if (_vm->_playerActorIdle) {
 		result = true;
 		_vm->_playerActorIdle = false;
 	}
-	if (isRunning == 1) {
-		_vm->_walkingActorId = actorId;
+	if (isRunning) {
+		_vm->_runningActorId = actorId;
 	}
 	Global_Variable_Set(kVariableWalkLoopActor, actorId);
 	Global_Variable_Set(kVariableWalkLoopRun, isRunning);
@@ -477,20 +480,21 @@ bool ScriptBase::Loop_Actor_Walk_To_Scene_Object(int actorId, const char *object
 bool ScriptBase::Loop_Actor_Walk_To_Waypoint(int actorId, int waypointId, int destinationOffset, bool interruptible, bool run) {
 	_vm->gameWaitForActive();
 
-	if (_vm->_walkingActorId == actorId) {
+	if (_vm->_runningActorId == actorId) {
 		run = true;
 	}
+
 	_vm->_playerActorIdle = false;
-	bool isRunning;
 
+	bool isRunning;
 	bool result = _vm->_actors[actorId]->loopWalkToWaypoint(waypointId, destinationOffset, interruptible, run, true, &isRunning);
 
 	if (_vm->_playerActorIdle) {
 		result = true;
 		_vm->_playerActorIdle = false;
 	}
-	if (isRunning == 1) {
-		_vm->_walkingActorId = actorId;
+	if (isRunning) {
+		_vm->_runningActorId = actorId;
 	}
 	Global_Variable_Set(kVariableWalkLoopActor, actorId);
 	Global_Variable_Set(kVariableWalkLoopRun, isRunning);
@@ -500,16 +504,16 @@ bool ScriptBase::Loop_Actor_Walk_To_Waypoint(int actorId, int waypointId, int de
 bool ScriptBase::Loop_Actor_Walk_To_XYZ(int actorId, float x, float y, float z, int destinationOffset, bool interruptible, bool run, int a7) {
 	_vm->gameWaitForActive();
 
-	if (_vm->_walkingActorId == actorId) {
+	if (_vm->_runningActorId == actorId) {
 		if (a7) {
-			_vm->_walkingActorId = -1;
+			_vm->_runningActorId = -1;
 		} else {
 			run = true;
 		}
 	}
 	_vm->_playerActorIdle = false;
-	bool isRunning;
 
+	bool isRunning;
 	bool result = _vm->_actors[actorId]->loopWalkToXYZ(Vector3(x, y, z), destinationOffset, interruptible, run, true, &isRunning);
 
 	if (_vm->_playerActorIdle) {
@@ -517,7 +521,7 @@ bool ScriptBase::Loop_Actor_Walk_To_XYZ(int actorId, float x, float y, float z,
 		_vm->_playerActorIdle = false;
 	}
 	if (isRunning) {
-		_vm->_walkingActorId = actorId;
+		_vm->_runningActorId = actorId;
 	}
 	Global_Variable_Set(kVariableWalkLoopActor, actorId);
 	Global_Variable_Set(kVariableWalkLoopRun, isRunning);
@@ -527,7 +531,7 @@ bool ScriptBase::Loop_Actor_Walk_To_XYZ(int actorId, float x, float y, float z,
 void ScriptBase::Async_Actor_Walk_To_Waypoint(int actorId, int waypointId, int destinationOffset, bool run) {
 	_vm->gameWaitForActive();
 
-	if (_vm->_walkingActorId == actorId) {
+	if (_vm->_runningActorId == actorId) {
 		run = true;
 	}
 
@@ -537,7 +541,7 @@ void ScriptBase::Async_Actor_Walk_To_Waypoint(int actorId, int waypointId, int d
 void ScriptBase::Async_Actor_Walk_To_XYZ(int actorId, float x, float y, float z, int destinationOffset, bool run) {
 	_vm->gameWaitForActive();
 
-	if (_vm->_walkingActorId == actorId) {
+	if (_vm->_runningActorId == actorId) {
 		run = true;
 	}
 
@@ -1234,13 +1238,13 @@ void ScriptBase::I_Sez(const char *str) {
 
 void ScriptBase::AI_Countdown_Timer_Start(int actorId, signed int timer, int seconds) {
 	if (timer >= 0 && timer <= 2) {
-		_vm->_actors[actorId]->countdownTimerStart(timer, 1000 * seconds);
+		_vm->_actors[actorId]->timerStart(timer, 1000 * seconds);
 	}
 }
 
 void ScriptBase::AI_Countdown_Timer_Reset(int actorId, int timer) {
 	if (timer >= 0 && timer <= 2) {
-		_vm->_actors[actorId]->countdownTimerReset(timer);
+		_vm->_actors[actorId]->timerReset(timer);
 	}
 }
 
@@ -1258,19 +1262,19 @@ void ScriptBase::AI_Movement_Track_Repeat(int actorId) {
 }
 
 void ScriptBase::AI_Movement_Track_Append_Run_With_Facing(int actorId, int waypointId, int delay, int angle) {
-	_vm->_actors[actorId]->_movementTrack->append(waypointId, delay, angle, 1);
+	_vm->_actors[actorId]->_movementTrack->append(waypointId, delay * 1000, angle, true);
 }
 
 void ScriptBase::AI_Movement_Track_Append_With_Facing(int actorId, int waypointId, int delay, int angle) {
-	_vm->_actors[actorId]->_movementTrack->append(waypointId, delay, angle, 0);
+	_vm->_actors[actorId]->_movementTrack->append(waypointId, delay * 1000, angle, false);
 }
 
 void ScriptBase::AI_Movement_Track_Append_Run(int actorId, int waypointId, int delay) {
-	_vm->_actors[actorId]->_movementTrack->append(waypointId, delay, 1);
+	_vm->_actors[actorId]->_movementTrack->append(waypointId, delay * 1000, true);
 }
 
 void ScriptBase::AI_Movement_Track_Append(int actorId, int waypointId, int delay) {
-	_vm->_actors[actorId]->_movementTrack->append(waypointId, delay, 0);
+	_vm->_actors[actorId]->_movementTrack->append(waypointId, delay * 1000, false);
 }
 
 void ScriptBase::AI_Movement_Track_Flush(int actorId) {
diff --git a/engines/bladerunner/set.cpp b/engines/bladerunner/set.cpp
index a68799a..fe10c18 100644
--- a/engines/bladerunner/set.cpp
+++ b/engines/bladerunner/set.cpp
@@ -23,6 +23,7 @@
 #include "bladerunner/set.h"
 
 #include "bladerunner/bladerunner.h"
+#include "bladerunner/game_constants.h"
 #include "bladerunner/lights.h"
 #include "bladerunner/scene_objects.h"
 #include "bladerunner/set_effects.h"
diff --git a/engines/bladerunner/settings.cpp b/engines/bladerunner/settings.cpp
index d0ba843..a5540fc 100644
--- a/engines/bladerunner/settings.cpp
+++ b/engines/bladerunner/settings.cpp
@@ -111,31 +111,51 @@ bool Settings::openNewScene() {
 	return true;
 }
 
-int Settings::getAmmoType() {
+int Settings::getAmmoType() const {
 	return _ammoType;
 }
 
-int Settings::getAmmoAmount(int ammoType) {
-	return _ammoAmounts[ammoType];
-}
-
 void Settings::setAmmoType(int ammoType) {
 	if (_ammoAmounts[ammoType] > 0) {
 		_ammoType = ammoType;
 	}
 }
 
+int Settings::getAmmo(int ammoType) const {
+	return _ammoAmounts[ammoType];
+}
+
 void Settings::addAmmo(int ammoType, int ammo) {
-	if (ammoType > _ammoType || _ammoAmounts[_ammoType] == 0)
+	if (ammoType > _ammoType || _ammoAmounts[_ammoType] == 0) {
 		_ammoType = ammoType;
+	}
 	_ammoAmounts[ammoType] += ammo;
 }
 
-int Settings::getDifficulty() {
+void Settings::decreaseAmmo() {
+	if (_difficulty == 0 || _ammoType == 0) {
+		return;
+	}
+
+	if (_ammoAmounts[_ammoType] > 0) {
+		--_ammoAmounts[_ammoType];
+	}
+
+	if (_ammoAmounts[_ammoType] == 0) {
+		for (int i = 2; i >= 0; --i) {
+			if (_ammoAmounts[i] > 0) {
+				_ammoType = i;
+				return;
+			}
+		}
+	}
+}
+
+int Settings::getDifficulty() const {
 	return _difficulty;
 }
 
-int Settings::getPlayerAgenda() {
+int Settings::getPlayerAgenda() const {
 	return _playerAgenda;
 }
 
@@ -143,4 +163,12 @@ void Settings::setPlayerAgenda(int agenda) {
 	_playerAgenda = agenda;
 }
 
+bool Settings::getLearyMode() const {
+	return _learyMode;
+}
+
+void Settings::setLearyMode(bool learyMode) {
+	_learyMode = learyMode;
+}
+
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/settings.h b/engines/bladerunner/settings.h
index 85674d2..bf2d2d3 100644
--- a/engines/bladerunner/settings.h
+++ b/engines/bladerunner/settings.h
@@ -77,11 +77,11 @@ public:
 		_newScene = -1;
 	}
 
-	int getNewScene() {
+	int getNewScene() const {
 		return _newScene;
 	}
 
-	int getNewSet() {
+	int getNewSet() const {
 		return _newSet;
 	}
 
@@ -94,7 +94,7 @@ public:
 		_loadingGame = loadingGame;
 	}
 
-	bool getLoadingGame() {
+	bool getLoadingGame() const {
 		return _loadingGame;
 	}
 
@@ -104,22 +104,19 @@ public:
 
 	bool openNewScene();
 
-	int getAmmoType();
-	int getAmmoAmount(int ammoType);
+	int getAmmoType() const;
 	void setAmmoType(int ammoType);
-
-	int getDifficulty();
-	int getPlayerAgenda();
-	void setPlayerAgenda(int agenda);
+	int getAmmo(int ammoType) const;
 	void addAmmo(int ammoType, int ammo);
+	void decreaseAmmo();
 
-	bool getLearyMode() {
-		return _learyMode;
-	}
+	int getDifficulty() const;
 
-	void setLearyMode(bool learyMode) {
-		_learyMode = learyMode;
-	}
+	int getPlayerAgenda() const;
+	void setPlayerAgenda(int agenda);
+
+	bool getLearyMode() const;
+	void setLearyMode(bool learyMode);
 };
 
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/ui/kia.cpp b/engines/bladerunner/ui/kia.cpp
index a738923..9f7ec13 100644
--- a/engines/bladerunner/ui/kia.cpp
+++ b/engines/bladerunner/ui/kia.cpp
@@ -329,21 +329,21 @@ void KIA::tick() {
 			_currentSection->draw(_vm->_surfaceFront);
 		}
 	}
-	if (_vm->_settings->getAmmoAmount(0) > 0) {
+	if (_vm->_settings->getAmmo(0) > 0) {
 		if (_vm->_settings->getAmmoType() == 0) {
 			_shapes->get(42)->draw(_vm->_surfaceFront, 147, 405);
 		} else {
 			_shapes->get(45)->draw(_vm->_surfaceFront, 140, 446);
 		}
 	}
-	if (_vm->_settings->getAmmoAmount(1) > 0) {
+	if (_vm->_settings->getAmmo(1) > 0) {
 		if (_vm->_settings->getAmmoType() == 1) {
 			_shapes->get(43)->draw(_vm->_surfaceFront, 167, 394);
 		} else {
 			_shapes->get(46)->draw(_vm->_surfaceFront, 160, 446);
 		}
 	}
-	if (_vm->_settings->getAmmoAmount(2) > 0) {
+	if (_vm->_settings->getAmmo(2) > 0) {
 		if (_vm->_settings->getAmmoType() == 2) {
 			_shapes->get(44)->draw(_vm->_surfaceFront, 189, 385);
 		} else {
@@ -826,21 +826,21 @@ void KIA::createButtons(int sectionId) {
 
 		_buttons->defineImage(19, kiaButton19, nullptr, nullptr, nullptr, _vm->_textKIA->getText(44));
 
-		if (_vm->_settings->getAmmoAmount(0) > 0) {
+		if (_vm->_settings->getAmmo(0) > 0) {
 			_buttons->defineImage(16, kiaButton16, nullptr, nullptr, nullptr, _vm->_textKIA->getText(50));
 		}
 		Common::String tooltip;
-		if (_vm->_settings->getAmmoAmount(1) > 0) {
+		if (_vm->_settings->getAmmo(1) > 0) {
 			if (_vm->_settings->getDifficulty() > 0) {
-				tooltip = Common::String::format("%d", _vm->_settings->getAmmoAmount(1));
+				tooltip = Common::String::format("%d", _vm->_settings->getAmmo(1));
 			} else {
 				tooltip = _vm->_textKIA->getText(50);
 			}
 			_buttons->defineImage(17, kiaButton17, nullptr, nullptr, nullptr, tooltip.c_str());
 		}
-		if (_vm->_settings->getAmmoAmount(2) > 0) {
+		if (_vm->_settings->getAmmo(2) > 0) {
 			if (_vm->_settings->getDifficulty() > 0) {
-				tooltip = Common::String::format("%d", _vm->_settings->getAmmoAmount(2));
+				tooltip = Common::String::format("%d", _vm->_settings->getAmmo(2));
 			} else {
 				tooltip = _vm->_textKIA->getText(50);
 			}
diff --git a/engines/bladerunner/vector.h b/engines/bladerunner/vector.h
index d04070f..f3cc1f1 100644
--- a/engines/bladerunner/vector.h
+++ b/engines/bladerunner/vector.h
@@ -143,6 +143,23 @@ inline float cos_1024(int angle1024) {
 inline float sin_1024(int angle1024) {
 	return sin(angle1024 * (M_PI / 512.0f));
 }
+
+inline bool lineIntersection(Vector2 a1, Vector2 a2, Vector2 b1, Vector2 b2, Vector2 *intersection) {
+	Vector2 s1(a2.x - a1.x, a2.y - a1.y);
+	Vector2 s2(b2.x - b1.x, b2.y - b1.y);
+
+	float s = (s1.x * (a1.y - b1.y) - s1.y * (a1.x - b1.x)) / (s1.x * s2.y - s2.x * s1.y);
+	float t = (s2.x * (a1.y - b1.y) - s2.y * (a1.x - b1.x)) / (s1.x * s2.y - s2.x * s1.y);
+
+	if (s >= 0.0f && s <= 1.0f && t >= 0.0f && t <= 1.0f) {
+		intersection->x = a1.x + (t * s1.x);
+		intersection->y = a1.y + (t * s1.y);
+		return true;
+	}
+
+	return false; // No collision
+}
+
 } // End of namespace BladeRunner
 
 #endif





More information about the Scummvm-git-logs mailing list