[Scummvm-git-logs] scummvm master -> 62b75b99908f9cf1ea60bd4dfa415395e80d5c78

peterkohaut peterkohaut at users.noreply.github.com
Sun Feb 25 22:45:18 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:
62b75b9990 BLADERUNNER: Added Generic Walker actors


Commit: 62b75b99908f9cf1ea60bd4dfa415395e80d5c78
    https://github.com/scummvm/scummvm/commit/62b75b99908f9cf1ea60bd4dfa415395e80d5c78
Author: Peter Kohaut (peter.kohaut at gmail.com)
Date: 2018-02-25T22:38:52+01:00

Commit Message:
BLADERUNNER: Added Generic Walker actors

Fixed isseue of duplicating items in world
Fixed fog issue with incorrect rendering in special occasions
Added basic debugger console
Refactored looping code for better readability

Changed paths:
  A engines/bladerunner/debugger.cpp
  A engines/bladerunner/debugger.h
  A engines/bladerunner/script/ai/_template.cpp
  A engines/bladerunner/script/ai/generic_walker_a.cpp
  A engines/bladerunner/script/ai/generic_walker_b.cpp
  A engines/bladerunner/script/ai/generic_walker_c.cpp
    engines/bladerunner/bladerunner.cpp
    engines/bladerunner/bladerunner.h
    engines/bladerunner/fog.cpp
    engines/bladerunner/game_constants.h
    engines/bladerunner/items.cpp
    engines/bladerunner/light.h
    engines/bladerunner/lights.h
    engines/bladerunner/module.mk
    engines/bladerunner/music.cpp
    engines/bladerunner/regions.h
    engines/bladerunner/scene.cpp
    engines/bladerunner/scene.h
    engines/bladerunner/scene_objects.cpp
    engines/bladerunner/scene_objects.h
    engines/bladerunner/script/ai/mccoy.cpp
    engines/bladerunner/script/ai_script.cpp
    engines/bladerunner/script/ai_script.h
    engines/bladerunner/script/init_script.cpp
    engines/bladerunner/script/scene/bb02.cpp
    engines/bladerunner/script/scene/ct02.cpp
    engines/bladerunner/script/scene/ct12.cpp
    engines/bladerunner/script/scene/dr04.cpp
    engines/bladerunner/script/scene/hc03.cpp
    engines/bladerunner/script/scene/hf04.cpp
    engines/bladerunner/script/scene/hf05.cpp
    engines/bladerunner/script/scene/hf06.cpp
    engines/bladerunner/script/scene/kp03.cpp
    engines/bladerunner/script/scene/ma05.cpp
    engines/bladerunner/script/scene/ma06.cpp
    engines/bladerunner/script/scene/nr08.cpp
    engines/bladerunner/script/scene/nr10.cpp
    engines/bladerunner/script/scene/nr11.cpp
    engines/bladerunner/script/scene/rc01.cpp
    engines/bladerunner/script/scene/tb07.cpp
    engines/bladerunner/script/scene/ug01.cpp
    engines/bladerunner/script/scene/ug10.cpp
    engines/bladerunner/script/scene/ug13.cpp
    engines/bladerunner/script/scene/ug15.cpp
    engines/bladerunner/script/script.cpp
    engines/bladerunner/set.h
    engines/bladerunner/ui/esper.cpp
    engines/bladerunner/ui/ui_image_picker.cpp
    engines/bladerunner/waypoints.h


diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp
index 7a24f8d..87f3528 100644
--- a/engines/bladerunner/bladerunner.cpp
+++ b/engines/bladerunner/bladerunner.cpp
@@ -31,6 +31,7 @@
 #include "bladerunner/chapters.h"
 #include "bladerunner/combat.h"
 #include "bladerunner/crimes_database.h"
+#include "bladerunner/debugger.h"
 #include "bladerunner/dialogue_menu.h"
 #include "bladerunner/font.h"
 #include "bladerunner/game_flags.h"
@@ -176,9 +177,12 @@ BladeRunnerEngine::BladeRunnerEngine(OSystem *syst, const ADGameDescription *des
 	_scene                   = nullptr;
 	_aiScripts               = nullptr;
 	for (int i = 0; i != kActorCount; ++i) {
-		_actors[i] = nullptr;
+		_actors[i]           = nullptr;
 	}
+	_debugger                = nullptr;
 	walkingReset();
+
+	_actorUpdateCounter = 0;
 }
 
 BladeRunnerEngine::~BladeRunnerEngine() {
@@ -244,6 +248,8 @@ bool BladeRunnerEngine::startup(bool hasSavegames) {
 
 	_sceneScript = new SceneScript(this);
 
+	_debugger = new Debugger(this);
+
 	// This is the original startup in the game
 
 	bool r;
@@ -637,6 +643,9 @@ void BladeRunnerEngine::shutdown() {
 
 	// These are static objects in original game
 
+	delete _debugger;
+	_debugger = nullptr;
+
 	delete _zbuffer;
 	_zbuffer = nullptr;
 
@@ -701,36 +710,6 @@ void BladeRunnerEngine::gameLoop() {
 	} while (_gameIsRunning);
 }
 
-#if BLADERUNNER_DEBUG_RENDERING
-
-void drawBBox(Vector3 start, Vector3 end, View *view, Graphics::Surface *surface, int color) {
-	Vector3 bfl = view->calculateScreenPosition(Vector3(start.x, start.y, start.z));
-	Vector3 bfr = view->calculateScreenPosition(Vector3(start.x, end.y, start.z));
-	Vector3 bbr = view->calculateScreenPosition(Vector3(end.x, end.y, start.z));
-	Vector3 bbl = view->calculateScreenPosition(Vector3(end.x, start.y, start.z));
-
-	Vector3 tfl = view->calculateScreenPosition(Vector3(start.x, start.y, end.z));
-	Vector3 tfr = view->calculateScreenPosition(Vector3(start.x, end.y, end.z));
-	Vector3 tbr = view->calculateScreenPosition(Vector3(end.x, end.y, end.z));
-	Vector3 tbl = view->calculateScreenPosition(Vector3(end.x, start.y, end.z));
-
-	surface->drawLine(bfl.x, bfl.y, bfr.x, bfr.y, color);
-	surface->drawLine(bfr.x, bfr.y, bbr.x, bbr.y, color);
-	surface->drawLine(bbr.x, bbr.y, bbl.x, bbl.y, color);
-	surface->drawLine(bbl.x, bbl.y, bfl.x, bfl.y, color);
-
-	surface->drawLine(tfl.x, tfl.y, tfr.x, tfr.y, color);
-	surface->drawLine(tfr.x, tfr.y, tbr.x, tbr.y, color);
-	surface->drawLine(tbr.x, tbr.y, tbl.x, tbl.y, color);
-	surface->drawLine(tbl.x, tbl.y, tfl.x, tfl.y, color);
-
-	surface->drawLine(bfl.x, bfl.y, tfl.x, tfl.y, color);
-	surface->drawLine(bfr.x, bfr.y, tfr.x, tfr.y, color);
-	surface->drawLine(bbr.x, bbr.y, tbr.x, tbr.y, color);
-	surface->drawLine(bbl.x, bbl.y, tbl.x, tbl.y, color);
-}
-#endif
-
 void BladeRunnerEngine::gameTick() {
 	handleEvents();
 
@@ -814,15 +793,9 @@ void BladeRunnerEngine::gameTick() {
 			int setId = _scene->getSetId();
 			for (int i = 0, end = _gameInfo->getActorCount(); i != end; ++i) {
 				if (_actors[i]->getSetId() == setId) {
-					// TODO: remove this limitation
-					if (i == kActorMcCoy
-						|| i == kActorRunciter
-						|| i == kActorOfficerLeary
-						|| i == kActorMaggie) {
-						Common::Rect screenRect;
-						if (_actors[i]->tick(backgroundChanged, &screenRect)) {
-							_zbuffer->mark(screenRect);
-						}
+					Common::Rect screenRect;
+					if (_actors[i]->tick(backgroundChanged, &screenRect)) {
+						_zbuffer->mark(screenRect);
 					}
 				}
 			}
@@ -839,8 +812,9 @@ void BladeRunnerEngine::gameTick() {
 				_dialogueMenu->draw(_surfaceFront);
 			}
 
-			// TODO: remove zbuffer draw
-			// _surfaceFront.copyRectToSurface(_zbuffer->getData(), 1280, 0, 0, 640, 480);
+			if (_debugger->_viewZBuffer) {
+				_surfaceFront.copyRectToSurface(_zbuffer->getData(), 1280, 0, 0, 640, 480);
+			}
 
 			_mouse->tick(p.x, p.y);
 			_mouse->draw(_surfaceFront, p.x, p.y);
@@ -853,141 +827,10 @@ void BladeRunnerEngine::gameTick() {
 				_walkSoundId = -1;
 			}
 
-#if BLADERUNNER_DEBUG_RENDERING
-			//draw scene objects
-			int count = _sceneObjects->_count;
-			if (count > 0) {
-				for (int i = 0; i < count; i++) {
-					SceneObjects::SceneObject *sceneObject = &_sceneObjects->_sceneObjects[_sceneObjects->_sceneObjectsSortedByDistance[i]];
-
-					const BoundingBox *bbox = sceneObject->boundingBox;
-					Vector3 a, b;
-					bbox->getXYZ(&a.x, &a.y, &a.z, &b.x, &b.y, &b.z);
-					Vector3 pos = _view->calculateScreenPosition(0.5 * (a + b));
-					int color;
-
-					switch (sceneObject->type) {
-					case kSceneObjectTypeActor:
-						color = 0b111110000000000;
-						drawBBox(a, b, _view, &_surfaceFront, 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->id - kSceneObjectOffsetItems);
-						_mainFont->drawColor(itemText, _surfaceFront, pos.x, pos.y, color);
-						break;
-					case kSceneObjectTypeObject:
-						color = 0b011110111101111;
-						//if (sceneObject->_isObstacle)
-						//	color += 0b100000000000000;
-						if (sceneObject->isClickable) {
-							color = 0b000001111100000;
-						}
-						drawBBox(a, b, _view, &_surfaceFront, color);
-						_mainFont->drawColor(_scene->objectGetName(sceneObject->id - kSceneObjectOffsetObjects), _surfaceFront, pos.x, pos.y, color);
-						break;
-					}
-					_surfaceFront.frameRect(*sceneObject->screenRectangle, color);
-				}
-			}
-
-			//draw regions
-			for (int i = 0; i < 10; i++) {
-				Regions::Region *region = &_scene->_regions->_regions[i];
-				if (!region->present) continue;
-				_surfaceFront.frameRect(region->rectangle, 0b000000000011111);
-			}
-
-			for (int i = 0; i < 10; i++) {
-				Regions::Region *region = &_scene->_exits->_regions[i];
-				if (!region->present) continue;
-				_surfaceFront.frameRect(region->rectangle, 0b111111111111111);
-			}
-
-			//draw walkboxes
-			for (int i = 0; i < _scene->_set->_walkboxCount; i++) {
-				Set::Walkbox *walkbox = &_scene->_set->_walkboxes[i];
-
-				for (int j = 0; j < walkbox->vertexCount; j++) {
-					Vector3 start = _view->calculateScreenPosition(walkbox->vertices[j]);
-					Vector3 end = _view->calculateScreenPosition(walkbox->vertices[(j + 1) % walkbox->vertexCount]);
-					_surfaceFront.drawLine(start.x, start.y, end.x, end.y, 0b111111111100000);
-					Vector3 pos = _view->calculateScreenPosition(0.5 * (start + end));
-					_mainFont->drawColor(walkbox->name, _surfaceFront, pos.x, pos.y, 0b111111111100000);
-				}
-			}
-
-			// draw lights
-			for (int i = 0; i < (int)_lights->_lights.size(); i++) {
-				Light *light = _lights->_lights[i];
-				Matrix4x3 m = light->_matrix;
-				m = invertMatrix(m);
-				//todo do this properly
-				Vector3 posOrigin = m * Vector3(0.0f, 0.0f, 0.0f);
-				float t = posOrigin.y;
-				posOrigin.y = posOrigin.z;
-				posOrigin.z = -t;
-
-				Vector3 posTarget = m * Vector3(0.0f, 0.0f, -100.0f);
-				t = posTarget.y;
-				posTarget.y = posTarget.z;
-				posTarget.z = -t;
-
-				Vector3 size = Vector3(5.0f, 5.0f, 5.0f);
-				int colorR = (light->_color.r * 31.0f);
-				int colorG = (light->_color.g * 31.0f);
-				int colorB = (light->_color.b * 31.0f);
-				int color = (colorR << 10) + (colorG << 5) + colorB;
-
-				drawBBox(posOrigin - size, posOrigin + size, _view, &_surfaceFront, color);
-
-				Vector3 posOriginT = _view->calculateScreenPosition(posOrigin);
-				Vector3 posTargetT = _view->calculateScreenPosition(posTarget);
-				_surfaceFront.drawLine(posOriginT.x, posOriginT.y, posTargetT.x, posTargetT.y, color);
-				_mainFont->drawColor(light->_name, _surfaceFront, posOriginT.x, posOriginT.y, color);
+			if (_debugger->_viewSceneObjects) {
+				_debugger->drawSceneObjects();
 			}
 
-			//draw waypoints
-			for(int i = 0; i < _waypoints->_count; i++) {
-				Waypoints::Waypoint *waypoint = &_waypoints->_waypoints[i];
-				if(waypoint->setId != _scene->getSetId())
-					continue;
-				Vector3 pos = waypoint->position;
-				Vector3 size = Vector3(5.0f, 5.0f, 5.0f);
-				int color = 0b111111111111111;
-				drawBBox(pos - size, pos + size, _view, &_surfaceFront, color);
-				Vector3 spos = _view->calculateScreenPosition(pos);
-				char waypointText[40];
-				sprintf(waypointText, "waypoint %i", i);
-				_mainFont->drawColor(waypointText, _surfaceFront, spos.x, spos.y, color);
-			}
-#endif
-#if BLADERUNNER_DEBUG_RENDERING
-			//draw aesc
-			for (uint i = 0; i < _screenEffects->_entries.size(); i++) {
-				ScreenEffects::Entry &entry = _screenEffects->_entries[i];
-				int j = 0;
-				for (int y = 0; y < entry.height; y++) {
-					for (int x = 0; x < entry.width; x++) {
-						Common::Rect r((entry.x + x) * 2, (entry.y + y) * 2, (entry.x + x) * 2 + 2, (entry.y + y) * 2 + 2);
-
-						int ec = entry.data[j++];
-						Color256 color = entry.palette[ec];
-						int bladeToScummVmConstant = 256 / 16;
-
-						Graphics::PixelFormat _pixelFormat = createRGB555();
-						int color555 = _pixelFormat.RGBToColor(
-							CLIP(color.r * bladeToScummVmConstant, 0, 255),
-							CLIP(color.g * bladeToScummVmConstant, 0, 255),
-							CLIP(color.b * bladeToScummVmConstant, 0, 255));
-						_surfaceFront.fillRect(r, color555);
-					}
-				}
-			}
-#endif
-
 			blitToScreen(_surfaceFront);
 			_system->delayMillis(10);
 		}
@@ -998,15 +841,18 @@ void BladeRunnerEngine::actorsUpdate() {
 	int actorCount = (int)_gameInfo->getActorCount();
 	int setId = _scene->getSetId();
 
-	//TODO: original game updates every non-visible characters by updating only one character in one frame
 	if (setId != kSetUG18 || _gameVars[kVariableChapter] != 4 || !_gameFlags->query(670) || !_aiScripts->isInsideScript()) {
 		for (int i = 0; i < actorCount; i++) {
 			Actor *actor = _actors[i];
-			if (actor->getSetId() == setId) {
+			if (actor->getSetId() == setId || i == _actorUpdateCounter) {
 				_aiScripts->update(i);
 				actor->timersUpdate();
 			}
 		}
+		++_actorUpdateCounter;
+		if (_actorUpdateCounter >= actorCount) {
+			_actorUpdateCounter = 0;
+		}
 	}
 }
 
@@ -1117,6 +963,12 @@ void BladeRunnerEngine::handleKeyUp(Common::Event &event) {
 }
 
 void BladeRunnerEngine::handleKeyDown(Common::Event &event) {
+	if ((event.kbd.keycode == Common::KEYCODE_d) && (event.kbd.flags & Common::KBD_CTRL)) {
+		getDebugger()->attach();
+		getDebugger()->onFrame();
+		return;
+	}
+
 	//TODO:
 	if (!playerHasControl() /* || ActorWalkingLoop || ActorSpeaking || VqaIsPlaying */) {
 		return;
@@ -1426,7 +1278,7 @@ void BladeRunnerEngine::handleMouseClickEmpty(int x, int y, Vector3 &scenePositi
 
 		//TODO mouse::randomize(Mouse);
 
-		if (actorId) {
+		if (actorId > 0) {
 			_aiScripts->shotAtAndMissed(actorId);
 		}
 	} else {
@@ -1696,7 +1548,7 @@ Common::SeekableReadStream *BladeRunnerEngine::getResourceStream(const Common::S
 		}
 	}
 
-	debug("getResource: Resource %s not found.", name.c_str());
+	error("getResource: Resource %s not found", name.c_str());
 	return nullptr;
 }
 
@@ -1735,6 +1587,10 @@ void BladeRunnerEngine::blitToScreen(const Graphics::Surface &src) {
 	_system->updateScreen();
 }
 
+GUI::Debugger *BladeRunnerEngine::getDebugger() {
+	return _debugger;
+}
+
 void blit(const Graphics::Surface &src, Graphics::Surface &dst) {
 	dst.copyRectToSurface(src.getPixels(), src.pitch, 0, 0, src.w, src.h);
 }
diff --git a/engines/bladerunner/bladerunner.h b/engines/bladerunner/bladerunner.h
index 373974f..88f4cf7 100644
--- a/engines/bladerunner/bladerunner.h
+++ b/engines/bladerunner/bladerunner.h
@@ -34,7 +34,6 @@
 #include "graphics/surface.h"
 
 //TODO: remove these when game is playable
-#define BLADERUNNER_DEBUG_RENDERING 0
 #define BLADERUNNER_DEBUG_CONSOLE 0
 #define BLADERUNNER_DEBUG_GAME 0
 
@@ -42,6 +41,10 @@ namespace Common {
 struct Event;
 }
 
+namespace GUI {
+class Debugger;
+}
+
 struct ADGameDescription;
 
 namespace BladeRunner {
@@ -57,6 +60,7 @@ class AudioSpeech;
 class Chapters;
 class CrimesDatabase;
 class Combat;
+class Debugger;
 class DialogueMenu;
 class Elevator;
 class ESPER;
@@ -161,6 +165,8 @@ public:
 
 	Common::RandomSource _rnd;
 
+	Debugger *_debugger;
+
 	bool _isWalkingInterruptible;
 	bool _interruptWalking;
 	bool _playerActorIdle;
@@ -194,6 +200,8 @@ public:
 	int _walkingToActorId;
 	bool _isInsideScriptActor;
 
+	int _actorUpdateCounter;
+
 private:
 	MIXArchive _archives[kArchiveCount];
 
@@ -251,6 +259,8 @@ public:
 	void ISez(const char *str);
 
 	void blitToScreen(const Graphics::Surface &src);
+
+	GUI::Debugger *getDebugger();
 };
 
 static inline const Graphics::PixelFormat createRGB555() {
diff --git a/engines/bladerunner/debugger.cpp b/engines/bladerunner/debugger.cpp
new file mode 100644
index 0000000..94fb7c5
--- /dev/null
+++ b/engines/bladerunner/debugger.cpp
@@ -0,0 +1,344 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "bladerunner/debugger.h"
+
+#include "bladerunner/bladerunner.h"
+#include "bladerunner/boundingbox.h"
+#include "bladerunner/font.h"
+#include "bladerunner/game_constants.h"
+#include "bladerunner/game_flags.h"
+#include "bladerunner/game_info.h"
+#include "bladerunner/light.h"
+#include "bladerunner/lights.h"
+#include "bladerunner/regions.h"
+#include "bladerunner/scene.h"
+#include "bladerunner/scene_objects.h"
+#include "bladerunner/settings.h"
+#include "bladerunner/set.h"
+#include "bladerunner/text_resource.h"
+#include "bladerunner/vector.h"
+#include "bladerunner/view.h"
+#include "bladerunner/waypoints.h"
+#include "bladerunner/zbuffer.h"
+
+#include "common/debug.h"
+#include "common/str.h"
+
+#include "graphics/surface.h"
+
+namespace BladeRunner {
+
+Debugger::Debugger(BladeRunnerEngine *vm) : GUI::Debugger() {
+	_vm = vm;
+
+	_viewSceneObjects = false;
+	_viewUI = false;
+	_viewZBuffer = false;
+
+	registerCmd("draw", WRAP_METHOD(Debugger, cmdDraw));
+	registerCmd("scene", WRAP_METHOD(Debugger, cmdScene));
+	registerCmd("chapter", WRAP_METHOD(Debugger, cmdChapter));
+	registerCmd("flag", WRAP_METHOD(Debugger, cmdFlag));
+	registerCmd("var", WRAP_METHOD(Debugger, cmdVariable));
+}
+
+Debugger::~Debugger() {
+}
+
+bool Debugger::cmdDraw(int argc, const char **argv) {
+	if (argc != 2) {
+		debugPrintf("Usage: %s (obj | ui | zbuf | reset)\n", argv[0]);
+		return true;
+	}
+
+	Common::String arg = argv[1];
+	if (arg == "obj") {
+		_viewSceneObjects = !_viewSceneObjects;
+		debugPrintf("Drawing scene objects = %i\n", _viewSceneObjects);
+	} else if (arg == "ui") {
+		_viewUI = !_viewUI;
+		debugPrintf("Drawing UI elements = %i\n", _viewUI);
+	} else if (arg == "zbuf") {
+		_viewZBuffer = !_viewZBuffer;
+		debugPrintf("Drawing Z buffer = %i\n", _viewZBuffer);
+	} else if (arg == "reset") {
+		_viewSceneObjects = false;
+		_viewUI = false;
+		_viewZBuffer = false;
+		debugPrintf("Drawing scene objects = %i\n", _viewSceneObjects);
+		debugPrintf("Drawing UI elements = %i\n", _viewUI);
+		debugPrintf("Drawing Z buffer = %i\n", _viewZBuffer);
+	}
+
+	return true;
+}
+
+bool Debugger::cmdScene(int argc, const char **argv) {
+	if (argc != 1 && argc != 3) {
+		debugPrintf("Usage: %s [<set_id> <scene_id>]\n", argv[0]);
+		return true;
+	}
+
+	if (argc == 1) {
+		debugPrintf("set = %i\nscene = %i\n", _vm->_scene->getSetId(), _vm->_scene->getSceneId());
+		return true;
+	}
+
+	if (argc == 3) {
+		int setId = atoi(argv[1]);
+		int sceneId = atoi(argv[2]);
+		_vm->_settings->setNewSetAndScene(setId, sceneId);
+	}
+
+	return true;
+}
+
+bool Debugger::cmdChapter(int argc, const char **argv) {
+	if (argc != 2) {
+		debugPrintf("Usage: %s <chapter>\n", argv[0]);
+		return true;
+	}
+
+	int chapter = atoi(argv[1]);
+	if (chapter >= 1 && chapter <= 5) {
+		_vm->_settings->setChapter(chapter);
+	} else {
+		debugPrintf("Chapter must be between 1 and 5\n");
+	}
+
+	return true;
+}
+
+bool Debugger::cmdFlag(int argc, const char **argv) {
+	if (argc != 2 && argc != 3) {
+		debugPrintf("Usage: %s <id> [<new_value>]\n", argv[0]);
+		return true;
+	}
+
+	int flag = atoi(argv[1]);
+	int flagCount = _vm->_gameInfo->getFlagCount();
+	if (flag > 0 && flag < flagCount) {
+		if (argc == 3) {
+			int value = atoi(argv[2]);
+			if (value == 0) {
+				_vm->_gameFlags->reset(flag);
+			} else {
+				_vm->_gameFlags->set(flag);
+			}
+		}
+		debugPrintf("flag(%i) = %i\n", flag, _vm->_gameFlags->query(flag));
+	} else {
+		debugPrintf("Flag id must be between 0 and %i\n", flagCount - 1);
+	}
+
+	return true;
+}
+
+bool Debugger::cmdVariable(int argc, const char **argv) {
+	if (argc != 2 && argc != 3) {
+		debugPrintf("Usage: %s <id> [<new_value>]\n", argv[0]);
+		return true;
+	}
+
+	int variable = atoi(argv[1]);
+	int variableCount = _vm->_gameInfo->getGlobalVarCount();
+	if (variable >= 0 && variable < variableCount) {
+		if (argc == 3) {
+			_vm->_gameVars[variable] = atoi(argv[2]);
+		}
+		debugPrintf("variable(%i) = %i\n", variable, _vm->_gameVars[variable]);
+	} else {
+		debugPrintf("Variable id must be between 0 and %i\n", variableCount - 1);
+	}
+	return true;
+}
+
+void Debugger::drawBBox(Vector3 start, Vector3 end, View *view, Graphics::Surface *surface, int color) {
+	Vector3 bfl = view->calculateScreenPosition(Vector3(start.x, start.y, start.z));
+	Vector3 bfr = view->calculateScreenPosition(Vector3(start.x, end.y, start.z));
+	Vector3 bbr = view->calculateScreenPosition(Vector3(end.x, end.y, start.z));
+	Vector3 bbl = view->calculateScreenPosition(Vector3(end.x, start.y, start.z));
+
+	Vector3 tfl = view->calculateScreenPosition(Vector3(start.x, start.y, end.z));
+	Vector3 tfr = view->calculateScreenPosition(Vector3(start.x, end.y, end.z));
+	Vector3 tbr = view->calculateScreenPosition(Vector3(end.x, end.y, end.z));
+	Vector3 tbl = view->calculateScreenPosition(Vector3(end.x, start.y, end.z));
+
+	surface->drawLine(bfl.x, bfl.y, bfr.x, bfr.y, color);
+	surface->drawLine(bfr.x, bfr.y, bbr.x, bbr.y, color);
+	surface->drawLine(bbr.x, bbr.y, bbl.x, bbl.y, color);
+	surface->drawLine(bbl.x, bbl.y, bfl.x, bfl.y, color);
+
+	surface->drawLine(tfl.x, tfl.y, tfr.x, tfr.y, color);
+	surface->drawLine(tfr.x, tfr.y, tbr.x, tbr.y, color);
+	surface->drawLine(tbr.x, tbr.y, tbl.x, tbl.y, color);
+	surface->drawLine(tbl.x, tbl.y, tfl.x, tfl.y, color);
+
+	surface->drawLine(bfl.x, bfl.y, tfl.x, tfl.y, color);
+	surface->drawLine(bfr.x, bfr.y, tfr.x, tfr.y, color);
+	surface->drawLine(bbr.x, bbr.y, tbr.x, tbr.y, color);
+	surface->drawLine(bbl.x, bbl.y, tbl.x, tbl.y, color);
+}
+
+void Debugger::drawSceneObjects() {
+	//draw scene objects
+	int count = _vm->_sceneObjects->_count;
+	if (count > 0) {
+		for (int i = 0; i < count; i++) {
+			SceneObjects::SceneObject *sceneObject = &_vm->_sceneObjects->_sceneObjects[_vm->_sceneObjects->_sceneObjectsSortedByDistance[i]];
+
+			const BoundingBox *bbox = sceneObject->boundingBox;
+			Vector3 a, b;
+			bbox->getXYZ(&a.x, &a.y, &a.z, &b.x, &b.y, &b.z);
+			Vector3 pos = _vm->_view->calculateScreenPosition(0.5 * (a + b));
+			int color;
+
+			switch (sceneObject->type) {
+			case kSceneObjectTypeUnknown:
+				break;
+			case kSceneObjectTypeActor:
+				color = 0x7C00; // 11111 00000 00000;
+				drawBBox(a, b, _vm->_view, &_vm->_surfaceFront, color);
+				_vm->_surfaceFront.frameRect(*sceneObject->screenRectangle, color);
+				_vm->_mainFont->drawColor(_vm->_textActorNames->getText(sceneObject->id - kSceneObjectOffsetActors), _vm->_surfaceFront, pos.x, pos.y, color);
+				break;
+			case kSceneObjectTypeItem:
+				color = 0x03E0; // 00000 11111 00000
+				char itemText[40];
+				drawBBox(a, b, _vm->_view, &_vm->_surfaceFront, color);
+				sprintf(itemText, "item %i", sceneObject->id - kSceneObjectOffsetItems);
+				_vm->_surfaceFront.frameRect(*sceneObject->screenRectangle, color);
+				_vm->_mainFont->drawColor(itemText, _vm->_surfaceFront, pos.x, pos.y, color);
+				break;
+			case kSceneObjectTypeObject:
+				color = 0x3DEF; //01111 01111 01111;
+				//if (sceneObject->_isObstacle)
+				//	color += 0b100000000000000;
+				if (sceneObject->isClickable) {
+					color = 0x03E0; // 00000 11111 00000;
+				}
+				drawBBox(a, b, _vm->_view, &_vm->_surfaceFront, color);
+				_vm->_surfaceFront.frameRect(*sceneObject->screenRectangle, color);
+				_vm->_mainFont->drawColor(_vm->_scene->objectGetName(sceneObject->id - kSceneObjectOffsetObjects), _vm->_surfaceFront, pos.x, pos.y, color);
+				break;
+			}
+		}
+	}
+
+	//draw regions
+	for (int i = 0; i < 10; i++) {
+		Regions::Region *region = &_vm->_scene->_regions->_regions[i];
+		if (!region->present) continue;
+		_vm->_surfaceFront.frameRect(region->rectangle, 0x001F); // 00000 00000 11111
+	}
+
+	for (int i = 0; i < 10; i++) {
+		Regions::Region *region = &_vm->_scene->_exits->_regions[i];
+		if (!region->present) continue;
+		_vm->_surfaceFront.frameRect(region->rectangle, 0x7FFF); // 11111 11111 11111
+	}
+
+	//draw walkboxes
+	for (int i = 0; i < _vm->_scene->_set->_walkboxCount; i++) {
+		Set::Walkbox *walkbox = &_vm->_scene->_set->_walkboxes[i];
+
+		for (int j = 0; j < walkbox->vertexCount; j++) {
+			Vector3 start = _vm->_view->calculateScreenPosition(walkbox->vertices[j]);
+			Vector3 end = _vm->_view->calculateScreenPosition(walkbox->vertices[(j + 1) % walkbox->vertexCount]);
+			_vm->_surfaceFront.drawLine(start.x, start.y, end.x, end.y, 0x7FE0); // 11111 11111 00000
+			Vector3 pos = _vm->_view->calculateScreenPosition(0.5 * (start + end));
+			_vm->_mainFont->drawColor(walkbox->name, _vm->_surfaceFront, pos.x, pos.y, 0x7FE0); // 11111 11111 00000
+		}
+	}
+
+	// draw lights
+	for (int i = 0; i < (int)_vm->_lights->_lights.size(); i++) {
+		Light *light = _vm->_lights->_lights[i];
+		Matrix4x3 m = light->_matrix;
+		m = invertMatrix(m);
+		//todo do this properly
+		Vector3 posOrigin = m * Vector3(0.0f, 0.0f, 0.0f);
+		float t = posOrigin.y;
+		posOrigin.y = posOrigin.z;
+		posOrigin.z = -t;
+
+		Vector3 posTarget = m * Vector3(0.0f, 0.0f, -100.0f);
+		t = posTarget.y;
+		posTarget.y = posTarget.z;
+		posTarget.z = -t;
+
+		Vector3 size = Vector3(5.0f, 5.0f, 5.0f);
+		int colorR = (light->_color.r * 31.0f);
+		int colorG = (light->_color.g * 31.0f);
+		int colorB = (light->_color.b * 31.0f);
+		int color = (colorR << 10) + (colorG << 5) + colorB;
+
+		drawBBox(posOrigin - size, posOrigin + size, _vm->_view, &_vm->_surfaceFront, color);
+
+		Vector3 posOriginT = _vm->_view->calculateScreenPosition(posOrigin);
+		Vector3 posTargetT = _vm->_view->calculateScreenPosition(posTarget);
+		_vm->_surfaceFront.drawLine(posOriginT.x, posOriginT.y, posTargetT.x, posTargetT.y, color);
+		_vm->_mainFont->drawColor(light->_name, _vm->_surfaceFront, posOriginT.x, posOriginT.y, color);
+	}
+
+	//draw waypoints
+	for(int i = 0; i < _vm->_waypoints->_count; i++) {
+		Waypoints::Waypoint *waypoint = &_vm->_waypoints->_waypoints[i];
+		if(waypoint->setId != _vm->_scene->getSetId())
+			continue;
+		Vector3 pos = waypoint->position;
+		Vector3 size = Vector3(5.0f, 5.0f, 5.0f);
+		int color = 0x7FFF; // 11111 11111 11111
+		drawBBox(pos - size, pos + size, _vm->_view, &_vm->_surfaceFront, color);
+		Vector3 spos = _vm->_view->calculateScreenPosition(pos);
+		char waypointText[40];
+		sprintf(waypointText, "waypoint %i", i);
+		_vm->_mainFont->drawColor(waypointText, _vm->_surfaceFront, spos.x, spos.y, color);
+	}
+
+#if 0
+	//draw aesc
+	for (uint i = 0; i < _screenEffects->_entries.size(); i++) {
+		ScreenEffects::Entry &entry = _screenEffects->_entries[i];
+		int j = 0;
+		for (int y = 0; y < entry.height; y++) {
+			for (int x = 0; x < entry.width; x++) {
+				Common::Rect r((entry.x + x) * 2, (entry.y + y) * 2, (entry.x + x) * 2 + 2, (entry.y + y) * 2 + 2);
+
+				int ec = entry.data[j++];
+				Color256 color = entry.palette[ec];
+				int bladeToScummVmConstant = 256 / 16;
+
+				Graphics::PixelFormat _pixelFormat = createRGB555();
+				int color555 = _pixelFormat.RGBToColor(
+					CLIP(color.r * bladeToScummVmConstant, 0, 255),
+					CLIP(color.g * bladeToScummVmConstant, 0, 255),
+					CLIP(color.b * bladeToScummVmConstant, 0, 255));
+				_surfaceFront.fillRect(r, color555);
+			}
+		}
+	}
+#endif
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/debugger.h b/engines/bladerunner/debugger.h
new file mode 100644
index 0000000..47b06d2
--- /dev/null
+++ b/engines/bladerunner/debugger.h
@@ -0,0 +1,63 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef BLADERUNNER_DEBUGGER_H
+#define BLADERUNNER_DEBUGGER_H
+
+#include "bladerunner/vector.h"
+
+#include "gui/debugger.h"
+
+namespace Graphics {
+struct Surface;
+}
+
+namespace BladeRunner {
+
+class BladeRunnerEngine;
+class View;
+
+class Debugger : public GUI::Debugger{
+	BladeRunnerEngine *_vm;
+
+public:
+	bool _viewSceneObjects;
+	bool _viewUI;
+	bool _viewZBuffer;
+
+	Debugger(BladeRunnerEngine *vm);
+	~Debugger();
+
+	bool cmdDraw(int argc, const char **argv);
+	bool cmdScene(int argc, const char **argv);
+	bool cmdChapter(int argc, const char **argv);
+	bool cmdFlag(int argc, const char **argv);
+	bool cmdVariable(int argc, const char **argv);
+
+	void drawBBox(Vector3 start, Vector3 end, View *view, Graphics::Surface *surface, int color);
+	void drawSceneObjects();
+	void drawZBuffer();
+};
+
+} // End of namespace BladeRunner
+
+#endif
diff --git a/engines/bladerunner/fog.cpp b/engines/bladerunner/fog.cpp
index 2befaf3..fff27b0 100644
--- a/engines/bladerunner/fog.cpp
+++ b/engines/bladerunner/fog.cpp
@@ -118,13 +118,13 @@ void FogCone::read(Common::ReadStream *stream, int frameCount) {
 void FogCone::calculateCoeficient(Vector3 position, Vector3 viewPosition, float *coeficient) {
 	*coeficient = 0.0f;
 
-	Vector3 positionT = this->_matrix * position;
-	Vector3 viewPositionT = this->_matrix * viewPosition;
+	Vector3 positionT = _matrix * position;
+	Vector3 viewPositionT = _matrix * viewPosition;
 
 	Vector3 vectorT = (viewPositionT - positionT).normalize();
 
 	float v67 = - positionT.x * vectorT.x - positionT.y * vectorT.y - positionT.z * vectorT.z;
-	float v66 = - (positionT.z * positionT.z) - (positionT.y * positionT.y) - (positionT.x * positionT.x) + (v67 * v67) + (this->_parameter1 * this->_parameter1);
+	float v66 = - (positionT.z * positionT.z) - (positionT.y * positionT.y) - (positionT.x * positionT.x) + (v67 * v67) + (_parameter1 * _parameter1);
 
 	if (v66 >= 0.0f) {
 		float v24 = sqrt(v66);
@@ -132,8 +132,8 @@ void FogCone::calculateCoeficient(Vector3 position, Vector3 viewPosition, float
 		Vector3 v29 = positionT + (v67 - v24) * vectorT;
 		Vector3 v36 = positionT + (v67 + v24) * vectorT;
 
-		Vector3 v39 = this->_inverted * v29;
-		Vector3 v42 = this->_inverted * v36;
+		Vector3 v39 = _inverted * v29;
+		Vector3 v42 = _inverted * v36;
 
 		float v74 = (v39 - position).length();
 		float v76 = (v42 - position).length();
@@ -164,8 +164,8 @@ void FogSphere::read(Common::ReadStream *stream, int frameCount) {
 void FogSphere::calculateCoeficient(Vector3 position, Vector3 viewPosition, float *coeficient) {
 	*coeficient = 0.0f;
 
-	Vector3 positionT = this->_matrix * position;
-	Vector3 viewPositionT = this->_matrix * viewPosition;
+	Vector3 positionT = _matrix * position;
+	Vector3 viewPositionT = _matrix * viewPosition;
 
 	Vector3 v158 = Vector3::cross(positionT, viewPositionT);
 
@@ -176,12 +176,12 @@ void FogSphere::calculateCoeficient(Vector3 position, Vector3 viewPosition, floa
 		}
 
 		float v173 = sqrt(1.0f - v167.z * v167.z);
-		if (v173 > cos(this->_parameter1)) {
+		if (v173 > cos(_parameter1)) {
 			Vector3 v37 = Vector3(v167.y, -v167.x, 0.0f).normalize();
 
 			float v41 = 1.0f / v173 / v173 - 1.0f;
 			float v42 = sqrt(v41);
-			float v43 = tan(this->_parameter1);
+			float v43 = tan(_parameter1);
 			float v44 = sqrt(v43 * v43 - v41);
 
 			Vector3 v45 = v44 * v37;
@@ -271,10 +271,10 @@ void FogSphere::calculateCoeficient(Vector3 position, Vector3 viewPosition, floa
 				}
 
 				Vector3 v139 = positionT + (v88 * vector);
-				Vector3 v142 = this->_inverted * v139;
+				Vector3 v142 = _inverted * v139;
 
 				Vector3 v148 = positionT + (v114 * vector);
-				Vector3 v151 = this->_inverted * v148;
+				Vector3 v151 = _inverted * v148;
 
 				*coeficient = (v151 - v142).length();
 			}
@@ -292,102 +292,102 @@ void FogBox::read(Common::ReadStream *stream, int frameCount) {
 }
 
 void FogBox::calculateCoeficient(Vector3 position, Vector3 viewPosition, float *coeficient) {
-	Vector3 v159 = this->_matrix * position;
-	Vector3 v146 = v159;
-	Vector3 v156 = this->_matrix * viewPosition;
-	Vector3 v153 = v156;
-	Vector3 v150 = v156 - v159;
-
-	float v149 = this->_parameter1 * 0.5f;
-	if (v159.x < -v149) {
-		if (v156.x < -v149) {
+	Vector3 positionT = _matrix * position;
+	Vector3 viewPositionT = _matrix * viewPosition;
+
+	Vector3 positionTadj = positionT;
+	Vector3 viewPositionTadj = viewPositionT;
+
+	Vector3 direction = viewPositionT - positionT;
+
+	float parameter1half = _parameter1 * 0.5f;
+	if (positionT.x < -parameter1half) {
+		if (viewPositionT.x < -parameter1half) {
+			*coeficient = 0.0f;
 			return;
 		}
-		float v28 = (-v159.x - v149) / v150.x;
-		Vector3 v29 = v28 * v150;
-		v146 = v159 + v29;
-	} else {
-		if (v156.x < -v149) {
-			float v19 = (-v156.x - v149) / v150.x;
-			Vector3 v20 = v19 * v150;
-			v153 = v156 + v20;
-		}
+		float v28 = (-positionT.x - parameter1half) / direction.x;
+		Vector3 v29 = v28 * direction;
+		positionTadj = positionT + v29;
+	} else if (viewPositionT.x < -parameter1half) {
+		float v19 = (-viewPositionT.x - parameter1half) / direction.x;
+		Vector3 v20 = v19 * direction;
+		viewPositionTadj = viewPositionT + v20;
 	}
-	if (v149 < v146.x) {
-		if (v149 < v153.x) {
+
+	if (parameter1half < positionTadj.x) {
+		if (parameter1half < viewPositionTadj.x) {
+			*coeficient = 0.0f;
 			return;
 		}
-		float v48 = (v149 - v146.x) / v150.x;
-		Vector3 v49 = v48 * v150;
-		v146 = v146 + v49;
-	} else {
-		if (v149 < v153.x) {
-			float v40 = (v149 - v153.x) / v150.x;
-			Vector3 v41 = v40 * v150;
-			v153 = v153 + v41;
-		}
+		float v48 = (parameter1half - positionTadj.x) / direction.x;
+		Vector3 v49 = v48 * direction;
+		positionTadj = positionTadj + v49;
+	} else if (parameter1half < viewPositionTadj.x) {
+		float v40 = (parameter1half - viewPositionTadj.x) / direction.x;
+		Vector3 v41 = v40 * direction;
+		viewPositionTadj = viewPositionTadj + v41;
 	}
-	float v162 = this->_parameter2 * 0.5f;
-	if (v146.y < -v162) {
-		if (v153.y < -v162) {
+
+	float parameter2half = _parameter2 * 0.5f;
+	if (positionTadj.y < -parameter2half) {
+		if (viewPositionTadj.y < -parameter2half) {
+			*coeficient = 0.0f;
 			return;
 		}
-		float v71 = (-v146.y - v162) / v150.y;
-		Vector3 v72 = v71 * v150;
-		v146 = v146 + v72;
-	} else {
-		if (v153.y < -v162) {
-			float v62 = (-v153.y - v162) / v150.y;
-			Vector3 v63 = v62 * v150;
-			v153 = v153 + v63;
-		}
+		float v71 = (-positionTadj.y - parameter2half) / direction.y;
+		Vector3 v72 = v71 * direction;
+		positionTadj = positionTadj + v72;
+	} else if (viewPositionTadj.y < -parameter2half) {
+		float v62 = (-viewPositionTadj.y - parameter2half) / direction.y;
+		Vector3 v63 = v62 * direction;
+		viewPositionTadj = viewPositionTadj + v63;
 	}
-	if (v162 < v146.y) {
-		if (v162 < v153.y) {
+
+	if (parameter2half < positionTadj.y) {
+		if (parameter2half < viewPositionTadj.y) {
+			*coeficient = 0.0f;
 			return;
 		}
-		float v91 = (v162 - v146.y) / v150.y;
-		Vector3 v92 = v91 * v150;
-		v146 = v146 + v92;
-	} else {
-		if (v162 < v153.y) {
-			float v83 = (v162 - v153.y) / v150.y;
-			Vector3 v84 = v83 * v150;
-			v153 = v153 + v84;
-		}
+		float v91 = (parameter2half - positionTadj.y) / direction.y;
+		Vector3 v92 = v91 * direction;
+		positionTadj = positionTadj + v92;
+	} else if (parameter2half < viewPositionTadj.y) {
+		float v83 = (parameter2half - viewPositionTadj.y) / direction.y;
+		Vector3 v84 = v83 * direction;
+		viewPositionTadj = viewPositionTadj + v84;
 	}
 
-	if (0.0f <= v146.z) {
-		if (0.0f > v153.z) {
-			float v103 = -v153.z / v150.z;
-			Vector3 v104 = v103 * v150;
-			v153 = v153 + v104;
-		}
-	} else {
-		if (0.0f > v153.z) {
+	if (0.0f > positionTadj.z) {
+		if (0.0f > viewPositionTadj.z) {
+			*coeficient = 0.0f;
 			return;
 		}
-		float v111 = -v146.z / v150.z;
-		Vector3 v112 = v111 * v150;
-		v146 = v146 + v112;
+		float v111 = -positionTadj.z / direction.z;
+		Vector3 v112 = v111 * direction;
+		positionTadj = positionTadj + v112;
+	} else if (0.0f > viewPositionTadj.z) {
+		float v103 = -viewPositionTadj.z / direction.z;
+		Vector3 v104 = v103 * direction;
+		viewPositionTadj = viewPositionTadj + v104;
 	}
 
-	if (v146.z <= this->_parameter3) {
-		if (v153.z > this->_parameter3) {
-			float v124 = (this->_parameter3 - v153.z) / v150.z;
-			Vector3 v125 = v124 * v150;
-			v153 = v153 + v125;
-		}
-	} else {
-		if (v153.z <= this->_parameter3) {
-			float v132 = (this->_parameter3 - v146.z) / v150.z;
-			Vector3 v133 = v132 * v150;
-			v146 = v146 + v133;
+	if (positionTadj.z > _parameter3) {
+		if (viewPositionTadj.z > _parameter3) {
+			*coeficient = 0.0f;
+			return;
 		}
+		float v132 = (_parameter3 - positionTadj.z) / direction.z;
+		Vector3 v133 = v132 * direction;
+		positionTadj = positionTadj + v133;
+	} else if (viewPositionTadj.z > _parameter3) {
+		float v124 = (_parameter3 - viewPositionTadj.z) / direction.z;
+		Vector3 v125 = v124 * direction;
+		viewPositionTadj = viewPositionTadj + v125;
 	}
 
-	Vector3 v137 = this->_inverted * v146;
-	Vector3 v140 = this->_inverted * v153;
+	Vector3 v137 = _inverted * positionTadj;
+	Vector3 v140 = _inverted * viewPositionTadj;
 	Vector3 v143 = v140 - v137;
 
 	*coeficient = v143.length();
diff --git a/engines/bladerunner/game_constants.h b/engines/bladerunner/game_constants.h
index 032c40c..edc8807 100644
--- a/engines/bladerunner/game_constants.h
+++ b/engines/bladerunner/game_constants.h
@@ -488,6 +488,7 @@ enum Flags {
 	kFlagDirectorsCut = 378,
 	KFlagMcCoyAndOfficerLearyTalking = 392,
 	KFlagMcCoyAndOfficerLearyArtMetaphor = 397,
+	kFlagGenericWalkerWaiting = 443,
 	kFlagMaggieIsHurt = 461,
 	kFlagKIAPrivacyAddon = 487,
 	kFlagKIAPrivacyAddonIntro = 599,
@@ -503,6 +504,9 @@ enum Flags {
 enum Variables {
 	kVariableChapter = 1,
 	kVariableChinyen = 2,
+	kVariableGenericWalkerAModel = 32,
+	kVariableGenericWalkerBModel = 33,
+	kVariableGenericWalkerCModel = 34,
 	kVariableWalkLoopActor = 37,
 	kVariableWalkLoopRun = 38,
 	kVariableAffectionTowards = 45, // 0 none, 1 steele, 2 dektora, 3 lucy
@@ -568,9 +572,10 @@ enum AnimationModes {
 };
 
 enum SceneLoopMode {
+	kSceneLoopModeNone = -1,
 	kSceneLoopModeLoseControl = 0,
 	kSceneLoopModeChangeSet = 1,
-	kSceneLoopMode2 = 2,
+	kSceneLoopModeOnce = 2,
 	kSceneLoopModeSpinner = 3
 };
 
diff --git a/engines/bladerunner/items.cpp b/engines/bladerunner/items.cpp
index 6360d4a..9d9efd6 100644
--- a/engines/bladerunner/items.cpp
+++ b/engines/bladerunner/items.cpp
@@ -74,11 +74,11 @@ bool Items::addToWorld(int itemId, int animationId, int setId, Vector3 position,
 	int itemIndex = findItem(itemId);
 	if (itemIndex == -1) {
 		itemIndex = _items.size();
+		_items.push_back(new Item(_vm));
 	}
 
-	Item *item = new Item(_vm);
+	Item *item = _items[itemIndex];
 	item->setup(itemId, setId, animationId, position, facing, height, width, isTargetFlag, isVisible, isPoliceMazeEnemy);
-	_items.push_back(item);
 
 	if (addToSetFlag && setId == _vm->_scene->getSetId()) {
 		return _vm->_sceneObjects->addItem(itemId + kSceneObjectOffsetItems, &item->_boundingBox, &item->_screenRectangle, isTargetFlag, isVisible);
@@ -87,12 +87,12 @@ bool Items::addToWorld(int itemId, int animationId, int setId, Vector3 position,
 }
 
 bool Items::addToSet(int setId) {
-	int itemCount = _vm->_items->_items.size();
+	int itemCount = _items.size();
 	if (itemCount == 0) {
 		return true;
 	}
 	for (int i = 0; i < itemCount; i++) {
-		Item *item = _vm->_items->_items[i];
+		Item *item = _items[i];
 		if (item->_setId == setId) {
 			_vm->_sceneObjects->addItem(item->_itemId + kSceneObjectOffsetItems, &item->_boundingBox, &item->_screenRectangle, item->isTarget(), item->_isVisible);
 		}
@@ -112,7 +112,9 @@ bool Items::remove(int itemId) {
 	if (_items[itemIndex]->_setId == _vm->_scene->getSetId()) {
 		_vm->_sceneObjects->remove(itemId + kSceneObjectOffsetItems);
 	}
-	_items.remove_at(itemIndex);
+
+	delete _items.remove_at(itemIndex);
+
 	return true;
 }
 
diff --git a/engines/bladerunner/light.h b/engines/bladerunner/light.h
index 8ad8636..1ef9f30 100644
--- a/engines/bladerunner/light.h
+++ b/engines/bladerunner/light.h
@@ -29,7 +29,7 @@
 #include "common/stream.h"
 
 namespace Common{
-	class ReadStream;
+class ReadStream;
 }
 
 namespace BladeRunner {
@@ -37,9 +37,7 @@ namespace BladeRunner {
 class Lights;
 
 class Light {
-#if BLADERUNNER_DEBUG_RENDERING
-	friend class BladeRunnerEngine;
-#endif
+	friend class Debugger;
 	friend class Lights;
 	friend class SliceRenderer;
 
diff --git a/engines/bladerunner/lights.h b/engines/bladerunner/lights.h
index ee89fbb..376b860 100644
--- a/engines/bladerunner/lights.h
+++ b/engines/bladerunner/lights.h
@@ -32,7 +32,7 @@
 namespace BladeRunner {
 
 class Lights {
-	friend class BladeRunnerEngine;
+	friend class Debugger;
 	friend class SliceRendererLights;
 
 	BladeRunnerEngine *_vm;
diff --git a/engines/bladerunner/module.mk b/engines/bladerunner/module.mk
index eefae18..4a929a4 100644
--- a/engines/bladerunner/module.mk
+++ b/engines/bladerunner/module.mk
@@ -18,6 +18,7 @@ MODULE_OBJS = \
 	chapters.o \
 	combat.o \
 	crimes_database.o \
+	debugger.o \
 	decompress_lcw.o \
 	decompress_lzo.o \
 	detection.o \
@@ -49,6 +50,9 @@ MODULE_OBJS = \
 	script/vk_script.o \
 	script/esper_script.o \
 	script/ai_script.o \
+	script/ai/generic_walker_a.o \
+	script/ai/generic_walker_b.o \
+	script/ai/generic_walker_c.o \
 	script/ai/leon.o \
 	script/ai/maggie.o \
 	script/ai/mccoy.o \
diff --git a/engines/bladerunner/music.cpp b/engines/bladerunner/music.cpp
index 88fb3e0..818d412 100644
--- a/engines/bladerunner/music.cpp
+++ b/engines/bladerunner/music.cpp
@@ -108,8 +108,10 @@ bool Music::play(const Common::String &trackName, int volume, int pan, int timeF
 	}
 	_current.name = trackName;
 	if (timePlay > 0) {
+		_vm->getTimerManager()->removeTimerProc(timerCallbackFadeOut);
 		_vm->getTimerManager()->installTimerProc(timerCallbackFadeOut, timePlay * 1000 * 1000, this, "BladeRunnerMusicFadeoutTimer");
 	} else if (timeFadeOut > 0) {
+		_vm->getTimerManager()->removeTimerProc(timerCallbackFadeOut);
 		_vm->getTimerManager()->installTimerProc(timerCallbackFadeOut, (_stream->getLength() - timeFadeOut * 1000) * 1000, this, "BladeRunnerMusicFadeoutTimer");
 	}
 	_isPlaying = true;
diff --git a/engines/bladerunner/regions.h b/engines/bladerunner/regions.h
index 4501f00..9868f46 100644
--- a/engines/bladerunner/regions.h
+++ b/engines/bladerunner/regions.h
@@ -31,9 +31,7 @@
 namespace BladeRunner {
 
 class Regions {
-#if BLADERUNNER_DEBUG_RENDERING
-	friend class BladeRunnerEngine;
-#endif
+	friend class Debugger;
 
 	struct Region {
 		Common::Rect rectangle;
diff --git a/engines/bladerunner/scene.cpp b/engines/bladerunner/scene.cpp
index c327e80..0a4877e 100644
--- a/engines/bladerunner/scene.cpp
+++ b/engines/bladerunner/scene.cpp
@@ -52,7 +52,7 @@ Scene::Scene(BladeRunnerEngine *vm)
 	_defaultLoopSet(false),
 	_specialLoopMode(kSceneLoopModeLoseControl),
 	_specialLoop(0),
-	_specialLoopAtEnd(false),
+	_defaultLoopPreloadedSet(false),
 	// _introFinished(false),
 	_nextSetId(-1),
 	_nextSceneId(-1),
@@ -92,8 +92,8 @@ bool Scene::open(int setId, int sceneId, bool isLoadingGame) {
 		_vm->_overlays->removeAll();
 		_defaultLoop = 0;
 		_defaultLoopSet = false;
-		_specialLoopAtEnd = false;
-		_specialLoopMode = -1;
+		_defaultLoopPreloadedSet = false;
+		_specialLoopMode = kSceneLoopModeNone;
 		_specialLoop = -1;
 		_frame = -1;
 	}
@@ -139,10 +139,10 @@ bool Scene::open(int setId, int sceneId, bool isLoadingGame) {
 		return false;
 	}
 
-	if (_specialLoop == -1) {
+	if (_specialLoopMode == kSceneLoopModeNone) {
 		_vqaPlayer->setLoop(_defaultLoop, -1, kLoopSetModeImmediate, nullptr, nullptr);
 		_defaultLoopSet = true;
-		_specialLoopAtEnd = false;
+		_defaultLoopPreloadedSet = false;
 	}
 	_vm->_scene->advanceFrame();
 
@@ -162,8 +162,8 @@ bool Scene::open(int setId, int sceneId, bool isLoadingGame) {
 				   i + kSceneObjectOffsetActors,
 				   actor->getBoundingBox(),
 				   actor->getScreenRectangle(),
-				   1,
-				   0,
+				   true,
+				   false,
 				   actor->isTarget(),
 				   actor->isRetired());
 		}
@@ -216,21 +216,24 @@ int Scene::advanceFrame() {
 		_vqaPlayer->updateScreenEffects(_vm->_screenEffects);
 		_vqaPlayer->updateLights(_vm->_lights);
 	}
-	if (_specialLoopMode && _specialLoopMode != kSceneLoopMode2 && _specialLoopMode != kSceneLoopModeSpinner) {
-		if (_specialLoopMode == kSceneLoopModeChangeSet) {
-			if (frame == -3) { // TODO: when will this happen? bad data in/eof of vqa
-				_vm->_settings->setNewSetAndScene(_nextSetId, _nextSceneId);
-				_vm->playerGainsControl();
+
+	if (_specialLoopMode == kSceneLoopModeLoseControl || _specialLoopMode == kSceneLoopModeOnce || _specialLoopMode == kSceneLoopModeSpinner) {
+		if (!_defaultLoopSet) {
+			_vqaPlayer->setLoop(_defaultLoop, -1, kLoopSetModeEnqueue, &Scene::loopEndedStatic, this);
+			_defaultLoopSet = true;
+			if (_specialLoopMode == kSceneLoopModeLoseControl) {
+				_vm->playerLosesControl();
 			}
-		} else if (!_specialLoopAtEnd) {
-			_vqaPlayer->setLoop(_defaultLoop + 1, -1, kLoopSetModeJustStart, &Scene::loopEndedStatic, this);
-			_specialLoopAtEnd = true;
 		}
-	} else if (!_defaultLoopSet) {
-		_vqaPlayer->setLoop(_defaultLoop, -1, kLoopSetModeEnqueue, &Scene::loopEndedStatic, this);
-		_defaultLoopSet = true;
-		if (_specialLoopMode == kSceneLoopModeLoseControl) {
-			_vm->playerLosesControl();
+	} else if (_specialLoopMode == kSceneLoopModeChangeSet) {
+		if (frame == -3) { // EOF
+			_vm->_settings->setNewSetAndScene(_nextSetId, _nextSceneId);
+			_vm->playerGainsControl();
+		}
+	} else if (_specialLoopMode == kSceneLoopModeNone) {
+		if (!_defaultLoopPreloadedSet) {
+			_vqaPlayer->setLoop(_defaultLoop + 1, -1, kLoopSetModeJustStart, &Scene::loopEndedStatic, this);
+			_defaultLoopPreloadedSet = true;
 		}
 	}
 
@@ -270,7 +273,7 @@ void Scene::loopStartSpecial(int specialLoopMode, int loopId, bool immediately)
 		_nextSceneId = _vm->_settings->getNewScene();
 	}
 	if (immediately) {
-		_specialLoopAtEnd = true;
+		_defaultLoopPreloadedSet = true;
 		loopEnded(0, _specialLoop);
 	}
 }
@@ -326,31 +329,31 @@ const char *Scene::objectGetName(int objectId) {
 }
 
 void Scene::loopEnded(int frame, int loopId) {
-	if (_specialLoopMode && _specialLoopMode != kSceneLoopMode2 && _specialLoopMode != kSceneLoopModeSpinner) {
-		if (_specialLoopMode == kSceneLoopModeChangeSet) {
+	if (_specialLoopMode == kSceneLoopModeLoseControl || _specialLoopMode == kSceneLoopModeOnce || _specialLoopMode == kSceneLoopModeSpinner) {
+		if (_defaultLoopPreloadedSet) {
+			_vqaPlayer->setLoop(_defaultLoop, -1, kLoopSetModeEnqueue, &Scene::loopEndedStatic, this);
 			_defaultLoopSet = true;
-			_specialLoopAtEnd = false;
-			_vm->playerLosesControl();
+			_defaultLoopPreloadedSet = false;
+			if (_specialLoopMode == kSceneLoopModeLoseControl) {
+				_vm->playerLosesControl();
+			}
+		} else {
+			if (_specialLoopMode == kSceneLoopModeLoseControl) {
+				_vm->playerGainsControl();
+				_playerWalkedIn = true;
+			}
+			if (_specialLoopMode == kSceneLoopModeSpinner) {
+				_vm->_spinner->open();
+			}
+			_specialLoopMode = kSceneLoopModeNone;
+			_specialLoop = -1;
+			_vqaPlayer->setLoop(_defaultLoop + 1, -1, kLoopSetModeJustStart, nullptr, nullptr);
+			_defaultLoopPreloadedSet = true;
 		}
-	} else if (_specialLoopAtEnd) {
-		_vqaPlayer->setLoop(_defaultLoop, -1, kLoopSetModeEnqueue, &Scene::loopEndedStatic, this);
+	} else if (_specialLoopMode == kSceneLoopModeChangeSet) {
 		_defaultLoopSet = true;
-		_specialLoopAtEnd = false;
-		if (_specialLoopMode == kSceneLoopModeLoseControl) {
-			_vm->playerLosesControl();
-		}
-	} else {
-		if (_specialLoopMode == kSceneLoopModeLoseControl) {
-			_vm->playerGainsControl();
-			_playerWalkedIn = true;
-		}
-		if (_specialLoopMode == kSceneLoopModeSpinner) {
-			_vm->_spinner->open();
-		}
-		_specialLoopMode = -1;
-		_specialLoop = -1;
-		_vqaPlayer->setLoop(_defaultLoop + 1, -1, kLoopSetModeJustStart, nullptr, nullptr);
-		_specialLoopAtEnd = true;
+		_defaultLoopPreloadedSet = false;
+		_vm->playerLosesControl();
 	}
 }
 
diff --git a/engines/bladerunner/scene.h b/engines/bladerunner/scene.h
index 0220bd0..e0d0175 100644
--- a/engines/bladerunner/scene.h
+++ b/engines/bladerunner/scene.h
@@ -42,9 +42,9 @@ class Scene {
 
 	int         _defaultLoop;
 	bool        _defaultLoopSet;
+	bool        _defaultLoopPreloadedSet;
 	int         _specialLoopMode;
 	int         _specialLoop;
-	bool        _specialLoopAtEnd;
 	// int         _introFinished;
 	int         _nextSetId;
 	int         _nextSceneId;
diff --git a/engines/bladerunner/scene_objects.cpp b/engines/bladerunner/scene_objects.cpp
index 79c3e0b..64cb04f 100644
--- a/engines/bladerunner/scene_objects.cpp
+++ b/engines/bladerunner/scene_objects.cpp
@@ -58,6 +58,8 @@ void SceneObjects::clear() {
 		_sceneObjects[i].isTarget         = false;
 		_sceneObjects[i].isMoving         = false;
 		_sceneObjects[i].isRetired        = false;
+
+		_sceneObjectsSortedByDistance[i]  = -1;
 	}
 	_count = 0;
 }
diff --git a/engines/bladerunner/scene_objects.h b/engines/bladerunner/scene_objects.h
index f0a78da..dbd61b6 100644
--- a/engines/bladerunner/scene_objects.h
+++ b/engines/bladerunner/scene_objects.h
@@ -40,9 +40,8 @@ enum SceneObjectType {
 };
 
 class SceneObjects {
-#if BLADERUNNER_DEBUG_RENDERING
-	friend class BladeRunnerEngine;
-#endif
+	friend class Debugger;
+
 	static const int kSceneObjectCount = 115;
 
 	struct SceneObject {
diff --git a/engines/bladerunner/script/ai/_template.cpp b/engines/bladerunner/script/ai/_template.cpp
new file mode 100644
index 0000000..af7c685
--- /dev/null
+++ b/engines/bladerunner/script/ai/_template.cpp
@@ -0,0 +1,113 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "bladerunner/script/ai_script.h"
+
+namespace BladeRunner {
+
+AIScriptGenericWalkerA::AIScriptGenericWalkerA(BladeRunnerEngine *vm) : AIScriptBase(vm) {
+}
+
+void AIScriptGenericWalkerA::Initialize() {
+	_animationStateNext = 0;
+	_animationNext = 0;
+	_animationFrame = 0;
+	_animationState = 0;
+}
+
+bool AIScriptGenericWalkerA::Update() {
+	return false;
+}
+
+void AIScriptGenericWalkerA::TimerExpired(int timer) {
+}
+
+void AIScriptGenericWalkerA::CompletedMovementTrack() {
+}
+
+void AIScriptGenericWalkerA::ReceivedClue(int clueId, int fromActorId) {
+}
+
+void AIScriptGenericWalkerA::ClickedByPlayer() {
+}
+
+void AIScriptGenericWalkerA::EnteredScene(int sceneId) {
+}
+
+void AIScriptGenericWalkerA::OtherAgentEnteredThisScene(int otherActorId) {
+}
+
+void AIScriptGenericWalkerA::OtherAgentExitedThisScene(int otherActorId) {
+}
+
+void AIScriptGenericWalkerA::OtherAgentEnteredCombatMode(int otherActorId, int combatMode) {
+}
+
+void AIScriptGenericWalkerA::ShotAtAndMissed() {
+}
+
+bool AIScriptGenericWalkerA::ShotAtAndHit() {
+	return false;
+}
+
+void AIScriptGenericWalkerA::Retired(int byActorId) {
+}
+
+int AIScriptGenericWalkerA::GetFriendlinessModifierIfGetsClue(int otherActorId, int clueId) {
+	return 0;
+}
+
+bool AIScriptGenericWalkerA::GoalChanged(int currentGoalNumber, int newGoalNumber) {
+	return false;
+}
+
+bool AIScriptGenericWalkerA::UpdateAnimation(int *animation, int *frame) {
+	*animation = 0;
+	*frame = _animationFrame;
+	return true;
+}
+
+bool AIScriptGenericWalkerA::ChangeAnimationMode(int mode) {
+	return true;
+}
+
+void AIScriptGenericWalkerA::QueryAnimationState(int *animationState, int *animationFrame, int *animationStateNext, int *animationNext) {
+	*animationState     = _animationState;
+	*animationFrame     = _animationFrame;
+	*animationStateNext = _animationStateNext;
+	*animationNext      = _animationNext;
+}
+
+void AIScriptGenericWalkerA::SetAnimationState(int animationState, int animationFrame, int animationStateNext, int animationNext) {
+	_animationState     = animationState;
+	_animationFrame     = animationFrame;
+	_animationStateNext = animationStateNext;
+	_animationNext      = animationNext;
+}
+
+bool AIScriptGenericWalkerA::ReachedMovementTrackWaypoint(int waypointId) {
+	return true;
+}
+
+void AIScriptGenericWalkerA::FledCombat() {}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/ai/generic_walker_a.cpp b/engines/bladerunner/script/ai/generic_walker_a.cpp
new file mode 100644
index 0000000..4bb5b14
--- /dev/null
+++ b/engines/bladerunner/script/ai/generic_walker_a.cpp
@@ -0,0 +1,483 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "bladerunner/script/ai_script.h"
+
+namespace BladeRunner {
+enum kGenericWalkerAStates {
+	kGenericWalkerAStatesIdle = 0,
+	kGenericWalkerAStatesWalk = 1,
+	kGenericWalkerAStatesDie  = 2,
+	kGenericWalkerAStatesGun  = 3
+};
+
+AIScriptGenericWalkerA::AIScriptGenericWalkerA(BladeRunnerEngine *vm) : AIScriptBase(vm) {
+	isInside = false;
+	deltaX = 0.0f;
+	deltaZ = 0.0f;
+}
+
+void AIScriptGenericWalkerA::Initialize() {
+	_animationState = kGenericWalkerAStatesIdle;
+	_animationFrame = 0;
+	_animationStateNext = 0;
+	isInside = false;
+	deltaX = 0.0f;
+	deltaZ = 0.0f;
+	Actor_Set_Goal_Number(kActorGenwalkerA, 0);
+}
+
+bool AIScriptGenericWalkerA::Update() {
+	switch (Actor_Query_Goal_Number(kActorGenwalkerA)) {
+		case 0:
+			if (prepareWalker()) {
+				return true;
+			}
+			break;
+		case 1:
+			if (deltaX != 0.0f || deltaZ != 0.0f) {
+				movingUpdate();
+			}
+			break;
+		case 200:
+			Actor_Face_Actor(kActorGenwalkerA, kActorMcCoy, true);
+			break;
+	}
+	return false;
+}
+
+void AIScriptGenericWalkerA::TimerExpired(int timer) {
+	if (timer == 2) {
+		AI_Countdown_Timer_Reset(kActorGenwalkerA, 2);
+		Game_Flag_Reset(kFlagGenericWalkerWaiting);
+		return;// true;
+	}
+	//return false;
+}
+
+void AIScriptGenericWalkerA::CompletedMovementTrack() {
+	if (Actor_Query_Goal_Number(kActorGenwalkerA) > 0) {
+		Actor_Set_Goal_Number(kActorGenwalkerA, 0);
+		if (!Game_Flag_Query(kFlagGenericWalkerWaiting)) {
+			Game_Flag_Set(kFlagGenericWalkerWaiting);
+			AI_Countdown_Timer_Reset(kActorGenwalkerA, 2);
+			AI_Countdown_Timer_Start(kActorGenwalkerA, 2, Random_Query(6, 10));
+		}
+		// return true;
+	}
+	// return false;
+}
+
+void AIScriptGenericWalkerA::ReceivedClue(int clueId, int fromActorId) {
+	//return false;
+}
+
+void AIScriptGenericWalkerA::ClickedByPlayer() {
+	Actor_Face_Actor(kActorMcCoy, kActorGenwalkerA, true);
+	if (Actor_Query_Goal_Number(kActorGenwalkerA) == 200) {
+		Actor_Says(kActorMcCoy, 5290, 18);
+	} else {
+		switch (Random_Query(1, 10)) {
+		case 1:
+			Actor_Says(kActorMcCoy, 365, 3);
+			break;
+		case 2:
+			Actor_Says(kActorMcCoy, 755, 3);
+			break;
+		case 3:
+			Actor_Says(kActorMcCoy, 940, 3);
+			break;
+		case 4:
+			Actor_Says(kActorMcCoy, 4560, 3);
+			break;
+		case 5:
+			Actor_Says(kActorMcCoy, 4870, 3);
+			break;
+		case 6:
+			Actor_Says(kActorMcCoy, 5125, 3);
+			break;
+		case 7:
+			Actor_Says(kActorMcCoy, 8450, 3);
+			break;
+		case 8:
+			Actor_Says(kActorMcCoy, 1085, 3);
+			break;
+		case 9:
+			Actor_Says(kActorMcCoy, 365, 3);
+			break;
+		case 10:
+			Actor_Says(kActorMcCoy, 7415, 3);
+			break;
+		}
+	}
+	//return false;
+}
+
+void AIScriptGenericWalkerA::EnteredScene(int sceneId) {
+	//return false;
+}
+
+void AIScriptGenericWalkerA::OtherAgentEnteredThisScene(int otherActorId) {
+	//return false;
+}
+
+void AIScriptGenericWalkerA::OtherAgentExitedThisScene(int otherActorId) {
+	if (Actor_Query_Goal_Number(kActorGenwalkerA) && otherActorId == kActorMcCoy) {
+		Actor_Set_Goal_Number(kActorGenwalkerA, 0);
+	}
+	//return false;
+}
+
+void AIScriptGenericWalkerA::OtherAgentEnteredCombatMode(int otherActorId, int combatMode) {
+	//return false;
+}
+
+void AIScriptGenericWalkerA::ShotAtAndMissed() {
+	//return false;
+}
+
+bool AIScriptGenericWalkerA::ShotAtAndHit() {
+	if (Actor_Query_Goal_Number(kActorGenwalkerA)) {
+		AI_Movement_Track_Flush(kActorGenwalkerA);
+		_animationState = kGenericWalkerAStatesDie;
+		_animationFrame = 0;
+		Sound_Play(203, 100, 0, 0, 50);
+		movingStart();
+		return true;
+	}
+	return false;
+}
+
+void AIScriptGenericWalkerA::Retired(int byActorId) {
+	//return false;
+}
+
+int AIScriptGenericWalkerA::GetFriendlinessModifierIfGetsClue(int otherActorId, int clueId) {
+	return 0;
+}
+
+bool AIScriptGenericWalkerA::GoalChanged(int currentGoalNumber, int newGoalNumber) {
+	if (newGoalNumber == 0) {
+		AI_Movement_Track_Flush(kActorGenwalkerA);
+		Actor_Put_In_Set(kActorGenwalkerA, kSetFreeSlotH);
+		Global_Variable_Set(kVariableGenericWalkerAModel, -1);
+		return false;
+	} else if (newGoalNumber == 1) {
+		return true;
+	} else if (newGoalNumber == 200) {
+		Actor_Put_In_Set(kActorGenwalkerA, kSetRC04);
+		Actor_Set_At_XYZ(kActorGenwalkerA, 0.0, 36.0, -172.0, 491);
+		Actor_Change_Animation_Mode(kActorGenwalkerA, kAnimationModeCombatIdle);
+		return true;
+	}
+	return false;
+}
+
+bool AIScriptGenericWalkerA::UpdateAnimation(int *animation, int *frame) {
+	switch (_animationState) {
+	case kGenericWalkerAStatesIdle:
+		switch (Global_Variable_Query(kVariableGenericWalkerAModel)) {
+		case 0:
+			*animation = 426;
+			break;
+		case 1:
+			*animation = 430;
+			break;
+		case 2:
+			*animation = 437;
+			break;
+		case 3:
+			*animation = 431;
+			break;
+		case 4:
+			*animation = 427;
+			break;
+		case 5:
+			*animation = 433;
+			break;
+		}
+		_animationFrame = 0;
+		break;
+	case kGenericWalkerAStatesWalk:
+		switch (Global_Variable_Query(kVariableGenericWalkerAModel)){
+		case 0:
+			*animation = 424;
+			break;
+		case 1:
+			*animation = 428;
+			break;
+		case 2:
+			*animation = 436;
+			break;
+		case 3:
+			*animation = 429;
+			break;
+		case 4:
+			*animation = 425;
+			break;
+		case 5:
+			*animation = 432;
+			break;
+		}
+		++_animationFrame;
+		if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(*animation)) {
+			_animationFrame = 0;
+		}
+		break;
+	case kGenericWalkerAStatesDie:
+		*animation = 874;
+		++_animationFrame;
+		if (++_animationFrame >= Slice_Animation_Query_Number_Of_Frames(874))
+		{
+			_animationFrame = 0;
+			Actor_Set_Goal_Number(kActorGenwalkerA, 0);
+			_animationState = kGenericWalkerAStatesIdle;
+			deltaX = 0.0f;
+			deltaZ = 0.0f;
+		}
+		break;
+	case kGenericWalkerAStatesGun:
+		*animation = 440;
+		++_animationFrame;
+		if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(440)) {
+			_animationFrame = 0;
+		}
+		break;
+	}
+	*frame = _animationFrame;
+	return true;
+}
+
+bool AIScriptGenericWalkerA::ChangeAnimationMode(int mode) {
+	switch (mode) {
+	case kAnimationModeIdle:
+		_animationState = kGenericWalkerAStatesIdle;
+		_animationFrame = 0;
+		break;
+	case kAnimationModeWalk:
+		_animationState = kGenericWalkerAStatesWalk;
+		_animationFrame = 0;
+		break;
+	case kAnimationModeCombatIdle:
+		_animationState = kGenericWalkerAStatesGun;
+		_animationFrame = 0;
+		break;
+	}
+	return true;
+}
+
+void AIScriptGenericWalkerA::QueryAnimationState(int *animationState, int *animationFrame, int *animationStateNext, int *animationNext) {
+	*animationState     = _animationState;
+	*animationFrame     = _animationFrame;
+	*animationStateNext = _animationStateNext;
+	*animationNext      = _animationNext;
+}
+
+void AIScriptGenericWalkerA::SetAnimationState(int animationState, int animationFrame, int animationStateNext, int animationNext) {
+	_animationState     = animationState;
+	_animationFrame     = animationFrame;
+	_animationStateNext = animationStateNext;
+	_animationNext      = animationNext;
+}
+
+bool AIScriptGenericWalkerA::ReachedMovementTrackWaypoint(int waypointId) {
+	return true;
+}
+
+void AIScriptGenericWalkerA::FledCombat() {
+	//return false;
+}
+
+void AIScriptGenericWalkerA::movingStart() {
+	float mccoyX, mccoyY, mccoyZ;
+	float walkerX, walkerY, walkerZ;
+
+	Actor_Query_XYZ(kActorMcCoy, &mccoyX, &mccoyY, &mccoyZ);
+	Actor_Query_XYZ(kActorGenwalkerA, &walkerX, &walkerY, &walkerZ);
+
+	deltaX = walkerX - mccoyX;
+	deltaZ = walkerZ - mccoyZ;
+
+	float dist = sqrt(deltaX * deltaX + deltaZ * deltaZ);
+	if (dist == 0.0f) {
+		deltaZ = 0.0f;
+		deltaX = 0.0f;
+	} else {
+		deltaX *= 10.0f / dist;
+		deltaZ *= 10.0f / dist;
+	}
+}
+
+void AIScriptGenericWalkerA::movingUpdate() {
+	float walkerX, walkerY, walkerZ;
+
+	Actor_Query_XYZ(kActorGenwalkerA, &walkerX, &walkerY, &walkerZ);
+	int facing = Actor_Query_Facing_1024(kActorGenwalkerA);
+
+	walkerX += deltaX;
+	walkerZ += deltaZ;
+
+	deltaX = deltaX * 0.97f;
+	deltaZ = deltaZ * 0.97f;
+
+	Actor_Set_At_XYZ(kActorGenwalkerA, walkerX, walkerY, walkerZ, facing);
+
+}
+
+bool AIScriptGenericWalkerA::prepareWalker() {
+	if (Game_Flag_Query(kFlagGenericWalkerWaiting) || Global_Variable_Query(35) < 0 || !preparePath()) {
+		return false;
+	}
+
+	int model = 0;
+	do {
+		if (isInside) {
+			model = Random_Query(3, 5);
+		} else {
+			model = Random_Query(0, 5);
+		}
+	}
+	while (model == Global_Variable_Query(kVariableGenericWalkerBModel) || model == Global_Variable_Query(kVariableGenericWalkerCModel));
+
+	Global_Variable_Set(kVariableGenericWalkerAModel, model);
+	Game_Flag_Set(kFlagGenericWalkerWaiting);
+	AI_Countdown_Timer_Reset(kActorGenwalkerA, 2);
+	AI_Countdown_Timer_Start(kActorGenwalkerA, 2, Random_Query(4, 12));
+	Actor_Set_Goal_Number(kActorGenwalkerA, 1);
+	return true;
+}
+
+bool AIScriptGenericWalkerA::preparePath() {
+	AI_Movement_Track_Flush(kActorGenwalkerA);
+	int set = Player_Query_Current_Set();
+
+	if (set == kSetAR01_AR02) {
+		isInside = false;
+		int waypointStart = Random_Query(155, 158);
+		int waypointEnd = 0;
+		AI_Movement_Track_Append(kActorGenwalkerA, waypointStart, 0);
+		do {
+			waypointEnd = Random_Query(155, 158);
+		} while (waypointEnd == waypointStart);
+		if ((waypointStart == 155 || waypointStart == 156) && (waypointEnd == 157 || waypointEnd == 158)) {
+			AI_Movement_Track_Append(kActorGenwalkerA, 159, 0);
+			AI_Movement_Track_Append(kActorGenwalkerA, 160, 0);
+			if (Random_Query(0, 3) == 0) {
+				AI_Movement_Track_Append_With_Facing(kActorGenwalkerA, 161, Random_Query(15, 30), 904);
+			}
+		} else if ((waypointEnd == 155 || waypointEnd == 156) && (waypointStart == 157 || waypointStart == 158)) {
+			if (Random_Query(0, 3) == 0) {
+				AI_Movement_Track_Append_With_Facing(kActorGenwalkerA, 161, Random_Query(15, 30), 904);
+			}
+			AI_Movement_Track_Append(kActorGenwalkerA, 160, 0);
+			AI_Movement_Track_Append(kActorGenwalkerA, 159, 0);
+		} else if ((waypointStart == 155 && waypointEnd == 156) || (waypointStart == 156 && waypointEnd == 155)) {
+			AI_Movement_Track_Append(kActorGenwalkerA, 159, 0);
+		}
+		AI_Movement_Track_Append(kActorGenwalkerA, waypointEnd, 0);
+		AI_Movement_Track_Repeat(kActorGenwalkerA);
+		return true;
+	}
+
+	if (set == kSetCT01_CT12) {
+		isInside = false;
+		if (Random_Query(0, 1)) {
+			AI_Movement_Track_Append(kActorGenwalkerA, 54, 1);
+			if (Random_Query(1, 3) == 1) {
+				AI_Movement_Track_Append(kActorGenwalkerA, 56, 0);
+				AI_Movement_Track_Append(kActorGenwalkerA, 43, 1);
+			} else {
+				AI_Movement_Track_Append(kActorGenwalkerA, 53, 1);
+			}
+			AI_Movement_Track_Append(kActorGenwalkerA, 40, 1);
+			AI_Movement_Track_Repeat(kActorGenwalkerA);
+		} else {
+			AI_Movement_Track_Append(kActorGenwalkerA, 53, 1);
+			if (Random_Query(1, 3) == 1) {
+				AI_Movement_Track_Append(kActorGenwalkerA, 43, 1);
+			} else {
+				AI_Movement_Track_Append(kActorGenwalkerA, 54, 1);
+			}
+			AI_Movement_Track_Append(kActorGenwalkerA, 40, 1);
+			AI_Movement_Track_Repeat(kActorGenwalkerA);
+		}
+		return true;
+	}
+
+	if (set == kSetHC01_HC02_HC03_HC04) {
+		isInside = true;
+		if (Random_Query(0, 1)) {
+			AI_Movement_Track_Append(kActorGenwalkerA, 164, 0);
+			if (Random_Query(0, 1)) {
+				AI_Movement_Track_Append(kActorGenwalkerA, 163, 0);
+				AI_Movement_Track_Append(kActorGenwalkerA, 162, 0);
+			} else if (Random_Query(0, 1)) {
+				AI_Movement_Track_Append(kActorGenwalkerA, 163, 0);
+				AI_Movement_Track_Append(kActorGenwalkerA, 162, 0);
+			} else {
+				AI_Movement_Track_Append(kActorGenwalkerA, 163, 0);
+				AI_Movement_Track_Append(kActorGenwalkerA, 162, 0);
+			}
+		} else {
+			AI_Movement_Track_Append(kActorGenwalkerA, 162, 0);
+			if (Random_Query(0, 1)) {
+				AI_Movement_Track_Append(kActorGenwalkerA, 163, 0);
+				AI_Movement_Track_Append(kActorGenwalkerA, 164, 0);
+			} else {
+				if (Random_Query(0, 1)) {
+					AI_Movement_Track_Append_With_Facing(kActorGenwalkerA, 166, 0, 30);
+				}
+				AI_Movement_Track_Append(kActorGenwalkerA, 163, 0);
+				AI_Movement_Track_Append(kActorGenwalkerA, 164, 0);
+			}
+		}
+		AI_Movement_Track_Repeat(kActorGenwalkerA);
+		return true;
+	}
+
+	if (set == kSetRC03) {
+		isInside = false;
+		int waypointStart = 0;
+		int waypointEnd = 0;
+		do {
+			waypointStart = Random_Query(167, 171);
+		} while (waypointEnd == 168 || waypointEnd == 169);
+		do {
+			waypointEnd = Random_Query(167, 171);
+		} while (waypointEnd == waypointStart || waypointEnd == 168 || waypointEnd == 169);
+		AI_Movement_Track_Append(kActorGenwalkerA, waypointStart, 0);
+		if (waypointStart == 170) {
+			AI_Movement_Track_Append(kActorGenwalkerA, 169, 0);
+			AI_Movement_Track_Append(kActorGenwalkerA, 168, 0);
+		} else if (waypointEnd == 170) {
+			AI_Movement_Track_Append(kActorGenwalkerA, 168, 0);
+			AI_Movement_Track_Append(kActorGenwalkerA, 169, 0);
+		}
+		AI_Movement_Track_Append(kActorGenwalkerA, waypointEnd, 0);
+		AI_Movement_Track_Repeat(kActorGenwalkerA);
+		return true;
+	}
+
+	return false;
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/ai/generic_walker_b.cpp b/engines/bladerunner/script/ai/generic_walker_b.cpp
new file mode 100644
index 0000000..a2ff581
--- /dev/null
+++ b/engines/bladerunner/script/ai/generic_walker_b.cpp
@@ -0,0 +1,458 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "bladerunner/script/ai_script.h"
+
+namespace BladeRunner {
+enum kGenericWalkerBStates {
+	kGenericWalkerBStatesIdle = 0,
+	kGenericWalkerBStatesWalk = 1,
+	kGenericWalkerBStatesDie  = 2
+};
+
+AIScriptGenericWalkerB::AIScriptGenericWalkerB(BladeRunnerEngine *vm) : AIScriptBase(vm) {
+	isInside = false;
+	deltaX = 0.0f;
+	deltaZ = 0.0f;
+}
+
+void AIScriptGenericWalkerB::Initialize() {
+	_animationState = kGenericWalkerBStatesIdle;
+	_animationFrame = 0;
+	_animationStateNext = 0;
+	isInside = false;
+	deltaX = 0.0f;
+	deltaZ = 0.0f;
+	Actor_Set_Goal_Number(kActorGenwalkerB, 0);
+}
+
+bool AIScriptGenericWalkerB::Update() {
+	switch (Actor_Query_Goal_Number(kActorGenwalkerB)) {
+		case 0:
+			if (prepareWalker()) {
+				return true;
+			}
+			break;
+		case 1:
+			if (deltaX != 0.0f || deltaZ != 0.0f) {
+				movingUpdate();
+			}
+			break;
+	}
+	return false;
+}
+
+void AIScriptGenericWalkerB::TimerExpired(int timer) {
+	if (timer == 2) {
+		AI_Countdown_Timer_Reset(kActorGenwalkerB, 2);
+		Game_Flag_Reset(kFlagGenericWalkerWaiting);
+		return;// true;
+	}
+	//return false;
+}
+
+void AIScriptGenericWalkerB::CompletedMovementTrack() {
+	if (Actor_Query_Goal_Number(kActorGenwalkerB) > 0) {
+		Actor_Set_Goal_Number(kActorGenwalkerB, 0);
+		if (!Game_Flag_Query(kFlagGenericWalkerWaiting)) {
+			Game_Flag_Set(kFlagGenericWalkerWaiting);
+			AI_Countdown_Timer_Reset(kActorGenwalkerB, 2);
+			AI_Countdown_Timer_Start(kActorGenwalkerB, 2, Random_Query(6, 10));
+		}
+		// return true;
+	}
+	// return false;
+}
+
+void AIScriptGenericWalkerB::ReceivedClue(int clueId, int fromActorId) {
+	//return false;
+}
+
+void AIScriptGenericWalkerB::ClickedByPlayer() {
+	Actor_Face_Actor(kActorMcCoy, kActorGenwalkerB, true);
+	switch (Random_Query(1, 10)) {
+	case 1:
+		Actor_Says(kActorMcCoy, 365, 3);
+		break;
+	case 2:
+		Actor_Says(kActorMcCoy, 755, 3);
+		break;
+	case 3:
+		Actor_Says(kActorMcCoy, 940, 3);
+		break;
+	case 4:
+		Actor_Says(kActorMcCoy, 4560, 3);
+		break;
+	case 5:
+		Actor_Says(kActorMcCoy, 4870, 3);
+		break;
+	case 6:
+		Actor_Says(kActorMcCoy, 5125, 3);
+		break;
+	case 7:
+		Actor_Says(kActorMcCoy, 8450, 3);
+		break;
+	case 8:
+		Actor_Says(kActorMcCoy, 1085, 3);
+		break;
+	case 9:
+		Actor_Says(kActorMcCoy, 365, 3);
+		break;
+	case 10:
+		Actor_Says(kActorMcCoy, 7415, 3);
+		break;
+	}
+	//return false;
+}
+
+void AIScriptGenericWalkerB::EnteredScene(int sceneId) {
+	//return false;
+}
+
+void AIScriptGenericWalkerB::OtherAgentEnteredThisScene(int otherActorId) {
+	//return false;
+}
+
+void AIScriptGenericWalkerB::OtherAgentExitedThisScene(int otherActorId) {
+	if (Actor_Query_Goal_Number(kActorGenwalkerB) && otherActorId == kActorMcCoy) {
+		Actor_Set_Goal_Number(kActorGenwalkerB, 0);
+	}
+	//return false;
+}
+
+void AIScriptGenericWalkerB::OtherAgentEnteredCombatMode(int otherActorId, int combatMode) {
+	//return false;
+}
+
+void AIScriptGenericWalkerB::ShotAtAndMissed() {
+	//return false;
+}
+
+bool AIScriptGenericWalkerB::ShotAtAndHit() {
+	if (Actor_Query_Goal_Number(kActorGenwalkerB)) {
+		AI_Movement_Track_Flush(kActorGenwalkerB);
+		_animationState = kGenericWalkerBStatesDie;
+		_animationFrame = 0;
+		Sound_Play(203, 100, 0, 0, 50);
+		movingStart();
+		return true;
+	}
+	return false;
+}
+
+void AIScriptGenericWalkerB::Retired(int byActorId) {
+	//return false;
+}
+
+int AIScriptGenericWalkerB::GetFriendlinessModifierIfGetsClue(int otherActorId, int clueId) {
+	return 0;
+}
+
+bool AIScriptGenericWalkerB::GoalChanged(int currentGoalNumber, int newGoalNumber) {
+	if (newGoalNumber == 0) {
+		AI_Movement_Track_Flush(kActorGenwalkerB);
+		Actor_Put_In_Set(kActorGenwalkerB, kSetFreeSlotH);
+		Global_Variable_Set(kVariableGenericWalkerBModel, -1);
+		return false;
+	} else if (newGoalNumber == 1) {
+		return true;
+	}
+	return false;
+}
+
+bool AIScriptGenericWalkerB::UpdateAnimation(int *animation, int *frame) {
+	switch (_animationState) {
+	case kGenericWalkerBStatesIdle:
+		switch (Global_Variable_Query(kVariableGenericWalkerBModel)) {
+		case 0:
+			*animation = 426;
+			break;
+		case 1:
+			*animation = 430;
+			break;
+		case 2:
+			*animation = 437;
+			break;
+		case 3:
+			*animation = 431;
+			break;
+		case 4:
+			*animation = 427;
+			break;
+		case 5:
+			*animation = 433;
+			break;
+		}
+		_animationFrame = 0;
+		break;
+	case kGenericWalkerBStatesWalk:
+		switch (Global_Variable_Query(kVariableGenericWalkerBModel)){
+		case 0:
+			*animation = 424;
+			break;
+		case 1:
+			*animation = 428;
+			break;
+		case 2:
+			*animation = 436;
+			break;
+		case 3:
+			*animation = 429;
+			break;
+		case 4:
+			*animation = 425;
+			break;
+		case 5:
+			*animation = 432;
+			break;
+		}
+		++_animationFrame;
+		if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(*animation)) {
+			_animationFrame = 0;
+		}
+		break;
+	case kGenericWalkerBStatesDie:
+		*animation = 874;
+		++_animationFrame;
+		if (++_animationFrame >= Slice_Animation_Query_Number_Of_Frames(874))
+		{
+			_animationFrame = 0;
+			Actor_Set_Goal_Number(kActorGenwalkerB, 0);
+			_animationState = kGenericWalkerBStatesIdle;
+			deltaX = 0.0f;
+			deltaZ = 0.0f;
+		}
+		break;
+	}
+	*frame = _animationFrame;
+	return true;
+}
+
+bool AIScriptGenericWalkerB::ChangeAnimationMode(int mode) {
+	switch (mode) {
+	case kAnimationModeIdle:
+		_animationState = kGenericWalkerBStatesIdle;
+		_animationFrame = 0;
+		break;
+	case kAnimationModeWalk:
+		_animationState = kGenericWalkerBStatesWalk;
+		_animationFrame = 0;
+		break;
+	}
+	return true;
+}
+
+void AIScriptGenericWalkerB::QueryAnimationState(int *animationState, int *animationFrame, int *animationStateNext, int *animationNext) {
+	*animationState     = _animationState;
+	*animationFrame     = _animationFrame;
+	*animationStateNext = _animationStateNext;
+	*animationNext      = _animationNext;
+}
+
+void AIScriptGenericWalkerB::SetAnimationState(int animationState, int animationFrame, int animationStateNext, int animationNext) {
+	_animationState     = animationState;
+	_animationFrame     = animationFrame;
+	_animationStateNext = animationStateNext;
+	_animationNext      = animationNext;
+}
+
+bool AIScriptGenericWalkerB::ReachedMovementTrackWaypoint(int waypointId) {
+	return true;
+}
+
+void AIScriptGenericWalkerB::FledCombat() {
+	//return false;
+}
+
+void AIScriptGenericWalkerB::movingStart() {
+	float mccoyX, mccoyY, mccoyZ;
+	float walkerX, walkerY, walkerZ;
+
+	Actor_Query_XYZ(kActorMcCoy, &mccoyX, &mccoyY, &mccoyZ);
+	Actor_Query_XYZ(kActorGenwalkerB, &walkerX, &walkerY, &walkerZ);
+
+	deltaX = walkerX - mccoyX;
+	deltaZ = walkerZ - mccoyZ;
+
+	float dist = sqrt(deltaX * deltaX + deltaZ * deltaZ);
+	if (dist == 0.0f) {
+		deltaZ = 0.0f;
+		deltaX = 0.0f;
+	} else {
+		deltaX *= 10.0f / dist;
+		deltaZ *= 10.0f / dist;
+	}
+}
+
+void AIScriptGenericWalkerB::movingUpdate() {
+	float walkerX, walkerY, walkerZ;
+
+	Actor_Query_XYZ(kActorGenwalkerB, &walkerX, &walkerY, &walkerZ);
+	int facing = Actor_Query_Facing_1024(kActorGenwalkerB);
+
+	walkerX += deltaX;
+	walkerZ += deltaZ;
+
+	deltaX = deltaX * 0.97f;
+	deltaZ = deltaZ * 0.97f;
+
+	Actor_Set_At_XYZ(kActorGenwalkerB, walkerX, walkerY, walkerZ, facing);
+}
+
+bool AIScriptGenericWalkerB::prepareWalker() {
+	if (Game_Flag_Query(kFlagGenericWalkerWaiting) || Global_Variable_Query(35) < 0 || !preparePath()) {
+		return false;
+	}
+
+	int model = 0;
+	do {
+		if (isInside) {
+			model = Random_Query(3, 5);
+		} else {
+			model = Random_Query(0, 5);
+		}
+	}
+	while (model == Global_Variable_Query(kVariableGenericWalkerAModel) || model == Global_Variable_Query(kVariableGenericWalkerCModel));
+
+	Global_Variable_Set(kVariableGenericWalkerBModel, model);
+	Game_Flag_Set(kFlagGenericWalkerWaiting);
+	AI_Countdown_Timer_Reset(kActorGenwalkerB, 2);
+	AI_Countdown_Timer_Start(kActorGenwalkerB, 2, Random_Query(4, 12));
+	Actor_Set_Goal_Number(kActorGenwalkerB, 1);
+	return true;
+}
+
+bool AIScriptGenericWalkerB::preparePath() {
+	AI_Movement_Track_Flush(kActorGenwalkerB);
+	int set = Player_Query_Current_Set();
+
+	if (set == kSetAR01_AR02) {
+		isInside = false;
+		int waypointStart = Random_Query(155, 158);
+		int waypointEnd = 0;
+		AI_Movement_Track_Append(kActorGenwalkerB, waypointStart, 0);
+		do {
+			waypointEnd = Random_Query(155, 158);
+		} while (waypointEnd == waypointStart);
+		if ((waypointStart == 155 || waypointStart == 156) && (waypointEnd == 157 || waypointEnd == 158)) {
+			AI_Movement_Track_Append(kActorGenwalkerB, 159, 0);
+			AI_Movement_Track_Append(kActorGenwalkerB, 160, 0);
+			if (Random_Query(0, 3) == 0) {
+				AI_Movement_Track_Append_With_Facing(kActorGenwalkerB, 161, Random_Query(15, 30), 904);
+			}
+		} else if ((waypointEnd == 155 || waypointEnd == 156) && (waypointStart == 157 || waypointStart == 158)) {
+			if (Random_Query(0, 3) == 0) {
+				AI_Movement_Track_Append_With_Facing(kActorGenwalkerB, 161, Random_Query(15, 30), 904);
+			}
+			AI_Movement_Track_Append(kActorGenwalkerB, 160, 0);
+			AI_Movement_Track_Append(kActorGenwalkerB, 159, 0);
+		} else if ((waypointStart == 155 && waypointEnd == 156) || (waypointStart == 156 && waypointEnd == 155)) {
+			AI_Movement_Track_Append(kActorGenwalkerB, 159, 0);
+		}
+		AI_Movement_Track_Append(kActorGenwalkerB, waypointEnd, 0);
+		AI_Movement_Track_Repeat(kActorGenwalkerB);
+		return true;
+	}
+
+	if (set == kSetCT01_CT12) {
+		isInside = false;
+		if (Random_Query(0, 1)) {
+			AI_Movement_Track_Append(kActorGenwalkerB, 54, 1);
+			if (Random_Query(1, 3) == 1) {
+				AI_Movement_Track_Append(kActorGenwalkerB, 56, 0);
+				AI_Movement_Track_Append(kActorGenwalkerB, 43, 1);
+			} else {
+				AI_Movement_Track_Append(kActorGenwalkerB, 53, 1);
+			}
+			AI_Movement_Track_Append(kActorGenwalkerB, 40, 1);
+			AI_Movement_Track_Repeat(kActorGenwalkerB);
+		} else {
+			AI_Movement_Track_Append(kActorGenwalkerB, 53, 1);
+			if (Random_Query(1, 3) == 1) {
+				AI_Movement_Track_Append(kActorGenwalkerB, 43, 1);
+			} else {
+				AI_Movement_Track_Append(kActorGenwalkerB, 54, 1);
+			}
+			AI_Movement_Track_Append(kActorGenwalkerB, 40, 1);
+			AI_Movement_Track_Repeat(kActorGenwalkerB);
+		}
+		return true;
+	}
+
+	if (set == kSetHC01_HC02_HC03_HC04) {
+		isInside = true;
+		if (Random_Query(0, 1)) {
+			AI_Movement_Track_Append(kActorGenwalkerB, 164, 0);
+			if (Random_Query(0, 1)) {
+				AI_Movement_Track_Append(kActorGenwalkerB, 163, 0);
+				AI_Movement_Track_Append(kActorGenwalkerB, 162, 0);
+			} else if (Random_Query(0, 1)) {
+				AI_Movement_Track_Append(kActorGenwalkerB, 163, 0);
+				AI_Movement_Track_Append(kActorGenwalkerB, 162, 0);
+			} else {
+				AI_Movement_Track_Append(kActorGenwalkerB, 163, 0);
+				AI_Movement_Track_Append(kActorGenwalkerB, 162, 0);
+			}
+		} else {
+			AI_Movement_Track_Append(kActorGenwalkerB, 162, 0);
+			if (Random_Query(0, 1)) {
+				AI_Movement_Track_Append(kActorGenwalkerB, 163, 0);
+				AI_Movement_Track_Append(kActorGenwalkerB, 164, 0);
+			} else if (Random_Query(0, 1)) {
+				AI_Movement_Track_Append(kActorGenwalkerB, 163, 0);
+				AI_Movement_Track_Append(kActorGenwalkerB, 164, 0);
+			} else {
+				AI_Movement_Track_Append(kActorGenwalkerB, 163, 0);
+				AI_Movement_Track_Append(kActorGenwalkerB, 164, 0);
+			}
+		}
+		AI_Movement_Track_Repeat(kActorGenwalkerB);
+		return true;
+	}
+
+	if (set == kSetRC03) {
+		isInside = false;
+		int waypointStart = 0;
+		int waypointEnd = 0;
+		do {
+			waypointStart = Random_Query(167, 171);
+		} while (waypointEnd == 168 || waypointEnd == 169);
+		do {
+			waypointEnd = Random_Query(167, 171);
+		} while (waypointEnd == waypointStart || waypointEnd == 168 || waypointEnd == 169);
+		AI_Movement_Track_Append(kActorGenwalkerB, waypointStart, 0);
+		if (waypointStart == 170) {
+			AI_Movement_Track_Append(kActorGenwalkerB, 169, 0);
+			AI_Movement_Track_Append(kActorGenwalkerB, 168, 0);
+		} else if (waypointEnd == 170) {
+			AI_Movement_Track_Append(kActorGenwalkerB, 168, 0);
+			AI_Movement_Track_Append(kActorGenwalkerB, 169, 0);
+		}
+		AI_Movement_Track_Append(kActorGenwalkerB, waypointEnd, 0);
+		AI_Movement_Track_Repeat(kActorGenwalkerB);
+		return true;
+	}
+
+	return false;
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/ai/generic_walker_c.cpp b/engines/bladerunner/script/ai/generic_walker_c.cpp
new file mode 100644
index 0000000..0f86c23
--- /dev/null
+++ b/engines/bladerunner/script/ai/generic_walker_c.cpp
@@ -0,0 +1,462 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "bladerunner/script/ai_script.h"
+
+namespace BladeRunner {
+enum kGenericWalkerCStates {
+	kGenericWalkerCStatesIdle = 0,
+	kGenericWalkerCStatesWalk = 1,
+	kGenericWalkerCStatesDie  = 2,
+	kGenericWalkerCStatesGun  = 3
+};
+
+AIScriptGenericWalkerC::AIScriptGenericWalkerC(BladeRunnerEngine *vm) : AIScriptBase(vm) {
+	isInside = false;
+	deltaX = 0.0f;
+	deltaZ = 0.0f;
+}
+
+void AIScriptGenericWalkerC::Initialize() {
+	_animationState = kGenericWalkerCStatesIdle;
+	_animationFrame = 0;
+	_animationStateNext = 0;
+	isInside = false;
+	deltaX = 0.0f;
+	deltaZ = 0.0f;
+	Actor_Set_Goal_Number(kActorGenwalkerC, 0);
+}
+
+bool AIScriptGenericWalkerC::Update() {
+	switch (Actor_Query_Goal_Number(kActorGenwalkerC)) {
+		case 0:
+			if (prepareWalker()) {
+				return true;
+			}
+			break;
+		case 1:
+			if (deltaX != 0.0f || deltaZ != 0.0f) {
+				movingUpdate();
+			}
+			break;
+	}
+	return false;
+}
+
+void AIScriptGenericWalkerC::TimerExpired(int timer) {
+	if (timer == 2) {
+		AI_Countdown_Timer_Reset(kActorGenwalkerC, 2);
+		Game_Flag_Reset(kFlagGenericWalkerWaiting);
+		return;// true;
+	}
+	//return false;
+}
+
+void AIScriptGenericWalkerC::CompletedMovementTrack() {
+	if (Actor_Query_Goal_Number(kActorGenwalkerC) > 0) {
+		Actor_Set_Goal_Number(kActorGenwalkerC, 0);
+		if (!Game_Flag_Query(kFlagGenericWalkerWaiting)) {
+			Game_Flag_Set(kFlagGenericWalkerWaiting);
+			AI_Countdown_Timer_Reset(kActorGenwalkerC, 2);
+			AI_Countdown_Timer_Start(kActorGenwalkerC, 2, Random_Query(6, 10));
+		}
+		// return true;
+	}
+	// return false;
+}
+
+void AIScriptGenericWalkerC::ReceivedClue(int clueId, int fromActorId) {
+	//return false;
+}
+
+void AIScriptGenericWalkerC::ClickedByPlayer() {
+	Actor_Face_Actor(kActorMcCoy, kActorGenwalkerC, true);
+	switch (Random_Query(1, 10)) {
+	case 1:
+		Actor_Says(kActorMcCoy, 365, 3);
+		break;
+	case 2:
+		Actor_Says(kActorMcCoy, 755, 3);
+		break;
+	case 3:
+		Actor_Says(kActorMcCoy, 940, 3);
+		break;
+	case 4:
+		Actor_Says(kActorMcCoy, 4560, 3);
+		break;
+	case 5:
+		Actor_Says(kActorMcCoy, 4870, 3);
+		break;
+	case 6:
+		Actor_Says(kActorMcCoy, 5125, 3);
+		break;
+	case 7:
+		Actor_Says(kActorMcCoy, 8450, 3);
+		break;
+	case 8:
+		Actor_Says(kActorMcCoy, 1085, 3);
+		break;
+	case 9:
+		Actor_Says(kActorMcCoy, 365, 3);
+		break;
+	case 10:
+		Actor_Says(kActorMcCoy, 7415, 3);
+		break;
+	}
+	//return false;
+}
+
+void AIScriptGenericWalkerC::EnteredScene(int sceneId) {
+	//return false;
+}
+
+void AIScriptGenericWalkerC::OtherAgentEnteredThisScene(int otherActorId) {
+	//return false;
+}
+
+void AIScriptGenericWalkerC::OtherAgentExitedThisScene(int otherActorId) {
+	if (Actor_Query_Goal_Number(kActorGenwalkerC) && otherActorId == kActorMcCoy) {
+		Actor_Set_Goal_Number(kActorGenwalkerC, 0);
+	}
+	//return false;
+}
+
+void AIScriptGenericWalkerC::OtherAgentEnteredCombatMode(int otherActorId, int combatMode) {
+	//return false;
+}
+
+void AIScriptGenericWalkerC::ShotAtAndMissed() {
+	//return false;
+}
+
+bool AIScriptGenericWalkerC::ShotAtAndHit() {
+	if (Actor_Query_Goal_Number(kActorGenwalkerC)) {
+		AI_Movement_Track_Flush(kActorGenwalkerC);
+		_animationState = kGenericWalkerCStatesDie;
+		_animationFrame = 0;
+		Sound_Play(203, 100, 0, 0, 50);
+		movingStart();
+		return true;
+	}
+	return false;
+}
+
+void AIScriptGenericWalkerC::Retired(int byActorId) {
+	//return false;
+}
+
+int AIScriptGenericWalkerC::GetFriendlinessModifierIfGetsClue(int otherActorId, int clueId) {
+	return 0;
+}
+
+bool AIScriptGenericWalkerC::GoalChanged(int currentGoalNumber, int newGoalNumber) {
+	if (newGoalNumber == 0) {
+		AI_Movement_Track_Flush(kActorGenwalkerC);
+		Actor_Put_In_Set(kActorGenwalkerC, kSetFreeSlotH);
+		Global_Variable_Set(kVariableGenericWalkerCModel, -1);
+		return false;
+	} else if (newGoalNumber == 1) {
+		return true;
+	}
+	return false;
+}
+
+bool AIScriptGenericWalkerC::UpdateAnimation(int *animation, int *frame) {
+	switch (_animationState) {
+	case kGenericWalkerCStatesIdle:
+		switch (Global_Variable_Query(kVariableGenericWalkerCModel)) {
+		case 0:
+			*animation = 426;
+			break;
+		case 1:
+			*animation = 430;
+			break;
+		case 2:
+			*animation = 437;
+			break;
+		case 3:
+			*animation = 431;
+			break;
+		case 4:
+			*animation = 427;
+			break;
+		case 5:
+			*animation = 433;
+			break;
+		}
+		_animationFrame = 0;
+		break;
+	case kGenericWalkerCStatesWalk:
+		switch (Global_Variable_Query(kVariableGenericWalkerCModel)){
+		case 0:
+			*animation = 424;
+			break;
+		case 1:
+			*animation = 428;
+			break;
+		case 2:
+			*animation = 436;
+			break;
+		case 3:
+			*animation = 429;
+			break;
+		case 4:
+			*animation = 425;
+			break;
+		case 5:
+			*animation = 432;
+			break;
+		}
+		++_animationFrame;
+		if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(*animation)) {
+			_animationFrame = 0;
+		}
+		break;
+	case kGenericWalkerCStatesDie:
+		*animation = 874;
+		++_animationFrame;
+		if (++_animationFrame >= Slice_Animation_Query_Number_Of_Frames(874))
+		{
+			_animationFrame = 0;
+			Actor_Set_Goal_Number(kActorGenwalkerC, 0);
+			_animationState = kGenericWalkerCStatesIdle;
+			deltaX = 0.0f;
+			deltaZ = 0.0f;
+		}
+		break;
+	}
+	*frame = _animationFrame;
+	return true;
+}
+
+bool AIScriptGenericWalkerC::ChangeAnimationMode(int mode) {
+	switch (mode) {
+	case kAnimationModeIdle:
+		_animationState = kGenericWalkerCStatesIdle;
+		_animationFrame = 0;
+		break;
+	case kAnimationModeWalk:
+		_animationState = kGenericWalkerCStatesWalk;
+		_animationFrame = 0;
+		break;
+	}
+	return true;
+}
+
+void AIScriptGenericWalkerC::QueryAnimationState(int *animationState, int *animationFrame, int *animationStateNext, int *animationNext) {
+	*animationState     = _animationState;
+	*animationFrame     = _animationFrame;
+	*animationStateNext = _animationStateNext;
+	*animationNext      = _animationNext;
+}
+
+void AIScriptGenericWalkerC::SetAnimationState(int animationState, int animationFrame, int animationStateNext, int animationNext) {
+	_animationState     = animationState;
+	_animationFrame     = animationFrame;
+	_animationStateNext = animationStateNext;
+	_animationNext      = animationNext;
+}
+
+bool AIScriptGenericWalkerC::ReachedMovementTrackWaypoint(int waypointId) {
+	return true;
+}
+
+void AIScriptGenericWalkerC::FledCombat() {
+	//return false;
+}
+
+void AIScriptGenericWalkerC::movingStart() {
+	float mccoyX, mccoyY, mccoyZ;
+	float walkerX, walkerY, walkerZ;
+
+	Actor_Query_XYZ(kActorMcCoy, &mccoyX, &mccoyY, &mccoyZ);
+	Actor_Query_XYZ(kActorGenwalkerC, &walkerX, &walkerY, &walkerZ);
+
+	deltaX = walkerX - mccoyX;
+	deltaZ = walkerZ - mccoyZ;
+
+	float dist = sqrt(deltaX * deltaX + deltaZ * deltaZ);
+	if (dist == 0.0f) {
+		deltaZ = 0.0f;
+		deltaX = 0.0f;
+	} else {
+		deltaX *= 10.0f / dist;
+		deltaZ *= 10.0f / dist;
+	}
+}
+
+void AIScriptGenericWalkerC::movingUpdate() {
+	float walkerX, walkerY, walkerZ;
+
+	Actor_Query_XYZ(kActorGenwalkerC, &walkerX, &walkerY, &walkerZ);
+	int facing = Actor_Query_Facing_1024(kActorGenwalkerC);
+
+	walkerX += deltaX;
+	walkerZ += deltaZ;
+
+	deltaX = deltaX * 0.97f;
+	deltaZ = deltaZ * 0.97f;
+
+	Actor_Set_At_XYZ(kActorGenwalkerC, walkerX, walkerY, walkerZ, facing);
+
+}
+
+bool AIScriptGenericWalkerC::prepareWalker() {
+	if (Game_Flag_Query(kFlagGenericWalkerWaiting) || Global_Variable_Query(35) < 2 || !preparePath()) {
+		return false;
+	}
+
+	int model = 0;
+	do {
+		if (isInside) {
+			model = Random_Query(3, 5);
+		} else {
+			model = Random_Query(0, 5);
+		}
+	}
+	// Here is probably bug in original code, because it not using kVariableGenericWalkerBModel but kVariableGenericWalkerCModel
+	while (model == Global_Variable_Query(kVariableGenericWalkerAModel) || model == Global_Variable_Query(kVariableGenericWalkerBModel));
+
+
+	Global_Variable_Set(kVariableGenericWalkerCModel, model);
+	Game_Flag_Set(kFlagGenericWalkerWaiting);
+	AI_Countdown_Timer_Reset(kActorGenwalkerC, 2);
+	AI_Countdown_Timer_Start(kActorGenwalkerC, 2, Random_Query(4, 12));
+	Actor_Set_Goal_Number(kActorGenwalkerC, 1);
+	return true;
+}
+
+bool AIScriptGenericWalkerC::preparePath() {
+	AI_Movement_Track_Flush(kActorGenwalkerC);
+	int set = Player_Query_Current_Set();
+
+	if (set == kSetAR01_AR02) {
+		isInside = false;
+		int waypointStart = Random_Query(155, 158);
+		int waypointEnd = 0;
+		AI_Movement_Track_Append(kActorGenwalkerC, waypointStart, 0);
+		do {
+			waypointEnd = Random_Query(155, 158);
+		} while (waypointEnd == waypointStart);
+		if ((waypointStart == 155 || waypointStart == 156) && (waypointEnd == 157 || waypointEnd == 158)) {
+			AI_Movement_Track_Append(kActorGenwalkerC, 159, 0);
+			AI_Movement_Track_Append(kActorGenwalkerC, 160, 0);
+			if (Random_Query(0, 3) == 0) {
+				AI_Movement_Track_Append_With_Facing(kActorGenwalkerC, 161, Random_Query(15, 30), 904);
+			}
+		} else if ((waypointEnd == 155 || waypointEnd == 156) && (waypointStart == 157 || waypointStart == 158)) {
+			if (Random_Query(0, 3) == 0) {
+				AI_Movement_Track_Append_With_Facing(kActorGenwalkerC, 161, Random_Query(15, 30), 904);
+			}
+			AI_Movement_Track_Append(kActorGenwalkerC, 160, 0);
+			AI_Movement_Track_Append(kActorGenwalkerC, 159, 0);
+		} else if ((waypointStart == 155 && waypointEnd == 156) || (waypointStart == 156 && waypointEnd == 155)) {
+			AI_Movement_Track_Append(kActorGenwalkerC, 159, 0);
+		}
+		AI_Movement_Track_Append(kActorGenwalkerC, waypointEnd, 0);
+		AI_Movement_Track_Repeat(kActorGenwalkerC);
+		return true;
+	}
+
+	if (set == kSetCT01_CT12) {
+		isInside = false;
+		if (Random_Query(0, 1)) {
+			AI_Movement_Track_Append(kActorGenwalkerC, 54, 1);
+			if (Random_Query(1, 3) == 1) {
+				AI_Movement_Track_Append(kActorGenwalkerC, 56, 0);
+				AI_Movement_Track_Append(kActorGenwalkerC, 43, 1);
+			} else {
+				AI_Movement_Track_Append(kActorGenwalkerC, 53, 1);
+			}
+			AI_Movement_Track_Append(kActorGenwalkerC, 40, 1);
+			AI_Movement_Track_Repeat(kActorGenwalkerC);
+		} else {
+			AI_Movement_Track_Append(kActorGenwalkerC, 53, 1);
+			if (Random_Query(1, 3) == 1) {
+				AI_Movement_Track_Append(kActorGenwalkerC, 43, 1);
+			} else {
+				AI_Movement_Track_Append(kActorGenwalkerC, 54, 1);
+			}
+			AI_Movement_Track_Append(kActorGenwalkerC, 40, 1);
+			AI_Movement_Track_Repeat(kActorGenwalkerC);
+		}
+		return true;
+	}
+
+	if (set == kSetHC01_HC02_HC03_HC04) {
+		isInside = true;
+		if (Random_Query(0, 1)) {
+			AI_Movement_Track_Append(kActorGenwalkerC, 164, 0);
+			if (Random_Query(0, 1)) {
+				AI_Movement_Track_Append(kActorGenwalkerC, 163, 0);
+				AI_Movement_Track_Append(kActorGenwalkerC, 162, 0);
+			} else if (Random_Query(0, 1)) {
+				AI_Movement_Track_Append(kActorGenwalkerC, 163, 0);
+				AI_Movement_Track_Append(kActorGenwalkerC, 162, 0);
+			} else {
+				AI_Movement_Track_Append(kActorGenwalkerC, 163, 0);
+				AI_Movement_Track_Append(kActorGenwalkerC, 162, 0);
+			}
+		} else {
+			AI_Movement_Track_Append(kActorGenwalkerC, 162, 0);
+			if (Random_Query(0, 1)) {
+				AI_Movement_Track_Append(kActorGenwalkerC, 163, 0);
+				AI_Movement_Track_Append(kActorGenwalkerC, 164, 0);
+			} else {
+				if (Random_Query(0, 1)) {
+					AI_Movement_Track_Append_With_Facing(kActorGenwalkerC, 166, 0, 30);
+				}
+				AI_Movement_Track_Append(kActorGenwalkerC, 163, 0);
+				AI_Movement_Track_Append(kActorGenwalkerC, 164, 0);
+			}
+		}
+		AI_Movement_Track_Repeat(kActorGenwalkerC);
+		return true;
+	}
+
+	if (set == kSetRC03) {
+		isInside = false;
+		int waypointStart = 0;
+		int waypointEnd = 0;
+		do {
+			waypointStart = Random_Query(167, 171);
+		} while (waypointEnd == 168 || waypointEnd == 169);
+		do {
+			waypointEnd = Random_Query(167, 171);
+		} while (waypointEnd == waypointStart || waypointEnd == 168 || waypointEnd == 169);
+		AI_Movement_Track_Append(kActorGenwalkerC, waypointStart, 0);
+		if (waypointStart == 170) {
+			AI_Movement_Track_Append(kActorGenwalkerC, 169, 0);
+			AI_Movement_Track_Append(kActorGenwalkerC, 168, 0);
+		} else if (waypointEnd == 170) {
+			AI_Movement_Track_Append(kActorGenwalkerC, 168, 0);
+			AI_Movement_Track_Append(kActorGenwalkerC, 169, 0);
+		}
+		AI_Movement_Track_Append(kActorGenwalkerC, waypointEnd, 0);
+		AI_Movement_Track_Repeat(kActorGenwalkerC);
+		return true;
+	}
+
+	return false;
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/ai/mccoy.cpp b/engines/bladerunner/script/ai/mccoy.cpp
index b38e328..f86a328 100644
--- a/engines/bladerunner/script/ai/mccoy.cpp
+++ b/engines/bladerunner/script/ai/mccoy.cpp
@@ -1699,7 +1699,7 @@ void AIScriptMcCoy::sub_4054F0() {
 		if ((z < 220.0f) && (-210.0f < x) && (-70.0f > x)) {
 			Game_Flag_Set(682);
 			Scene_Loop_Set_Default(3);
-			Scene_Loop_Start_Special(kSceneLoopMode2, 2, true);
+			Scene_Loop_Start_Special(kSceneLoopModeOnce, 2, true);
 			Actor_Set_Goal_Number(kActorMcCoy, 390);
 			Actor_Query_XYZ(kActorFreeSlotA, &x, &y, &z);
 			if (-200.0 < x && -62.0f > x) {
diff --git a/engines/bladerunner/script/ai_script.cpp b/engines/bladerunner/script/ai_script.cpp
index 7b211aa..4c03d61 100644
--- a/engines/bladerunner/script/ai_script.cpp
+++ b/engines/bladerunner/script/ai_script.cpp
@@ -44,6 +44,9 @@ AIScripts::AIScripts(BladeRunnerEngine *vm, int actorCount) {
 	_AIScripts[kActorOfficerLeary] = new AIScriptOfficerLeary(_vm);
 	_AIScripts[kActorLeon] = new AIScriptLeon(_vm);
 	_AIScripts[kActorMaggie] = new AIScriptMaggie(_vm);
+	_AIScripts[kActorGenwalkerA] = new AIScriptGenericWalkerA(_vm);
+	_AIScripts[kActorGenwalkerB] = new AIScriptGenericWalkerB(_vm);
+	_AIScripts[kActorGenwalkerC] = new AIScriptGenericWalkerC(_vm);
 }
 
 AIScripts::~AIScripts() {
@@ -64,13 +67,14 @@ void AIScripts::initialize(int actor) {
 
 void AIScripts::update(int actor) {
 	assert(actor < _actorCount);
-	if (this->_actorUpdating[actor] != 1) {
-		this->_actorUpdating[actor] = true;
-		++this->_inScriptCounter;
-		if (_AIScripts[actor])
+	if (!_actorUpdating[actor]) {
+		_actorUpdating[actor] = true;
+		++_inScriptCounter;
+		if (_AIScripts[actor]) {
 			_AIScripts[actor]->Update();
-		--this->_inScriptCounter;
-		this->_actorUpdating[actor] = false;
+		}
+		--_inScriptCounter;
+		_actorUpdating[actor] = false;
 	}
 }
 
diff --git a/engines/bladerunner/script/ai_script.h b/engines/bladerunner/script/ai_script.h
index 066de29..8577682 100644
--- a/engines/bladerunner/script/ai_script.h
+++ b/engines/bladerunner/script/ai_script.h
@@ -156,6 +156,39 @@ DECLARE_SCRIPT(Maggie)
 	float sub_44B200(int actorId, float x, float y, float z);
 END_SCRIPT
 
+DECLARE_SCRIPT(GenericWalkerA)
+	bool isInside;
+	float deltaX;
+	float deltaZ;
+
+	void movingStart();
+	void movingUpdate();
+	bool prepareWalker();
+	bool preparePath();
+END_SCRIPT
+
+DECLARE_SCRIPT(GenericWalkerB)
+	bool isInside;
+	float deltaX;
+	float deltaZ;
+
+	void movingStart();
+	void movingUpdate();
+	bool prepareWalker();
+	bool preparePath();
+END_SCRIPT
+
+DECLARE_SCRIPT(GenericWalkerC)
+	bool isInside;
+	float deltaX;
+	float deltaZ;
+
+	void movingStart();
+	void movingUpdate();
+	bool prepareWalker();
+	bool preparePath();
+END_SCRIPT
+
 #undef DECLARE_SCRIPT
 #undef END_SCRIPT
 
diff --git a/engines/bladerunner/script/init_script.cpp b/engines/bladerunner/script/init_script.cpp
index 2c0b530..fcb8968 100644
--- a/engines/bladerunner/script/init_script.cpp
+++ b/engines/bladerunner/script/init_script.cpp
@@ -59,8 +59,8 @@ void InitScript::Init_Globals() {
 		Global_Variable_Set(i, 0);
 
 	Global_Variable_Set(35, 2);
-	Global_Variable_Set(1, 1);
-	Global_Variable_Set(2, 100);
+	Global_Variable_Set(kVariableChapter, 1);
+	Global_Variable_Set(kVariableChinyen, 100);
 
 	Set_Score(0, 0);
 	Set_Score(1, 64);
diff --git a/engines/bladerunner/script/scene/bb02.cpp b/engines/bladerunner/script/scene/bb02.cpp
index a507f4d..fed5ee9 100644
--- a/engines/bladerunner/script/scene/bb02.cpp
+++ b/engines/bladerunner/script/scene/bb02.cpp
@@ -100,7 +100,7 @@ bool SceneScriptBB02::ClickedOnExit(int exitId) {
 		if (!Loop_Actor_Walk_To_XYZ(kActorMcCoy, -12.0f, -415.06f, -27.0f, 0, 1, false, 0)) {
 			Player_Loses_Control();
 			if (!Game_Flag_Query(493)) {
-				Scene_Loop_Start_Special(kSceneLoopMode2, 0, true);
+				Scene_Loop_Start_Special(kSceneLoopModeOnce, 0, true);
 			}
 			Game_Flag_Set(332);
 			Game_Flag_Reset(493);
diff --git a/engines/bladerunner/script/scene/ct02.cpp b/engines/bladerunner/script/scene/ct02.cpp
index e94e0ba..499ad13 100644
--- a/engines/bladerunner/script/scene/ct02.cpp
+++ b/engines/bladerunner/script/scene/ct02.cpp
@@ -152,7 +152,7 @@ void SceneScriptCT02::sub_401ACC() {
 			Actor_Set_Goal_Number(kActorZuben, 8);
 			Game_Flag_Set(293);
 			Scene_Loop_Set_Default(3);
-			Scene_Loop_Start_Special(kSceneLoopMode2, 2, true);
+			Scene_Loop_Start_Special(kSceneLoopModeOnce, 2, true);
 		}
 		break;
 	case 280:
@@ -165,7 +165,7 @@ void SceneScriptCT02::sub_401ACC() {
 			Actor_Set_Goal_Number(kActorZuben, 8);
 			Game_Flag_Set(293);
 			Scene_Loop_Set_Default(3);
-			Scene_Loop_Start_Special(kSceneLoopMode2, 2, true);
+			Scene_Loop_Start_Special(kSceneLoopModeOnce, 2, true);
 		}
 		break;
 	case 290:
@@ -181,7 +181,7 @@ void SceneScriptCT02::sub_401ACC() {
 			Actor_Set_Goal_Number(kActorZuben, 8);
 			Game_Flag_Set(293);
 			Scene_Loop_Set_Default(3);
-			Scene_Loop_Start_Special(kSceneLoopMode2, 2, true);
+			Scene_Loop_Start_Special(kSceneLoopModeOnce, 2, true);
 		}
 		break;
 	case 300:
@@ -192,7 +192,7 @@ void SceneScriptCT02::sub_401ACC() {
 			Actor_Set_Goal_Number(kActorZuben, 8);
 			Game_Flag_Set(293);
 			Scene_Loop_Set_Default(3);
-			Scene_Loop_Start_Special(kSceneLoopMode2, 2, true);
+			Scene_Loop_Start_Special(kSceneLoopModeOnce, 2, true);
 		}
 		break;
 	}
diff --git a/engines/bladerunner/script/scene/ct12.cpp b/engines/bladerunner/script/scene/ct12.cpp
index e8d3a5b..5acf2fe 100644
--- a/engines/bladerunner/script/scene/ct12.cpp
+++ b/engines/bladerunner/script/scene/ct12.cpp
@@ -271,7 +271,7 @@ void SceneScriptCT12::PlayerWalkedIn() {
 }
 
 void SceneScriptCT12::PlayerWalkedOut() {
-	Game_Flag_Reset(443);
+	Game_Flag_Reset(kFlagGenericWalkerWaiting);
 	if (Game_Flag_Query(433)) {
 		Game_Flag_Reset(176);
 		Game_Flag_Set(259);
diff --git a/engines/bladerunner/script/scene/dr04.cpp b/engines/bladerunner/script/scene/dr04.cpp
index 81302e4..937fd10 100644
--- a/engines/bladerunner/script/scene/dr04.cpp
+++ b/engines/bladerunner/script/scene/dr04.cpp
@@ -184,7 +184,7 @@ void SceneScriptDR04::SceneFrameAdvanced(int frame) {
 		Game_Flag_Reset(515);
 		Game_Flag_Reset(271);
 		Scene_Loop_Set_Default(1);
-		Scene_Loop_Start_Special(kSceneLoopMode2, 6, true);
+		Scene_Loop_Start_Special(kSceneLoopModeOnce, 6, true);
 		Music_Stop(4);
 		Actor_Set_Goal_Number(kActorMoraji, 99);
 	} else {
@@ -192,7 +192,7 @@ void SceneScriptDR04::SceneFrameAdvanced(int frame) {
 			Game_Flag_Reset(271);
 			Game_Flag_Set(272);
 			Scene_Loop_Set_Default(1);
-			Scene_Loop_Start_Special(kSceneLoopMode2, 6, true);
+			Scene_Loop_Start_Special(kSceneLoopModeOnce, 6, true);
 			Item_Remove_From_World(78);
 		}
 		switch (frame) {
diff --git a/engines/bladerunner/script/scene/hc03.cpp b/engines/bladerunner/script/scene/hc03.cpp
index 092fcca..7b89fc6 100644
--- a/engines/bladerunner/script/scene/hc03.cpp
+++ b/engines/bladerunner/script/scene/hc03.cpp
@@ -100,7 +100,7 @@ bool SceneScriptHC03::ClickedOnItem(int itemId, bool a2) {
 	if (itemId == 121) {
 		if (a2) {
 			Scene_Loop_Set_Default(3);
-			Scene_Loop_Start_Special(kSceneLoopMode2, 2, true);
+			Scene_Loop_Start_Special(kSceneLoopModeOnce, 2, true);
 			Game_Flag_Set(403);
 			Item_Remove_From_World(121);
 			Unobstacle_Object("GPscisGate", true);
@@ -146,7 +146,7 @@ bool SceneScriptHC03::ClickedOnExit(int exitId) {
 				Set_Enter(75, kSceneUG02);
 			} else {
 				Scene_Loop_Set_Default(6);
-				Scene_Loop_Start_Special(kSceneLoopMode2, 5, true);
+				Scene_Loop_Start_Special(kSceneLoopModeOnce, 5, true);
 				Game_Flag_Set(388);
 			}
 		}
diff --git a/engines/bladerunner/script/scene/hf04.cpp b/engines/bladerunner/script/scene/hf04.cpp
index 09a849c..192d0e9 100644
--- a/engines/bladerunner/script/scene/hf04.cpp
+++ b/engines/bladerunner/script/scene/hf04.cpp
@@ -108,14 +108,14 @@ void SceneScriptHF04::SceneFrameAdvanced(int frame) {
 	if (Game_Flag_Query(585)) {
 		Game_Flag_Reset(585);
 		Scene_Loop_Set_Default(3);
-		Scene_Loop_Start_Special(kSceneLoopMode2, 2, true);
+		Scene_Loop_Start_Special(kSceneLoopModeOnce, 2, true);
 		//return true;
 		return;
 	}
 	if (Game_Flag_Query(586)) {
 		Game_Flag_Reset(586);
 		Scene_Loop_Set_Default(0);
-		Scene_Loop_Start_Special(kSceneLoopMode2, 5, true);
+		Scene_Loop_Start_Special(kSceneLoopModeOnce, 5, true);
 		//return true;
 		return;
 	}
diff --git a/engines/bladerunner/script/scene/hf05.cpp b/engines/bladerunner/script/scene/hf05.cpp
index e98bc8c..ff497eb 100644
--- a/engines/bladerunner/script/scene/hf05.cpp
+++ b/engines/bladerunner/script/scene/hf05.cpp
@@ -92,7 +92,7 @@ bool SceneScriptHF05::ClickedOn3DObject(const char *objectName, bool a2) {
 				Actor_Face_Heading(kActorMcCoy, 0, false);
 				Actor_Change_Animation_Mode(kActorMcCoy, 23);
 				Scene_Loop_Set_Default(5);
-				Scene_Loop_Start_Special(kSceneLoopMode2, 4, true);
+				Scene_Loop_Start_Special(kSceneLoopModeOnce, 4, true);
 				if (sub_4048C0()) {
 					if (sub_4048C0() == 3) {
 						Actor_Face_Heading(kActorDektora, 0, false);
diff --git a/engines/bladerunner/script/scene/hf06.cpp b/engines/bladerunner/script/scene/hf06.cpp
index f06e099..7a41c9e 100644
--- a/engines/bladerunner/script/scene/hf06.cpp
+++ b/engines/bladerunner/script/scene/hf06.cpp
@@ -263,7 +263,7 @@ void SceneScriptHF06::sub_401EF4() {
 	Actor_Change_Animation_Mode(kActorSteele, 6);
 	Delay(500);
 	Scene_Loop_Set_Default(3);
-	Scene_Loop_Start_Special(kSceneLoopMode2, 2, true);
+	Scene_Loop_Start_Special(kSceneLoopModeOnce, 2, true);
 	Sound_Play(562, 50, 0, 0, 50);
 	Game_Flag_Set(559);
 	Scene_Exits_Disable();
diff --git a/engines/bladerunner/script/scene/kp03.cpp b/engines/bladerunner/script/scene/kp03.cpp
index bb8c005..cb96e8b 100644
--- a/engines/bladerunner/script/scene/kp03.cpp
+++ b/engines/bladerunner/script/scene/kp03.cpp
@@ -69,7 +69,7 @@ bool SceneScriptKP03::ClickedOn3DObject(const char *objectName, bool a2) {
 	if (Object_Query_Click("BRACK MID", objectName) && !Game_Flag_Query(422)) {
 		if (a2) {
 			Scene_Loop_Set_Default(5);
-			Scene_Loop_Start_Special(kSceneLoopMode2, 4, true);
+			Scene_Loop_Start_Special(kSceneLoopModeOnce, 4, true);
 			Actor_Change_Animation_Mode(kActorMcCoy, 39);
 			Actor_Retired_Here(kActorMcCoy, 72, 18, 1, -1);
 			Game_Flag_Set(422);
@@ -90,7 +90,7 @@ bool SceneScriptKP03::ClickedOn3DObject(const char *objectName, bool a2) {
 				Game_Flag_Set(484);
 				Game_Flag_Reset(421);
 				Scene_Loop_Set_Default(7);
-				Scene_Loop_Start_Special(kSceneLoopMode2, 0, false);
+				Scene_Loop_Start_Special(kSceneLoopModeOnce, 0, false);
 				Actor_Voice_Over(1110, kActorVoiceOver);
 				Actor_Voice_Over(1120, kActorVoiceOver);
 			} else {
@@ -178,7 +178,7 @@ void SceneScriptKP03::SceneFrameAdvanced(int frame) {
 		}
 		if (v1 != -1) {
 			Scene_Loop_Set_Default(5);
-			Scene_Loop_Start_Special(kSceneLoopMode2, 4, true);
+			Scene_Loop_Start_Special(kSceneLoopModeOnce, 4, true);
 			Game_Flag_Set(422);
 			Game_Flag_Reset(421);
 			Unclickable_Object("BRACK MID");
@@ -244,7 +244,7 @@ void SceneScriptKP03::sub_401E54() {
 	Game_Flag_Set(484);
 	Game_Flag_Reset(421);
 	Scene_Loop_Set_Default(7);
-	Scene_Loop_Start_Special(kSceneLoopMode2, 7, false);
+	Scene_Loop_Start_Special(kSceneLoopModeOnce, 7, false);
 	Actor_Set_Goal_Number(kActorSteele, 413);
 	Actor_Says(kActorMcCoy, 2195, 14);
 	Ambient_Sounds_Play_Sound(151, 40, -60, -60, 0);
diff --git a/engines/bladerunner/script/scene/ma05.cpp b/engines/bladerunner/script/scene/ma05.cpp
index 519f43e..a100861 100644
--- a/engines/bladerunner/script/scene/ma05.cpp
+++ b/engines/bladerunner/script/scene/ma05.cpp
@@ -117,7 +117,7 @@ void SceneScriptMA05::PlayerWalkedIn() {
 	Music_Play(2, 52, 0, 2, -1, 0, 0);
 	if ((Random_Query(0, 4) == 1 || (Game_Flag_Query(kFlagChapter1Ending) && !Game_Flag_Query(kFlagChapter1Ended))) && Global_Variable_Query(kVariableChapter) == 1) {
 		Scene_Loop_Set_Default(kMA05LoopMain);
-		Scene_Loop_Start_Special(kSceneLoopMode2, kMA05LoopSpinner, true);
+		Scene_Loop_Start_Special(kSceneLoopModeOnce, kMA05LoopSpinner, true);
 		Sound_Play(69, 100, 0, 0, 50);
 	}
 	if (Game_Flag_Query(kFlagChapter1Ending) && !Game_Flag_Query(kFlagChapter1Ended)) {
diff --git a/engines/bladerunner/script/scene/ma06.cpp b/engines/bladerunner/script/scene/ma06.cpp
index 3f38527..cf69ded 100644
--- a/engines/bladerunner/script/scene/ma06.cpp
+++ b/engines/bladerunner/script/scene/ma06.cpp
@@ -134,7 +134,7 @@ void SceneScriptMA06::activateElevator() {
 		Player_Gains_Control();
 		int floor = Elevator_Activate(kElevatorMA);
 		Player_Loses_Control();
-		Scene_Loop_Start_Special(kSceneLoopMode2, 1, true);
+		Scene_Loop_Start_Special(kSceneLoopModeOnce, kMA06LoopMain, true);
 		if (floor > 1) {
 			Game_Flag_Set(kFlagMA06toMA07);
 		} else if (floor == 1) {
diff --git a/engines/bladerunner/script/scene/nr08.cpp b/engines/bladerunner/script/scene/nr08.cpp
index ef54702..9af7490 100644
--- a/engines/bladerunner/script/scene/nr08.cpp
+++ b/engines/bladerunner/script/scene/nr08.cpp
@@ -150,7 +150,7 @@ void SceneScriptNR08::SceneFrameAdvanced(int frame) {
 		Game_Flag_Set(636);
 		Scene_Exits_Disable();
 		Scene_Loop_Set_Default(1);
-		Scene_Loop_Start_Special(kSceneLoopMode2, 3, true);
+		Scene_Loop_Start_Special(kSceneLoopModeOnce, 3, true);
 	}
 	if (frame == 95) {
 		Actor_Put_In_Set(kActorDektora, 91);
diff --git a/engines/bladerunner/script/scene/nr10.cpp b/engines/bladerunner/script/scene/nr10.cpp
index c3f7bd8..f580463 100644
--- a/engines/bladerunner/script/scene/nr10.cpp
+++ b/engines/bladerunner/script/scene/nr10.cpp
@@ -71,7 +71,7 @@ bool SceneScriptNR10::ClickedOn3DObject(const char *objectName, bool a2) {
 		Ambient_Sounds_Remove_Looping_Sound(452, true);
 		Sound_Play(453, 52, 0, 0, 50);
 		Scene_Loop_Set_Default(0);
-		Scene_Loop_Start_Special(kSceneLoopMode2, 0, true);
+		Scene_Loop_Start_Special(kSceneLoopModeOnce, 0, true);
 		Un_Combat_Target_Object("BOX18");
 		Scene_Exits_Enable();
 		return true;
diff --git a/engines/bladerunner/script/scene/nr11.cpp b/engines/bladerunner/script/scene/nr11.cpp
index 20a1706..95ef4b7 100644
--- a/engines/bladerunner/script/scene/nr11.cpp
+++ b/engines/bladerunner/script/scene/nr11.cpp
@@ -122,7 +122,7 @@ bool SceneScriptNR11::ClickedOn3DObject(const char *objectName, bool a2) {
 			}
 			Actor_Set_Goal_Number(kActorMcCoy, 230);
 			Scene_Loop_Set_Default(3);
-			Scene_Loop_Start_Special(kSceneLoopMode2, 2, true);
+			Scene_Loop_Start_Special(kSceneLoopModeOnce, 2, true);
 		} else if (Actor_Query_Goal_Number(kActorDektora) == 250) {
 			if (!Loop_Actor_Walk_To_XYZ(kActorMcCoy, 24.0f, 0.33f, 0.0f, 0, 1, false, 0)) {
 				Actor_Face_XYZ(kActorMcCoy, -180.0f, 0.0f, -170.0f, true);
@@ -260,7 +260,7 @@ void SceneScriptNR11::SceneFrameAdvanced(int frame) {
 		}
 		Actor_Set_Goal_Number(kActorMcCoy, 230);
 		Scene_Loop_Set_Default(3);
-		Scene_Loop_Start_Special(kSceneLoopMode2, 2, true);
+		Scene_Loop_Start_Special(kSceneLoopModeOnce, 2, true);
 		Game_Flag_Reset(635);
 	} else {
 		if (frame < 61 || frame > 120) {
diff --git a/engines/bladerunner/script/scene/rc01.cpp b/engines/bladerunner/script/scene/rc01.cpp
index 11eb28e..83d12d0 100644
--- a/engines/bladerunner/script/scene/rc01.cpp
+++ b/engines/bladerunner/script/scene/rc01.cpp
@@ -50,12 +50,12 @@ void SceneScriptRC01::InitializeScene() {
 #if BLADERUNNER_DEBUG_GAME
 	//TODO: not part of game, remove
 	Game_Flag_Set(kFlagIntroPlayed); // force skip intro
-	Game_Flag_Set(kFlagRC02toRC01); // no landing
+	 Game_Flag_Set(kFlagRC02toRC01); // no landing
 	// Game_Flag_Set(kFlagRC01PoliceDone);
 	// Game_Flag_Set(kFlagKIAPrivacyAddon);
 	// Game_Flag_Set(kFlagZubenRetired);
 	// Game_Flag_Set(kFlagSpinnerToMA01);
-	// Set_Enter(kSetMA02_MA04, kSceneMA02);
+	// Set_Enter(kSetMA02_MA04, kSceneMA04);
 
 	// Spinner_Set_Selectable_Destination_Flag(0, true);
 	// Spinner_Set_Selectable_Destination_Flag(1, true);
@@ -70,6 +70,10 @@ void SceneScriptRC01::InitializeScene() {
 
 	// ESPER_Flag_To_Activate();
 	// Voight_Kampff_Activate(kActorLucy, 50);
+
+	// Global_Variable_Set(kVariableChapter, 2);
+	// Chapter_Enter(2, kSetRC03, kSceneRC03);
+
 #endif
 
 	if (!Game_Flag_Query(kFlagIntroPlayed)) {
diff --git a/engines/bladerunner/script/scene/tb07.cpp b/engines/bladerunner/script/scene/tb07.cpp
index 21041fd..b45bc1e 100644
--- a/engines/bladerunner/script/scene/tb07.cpp
+++ b/engines/bladerunner/script/scene/tb07.cpp
@@ -254,7 +254,7 @@ void SceneScriptTB07::sub_401B0C() {
 	Actor_Set_At_XYZ(kActorTyrell, 68.0f, 12.0f, 288.0f, 0);
 	Actor_Change_Animation_Mode(kActorTyrell, 0);
 	Scene_Loop_Set_Default(3);
-	Scene_Loop_Start_Special(kSceneLoopMode2, 2, false);
+	Scene_Loop_Start_Special(kSceneLoopModeOnce, 2, false);
 	Actor_Start_Speech_Sample(kActorTyrell, 0);
 	Loop_Actor_Walk_To_XYZ(kActorTyrell, 44.0f, 12.0f, 176.0f, 0, 0, false, 0);
 	Actor_Face_Actor(kActorTyrell, kActorMcCoy, true);
diff --git a/engines/bladerunner/script/scene/ug01.cpp b/engines/bladerunner/script/scene/ug01.cpp
index 8c60aab..138f962 100644
--- a/engines/bladerunner/script/scene/ug01.cpp
+++ b/engines/bladerunner/script/scene/ug01.cpp
@@ -80,7 +80,7 @@ bool SceneScriptUG01::ClickedOn3DObject(const char *objectName, bool a2) {
 		if (!Loop_Actor_Walk_To_XYZ(kActorMcCoy, -9.0f, -50.13f, -148.0f, 0, 1, false, 0) && !Game_Flag_Query(324)) {
 			Actor_Says(kActorMcCoy, 8525, 13);
 			Scene_Loop_Set_Default(3);
-			Scene_Loop_Start_Special(kSceneLoopMode2, 2, true);
+			Scene_Loop_Start_Special(kSceneLoopModeOnce, 2, true);
 			Game_Flag_Set(324);
 		} else {
 			Actor_Says(kActorMcCoy, 8525, 13);
diff --git a/engines/bladerunner/script/scene/ug10.cpp b/engines/bladerunner/script/scene/ug10.cpp
index 123693d..bca6765 100644
--- a/engines/bladerunner/script/scene/ug10.cpp
+++ b/engines/bladerunner/script/scene/ug10.cpp
@@ -74,7 +74,7 @@ void SceneScriptUG10::SceneLoaded() {
 	Obstacle_Object("SLUICEGATE_LEVER", true);
 	if (Global_Variable_Query(kVariableChapter) == 4 && !Game_Flag_Query(474) && Game_Flag_Query(172) && !Game_Flag_Query(693)) {
 		Scene_Loop_Set_Default(1);
-		Scene_Loop_Start_Special(kSceneLoopMode2, 6, true);
+		Scene_Loop_Start_Special(kSceneLoopModeOnce, 6, true);
 		Game_Flag_Set(693);
 		//return true;
 	}
@@ -158,13 +158,13 @@ bool SceneScriptUG10::ClickedOn2DRegion(int region) {
 		} else if (!Loop_Actor_Walk_To_XYZ(kActorMcCoy, 4.98f, 0.38f, 83.15f, 0, 1, false, 0)) {
 			if (Game_Flag_Query(474)) {
 				Scene_Loop_Set_Default(1);
-				Scene_Loop_Start_Special(kSceneLoopMode2, 0, false);
+				Scene_Loop_Start_Special(kSceneLoopModeOnce, 0, false);
 				Game_Flag_Reset(474);
 				Obstacle_Object("BOX01 BRIDGE", true);
 				Player_Loses_Control();
 			} else {
 				Scene_Loop_Set_Default(4);
-				Scene_Loop_Start_Special(kSceneLoopMode2, 3, false);
+				Scene_Loop_Start_Special(kSceneLoopModeOnce, 3, false);
 				Game_Flag_Set(474);
 				Unobstacle_Object("BOX01 BRIDGE", true);
 				Player_Loses_Control();
diff --git a/engines/bladerunner/script/scene/ug13.cpp b/engines/bladerunner/script/scene/ug13.cpp
index 09e33e8..cdfa8ad 100644
--- a/engines/bladerunner/script/scene/ug13.cpp
+++ b/engines/bladerunner/script/scene/ug13.cpp
@@ -87,13 +87,13 @@ bool SceneScriptUG13::ClickedOn3DObject(const char *objectName, bool a2) {
 		Actor_Face_Object(kActorMcCoy, "BOLLARD", true);
 		if (Game_Flag_Query(431)) {
 			Scene_Loop_Set_Default(1);
-			Scene_Loop_Start_Special(kSceneLoopMode2, 0, false);
+			Scene_Loop_Start_Special(kSceneLoopModeOnce, 0, false);
 			Game_Flag_Reset(431);
 			Game_Flag_Set(436);
 			return true;
 		} else {
 			Scene_Loop_Set_Default(4);
-			Scene_Loop_Start_Special(kSceneLoopMode2, 3, false);
+			Scene_Loop_Start_Special(kSceneLoopModeOnce, 3, false);
 			Game_Flag_Set(431);
 			Scene_Exit_Remove(0);
 			return true;
diff --git a/engines/bladerunner/script/scene/ug15.cpp b/engines/bladerunner/script/scene/ug15.cpp
index 760e9c4..8477e5b 100644
--- a/engines/bladerunner/script/scene/ug15.cpp
+++ b/engines/bladerunner/script/scene/ug15.cpp
@@ -168,7 +168,7 @@ void SceneScriptUG15::SceneFrameAdvanced(int frame) {
 			Game_Flag_Set(724);
 			Game_Flag_Set(682);
 			Scene_Loop_Set_Default(3);
-			Scene_Loop_Start_Special(kSceneLoopMode2, 2, true);
+			Scene_Loop_Start_Special(kSceneLoopModeOnce, 2, true);
 			Actor_Set_Goal_Number(kActorMcCoy, 390);
 			Actor_Query_XYZ(kActorFreeSlotA, &x, &y, &z);
 			if (-200.0f < x && -62.0f > x) {
diff --git a/engines/bladerunner/script/script.cpp b/engines/bladerunner/script/script.cpp
index f88f330..b7b6e47 100644
--- a/engines/bladerunner/script/script.cpp
+++ b/engines/bladerunner/script/script.cpp
@@ -848,7 +848,7 @@ void ScriptBase::Scene_Loop_Set_Default(int loopId) {
 }
 
 void ScriptBase::Scene_Loop_Start_Special(int sceneLoopMode, int loopId, bool immediately) {
-	if (sceneLoopMode == kSceneLoopModeChangeSet) {
+	if (sceneLoopMode == kSceneLoopModeOnce) {
 		immediately = true;
 	}
 	_vm->_scene->loopStartSpecial(sceneLoopMode, loopId, immediately);
diff --git a/engines/bladerunner/set.h b/engines/bladerunner/set.h
index a6779d4..a6e7e9f 100644
--- a/engines/bladerunner/set.h
+++ b/engines/bladerunner/set.h
@@ -37,9 +37,7 @@ class SetEffects;
 class SceneObjects;
 
 class Set {
-#if BLADERUNNER_DEBUG_RENDERING
-	friend class BladeRunnerEngine;
-#endif
+	friend class Debugger;
 
 	struct Object {
 		char        name[20];
diff --git a/engines/bladerunner/ui/esper.cpp b/engines/bladerunner/ui/esper.cpp
index 79b8f5d..181ef0f 100644
--- a/engines/bladerunner/ui/esper.cpp
+++ b/engines/bladerunner/ui/esper.cpp
@@ -26,6 +26,7 @@
 #include "bladerunner/ambient_sounds.h"
 #include "bladerunner/audio_player.h"
 #include "bladerunner/bladerunner.h"
+#include "bladerunner/debugger.h"
 #include "bladerunner/decompress_lcw.h"
 #include "bladerunner/font.h"
 #include "bladerunner/game_info.h"
@@ -577,30 +578,31 @@ void ESPER::draw(Graphics::Surface &surface) {
 			if (_isDrawingSelection) {
 				drawSelection(surface, true, 1);
 			}
-#if BLADERUNNER_DEBUG_RENDERING
-			for (int i = 0; i < kRegionCount; ++i) {
-				if (_regions[i].isPresent) {
-					surface.frameRect(
-						Common::Rect(
-							viewportXToScreenX(_regions[i].rectInner.left),
-							viewportYToScreenY(_regions[i].rectInner.top),
-							viewportXToScreenX(_regions[i].rectInner.right),
-							viewportYToScreenY(_regions[i].rectInner.bottom)
-						),
-						0x7FE0
-					);
-					surface.frameRect(
-						Common::Rect(
-							viewportXToScreenX(_regions[i].rectOuter.left),
-							viewportYToScreenY(_regions[i].rectOuter.top),
-							viewportXToScreenX(_regions[i].rectOuter.right),
-							viewportYToScreenY(_regions[i].rectOuter.bottom)
-						),
-						0x7FE0
-					);
+
+			if (_vm->_debugger->_viewUI) {
+				for (int i = 0; i < kRegionCount; ++i) {
+					if (_regions[i].isPresent) {
+						surface.frameRect(
+							Common::Rect(
+								viewportXToScreenX(_regions[i].rectInner.left),
+								viewportYToScreenY(_regions[i].rectInner.top),
+								viewportXToScreenX(_regions[i].rectInner.right),
+								viewportYToScreenY(_regions[i].rectInner.bottom)
+							),
+							0x7FE0
+						);
+						surface.frameRect(
+							Common::Rect(
+								viewportXToScreenX(_regions[i].rectOuter.left),
+								viewportYToScreenY(_regions[i].rectOuter.top),
+								viewportXToScreenX(_regions[i].rectOuter.right),
+								viewportYToScreenY(_regions[i].rectOuter.bottom)
+							),
+							0x7FE0
+						);
+					}
 				}
 			}
-#endif
 			break;
 		case kEsperPhotoStateScrolling:
 			scrollUpdate();
diff --git a/engines/bladerunner/ui/ui_image_picker.cpp b/engines/bladerunner/ui/ui_image_picker.cpp
index 5cee12f..0e00bf0 100644
--- a/engines/bladerunner/ui/ui_image_picker.cpp
+++ b/engines/bladerunner/ui/ui_image_picker.cpp
@@ -23,6 +23,7 @@
 #include "bladerunner/ui/ui_image_picker.h"
 
 #include "bladerunner/bladerunner.h"
+#include "bladerunner/debugger.h"
 #include "bladerunner/font.h"
 #include "bladerunner/mouse.h"
 #include "bladerunner/shape.h"
@@ -212,10 +213,11 @@ void UIImagePicker::draw(Graphics::Surface &surface) {
 				img.shapeUp->draw(surface, img.rect.left, img.rect.top);
 			}
 		}
-#if BLADERUNNER_DEBUG_RENDERING
-		surface.frameRect(img.rect, 0x7fff);
-		_vm->_mainFont->drawColor(Common::String::format("%d", i), surface, (img.rect.left + img.rect.right) / 2, (img.rect.top + img.rect.bottom) / 2, 0x7fff);
-#endif
+
+		if (_vm->_debugger->_viewUI) {
+			surface.frameRect(img.rect, 0x7fff);
+			_vm->_mainFont->drawColor(Common::String::format("%d", i), surface, (img.rect.left + img.rect.right) / 2, (img.rect.top + img.rect.bottom) / 2, 0x7fff);
+		}
 	}
 }
 
diff --git a/engines/bladerunner/waypoints.h b/engines/bladerunner/waypoints.h
index 9977b71..826f8f5 100644
--- a/engines/bladerunner/waypoints.h
+++ b/engines/bladerunner/waypoints.h
@@ -31,9 +31,8 @@
 namespace BladeRunner {
 
 class Waypoints {
-#if BLADERUNNER_DEBUG_RENDERING
-	friend class BladeRunnerEngine;
-#endif
+	friend class Debugger;
+
 	struct Waypoint {
 		int     setId;
 		Vector3 position;





More information about the Scummvm-git-logs mailing list