[Scummvm-git-logs] scummvm master -> e232f13f5dd7c9119d0355cb93ff1cc2c705d16e

peterkohaut peterkohaut at users.noreply.github.com
Tue Mar 6 00:31:11 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:
e232f13f5d BLADERUNNER: Added Zuben actor


Commit: e232f13f5dd7c9119d0355cb93ff1cc2c705d16e
    https://github.com/scummvm/scummvm/commit/e232f13f5dd7c9119d0355cb93ff1cc2c705d16e
Author: Peter Kohaut (peter.kohaut at gmail.com)
Date: 2018-03-06T00:29:20+01:00

Commit Message:
BLADERUNNER: Added Zuben actor

Fixed animation position update
Added goal & anim commands to console

Changed paths:
  A engines/bladerunner/script/ai/zuben.cpp
    engines/bladerunner/actor.cpp
    engines/bladerunner/actor_dialogue_queue.h
    engines/bladerunner/audio_speech.cpp
    engines/bladerunner/audio_speech.h
    engines/bladerunner/bladerunner.cpp
    engines/bladerunner/bladerunner.h
    engines/bladerunner/debugger.cpp
    engines/bladerunner/debugger.h
    engines/bladerunner/game_constants.h
    engines/bladerunner/game_info.cpp
    engines/bladerunner/game_info.h
    engines/bladerunner/module.mk
    engines/bladerunner/overlays.cpp
    engines/bladerunner/overlays.h
    engines/bladerunner/script/ai/_template.cpp
    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/ct01.cpp
    engines/bladerunner/script/scene/ct02.cpp
    engines/bladerunner/script/scene_script.h
    engines/bladerunner/script/script.cpp
    engines/bladerunner/script/script.h
    engines/bladerunner/vqa_decoder.cpp


diff --git a/engines/bladerunner/actor.cpp b/engines/bladerunner/actor.cpp
index 50a96a4..3d14ccd 100644
--- a/engines/bladerunner/actor.cpp
+++ b/engines/bladerunner/actor.cpp
@@ -630,8 +630,10 @@ bool Actor::tick(bool forceDraw, Common::Rect *screenRect) {
 				float originalY = _position.y;
 				float originalZ = _position.z;
 
-				_position.x = _position.x + positionChange.x * cosx - positionChange.y * sinx;
-				_position.z = _position.z + positionChange.x * sinx + positionChange.y * cosx;
+				// Yes, Z & Y are switched between world space and model space. X is also negated for some unknown reason (wrong dirertion for angles?)
+
+				_position.x = _position.x - positionChange.x * cosx - positionChange.y * sinx;
+				_position.z = _position.z - positionChange.x * sinx + positionChange.y * cosx;
 				_position.y = _position.y + positionChange.z;
 
 				if (_vm->_sceneObjects->existsOnXZ(_id + kSceneObjectOffsetActors, _position.x, _position.z, false, false) == 1 && !_isImmuneToObstacles) {
diff --git a/engines/bladerunner/actor_dialogue_queue.h b/engines/bladerunner/actor_dialogue_queue.h
index 0a70021..841ca8a 100644
--- a/engines/bladerunner/actor_dialogue_queue.h
+++ b/engines/bladerunner/actor_dialogue_queue.h
@@ -56,7 +56,7 @@ public:
 	ActorDialogueQueue(BladeRunnerEngine *vm);
 	~ActorDialogueQueue();
 
-	void add(int actorId, int speechId, int animationMode);
+	void add(int actorId, int sentenceId, int animationMode);
 	void addPause(int delay);
 	void flush(int a1, bool callScript);
 	void tick();
diff --git a/engines/bladerunner/audio_speech.cpp b/engines/bladerunner/audio_speech.cpp
index 1f3465c..69883cb 100644
--- a/engines/bladerunner/audio_speech.cpp
+++ b/engines/bladerunner/audio_speech.cpp
@@ -25,9 +25,11 @@
 #include "bladerunner/actor.h"
 #include "bladerunner/aud_stream.h"
 #include "bladerunner/audio_mixer.h"
+#include "bladerunner/audio_player.h"
 #include "bladerunner/bladerunner.h"
 
 #include "common/debug.h"
+#include "common/str.h"
 
 namespace BladeRunner {
 
@@ -113,6 +115,12 @@ bool AudioSpeech::isPlaying() const {
 	return _isActive;
 }
 
+bool AudioSpeech::playSpeechLine(int actorId, int sentenceId, int volume, int a4, int priority) {
+	int balance = _vm->_actors[actorId]->soundBalance();
+	Common::String name = Common::String::format("%02d-%04d%s.AUD", actorId, sentenceId,  _vm->_languageCode);
+	return _vm->_audioPlayer->playAud(name, _speechVolume * volume / 100, balance, balance, priority, kAudioPlayerOverrideVolume);
+}
+
 void AudioSpeech::setVolume(int volume) {
 	_speechVolume = volume;
 }
diff --git a/engines/bladerunner/audio_speech.h b/engines/bladerunner/audio_speech.h
index 5b94bc9..010499f 100644
--- a/engines/bladerunner/audio_speech.h
+++ b/engines/bladerunner/audio_speech.h
@@ -48,6 +48,8 @@ public:
 	void stopSpeech();
 	bool isPlaying() const;
 
+	bool playSpeechLine(int actorId, int sentenceId, int volume, int a4, int priority);
+
 	void setVolume(int volume);
 	int getVolume() const;
 	void playSample();
diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp
index 87f3528..de7d824 100644
--- a/engines/bladerunner/bladerunner.cpp
+++ b/engines/bladerunner/bladerunner.cpp
@@ -1024,6 +1024,9 @@ void BladeRunnerEngine::handleKeyDown(Common::Event &event) {
 }
 
 void BladeRunnerEngine::handleMouseAction(int x, int y, bool mainButton, bool buttonDown) {
+	x = CLIP(x, 0, 639);
+	y = CLIP(y, 0, 479);
+
 	int timeNow = getTotalPlayTime();
 
 	if (buttonDown) {
@@ -1548,7 +1551,7 @@ Common::SeekableReadStream *BladeRunnerEngine::getResourceStream(const Common::S
 		}
 	}
 
-	error("getResource: Resource %s not found", name.c_str());
+	warning("getResource: Resource %s not found", name.c_str());
 	return nullptr;
 }
 
diff --git a/engines/bladerunner/bladerunner.h b/engines/bladerunner/bladerunner.h
index 88f4cf7..066e683 100644
--- a/engines/bladerunner/bladerunner.h
+++ b/engines/bladerunner/bladerunner.h
@@ -194,10 +194,10 @@ public:
 	int  _walkingToItemId;
 	bool _isInsideScriptItem;
 	bool _walkingToEmpty;
-	int _walkingToEmptyX;
-	int _walkingToEmptyY;
+	int  _walkingToEmptyX;
+	int  _walkingToEmptyY;
 	bool _isInsideScriptEmpty;
-	int _walkingToActorId;
+	int  _walkingToActorId;
 	bool _isInsideScriptActor;
 
 	int _actorUpdateCounter;
diff --git a/engines/bladerunner/debugger.cpp b/engines/bladerunner/debugger.cpp
index 94fb7c5..e71426d 100644
--- a/engines/bladerunner/debugger.cpp
+++ b/engines/bladerunner/debugger.cpp
@@ -22,6 +22,7 @@
 
 #include "bladerunner/debugger.h"
 
+#include "bladerunner/actor.h"
 #include "bladerunner/bladerunner.h"
 #include "bladerunner/boundingbox.h"
 #include "bladerunner/font.h"
@@ -55,18 +56,82 @@ Debugger::Debugger(BladeRunnerEngine *vm) : GUI::Debugger() {
 	_viewUI = false;
 	_viewZBuffer = false;
 
+	registerCmd("anim", WRAP_METHOD(Debugger, cmdAnimation));
+	registerCmd("goal", WRAP_METHOD(Debugger, cmdGoal));
 	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));
+	registerCmd("say", WRAP_METHOD(Debugger, cmdSay));
 }
 
 Debugger::~Debugger() {
 }
 
+bool Debugger::cmdAnimation(int argc, const char **argv) {
+	if (argc != 2 && argc != 3) {
+		debugPrintf("Get or set animation mode of the actor.\n");
+		debugPrintf("Usage: %s <actorId> [<animationMode>]\n", argv[0]);
+		return true;
+	}
+
+	int actorId = atoi(argv[1]);
+
+	Actor *actor = nullptr;
+	if (actorId >= 0 && actorId < (int)_vm->_gameInfo->getActorCount()) {
+		actor = _vm->_actors[actorId];
+	}
+
+	if (actor == nullptr) {
+		debugPrintf("Unknown actor %i\n", actorId);
+		return true;
+	}
+
+	if (argc == 3) {
+		int animationMode = atoi(argv[2]);
+		debugPrintf("actorAnimationMode(%i) = %i\n", actorId, animationMode);
+		actor->changeAnimationMode(animationMode);
+		return false;
+	}
+
+	debugPrintf("actorAnimationMode(%i) = %i\n", actorId, actor->getAnimationMode());
+	return true;
+}
+
+bool Debugger::cmdGoal(int argc, const char **argv) {
+	if (argc != 2 && argc != 3) {
+		debugPrintf("Get or set goal of the actor.\n");
+		debugPrintf("Usage: %s <actorId> [<goal>]\n", argv[0]);
+		return true;
+	}
+
+	int actorId = atoi(argv[1]);
+
+	Actor *actor = nullptr;
+	if (actorId >= 0 && actorId < (int)_vm->_gameInfo->getActorCount()) {
+		actor = _vm->_actors[actorId];
+	}
+
+	if (actor == nullptr) {
+		debugPrintf("Unknown actor %i\n", actorId);
+		return true;
+	}
+
+	if (argc == 3) {
+		int goal = atoi(argv[2]);
+		debugPrintf("actorGoal(%i) = %i\n", actorId, goal);
+		actor->setGoal(goal);
+		return false;
+	}
+
+	debugPrintf("actorGoal(%i) = %i\n", actorId, actor->getGoal());
+	return true;
+}
+
 bool Debugger::cmdDraw(int argc, const char **argv) {
 	if (argc != 2) {
+		debugPrintf("Enables debug rendering of scene objects, ui elements, zbuffer or disables debug rendering.\n");
 		debugPrintf("Usage: %s (obj | ui | zbuf | reset)\n", argv[0]);
 		return true;
 	}
@@ -93,28 +158,9 @@ bool Debugger::cmdDraw(int argc, const char **argv) {
 	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("Changes chapter of the game without changing scene.\n");
 		debugPrintf("Usage: %s <chapter>\n", argv[0]);
 		return true;
 	}
@@ -131,7 +177,8 @@ bool Debugger::cmdChapter(int argc, const char **argv) {
 
 bool Debugger::cmdFlag(int argc, const char **argv) {
 	if (argc != 2 && argc != 3) {
-		debugPrintf("Usage: %s <id> [<new_value>]\n", argv[0]);
+		debugPrintf("Get or set game flag (boolean value).\n");
+		debugPrintf("Usage: %s <id> [<value>]\n", argv[0]);
 		return true;
 	}
 
@@ -154,9 +201,52 @@ bool Debugger::cmdFlag(int argc, const char **argv) {
 	return true;
 }
 
+bool Debugger::cmdSay(int argc, const char **argv) {
+	if (argc != 3) {
+		debugPrintf("Actor will say specified line.\n");
+		debugPrintf("Usage: %s <actorId> <sentenceId>\n", argv[0]);
+		return true;
+	}
+
+	int actorId = atoi(argv[1]);
+	int sentenceId = atoi(argv[2]);
+
+	Actor *actor = nullptr;
+	if (actorId >= 0 && actorId < (int)_vm->_gameInfo->getActorCount()) {
+		actor = _vm->_actors[actorId];
+	}
+
+	if (actor == nullptr) {
+		debugPrintf("Unknown actor %i\n", actorId);
+		return true;
+	}
+
+	actor->speechPlay(sentenceId, true);
+	return false;
+}
+
+bool Debugger::cmdScene(int argc, const char **argv) {
+	if (argc != 1 && argc != 3) {
+		debugPrintf("Changes set and scene.\n");
+		debugPrintf("Usage: %s [<setId> <sceneId>]\n", argv[0]);
+		return true;
+	}
+
+	if (argc == 3) {
+		int setId = atoi(argv[1]);
+		int sceneId = atoi(argv[2]);
+		_vm->_settings->setNewSetAndScene(setId, sceneId);
+		return false;
+	}
+
+	debugPrintf("set = %i\nscene = %i\n", _vm->_scene->getSetId(), _vm->_scene->getSceneId());
+	return true;
+}
+
 bool Debugger::cmdVariable(int argc, const char **argv) {
 	if (argc != 2 && argc != 3) {
-		debugPrintf("Usage: %s <id> [<new_value>]\n", argv[0]);
+		debugPrintf("Get or set game variable (integer).\n");
+		debugPrintf("Usage: %s <id> [<value>]\n", argv[0]);
 		return true;
 	}
 
diff --git a/engines/bladerunner/debugger.h b/engines/bladerunner/debugger.h
index 47b06d2..70fb423 100644
--- a/engines/bladerunner/debugger.h
+++ b/engines/bladerunner/debugger.h
@@ -47,10 +47,13 @@ public:
 	Debugger(BladeRunnerEngine *vm);
 	~Debugger();
 
-	bool cmdDraw(int argc, const char **argv);
-	bool cmdScene(int argc, const char **argv);
+	bool cmdAnimation(int argc, const char **argv);
+	bool cmdGoal(int argc, const char **argv);
 	bool cmdChapter(int argc, const char **argv);
+	bool cmdDraw(int argc, const char **argv);
 	bool cmdFlag(int argc, const char **argv);
+	bool cmdSay(int argc, const char **argv);
+	bool cmdScene(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);
diff --git a/engines/bladerunner/game_constants.h b/engines/bladerunner/game_constants.h
index edc8807..fc04392 100644
--- a/engines/bladerunner/game_constants.h
+++ b/engines/bladerunner/game_constants.h
@@ -330,7 +330,7 @@ enum Clues {
 	kClueMcCoyRetiredDektora = 224,
 	kClueMcCoyRetiredGordo = 225,
 	kClueMcCoyRetiredSadik = 226,
-	kClueMcCoyShotZubenintheback = 227,
+	kClueMcCoyShotZubenInTheBack = 227,
 	kClueMcCoyRetiredLutherLance = 228,
 	kClueMcCoyBetrayal = 229,
 	kClueMcCoyKilledRunciter2 = 230,
@@ -563,6 +563,7 @@ enum AnimationModes {
 	kAnimationModeIdle = 0,
 	kAnimationModeWalk = 1,
 	kAnimationModeRun = 2,
+	kAnimationModeTalk = 3,
 	kAnimationModeCombatIdle = 4,
 	kAnimationModeCombatAim = 5,
 	kAnimationModeCombatShoot = 6,
@@ -593,8 +594,8 @@ enum Scenes {
 	kSceneBB09 = 10,
 	kSceneBB10 = 11,
 	kSceneBB11 = 12,
-	kSceneCT01 = 13,
-	kSceneCT02 = 14,
+	kSceneCT01 = 13, // Chinatown - Howie Lee Restaurant
+	kSceneCT02 = 14, // Chinatown - Kitchen
 	kSceneCT03 = 15,
 	kSceneCT04 = 16,
 	kSceneCT05 = 17,
@@ -724,6 +725,7 @@ enum Sets {
 	kSetCT02 = 27,
 	kSetCT05 = 28,
 	kSetCT06 = 29,
+	kSetCT07 = 30,
 	kSetCT09 = 31,
 	kSetCT10 = 32,
 	kSetCT11 = 33,
diff --git a/engines/bladerunner/game_info.cpp b/engines/bladerunner/game_info.cpp
index f3395d1..db664c0 100644
--- a/engines/bladerunner/game_info.cpp
+++ b/engines/bladerunner/game_info.cpp
@@ -135,4 +135,36 @@ bool GameInfo::open(const Common::String &name) {
 	return !err;
 }
 
+const char *GameInfo::getSceneName(int i) const {
+	if (i < 0 || i >= (int)_sceneNamesCount) {
+		warning("GameInfo::getSceneName: unknown id \"%i\"", i);
+		return nullptr;
+	}
+	return _sceneNames[i];
+}
+
+const char *GameInfo::getSfxTrack(int i) const {
+	if (i < 0 || i >= (int)_sfxTrackCount) {
+		warning("GameInfo::getSfxTrack: unknown id \"%i\"", i);
+		return nullptr;
+	}
+	return _sfxTracks[i];
+}
+
+const char *GameInfo::getMusicTrack(int i) const {
+	if (i < 0 || i >= (int)_musicTrackCount) {
+		warning("GameInfo::getMusicTrack: unknown id \"%i\"", i);
+		return nullptr;
+	}
+	return _musicTracks[i];
+}
+
+const char *GameInfo::getOuttake(int i) const {
+	if (i < 0 || i >= (int)_outtakeCount) {
+		warning("GameInfo::getOuttake: unknown id \"%i\"", i);
+		return nullptr;
+	}
+	return _outtakes[i];
+}
+
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/game_info.h b/engines/bladerunner/game_info.h
index 552d41d..bc7fc1e 100644
--- a/engines/bladerunner/game_info.h
+++ b/engines/bladerunner/game_info.h
@@ -77,10 +77,10 @@ public:
 	uint32 getCoverWaypointCount() const   { return _coverWaypointCount; }
 	uint32 getFleeWaypointCount() const    { return _fleeWaypointCount; }
 
-	const char *getSceneName(int i) const  { return _sceneNames[i]; }
-	const char *getSfxTrack(int i) const   { return _sfxTracks[i]; }
-	const char *getMusicTrack(int i) const { return _musicTracks[i]; }
-	const char *getOuttake(int i) const    { return _outtakes[i]; }
+	const char *getSceneName(int i) const;
+	const char *getSfxTrack(int i) const;
+	const char *getMusicTrack(int i) const;
+	const char *getOuttake(int i) const;
 };
 
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/module.mk b/engines/bladerunner/module.mk
index 4a929a4..87da3b1 100644
--- a/engines/bladerunner/module.mk
+++ b/engines/bladerunner/module.mk
@@ -58,6 +58,7 @@ MODULE_OBJS = \
 	script/ai/mccoy.o \
 	script/ai/officer_leary.o \
 	script/ai/runciter.o \
+	script/ai/zuben.o \
 	script/scene_script.o \
 	script/scene/ar01.o \
 	script/scene/ar02.o \
diff --git a/engines/bladerunner/overlays.cpp b/engines/bladerunner/overlays.cpp
index cd6afe8..b5cb130 100644
--- a/engines/bladerunner/overlays.cpp
+++ b/engines/bladerunner/overlays.cpp
@@ -55,7 +55,7 @@ Overlays::~Overlays() {
 	reset();
 }
 
-int Overlays::play(const Common::String &name, int loopId, int loopForever, int startNow, int a6) {
+int Overlays::play(const Common::String &name, int loopId, bool loopForever, bool startNow, int a6) {
 	int id = mix_id(name);
 	int index = findById(id);
 	if (index < 0) {
diff --git a/engines/bladerunner/overlays.h b/engines/bladerunner/overlays.h
index 5054051..38edf74 100644
--- a/engines/bladerunner/overlays.h
+++ b/engines/bladerunner/overlays.h
@@ -57,7 +57,7 @@ public:
 	bool init();
 	~Overlays();
 
-	int play(const Common::String &name, int a3, int a4, int a5, int a6);
+	int play(const Common::String &name, int loopId, bool loopForever, bool startNow, int a6);
 	void remove(const Common::String &name);
 	void removeAll();
 	void tick();
diff --git a/engines/bladerunner/script/ai/_template.cpp b/engines/bladerunner/script/ai/_template.cpp
index af7c685..cff8e62 100644
--- a/engines/bladerunner/script/ai/_template.cpp
+++ b/engines/bladerunner/script/ai/_template.cpp
@@ -24,90 +24,90 @@
 
 namespace BladeRunner {
 
-AIScriptGenericWalkerA::AIScriptGenericWalkerA(BladeRunnerEngine *vm) : AIScriptBase(vm) {
+AIScriptTemplate::AIScriptTemplate(BladeRunnerEngine *vm) : AIScriptBase(vm) {
 }
 
-void AIScriptGenericWalkerA::Initialize() {
-	_animationStateNext = 0;
-	_animationNext = 0;
+void AIScriptTemplate::Initialize() {
 	_animationFrame = 0;
 	_animationState = 0;
+	_animationStateNext = 0;
+	_animationNext = 0;
 }
 
-bool AIScriptGenericWalkerA::Update() {
+bool AIScriptTemplate::Update() {
 	return false;
 }
 
-void AIScriptGenericWalkerA::TimerExpired(int timer) {
+void AIScriptTemplate::TimerExpired(int timer) {
 }
 
-void AIScriptGenericWalkerA::CompletedMovementTrack() {
+void AIScriptTemplate::CompletedMovementTrack() {
 }
 
-void AIScriptGenericWalkerA::ReceivedClue(int clueId, int fromActorId) {
+void AIScriptTemplate::ReceivedClue(int clueId, int fromActorId) {
 }
 
-void AIScriptGenericWalkerA::ClickedByPlayer() {
+void AIScriptTemplate::ClickedByPlayer() {
 }
 
-void AIScriptGenericWalkerA::EnteredScene(int sceneId) {
+void AIScriptTemplate::EnteredScene(int sceneId) {
 }
 
-void AIScriptGenericWalkerA::OtherAgentEnteredThisScene(int otherActorId) {
+void AIScriptTemplate::OtherAgentEnteredThisScene(int otherActorId) {
 }
 
-void AIScriptGenericWalkerA::OtherAgentExitedThisScene(int otherActorId) {
+void AIScriptTemplate::OtherAgentExitedThisScene(int otherActorId) {
 }
 
-void AIScriptGenericWalkerA::OtherAgentEnteredCombatMode(int otherActorId, int combatMode) {
+void AIScriptTemplate::OtherAgentEnteredCombatMode(int otherActorId, int combatMode) {
 }
 
-void AIScriptGenericWalkerA::ShotAtAndMissed() {
+void AIScriptTemplate::ShotAtAndMissed() {
 }
 
-bool AIScriptGenericWalkerA::ShotAtAndHit() {
+bool AIScriptTemplate::ShotAtAndHit() {
 	return false;
 }
 
-void AIScriptGenericWalkerA::Retired(int byActorId) {
+void AIScriptTemplate::Retired(int byActorId) {
 }
 
-int AIScriptGenericWalkerA::GetFriendlinessModifierIfGetsClue(int otherActorId, int clueId) {
+int AIScriptTemplate::GetFriendlinessModifierIfGetsClue(int otherActorId, int clueId) {
 	return 0;
 }
 
-bool AIScriptGenericWalkerA::GoalChanged(int currentGoalNumber, int newGoalNumber) {
+bool AIScriptTemplate::GoalChanged(int currentGoalNumber, int newGoalNumber) {
 	return false;
 }
 
-bool AIScriptGenericWalkerA::UpdateAnimation(int *animation, int *frame) {
+bool AIScriptTemplate::UpdateAnimation(int *animation, int *frame) {
 	*animation = 0;
 	*frame = _animationFrame;
 	return true;
 }
 
-bool AIScriptGenericWalkerA::ChangeAnimationMode(int mode) {
+bool AIScriptTemplate::ChangeAnimationMode(int mode) {
 	return true;
 }
 
-void AIScriptGenericWalkerA::QueryAnimationState(int *animationState, int *animationFrame, int *animationStateNext, int *animationNext) {
+void AIScriptTemplate::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) {
+void AIScriptTemplate::SetAnimationState(int animationState, int animationFrame, int animationStateNext, int animationNext) {
 	_animationState     = animationState;
 	_animationFrame     = animationFrame;
 	_animationStateNext = animationStateNext;
 	_animationNext      = animationNext;
 }
 
-bool AIScriptGenericWalkerA::ReachedMovementTrackWaypoint(int waypointId) {
+bool AIScriptTemplate::ReachedMovementTrackWaypoint(int waypointId) {
 	return true;
 }
 
-void AIScriptGenericWalkerA::FledCombat() {}
+void AIScriptTemplate::FledCombat() {}
 
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/ai/mccoy.cpp b/engines/bladerunner/script/ai/mccoy.cpp
index f86a328..faecdf9 100644
--- a/engines/bladerunner/script/ai/mccoy.cpp
+++ b/engines/bladerunner/script/ai/mccoy.cpp
@@ -1618,7 +1618,7 @@ bool AIScriptMcCoy::ChangeAnimationMode(int mode) {
 		_animationState = 27;
 		_animationFrame = 0;
 		break;
-	case 52:
+	case kAnimationModeFeeding:
 		_animationState = 55;
 		_animationFrame = 0;
 		break;
diff --git a/engines/bladerunner/script/ai/zuben.cpp b/engines/bladerunner/script/ai/zuben.cpp
new file mode 100644
index 0000000..7f17811
--- /dev/null
+++ b/engines/bladerunner/script/ai/zuben.cpp
@@ -0,0 +1,1186 @@
+/* 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 {
+
+AIScriptZuben::AIScriptZuben(BladeRunnerEngine *vm) : AIScriptBase(vm) {
+	_var_45D258 = 0;
+	_var_45D25C = 0;
+	_animationFrameTarget2 = 0;
+	_animationFrameDelta = 0;
+	_animationFrameTarget1 = 0;
+}
+
+void AIScriptZuben::Initialize() {
+	_animationState = 0;
+	_animationFrame = 0;
+	_var_45D258 = 0;
+	_var_45D25C = 30;
+	_animationFrameTarget2 = 0;
+	_animationFrameDelta = 1;
+	_animationFrameTarget1 = 2;
+	Actor_Put_In_Set(kActorZuben, kSetCT01_CT12);
+	Actor_Set_At_XYZ(kActorZuben, -165.01f, -6.5f, 413.12f, 103);
+	Actor_Set_Goal_Number(kActorZuben, 0);
+}
+
+bool AIScriptZuben::Update() {
+	if (Actor_Query_Goal_Number(kActorZuben) == 599 && Actor_Query_Which_Set_In(kActorZuben) != kSetFreeSlotI) {
+		if (Actor_Query_Which_Set_In(kActorZuben) != Player_Query_Current_Set() ) {
+			Actor_Put_In_Set(kActorZuben, kSetFreeSlotI);
+			Actor_Set_At_Waypoint(kActorZuben, 41, 0);
+		}
+	}
+	if (Actor_Query_Goal_Number(kActorZuben) == 0 && Player_Query_Current_Scene() == kSceneCT01 && !Game_Flag_Query(129) ) {
+		AI_Countdown_Timer_Reset(kActorZuben, 2);
+		AI_Countdown_Timer_Start(kActorZuben, 2, 30);
+		Game_Flag_Set(129);
+		return true;
+	}
+	if (Actor_Query_Goal_Number(kActorZuben) == 0 && Actor_Query_Friendliness_To_Other(kActorZuben, kActorMcCoy) < 48 && Actor_Query_Is_In_Current_Set(kActorZuben)) {
+		Actor_Face_Actor(kActorZuben, kActorHowieLee, true);
+		Actor_Says(kActorZuben, 0, 14);
+		if (Random_Query(1, 3) == 1) {
+			Actor_Clue_Acquire(kActorZuben, kClueMcCoysDescription, true, -1);
+		}
+		Game_Flag_Set(29);
+		Actor_Set_Goal_Number(kActorZuben, 1);
+		return true;
+	}
+	if (Global_Variable_Query(kVariableChapter) >= 4 && !Game_Flag_Query(kFlagZubenRetired) && Actor_Query_Goal_Number(kActorZuben) < 200) {
+		AI_Movement_Track_Flush(kActorZuben);
+		Actor_Set_Goal_Number(kActorZuben, 200);
+		return true;
+	}
+	if (Global_Variable_Query(kVariableChapter) == 5 && !Game_Flag_Query(kFlagZubenRetired) && Actor_Query_Goal_Number(kActorZuben) < 400) {
+		AI_Movement_Track_Flush(kActorZuben);
+		Actor_Set_Goal_Number(kActorZuben, 400);
+		return true;
+	}
+	if (Actor_Query_Goal_Number(kActorZuben) == 12 && Player_Query_Current_Scene() == kSceneCT07) {
+		AI_Countdown_Timer_Reset(kActorZuben, 0);
+		Game_Flag_Set(94);
+		Actor_Set_Targetable(kActorZuben, true);
+		if (Actor_Query_Goal_Number(kActorGordo) == 0) {
+			Actor_Set_Goal_Number(kActorGordo, 1);
+		}
+		return true;
+	}
+	if (Actor_Query_Goal_Number(kActorZuben) == 14 && !Game_Flag_Query(210)) {
+		Game_Flag_Set(210);
+		return true;
+	}
+	return false;
+}
+
+void AIScriptZuben::TimerExpired(int timer) {
+	if (timer == 2) {
+		if (Actor_Query_Goal_Number(kActorZuben) == 0 && Player_Query_Current_Scene() == kSceneCT01 && Random_Query(1, 3) < 3) {
+			Actor_Modify_Friendliness_To_Other(kActorZuben, kActorMcCoy, -1);
+		}
+		Game_Flag_Reset(129);
+		// return true;
+	} else if (timer == 1) {
+		if (Actor_Query_Goal_Number(kActorZuben) == 2) {
+			Music_Stop(10);
+			Actor_Set_Goal_Number(kActorZuben, 13);
+			AI_Countdown_Timer_Reset(kActorZuben, 1);
+			// return true;
+		}
+	} else if (timer == 0) {
+		if (Player_Query_Current_Set() != kSetCT01_CT12) {
+			Music_Stop(2);
+		}
+		Actor_Set_Goal_Number(kActorZuben, 20);
+		AI_Countdown_Timer_Reset(kActorZuben, 0);
+		// return true;
+	}
+	// return false;
+}
+
+void AIScriptZuben::CompletedMovementTrack() {
+	if (Actor_Query_Goal_Number(kActorZuben) == 2 && Game_Flag_Query(719)) {
+		Set_Enter(kSetCT03_CT04, kSceneCT03);
+	}
+
+	if (Actor_Query_Goal_Number(kActorZuben) == 3) {
+		Actor_Set_Goal_Number(kActorZuben, 5);
+		//return true;
+	} else if (Actor_Query_Goal_Number(kActorZuben) == 13 && Game_Flag_Query(719)) {
+		AI_Countdown_Timer_Reset(kActorZuben, 0);
+		Game_Flag_Reset(719);
+		Game_Flag_Set(720);
+		Game_Flag_Set(721);
+		Music_Stop(2);
+		Actor_Set_Goal_Number(kActorZuben, 20);
+		Set_Enter(kSetCT02, kSceneCT02);
+		//return true;
+	} else if (Actor_Query_Goal_Number(kActorZuben) == 9) {
+		Actor_Set_Goal_Number(kActorZuben, 10);
+		//return true;
+	} else {
+		if (Actor_Query_Goal_Number(kActorZuben) == 5) {
+			Music_Stop(2);
+			Sound_Play(574, 40, 100, 100, 50);
+			Delay(2000);
+			Game_Flag_Set(144);
+			Game_Flag_Set(kFlagZubenSpared);
+			Game_Flag_Set(31);
+			Actor_Set_Goal_Number(kActorZuben, 7);
+			Actor_Set_Goal_Number(kActorGaff, 1);
+			Set_Enter(kSetCT06, kSceneCT06);
+		}
+		if (Actor_Query_Goal_Number(kActorZuben) == 21) {
+			Non_Player_Actor_Combat_Mode_On(kActorZuben, 0, 0, kActorMcCoy, 6, kAnimationModeCombatIdle, kAnimationModeCombatWalk, kAnimationModeCombatRun, 0, 0, 100, 15, 300, 0);
+		}
+		int goal = Actor_Query_Goal_Number(kActorZuben);
+		if (goal == 200) {
+			Actor_Set_Goal_Number(kActorZuben, 205);
+		} else if (goal == 205) {
+			Actor_Set_Goal_Number(kActorZuben, 206);
+		} else if (goal == 100) {
+			Actor_Set_Goal_Number(kActorZuben, 105);
+		} else if (goal == 105) {
+			Actor_Set_Goal_Number(kActorZuben, 106);
+		}
+		// return false;
+	}
+}
+
+void AIScriptZuben::ReceivedClue(int clueId, int fromActorId) {
+	//return false;
+}
+
+void AIScriptZuben::ClickedByPlayer() {
+	if (Actor_Query_Goal_Number(kActorZuben) == 599) {
+		if (Player_Query_Current_Scene() == kSceneCT06) {
+			// return true;
+			return;
+		}
+		Actor_Face_Actor(kActorMcCoy, kActorZuben, true);
+		Actor_Says(kActorMcCoy, 8529, 13);
+	}
+	if (Global_Variable_Query(kVariableChapter) > 1 && Global_Variable_Query(kVariableChapter) < 5) {
+		if (Actor_Query_Friendliness_To_Other(kActorZuben, kActorMcCoy) <= 20) {
+			Actor_Face_Actor(kActorMcCoy, kActorZuben, true);
+			Actor_Says(kActorMcCoy, 8910, 11);
+		} else if (Game_Flag_Query(699)) {
+			Actor_Face_Actor(kActorMcCoy, kActorZuben, true);
+			Actor_Says(kActorMcCoy, 8910, 11);
+		} else {
+			AI_Movement_Track_Pause(kActorZuben);
+			Actor_Face_Actor(kActorZuben, kActorMcCoy, true);
+			Actor_Says(kActorZuben, 140, 14);
+			Actor_Face_Actor(kActorMcCoy, kActorZuben, true);
+			Actor_Says(kActorMcCoy, 7280, 11);
+			Actor_Says(kActorZuben, 150, 15);
+			Actor_Says(kActorMcCoy, 7285, 12);
+			dialogue();
+			Game_Flag_Set(699);
+			AI_Movement_Track_Unpause(kActorZuben);
+		}
+		// return true;
+	}
+	// return false;
+}
+
+void AIScriptZuben::EnteredScene(int sceneId) {
+	//return false;
+}
+
+void AIScriptZuben::OtherAgentEnteredThisScene(int otherActorId) {
+	//return false;
+}
+
+void AIScriptZuben::OtherAgentExitedThisScene(int otherActorId) {
+	//return false;
+}
+
+void AIScriptZuben::OtherAgentEnteredCombatMode(int otherActorId, int combatMode) {
+	if (otherActorId == kActorMcCoy && !combatMode && Game_Flag_Query(516) && !Game_Flag_Query(712)) {
+		Non_Player_Actor_Combat_Mode_Off(kActorZuben);
+		Game_Flag_Reset(516);
+		AI_Movement_Track_Flush(kActorZuben);
+		Actor_Says(kActorMcCoy, 455, 18);
+		Actor_Modify_Friendliness_To_Other(kActorZuben, kActorMcCoy, 5);
+		Actor_Set_Goal_Number(kActorZuben, 4);
+		// return true;
+	}
+	// return false;
+}
+
+void AIScriptZuben::ShotAtAndMissed() {
+	//return false;
+}
+
+bool AIScriptZuben::ShotAtAndHit() {
+	Game_Flag_Set(712);
+	if (Actor_Query_Goal_Number(kActorZuben) == 5 && !Actor_Clue_Query(kActorZuben, kClueMcCoyShotZubenInTheBack)) {
+		Actor_Clue_Acquire(kActorZuben, kClueMcCoyShotZubenInTheBack, true, -1);
+		Actor_Clue_Lose(kActorZuben, kClueMcCoyLetZubenEscape);
+		Actor_Start_Speech_Sample(kActorMcCoy, 490);
+	}
+	if (Player_Query_Current_Scene() == kSceneCT07) {
+		Music_Stop(2);
+	}
+	return false;
+}
+
+void AIScriptZuben::Retired(int byActorId) {
+	if (!Actor_Query_In_Set(kActorZuben, kSetKP07)) {
+		// return false;
+		return;
+	}
+	Global_Variable_Decrement(51, 1);
+	Actor_Set_Goal_Number(kActorZuben, 599);
+	if (Global_Variable_Query(51)) {
+		// return false;
+		return;
+	}
+	Player_Loses_Control();
+	Delay(2000);
+	Player_Set_Combat_Mode(false);
+	Loop_Actor_Walk_To_XYZ(kActorMcCoy, -12.0f, -41.58f, 72.0f, 0, true, false, 0);
+	Ambient_Sounds_Remove_All_Non_Looping_Sounds(true);
+	Ambient_Sounds_Remove_All_Looping_Sounds(1);
+	Game_Flag_Set(579);
+	Game_Flag_Reset(653);
+	Set_Enter(kSetKP05_KP06, kSceneKP06);
+	// return true;
+}
+
+int AIScriptZuben::GetFriendlinessModifierIfGetsClue(int otherActorId, int clueId) {
+	return 0;
+}
+
+bool AIScriptZuben::GoalChanged(int currentGoalNumber, int newGoalNumber) {
+	switch (newGoalNumber) {
+	case 1:
+		AI_Movement_Track_Flush(kActorZuben);
+		AI_Movement_Track_Append(kActorZuben, 86, 0);
+		AI_Movement_Track_Append(kActorZuben, 106, 0);
+		AI_Movement_Track_Append_With_Facing(kActorZuben, 45, 0, 481);
+		AI_Movement_Track_Repeat(kActorZuben);
+		return false;
+	case 2:
+		AI_Movement_Track_Flush(kActorZuben);
+		AI_Movement_Track_Append_Run(kActorZuben, 84, 0);
+		AI_Movement_Track_Append_Run(kActorZuben, 85, 0);
+		AI_Movement_Track_Append(kActorZuben, 39, 0);
+		AI_Countdown_Timer_Reset(kActorZuben, 1);
+		AI_Countdown_Timer_Start(kActorZuben, 1, 10);
+		AI_Countdown_Timer_Reset(kActorZuben, 0);
+		AI_Countdown_Timer_Start(kActorZuben, 0, 70);
+		AI_Movement_Track_Repeat(kActorZuben);
+		return false;
+	case 4:
+		AI_Movement_Track_Flush(kActorZuben);
+		Actor_Face_Actor(kActorZuben, kActorMcCoy, true);
+		Music_Stop(3);
+		Actor_Says(kActorZuben, 100, 19);
+		Actor_Says(kActorMcCoy, 470, 12);
+		Actor_Says(kActorZuben, 110, 18);
+		Actor_Says(kActorMcCoy, 475, 12);
+		Actor_Says(kActorZuben, 120, 15);
+		Actor_Says(kActorMcCoy, 480, 16);
+		Actor_Says(kActorZuben, 130, 17);
+		Actor_Says(kActorMcCoy, 485, 14);
+		if (Random_Query(1, 3) < 3) {
+			Actor_Clue_Acquire(kActorZuben, kClueMcCoysDescription, 1, -1);
+		}
+		if (Random_Query(1, 5) < 5) {
+			Actor_Clue_Acquire(kActorZuben, kClueMcCoyIsABladeRunner, 1, -1);
+		}
+		Actor_Clue_Acquire(kActorZuben, kClueMcCoyLetZubenEscape, 1, -1);
+		Actor_Set_Goal_Number(kActorZuben, 5);
+		return false;
+	case 5:
+		AI_Movement_Track_Flush(kActorZuben);
+		AI_Movement_Track_Append_Run(kActorZuben, 94, 0);
+		AI_Movement_Track_Append_Run(kActorZuben, 33, 0);
+		AI_Movement_Track_Repeat(kActorZuben);
+		return false;
+	case 6:
+		Game_Flag_Set(kFlagZubenRetired);
+		Game_Flag_Set(31);
+		if (Actor_Query_In_Set(kActorZuben, kSetCT07)) {
+			Game_Flag_Set(144);
+			Actor_Set_Goal_Number(kActorGaff, 1);
+			Set_Enter(kSetCT06, kSceneCT06);
+		} else if (Actor_Query_In_Set(kActorZuben, kSetMA01)) {
+			Player_Set_Combat_Mode(false);
+			Actor_Set_Goal_Number(kActorGaff, 3);
+		}
+		Actor_Set_Goal_Number(kActorZuben, 599);
+		return false;
+	case 8:
+		_animationFrame = 0;
+		_animationState = 26;
+		return false;
+	case 9:
+		AI_Movement_Track_Flush(kActorZuben);
+		AI_Movement_Track_Append_Run(kActorZuben, 46, 0);
+		AI_Movement_Track_Repeat(kActorZuben);
+		return false;
+	case 10:
+		Actor_Face_Heading(kActorZuben, kActorMcCoy, false);
+		_animationFrame = 0;
+		_animationState = 27;
+		return false;
+	case 11:
+		AI_Countdown_Timer_Reset(kActorZuben, 0);
+		Actor_Put_In_Set(kActorZuben, kSetCT06);
+		Actor_Set_At_XYZ(kActorZuben, 37.14f, -58.23f, 4.0f, 256);
+		_animationFrame = 0;
+		_animationState = 28;
+		return false;
+	case 12:
+		Player_Loses_Control();
+		if (!Player_Query_Combat_Mode()) {
+			Player_Set_Combat_Mode(true);
+		}
+		Player_Gains_Control();
+		Game_Flag_Set(142);
+		Set_Enter(kSetCT07, kSceneCT07);
+		return false;
+	case 13:
+		Actor_Set_Targetable(kActorZuben, true);
+		AI_Movement_Track_Flush(kActorZuben);
+		AI_Movement_Track_Append_Run(kActorZuben, 51, 0);
+		AI_Movement_Track_Append_Run(kActorZuben, 48, 0);
+		AI_Movement_Track_Append(kActorZuben, 33, 1);
+		AI_Movement_Track_Repeat(kActorZuben);
+		return false;
+	case 14:
+		if (Actor_Query_Goal_Number(kActorMcCoy) != 1) {
+			Player_Loses_Control();
+			Actor_Change_Animation_Mode(kActorMcCoy, 48);
+			Game_Flag_Set(210);
+			Game_Flag_Set(719);
+		}
+		Actor_Set_Goal_Number(kActorZuben, 9);
+		return false;
+	case 21:
+		Game_Flag_Set(94);
+		Actor_Set_Targetable(kActorZuben, true);
+		AI_Movement_Track_Flush(kActorZuben);
+		AI_Movement_Track_Append_Run(kActorZuben, 125, 0);
+		AI_Movement_Track_Repeat(kActorZuben);
+		return false;
+	case 22:
+		AI_Movement_Track_Flush(kActorZuben);
+		AI_Movement_Track_Append_Run(kActorZuben, 125, 0);
+		AI_Movement_Track_Append_Run(kActorZuben, 33, 0);
+		AI_Movement_Track_Repeat(kActorZuben);
+		return false;
+	case 99:
+		AI_Movement_Track_Flush(kActorZuben);
+		Scene_Exits_Enable();
+		Music_Stop(2);
+		return false;
+	case 100:
+		AI_Movement_Track_Flush(kActorZuben);
+		AI_Movement_Track_Append_Run(kActorZuben, 33, 3);
+		AI_Movement_Track_Repeat(kActorZuben);
+		return false;
+	case 105:
+		{
+			int rnd1 = Random_Query(1, 3);
+
+			if (rnd1 == 1) {
+				int rnd2 = Random_Query(1, 3);
+				if (rnd2 == 1) {
+					AI_Movement_Track_Flush(kActorZuben);
+					AI_Movement_Track_Append(kActorZuben, 472, 0);
+					AI_Movement_Track_Append_With_Facing(kActorZuben, 470, 2, 506);
+					AI_Movement_Track_Append(kActorZuben, 471, 5);
+					AI_Movement_Track_Append(kActorZuben, 470, 0);
+					AI_Movement_Track_Append(kActorZuben, 469, 0);
+					AI_Movement_Track_Append(kActorZuben, 468, 2);
+				} else if (rnd2 == 2) {
+					AI_Movement_Track_Flush(kActorZuben);
+					AI_Movement_Track_Append(kActorZuben, 471, 0);
+					AI_Movement_Track_Append(kActorZuben, 472, 5);
+					AI_Movement_Track_Append_With_Facing(kActorZuben, 470, 3, 506);
+					AI_Movement_Track_Append(kActorZuben, 471, 5);
+					AI_Movement_Track_Append(kActorZuben, 472, 0);
+				} else if (rnd2 == 3){
+					AI_Movement_Track_Flush(kActorZuben);
+					AI_Movement_Track_Append(kActorZuben, 468, 0);
+					AI_Movement_Track_Append(kActorZuben, 469, 3);
+					AI_Movement_Track_Append(kActorZuben, 470, 0);
+					AI_Movement_Track_Append(kActorZuben, 471, 0);
+				}
+				AI_Movement_Track_Append(kActorZuben, 33, 15);
+				AI_Movement_Track_Repeat(kActorZuben);
+			}
+
+			if (rnd1 == 1 || rnd1 == 2) {
+				int rnd2 = Random_Query(1, 3);
+				if (rnd2 == 1) {
+					AI_Movement_Track_Append(kActorZuben, 473, 0);
+					AI_Movement_Track_Append(kActorZuben, 474, 5);
+					AI_Movement_Track_Append(kActorZuben, 473, 5);
+					AI_Movement_Track_Append(kActorZuben, 475, 0);
+				} else if (rnd2 == 2) {
+					AI_Movement_Track_Append(kActorZuben, 473, 0);
+					AI_Movement_Track_Append(kActorZuben, 476, 0);
+				} else if (rnd2 == 3) {
+					AI_Movement_Track_Append(kActorZuben, 475, 0);
+					AI_Movement_Track_Append(kActorZuben, 473, 5);
+					AI_Movement_Track_Append(kActorZuben, 474, 5);
+				}
+				AI_Movement_Track_Append(kActorZuben, 33, 15);
+				AI_Movement_Track_Repeat(kActorZuben);
+			}
+
+			if (rnd1 == 1 || rnd1 == 2 || rnd1 == 3) {
+				int rnd2 = Random_Query(1, 3);
+				if (rnd2 == 1) {
+					AI_Movement_Track_Append(kActorZuben, 477, 3);
+					AI_Movement_Track_Append(kActorZuben, 478, 0);
+				} else if (rnd2 == 2) {
+					AI_Movement_Track_Append(kActorZuben, 479, 0);
+					AI_Movement_Track_Append(kActorZuben, 488, 0);
+					AI_Movement_Track_Append(kActorZuben, 489, 0);
+					AI_Movement_Track_Append(kActorZuben, 480, 0);
+				} else if (rnd2 == 3) {
+					AI_Movement_Track_Append(kActorZuben, 481, 0);
+					AI_Movement_Track_Append(kActorZuben, 482, 5);
+					AI_Movement_Track_Append(kActorZuben, 483, 5);
+				}
+				AI_Movement_Track_Append(kActorZuben, 33, 15);
+				AI_Movement_Track_Repeat(kActorZuben);
+			}
+			return false;
+		}
+	case 106:
+		Actor_Set_Goal_Number(kActorZuben, 105);
+		return true;
+	case 200:
+		AI_Movement_Track_Flush(kActorZuben);
+		AI_Movement_Track_Append_Run(kActorZuben, 33, 3);
+		AI_Movement_Track_Repeat(kActorZuben);
+		return false;
+	case 205:
+		switch (Random_Query(1, 8)) {
+		case 1:
+			AI_Movement_Track_Flush(kActorZuben);
+			AI_Movement_Track_Append(kActorZuben, 490, 0);
+			AI_Movement_Track_Append(kActorZuben, 491, 8);
+			AI_Movement_Track_Append(kActorZuben, 492, 2);
+			AI_Movement_Track_Append(kActorZuben, 493, 5);
+			AI_Movement_Track_Append(kActorZuben, 494, 0);
+			AI_Movement_Track_Append(kActorZuben, 39, 10);
+			AI_Movement_Track_Append(kActorZuben, 33, Random_Query(15, 45));
+			AI_Movement_Track_Append(kActorZuben, 39, 10);
+			AI_Movement_Track_Repeat(kActorZuben);
+			break;
+		case 2:
+			AI_Movement_Track_Flush(kActorZuben);
+			AI_Movement_Track_Append(kActorZuben, 495, 0);
+			AI_Movement_Track_Append(kActorZuben, 496, 0);
+			AI_Movement_Track_Append(kActorZuben, 33, Random_Query(15, 45));
+			AI_Movement_Track_Repeat(kActorZuben);
+			break;
+		case 3:
+			AI_Movement_Track_Append(kActorZuben, 498, 0);
+			AI_Movement_Track_Append(kActorZuben, 497, 0);
+			AI_Movement_Track_Append(kActorZuben, 39, 10);
+			AI_Movement_Track_Append(kActorZuben, 33, 30);
+			AI_Movement_Track_Append(kActorZuben, 39, 10);
+			AI_Movement_Track_Repeat(kActorZuben);
+			break;
+		case 4:
+			AI_Movement_Track_Flush(kActorZuben);
+			AI_Movement_Track_Append(kActorZuben, 499, 2);
+			AI_Movement_Track_Append(kActorZuben, 500, 3);
+			AI_Movement_Track_Append(kActorZuben, 499, 2);
+			AI_Movement_Track_Append(kActorZuben, 39, 10);
+			AI_Movement_Track_Append(kActorZuben, 33, 30);
+			AI_Movement_Track_Append(kActorZuben, 39, 10);
+			AI_Movement_Track_Repeat(kActorZuben);
+			break;
+		case 5:
+			AI_Movement_Track_Flush(kActorZuben);
+			AI_Movement_Track_Append(kActorZuben, 503, 0);
+			AI_Movement_Track_Append(kActorZuben, 504, 0);
+			AI_Movement_Track_Append(kActorZuben, 505, 5);
+			AI_Movement_Track_Append(kActorZuben, 39, 10);
+			AI_Movement_Track_Append(kActorZuben, 33, 30);
+			AI_Movement_Track_Append(kActorZuben, 39, 10);
+			AI_Movement_Track_Repeat(kActorZuben);
+			break;
+		case 6:
+			AI_Movement_Track_Flush(kActorZuben);
+			AI_Movement_Track_Append(kActorZuben, 508, 0);
+			AI_Movement_Track_Append(kActorZuben, 509, 2);
+			AI_Movement_Track_Append(kActorZuben, 39, 10);
+			AI_Movement_Track_Append(kActorZuben, 33, 30);
+			AI_Movement_Track_Append(kActorZuben, 39, 10);
+			AI_Movement_Track_Repeat(kActorZuben);
+			break;
+		case 7:
+			AI_Movement_Track_Flush(kActorZuben);
+			AI_Movement_Track_Append(kActorZuben, 514, 0);
+			AI_Movement_Track_Append(kActorZuben, 515, 0);
+			AI_Movement_Track_Append(kActorZuben, 39, 10);
+			AI_Movement_Track_Append(kActorZuben, 33, 30);
+			AI_Movement_Track_Append(kActorZuben, 39, 10);
+			AI_Movement_Track_Repeat(kActorZuben);
+			break;
+		case 8:
+			AI_Movement_Track_Flush(kActorZuben);
+			AI_Movement_Track_Append(kActorZuben, 510, 0);
+			AI_Movement_Track_Append(kActorZuben, 511, 0);
+			AI_Movement_Track_Append(kActorZuben, 39, 10);
+			AI_Movement_Track_Append(kActorZuben, 33, 40);
+			AI_Movement_Track_Append(kActorZuben, 39, 10);
+			AI_Movement_Track_Repeat(kActorZuben);
+			break;
+		}
+		return false;
+	case 206:
+		Actor_Set_Goal_Number(kActorZuben, 205);
+		return true;
+	case 400:
+		AI_Movement_Track_Flush(kActorZuben);
+		Actor_Put_In_Set(kActorZuben, kSetFreeSlotA);
+		Actor_Set_At_Waypoint(kActorZuben, 33, 0);
+		return false;
+	}
+	return false;
+}
+
+bool AIScriptZuben::UpdateAnimation(int *animation, int *frame) {
+	switch (_animationState) {
+	case 0:
+		if (Actor_Query_Goal_Number(kActorZuben) != 0) {
+			*animation = 408;
+			if (_var_45D258 < _var_45D25C) {
+				_animationFrame += _animationFrameDelta;
+				if (_animationFrame > _animationFrameTarget1) {
+					_animationFrame = _animationFrameTarget1;
+					_animationFrameDelta = -1;
+				} else if (_animationFrame < _animationFrameTarget2) {
+					_animationFrame = _animationFrameTarget2;
+					_animationFrameDelta = 1;
+				}
+				_var_45D258++;
+			} else {
+				_animationFrame += _animationFrameDelta;
+				_var_45D25C = 0;
+				if (_animationFrame == 13 && Random_Query(0, 1)) {
+					_animationFrameDelta = -1;
+					_var_45D258 = 0;
+					_animationFrameTarget2 = 8;
+					_animationFrameTarget1 = 13;
+					_var_45D25C = Random_Query(0, 30);
+				}
+				if (_animationFrame == 23) {
+					if (Random_Query(0, 1)) {
+						_animationFrameDelta = -1;
+						_var_45D258 = 0;
+						_animationFrameTarget2 = 20;
+						_animationFrameTarget1 = 23;
+						_var_45D25C = Random_Query(0, 30);
+					}
+				}
+				if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(408)) {
+					_animationFrame = 0;
+					if (Random_Query(0, 1)) {
+						_var_45D258 = 0;
+						_animationFrameTarget2 = 0;
+						_animationFrameTarget1 = 2;
+						_var_45D25C = Random_Query(0, 45);
+					}
+				}
+				if (_animationFrame < 0) {
+					_animationFrame = Slice_Animation_Query_Number_Of_Frames(408) - 1;
+				}
+			}
+		} else {
+			*animation = 418;
+			_animationFrame++;
+			if (_animationFrame >= 24) {
+				_animationFrame = 5;
+			}
+			*frame = _animationFrame;
+		}
+		break;
+	case 1:
+		*animation = 399;
+		_animationFrame++;
+		if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(399)) {
+			_animationFrame = 0;
+		}
+		break;
+	case 2:
+		*animation = 391;
+		_animationFrame++;
+		if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(391)) {
+			_animationFrame = 0;
+		}
+		break;
+	case 3:
+		*animation = 400;
+		_animationFrame++;
+		if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(400)) {
+			_animationFrame = 0;
+		}
+		break;
+	case 4:
+		*animation = 392;
+		_animationFrame++;
+		if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(392)) {
+			_animationFrame = 0;
+		}
+		break;
+	case 5:
+		*animation = 396;
+		_animationFrame++;
+		if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(396)) {
+			_animationFrame = 0;
+			if (Actor_Query_Goal_Number(kActorZuben) == 14) {
+				_animationState = 8;
+			} else {
+				_animationState = 7;
+			}
+		}
+		break;
+	case 6:
+		*animation = 397;
+		_animationFrame++;
+		if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(397)) {
+			_animationFrame = 0;
+			_animationState = 0;
+		}
+		break;
+	case 7:
+		*animation = 388;
+		_animationFrame++;
+		if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(388)) {
+			_animationFrame = 0;
+		}
+		break;
+	case 8:
+		*animation = 398;
+		_animationFrame++;
+		if (_animationFrame == 8) {
+			int sentenceId;
+			if (Random_Query(1, 2) == 1) {
+				sentenceId = 9010;
+			} else {
+				sentenceId = 9015;
+			}
+			Sound_Play_Speech_Line(kActorZuben, sentenceId, 75, 0, 99);
+		}
+		if (_animationFrame == 11) {
+			Actor_Combat_AI_Hit_Attempt(kActorZuben);
+		}
+		if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(398)) {
+			if (Actor_Query_Goal_Number(kActorZuben) == 14) {
+				Actor_Set_Goal_Number(kActorZuben, 9);
+				_animationFrame = 0;
+				_animationState = 0;
+			} else {
+				_animationFrame = 0;
+				_animationState = 7;
+				*animation = 388;
+				Actor_Change_Animation_Mode(kActorZuben, kAnimationModeCombatIdle);
+			}
+		}
+		break;
+	case 9:
+		*animation = 403;
+		_animationFrame++;
+		if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(403)) {
+			if (Actor_Query_Goal_Number(kActorZuben) == 99) {
+				_animationFrame = 0;
+				_animationState = 13;
+				*animation = 405;
+				Actor_Change_Animation_Mode(kActorZuben, 48);
+			} else {
+				_animationFrame = 0;
+				_animationState = 0;
+				*animation = 406;
+				Actor_Change_Animation_Mode(kActorZuben, kAnimationModeIdle);
+			}
+		}
+		break;
+	case 10:
+		*animation = 404;
+		_animationFrame++;
+		if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(404)) {
+			if (Actor_Query_Goal_Number(kActorZuben) == 99) {
+				_animationFrame = 0;
+				_animationState = 13;
+				*animation = 405;
+				Actor_Change_Animation_Mode(kActorZuben, 48);
+			} else {
+				_animationFrame = 0;
+				_animationState = 0;
+				*animation = 406;
+				Actor_Change_Animation_Mode(kActorZuben, kAnimationModeIdle);
+			}
+		}
+		break;
+	case 11:
+		*animation = 389;
+		_animationFrame++;
+		if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(389)) {
+			if (Actor_Query_Goal_Number(kActorZuben) == 99) {
+				_animationFrame = 0;
+				_animationState = 14;
+				*animation = 393;
+				Actor_Change_Animation_Mode(kActorZuben, 48);
+			} else {
+				_animationFrame = 0;
+				_animationState = 7;
+				*animation = 388;
+				Actor_Change_Animation_Mode(kActorZuben, kAnimationModeCombatIdle);
+			}
+		}
+		break;
+	case 12:
+		*animation = 390;
+		_animationFrame++;
+		if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(390)) {
+			if (Actor_Query_Goal_Number(kActorZuben) == 99) {
+				_animationFrame = 0;
+				_animationState = 14;
+				*animation = 393;
+				Actor_Change_Animation_Mode(kActorZuben, 48);
+			} else {
+				_animationFrame = 0;
+				_animationState = 7;
+				*animation = 388;
+				Actor_Change_Animation_Mode(kActorZuben, kAnimationModeCombatIdle);
+			}
+		}
+		break;
+	case 13:
+		*animation = 405;
+		_animationFrame++;
+		if (_animationFrame == 7) {
+			Sound_Play(207, 30, 0, 0, 50);
+		}
+		if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(*animation)) {
+			Actor_Set_Goal_Number(kActorZuben, 6);
+			_animationState = 15;
+			_animationFrame = Slice_Animation_Query_Number_Of_Frames(*animation) - 1;
+			Actor_Set_Targetable(kActorZuben, false);
+		}
+		break;
+	case 14:
+		*animation = 393;
+		_animationFrame++;
+		if (_animationFrame == 7) {
+			Sound_Play(207, 30, 0, 0, 50);
+		}
+		if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(*animation)) {
+			Actor_Set_Goal_Number(kActorZuben, 6);
+			_animationState = 16;
+			_animationFrame = Slice_Animation_Query_Number_Of_Frames(*animation) - 1;
+			Actor_Set_Targetable(kActorZuben, 0);
+		}
+		break;
+	case 15:
+		*animation = 405;
+		_animationFrame = Slice_Animation_Query_Number_Of_Frames(405) - 1;
+		Scene_Exits_Enable();
+		break;
+	case 16:
+		*animation = 393;
+		_animationFrame = Slice_Animation_Query_Number_Of_Frames(393) - 1;
+		break;
+	case 17:
+		*animation = 409;
+		_animationFrame++;
+		if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(409)) {
+			_animationFrame = 0;
+		}
+		break;
+	case 18:
+		*animation = 410;
+		_animationFrame++;
+		if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(410)) {
+			_animationFrame = 0;
+			_animationState = 17;
+			*animation = 409;
+		}
+		break;
+	case 19:
+		*animation = 411;
+		_animationFrame++;
+		if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(411)) {
+			_animationFrame = 0;
+			_animationState = 17;
+			*animation = 409;
+		}
+		break;
+	case 20:
+		*animation = 412;
+		_animationFrame++;
+		if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(412)) {
+			_animationFrame = 0;
+			_animationState = 17;
+			*animation = 409;
+		}
+		break;
+	case 21:
+		*animation = 413;
+		_animationFrame++;
+		if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(413)) {
+			_animationFrame = 0;
+			_animationState = 17;
+			*animation = 409;
+		}
+		break;
+	case 22:
+		*animation = 414;
+		_animationFrame++;
+		if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(414)) {
+			_animationFrame = 0;
+			_animationState = 17;
+			*animation = 409;
+		}
+		break;
+	case 23:
+		*animation = 415;
+		_animationFrame++;
+		if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(415)) {
+			_animationFrame = 0;
+			_animationState = 17;
+			*animation = 409;
+		}
+		break;
+	case 24:
+		*animation = 416;
+		_animationFrame++;
+		if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(416)) {
+			_animationFrame = 0;
+			_animationState = 17;
+			*animation = 409;
+		}
+		break;
+	case 25:
+		*animation = 417;
+		 _animationFrame++;
+		if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(417)) {
+			_animationFrame = 0;
+			_animationState = 17;
+			*animation = 409;
+		}
+		break;
+	case 26:
+		Actor_Set_Frame_Rate_FPS(kActorZuben, -1);
+		*animation = 419;
+		_animationFrame++;
+		if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(419)) {
+			Actor_Set_Frame_Rate_FPS(kActorZuben, -2);
+			_animationState = 0;
+			_animationFrame = 0;
+			Actor_Set_Goal_Number(kActorZuben, 14);
+		}
+		break;
+	case 27:
+		Actor_Set_Frame_Rate_FPS(kActorZuben, -1);
+		*animation = 420;
+		_animationFrame++;
+		if (_animationFrame == 5) {
+			Overlay_Play("ct02over", 1, false, true, 0);
+		}
+		if (_animationFrame == 6) {
+			Sound_Play(201, 40, 0, 0, 50);
+		}
+		if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(420)) {
+			Actor_Set_Frame_Rate_FPS(kActorZuben, -2);
+			_animationState = 0;
+			_animationFrame = 0;
+			Actor_Set_Goal_Number(kActorZuben, 2);
+		}
+		break;
+	case 28:
+		*animation = 421;
+		_animationFrame++;
+		if (_animationFrame == 1) {
+			Sound_Play(206, 80, 0, 0, 50);
+		}
+		if (_animationFrame >= Slice_Animation_Query_Number_Of_Frames(421)) {
+			_animationFrame = 0;
+			_animationState = 5;
+			*animation = 396;
+			Actor_Set_Goal_Number(kActorZuben, 12);
+		}
+		break;
+	default:
+		*animation = 399;
+		break;
+	}
+	*frame = _animationFrame;
+	return true;
+}
+
+bool AIScriptZuben::ChangeAnimationMode(int mode) {
+	switch (mode) {
+	case kAnimationModeIdle:
+		_animationState = 0;
+		_animationFrame = 0;
+		break;
+	case kAnimationModeWalk:
+		_animationState = 1;
+		_animationFrame = 0;
+		break;
+	case kAnimationModeRun:
+		_animationState = 3;
+		_animationFrame = 0;
+		break;
+	case kAnimationModeTalk:
+		_animationState = 17;
+		_animationFrame = 0;
+		break;
+	case kAnimationModeCombatIdle:
+		switch (_animationState) {
+		case 2:
+		case 4:
+			_animationState = 7;
+			_animationFrame = 0;
+			break;
+		case 5:
+		case 7:
+			break;
+		default:
+			_animationState = 5;
+			_animationFrame = 0;
+			break;
+		}
+		break;
+	case kAnimationModeCombatShoot:
+		_animationState = 8;
+		_animationFrame = 0;
+		break;
+	case kAnimationModeCombatWalk:
+		_animationState = 2;
+		_animationFrame = 0;
+		break;
+	case kAnimationModeCombatRun:
+		_animationState = 4;
+		_animationFrame = 0;
+		break;
+	case 12:
+		_animationState = 18;
+		_animationFrame = 0;
+		break;
+	case 13:
+		_animationState = 19;
+		_animationFrame = 0;
+		break;
+	case 14:
+		_animationState = 20;
+		_animationFrame = 0;
+		break;
+	case 15:
+		_animationState = 21;
+		_animationFrame = 0;
+		break;
+	case 16:
+		_animationState = 22;
+		_animationFrame = 0;
+		break;
+	case 17:
+		_animationState = 23;
+		_animationFrame = 0;
+		break;
+	case 18:
+		_animationState = 24;
+		_animationFrame = 0;
+		break;
+	case 19:
+		_animationState = 25;
+		_animationFrame = 0;
+		break;
+	case 21:
+		switch (_animationState) {
+		case 2:
+		case 4:
+		case 5:
+		case 7:
+		case 8:
+			if (Random_Query(0, 1)) {
+				_animationState = 11;
+			} else {
+				_animationState = 12;
+			}
+			_animationFrame = 0;
+			break;
+		case 3:
+		case 6:
+			if (Random_Query(0, 1)) {
+				_animationState = 9;
+			} else {
+				_animationState = 10;
+			}
+			_animationFrame = 0;
+			break;
+		}
+		break;
+	case 22:
+		if (Random_Query(0, 1)) {
+			_animationState = 11;
+		} else {
+			_animationState = 12;
+		}
+		_animationFrame = 0;
+		break;
+	case 24:
+		_animationState = 26;
+		_animationFrame = 0;
+		break;
+	case 25:
+		_animationState = 27;
+		_animationFrame = 0;
+		break;
+	case 26:
+		_animationState = 28;
+		_animationFrame = 0;
+		break;
+	case 48:
+		Actor_Set_Targetable(kActorZuben, false);
+		switch (_animationState) {
+			case 2:
+			case 4:
+			case 5:
+			case 7:
+			case 8:
+			case 11:
+			case 12:
+				_animationState = 14;
+				_animationFrame = 0;
+				break;
+			case 3:
+			case 6:
+			case 9:
+			case 10:
+				_animationState = 13;
+				_animationFrame = 0;
+				break;
+		}
+		break;
+	case 49:
+		Actor_Set_Targetable(kActorZuben, false);
+		_animationState = 14;
+		_animationFrame = 0;
+		break;
+	}
+	return true;
+}
+
+void AIScriptZuben::QueryAnimationState(int *animationState, int *animationFrame, int *animationStateNext, int *animationNext) {
+	*animationState     = _animationState;
+	*animationFrame     = _animationFrame;
+	*animationStateNext = _animationStateNext;
+	*animationNext      = _animationNext;
+}
+
+void AIScriptZuben::SetAnimationState(int animationState, int animationFrame, int animationStateNext, int animationNext) {
+	_animationState     = animationState;
+	_animationFrame     = animationFrame;
+	_animationStateNext = animationStateNext;
+	_animationNext      = animationNext;
+}
+
+bool AIScriptZuben::ReachedMovementTrackWaypoint(int waypointId) {
+	return true;
+}
+
+void AIScriptZuben::FledCombat() {
+	// return false;
+}
+
+void AIScriptZuben::dialogue() {
+	Dialogue_Menu_Clear_List();
+	DM_Add_To_List_Never_Repeat_Once_Selected(1490, 5, 5, -1);
+	if (Actor_Query_Goal_Number(kActorLucy) != 599) {
+		DM_Add_To_List_Never_Repeat_Once_Selected(1500, 5, 5, 5);
+	}
+	DM_Add_To_List_Never_Repeat_Once_Selected(1510, -1, 5, 5);
+	Dialogue_Menu_Add_DONE_To_List(1520);
+	Dialogue_Menu_Appear(320, 240);
+	int answer = Dialogue_Menu_Query_Input();
+	Dialogue_Menu_Disappear();
+	switch (answer) {
+	case 1490:
+		Actor_Says(kActorMcCoy, 7290, 12);
+		Actor_Says(kActorZuben, 180, 15);
+		Actor_Says(kActorMcCoy, 7310, 16);
+		Actor_Says(kActorZuben, 190, 15);
+		break;
+	case 1500:
+		Actor_Says(kActorMcCoy, 7295, 11);
+		Actor_Says(kActorZuben, 200, 12);
+		Actor_Says(kActorMcCoy, 7315, 16);
+		Actor_Says(kActorZuben, 210, 12);
+		Delay(1000);
+		Actor_Says(kActorZuben, 220, 14);
+		Actor_Says(kActorMcCoy, 7320, 17);
+		if (Game_Flag_Query(kFlagLucyIsReplicant)) {
+			Actor_Says(kActorZuben, 230, 14);
+			Actor_Says(kActorMcCoy, 7325, 17);
+			Actor_Says(kActorZuben, 240, 15);
+			Actor_Says(kActorMcCoy, 7330, 16);
+			Actor_Clue_Acquire(kActorMcCoy, kClueZubenTalksAboutLucy1, false, kActorZuben);
+		} else {
+			Actor_Says(kActorZuben, 250, 14);
+			Actor_Says(kActorMcCoy, 7335, 14);
+			Actor_Says(kActorZuben, 260, 15);
+			Actor_Says(kActorMcCoy, 7340, 16);
+			Actor_Says(kActorZuben, 340, 15);
+			Actor_Says(kActorMcCoy, 7345, 12);
+			Actor_Clue_Acquire(kActorMcCoy, kClueZubenTalksAboutLucy2, false, kActorZuben);
+		}
+		break;
+	case 1510:
+		Actor_Says(kActorMcCoy, 7300, 13);
+		Actor_Says(kActorZuben, 280, 12);
+		Actor_Says(kActorMcCoy, 7355, 14);
+		Actor_Says(kActorZuben, 290, 15);
+		Actor_Says(kActorMcCoy, 7360, 14);
+		Actor_Says(kActorZuben, 300, 14);
+		Actor_Says(kActorZuben, 310, 13);
+		Delay(2000);
+		Actor_Says(kActorMcCoy, 7360, 11);
+		Actor_Says(kActorZuben, 320, 12);
+		Actor_Says(kActorZuben, 330, 12);
+		Actor_Clue_Acquire(kActorMcCoy, kClueZubensMotive, false, kActorZuben);
+		break;
+	case 1520:
+		Actor_Says(kActorZuben, 160, 13);
+		Actor_Says(kActorMcCoy, 7305, 15);
+		Actor_Says(kActorZuben, 170, 14);
+		break;
+	}
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/ai_script.cpp b/engines/bladerunner/script/ai_script.cpp
index 4c03d61..0d07cef 100644
--- a/engines/bladerunner/script/ai_script.cpp
+++ b/engines/bladerunner/script/ai_script.cpp
@@ -41,6 +41,7 @@ AIScripts::AIScripts(BladeRunnerEngine *vm, int actorCount) {
 
 	_AIScripts[kActorMcCoy] = new AIScriptMcCoy(_vm);
 	_AIScripts[kActorRunciter] = new AIScriptRunciter(_vm);
+	_AIScripts[kActorZuben] = new AIScriptZuben(_vm);
 	_AIScripts[kActorOfficerLeary] = new AIScriptOfficerLeary(_vm);
 	_AIScripts[kActorLeon] = new AIScriptLeon(_vm);
 	_AIScripts[kActorMaggie] = new AIScriptMaggie(_vm);
diff --git a/engines/bladerunner/script/ai_script.h b/engines/bladerunner/script/ai_script.h
index 8577682..530ba6b 100644
--- a/engines/bladerunner/script/ai_script.h
+++ b/engines/bladerunner/script/ai_script.h
@@ -128,6 +128,16 @@ DECLARE_SCRIPT(Runciter)
 	int var_45CD88;
 END_SCRIPT
 
+DECLARE_SCRIPT(Zuben)
+	int _var_45D258;
+	int _var_45D25C;
+	int _animationFrameTarget2;
+	int _animationFrameDelta;
+	int _animationFrameTarget1;
+
+	void dialogue();
+END_SCRIPT
+
 DECLARE_SCRIPT(OfficerLeary)
 	int var_45D5B8;
 	int var_45D5BC;
diff --git a/engines/bladerunner/script/init_script.cpp b/engines/bladerunner/script/init_script.cpp
index fcb8968..d1de07d 100644
--- a/engines/bladerunner/script/init_script.cpp
+++ b/engines/bladerunner/script/init_script.cpp
@@ -127,7 +127,7 @@ struct ClueWeight {
 
 static ClueWeight ClueWeightsForSteele[44] = {
 	{kClueMcCoyRetiredZuben, 100},
-	{kClueMcCoyShotZubenintheback, 100},
+	{kClueMcCoyShotZubenInTheBack, 100},
 	{kClueMcCoyRetiredLucy, 100},
 	{kClueMcCoyRetiredDektora, 100},
 	{kClueMcCoyRetiredSadik, 100},
@@ -173,7 +173,7 @@ static ClueWeight ClueWeightsForSteele[44] = {
 };
 
 static ClueWeight ClueWeightsForGordo[28] = {
-	{kClueMcCoyShotZubenintheback, 70},
+	{kClueMcCoyShotZubenInTheBack, 70},
 	{kClueMcCoyIsAnnoying, 65},
 	{kClueMcCoyIsKind, 70},
 	{kClueMcCoyIsInsane, 95},
@@ -204,7 +204,7 @@ static ClueWeight ClueWeightsForGordo[28] = {
 };
 
 static ClueWeight ClueWeightsForDektora[46] = {
-	{kClueMcCoyShotZubenintheback, 70},
+	{kClueMcCoyShotZubenInTheBack, 70},
 	{kClueMcCoyIsAnnoying, 45},
 	{kClueMcCoyIsKind, 70},
 	{kClueMcCoyIsInsane, 65},
@@ -279,7 +279,7 @@ static ClueWeight ClueWeightsForGuzza[23] = {
 };
 
 static ClueWeight ClueWeightsForClovis[46] = {
-	{kClueMcCoyShotZubenintheback, 70},
+	{kClueMcCoyShotZubenInTheBack, 70},
 	{kClueMcCoyIsKind, 70},
 	{kClueMcCoyKilledRunciter1, 70},
 	{kClueMcCoysDescription, 70},
@@ -328,7 +328,7 @@ static ClueWeight ClueWeightsForClovis[46] = {
 };
 
 static ClueWeight ClueWeightsForLucy[47] = {
-	{kClueMcCoyShotZubenintheback, 70},
+	{kClueMcCoyShotZubenInTheBack, 70},
 	{kClueMcCoyIsAnnoying, 45},
 	{kClueMcCoyIsKind, 70},
 	{kClueMcCoyIsInsane, 65},
@@ -378,7 +378,7 @@ static ClueWeight ClueWeightsForLucy[47] = {
 };
 
 static ClueWeight ClueWeightsForIzoAndSadik[47] = {
-	{kClueMcCoyShotZubenintheback, 70},
+	{kClueMcCoyShotZubenInTheBack, 70},
 	{kClueMcCoyIsAnnoying, 45},
 	{kClueMcCoyIsKind, 70},
 	{kClueMcCoyIsInsane, 65},
@@ -452,7 +452,7 @@ static ClueWeight ClueWeightsForCrazylegs[49] = {
 	{kClueDNALutherLance, 70},
 	{kClueDNAMarcus, 70},
 	{kCluePowerSource, 70},
-	{kClueMcCoyShotZubenintheback, 65},
+	{kClueMcCoyShotZubenInTheBack, 65},
 	{kClueMcCoyIsAnnoying, 65},
 	{kClueMcCoyIsInsane, 65},
 	{kClueMcCoysDescription, 65},
@@ -518,7 +518,7 @@ static ClueWeight ClueWeightsForLuther[44] = {
 	{kClueGordoInterview3, 50},
 	{kClueEarlyQInterview, 45},
 	{kClueCrystalArrestedCrazylegs, 45},
-	{kClueMcCoyShotZubenintheback, 35},
+	{kClueMcCoyShotZubenInTheBack, 35},
 	{kClueMcCoyKilledRunciter1, 35},
 	{kClueMcCoyKilledRunciter2, 35},
 	{kClueEarlyAttemptedToSeduceLucy, 35},
@@ -586,7 +586,7 @@ void InitScript::Init_Clues2() {
 	Actor_Clue_Add_To_Database(kActorTransient, kClueEarlyAttemptedToSeduceLucy, 65, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorTransient, kClueHomelessManKid, 70, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorTransient, kClueFlaskOfAbsinthe, 100, false, false, -1);
-	Actor_Clue_Add_To_Database(kActorLance, kClueMcCoyShotZubenintheback, 35, false, false, -1);
+	Actor_Clue_Add_To_Database(kActorLance, kClueMcCoyShotZubenInTheBack, 35, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorLance, kClueMcCoyIsAnnoying, 65, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorLance, kClueMcCoyIsKind, 70, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorLance, kClueMcCoyIsInsane, 55, false, false, -1);
@@ -636,7 +636,7 @@ void InitScript::Init_Clues2() {
 	Actor_Clue_Add_To_Database(kActorBulletBob, kClueMcCoyIsKind, 35, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorBulletBob, kClueMcCoyIsInsane, 70, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorBulletBob, kClueMcCoyRetiredZuben, 70, false, false, -1);
-	Actor_Clue_Add_To_Database(kActorBulletBob, kClueMcCoyShotZubenintheback, 70, false, false, -1);
+	Actor_Clue_Add_To_Database(kActorBulletBob, kClueMcCoyShotZubenInTheBack, 70, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorBulletBob, kClueMcCoyKilledRunciter1, 40, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorBulletBob, kClueMcCoyLetZubenEscape, 55, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorBulletBob, kClueMcCoyWarnedIzo, 55, false, false, -1);
@@ -683,7 +683,7 @@ void InitScript::Init_Clues2() {
 	Actor_Clue_Add_To_Database(kActorRunciter, kClueMcCoyRetiredSadik, 70, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorRunciter, kClueMcCoyRetiredLutherLance, 70, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorRunciter, kClueEarlyAttemptedToSeduceLucy, 70, false, false, -1);
-	Actor_Clue_Add_To_Database(kActorInsectDealer, kClueMcCoyShotZubenintheback, 55, false, false, -1);
+	Actor_Clue_Add_To_Database(kActorInsectDealer, kClueMcCoyShotZubenInTheBack, 55, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorInsectDealer, kClueMcCoyIsAnnoying, 55, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorInsectDealer, kClueMcCoyIsKind, 70, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorInsectDealer, kClueMcCoyIsInsane, 55, false, false, -1);
@@ -739,7 +739,7 @@ void InitScript::Init_Clues2() {
 	Actor_Clue_Add_To_Database(kActorEarlyQ, kClueMcCoyIsKind, 90, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorEarlyQ, kClueMcCoyIsInsane, 90, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorEarlyQ, kClueMcCoyRetiredZuben, 100, false, false, -1);
-	Actor_Clue_Add_To_Database(kActorEarlyQ, kClueMcCoyShotZubenintheback, 100, false, false, -1);
+	Actor_Clue_Add_To_Database(kActorEarlyQ, kClueMcCoyShotZubenInTheBack, 100, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorEarlyQ, kClueMcCoyKilledRunciter1, 55, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorEarlyQ, kClueMcCoyLetZubenEscape, 65, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorEarlyQ, kClueMcCoyWarnedIzo, 85, false, false, -1);
@@ -764,7 +764,7 @@ void InitScript::Init_Clues2() {
 	Actor_Clue_Add_To_Database(kActorEarlyQ, kClueCrystalArrestedCrazylegs, 55, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorEarlyQ, kClueSightingMcCoyRuncitersShop, 65, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorZuben, kClueMcCoyIsKind, 90, false, false, -1);
-	Actor_Clue_Add_To_Database(kActorZuben, kClueMcCoyShotZubenintheback, 70, false, false, -1);
+	Actor_Clue_Add_To_Database(kActorZuben, kClueMcCoyShotZubenInTheBack, 70, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorZuben, kClueMcCoyKilledRunciter1, 55, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorZuben, kClueMcCoyKilledRunciter2, 65, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorZuben, kClueMcCoyLetZubenEscape, 70, false, false, -1);
@@ -789,7 +789,7 @@ void InitScript::Init_Clues2() {
 	Actor_Clue_Add_To_Database(kActorZuben, kCluePowerSource, 70, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorZuben, kClueCrystalArrestedCrazylegs, 55, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorZuben, kClueSightingMcCoyRuncitersShop, 65, false, false, -1);
-	Actor_Clue_Add_To_Database(kActorHasan, kClueMcCoyShotZubenintheback, 55, false, false, -1);
+	Actor_Clue_Add_To_Database(kActorHasan, kClueMcCoyShotZubenInTheBack, 55, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorHasan, kClueMcCoyIsAnnoying, 55, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorHasan, kClueMcCoyIsKind, 70, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorHasan, kClueMcCoyIsInsane, 55, false, false, -1);
@@ -850,7 +850,7 @@ void InitScript::Init_Clues2() {
 	Actor_Clue_Add_To_Database(kActorMarcus, kClueCrazylegsInterview2, 60, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorMarcus, kCluePowerSource, 50, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorMarcus, kClueSightingMcCoyRuncitersShop, 60, false, false, -1);
-	Actor_Clue_Add_To_Database(kActorMia, kClueMcCoyShotZubenintheback, 55, false, false, -1);
+	Actor_Clue_Add_To_Database(kActorMia, kClueMcCoyShotZubenInTheBack, 55, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorMia, kClueMcCoyIsAnnoying, 55, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorMia, kClueMcCoyIsKind, 70, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorMia, kClueMcCoyIsInsane, 55, false, false, -1);
@@ -889,7 +889,7 @@ void InitScript::Init_Clues2() {
 	Actor_Clue_Add_To_Database(kActorOfficerLeary, kClueCrowdInterviewB, 65, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorOfficerLeary, kCluePaintTransfer, 25, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorOfficerLeary, kClueMcCoyIsKind, 90, false, false, -1);
-	Actor_Clue_Add_To_Database(kActorOfficerLeary, kClueMcCoyShotZubenintheback, 65, false, false, -1);
+	Actor_Clue_Add_To_Database(kActorOfficerLeary, kClueMcCoyShotZubenInTheBack, 65, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorOfficerLeary, kClueMcCoyKilledRunciter1, 55, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorOfficerLeary, kClueMcCoyKilledRunciter2, 65, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorOfficerLeary, kClueMcCoyLetZubenEscape, 70, false, false, -1);
@@ -912,7 +912,7 @@ void InitScript::Init_Clues2() {
 	Actor_Clue_Add_To_Database(kActorOfficerLeary, kClueRunciterConfession1, 65, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorOfficerLeary, kClueRunciterConfession2, 65, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorOfficerGrayford, kClueMcCoyIsKind, 90, false, false, -1);
-	Actor_Clue_Add_To_Database(kActorOfficerGrayford, kClueMcCoyShotZubenintheback, 65, false, false, -1);
+	Actor_Clue_Add_To_Database(kActorOfficerGrayford, kClueMcCoyShotZubenInTheBack, 65, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorOfficerGrayford, kClueMcCoyKilledRunciter1, 55, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorOfficerGrayford, kClueMcCoyKilledRunciter2, 65, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorOfficerGrayford, kClueMcCoyLetZubenEscape, 70, false, false, -1);
@@ -950,7 +950,7 @@ void InitScript::Init_Clues2() {
 	Actor_Clue_Add_To_Database(kActorBaker, kClueMcCoyIsKind, 90, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorBaker, kClueMcCoyIsInsane, 90, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorBaker, kClueMcCoyRetiredZuben, 70, false, false, -1);
-	Actor_Clue_Add_To_Database(kActorBaker, kClueMcCoyShotZubenintheback, 70, false, false, -1);
+	Actor_Clue_Add_To_Database(kActorBaker, kClueMcCoyShotZubenInTheBack, 70, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorBaker, kClueMcCoyKilledRunciter1, 55, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorBaker, kClueMcCoyLetZubenEscape, 65, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorBaker, kClueMcCoyWarnedIzo, 85, false, false, -1);
@@ -980,7 +980,7 @@ void InitScript::Init_Clues2() {
 	Actor_Clue_Add_To_Database(kActorBaker, kClueHollowayInterview, 65, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorBaker, kClueRunciterConfession1, 65, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorBaker, kClueRunciterConfession2, 65, false, false, -1);
-	Actor_Clue_Add_To_Database(kActorDeskClerk, kClueMcCoyShotZubenintheback, 45, false, false, -1);
+	Actor_Clue_Add_To_Database(kActorDeskClerk, kClueMcCoyShotZubenInTheBack, 45, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorDeskClerk, kClueMcCoyIsAnnoying, 65, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorDeskClerk, kClueMcCoyIsKind, 55, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorDeskClerk, kClueMcCoyIsInsane, 65, false, false, -1);
@@ -1041,7 +1041,7 @@ void InitScript::Init_Clues2() {
 	Actor_Clue_Add_To_Database(kActorHowieLee, kClueMcCoyRetiredGordo, 90, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorHowieLee, kClueMcCoyRetiredZuben, 90, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorHowieLee, kClueEarlyAttemptedToSeduceLucy, 70, false, false, -1);
-	Actor_Clue_Add_To_Database(kActorFishDealer, kClueMcCoyShotZubenintheback, 55, false, false, -1);
+	Actor_Clue_Add_To_Database(kActorFishDealer, kClueMcCoyShotZubenInTheBack, 55, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorFishDealer, kClueMcCoyIsAnnoying, 55, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorFishDealer, kClueMcCoyIsKind, 70, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorFishDealer, kClueMcCoyIsInsane, 55, false, false, -1);
@@ -1089,7 +1089,7 @@ void InitScript::Init_Clues2() {
 	Actor_Clue_Add_To_Database(kActorKlein, kClueMcCoysWeaponUsedonBob, 90, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorKlein, kClueMcCoyRecoveredHoldensBadge, 65, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorKlein, kClueMcCoyIsKind, 90, false, false, -1);
-	Actor_Clue_Add_To_Database(kActorKlein, kClueMcCoyShotZubenintheback, 70, false, false, -1);
+	Actor_Clue_Add_To_Database(kActorKlein, kClueMcCoyShotZubenInTheBack, 70, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorKlein, kClueMcCoyKilledRunciter1, 55, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorKlein, kClueMcCoyKilledRunciter2, 65, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorKlein, kClueMcCoyLetZubenEscape, 70, false, false, -1);
@@ -1112,7 +1112,7 @@ void InitScript::Init_Clues2() {
 	Actor_Clue_Add_To_Database(kActorKlein, kClueHollowayInterview, 65, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorKlein, kClueRunciterConfession1, 65, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorKlein, kClueRunciterConfession2, 65, false, false, -1);
-	Actor_Clue_Add_To_Database(kActorMurray, kClueMcCoyShotZubenintheback, 55, false, false, -1);
+	Actor_Clue_Add_To_Database(kActorMurray, kClueMcCoyShotZubenInTheBack, 55, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorMurray, kClueMcCoyIsAnnoying, 55, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorMurray, kClueMcCoyIsKind, 70, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorMurray, kClueMcCoyIsInsane, 55, false, false, -1);
@@ -1146,7 +1146,7 @@ void InitScript::Init_Clues2() {
 	Actor_Clue_Add_To_Database(kActorMurray, kClueCrazylegsInterview2, 50, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorMurray, kCluePowerSource, 50, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorMurray, kClueSightingMcCoyRuncitersShop, 60, false, false, -1);
-	Actor_Clue_Add_To_Database(kActorHawkersBarkeep, kClueMcCoyShotZubenintheback, 55, false, false, -1);
+	Actor_Clue_Add_To_Database(kActorHawkersBarkeep, kClueMcCoyShotZubenInTheBack, 55, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorHawkersBarkeep, kClueMcCoyIsAnnoying, 60, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorHawkersBarkeep, kClueMcCoyIsKind, 55, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorHawkersBarkeep, kClueMcCoyIsInsane, 55, false, false, -1);
@@ -1199,7 +1199,7 @@ void InitScript::Init_Clues2() {
 	Actor_Clue_Add_To_Database(kActorHolloway, kClueMcCoyIsKind, 90, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorHolloway, kClueMcCoyIsInsane, 90, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorHolloway, kClueMcCoyRetiredZuben, 70, false, false, -1);
-	Actor_Clue_Add_To_Database(kActorHolloway, kClueMcCoyShotZubenintheback, 70, false, false, -1);
+	Actor_Clue_Add_To_Database(kActorHolloway, kClueMcCoyShotZubenInTheBack, 70, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorHolloway, kClueMcCoyKilledRunciter1, 55, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorHolloway, kClueMcCoyLetZubenEscape, 65, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorHolloway, kClueMcCoyWarnedIzo, 85, false, false, -1);
@@ -1244,7 +1244,7 @@ void InitScript::Init_Clues2() {
 	Actor_Clue_Add_To_Database(kActorSergeantWalls, kClueMcCoyRecoveredHoldensBadge, 65, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorSergeantWalls, kClueMcCoyHelpedLucy, 90, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorSergeantWalls, kClueMcCoyIsKind, 90, false, false, -1);
-	Actor_Clue_Add_To_Database(kActorSergeantWalls, kClueMcCoyShotZubenintheback, 70, false, false, -1);
+	Actor_Clue_Add_To_Database(kActorSergeantWalls, kClueMcCoyShotZubenInTheBack, 70, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorSergeantWalls, kClueMcCoyKilledRunciter1, 55, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorSergeantWalls, kClueMcCoyKilledRunciter2, 65, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorSergeantWalls, kClueMcCoyLetZubenEscape, 70, false, false, -1);
@@ -1303,7 +1303,7 @@ void InitScript::Init_Clues2() {
 	Actor_Clue_Add_To_Database(kActorPhotographer, kClueMcCoyIsKind, 90, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorPhotographer, kClueMcCoyIsInsane, 90, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorPhotographer, kClueMcCoyRetiredZuben, 70, false, false, -1);
-	Actor_Clue_Add_To_Database(kActorPhotographer, kClueMcCoyShotZubenintheback, 70, false, false, -1);
+	Actor_Clue_Add_To_Database(kActorPhotographer, kClueMcCoyShotZubenInTheBack, 70, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorPhotographer, kClueMcCoyKilledRunciter1, 55, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorPhotographer, kClueMcCoyLetZubenEscape, 65, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorPhotographer, kClueMcCoyWarnedIzo, 85, false, false, -1);
@@ -1338,7 +1338,7 @@ void InitScript::Init_Clues2() {
 	Actor_Clue_Add_To_Database(kActorEarlyQBartender, kClueMcCoyIsKind, 65, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorEarlyQBartender, kClueMcCoyIsInsane, 65, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorEarlyQBartender, kClueMcCoyRetiredZuben, 50, false, false, -1);
-	Actor_Clue_Add_To_Database(kActorEarlyQBartender, kClueMcCoyShotZubenintheback, 50, false, false, -1);
+	Actor_Clue_Add_To_Database(kActorEarlyQBartender, kClueMcCoyShotZubenInTheBack, 50, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorEarlyQBartender, kClueMcCoyKilledRunciter1, 50, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorEarlyQBartender, kClueMcCoyLetZubenEscape, 50, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorEarlyQBartender, kClueMcCoyWarnedIzo, 50, false, false, -1);
@@ -1372,7 +1372,7 @@ void InitScript::Init_Clues2() {
 	Actor_Clue_Add_To_Database(kActorTaffyPatron, kClueRunciterConfession2, 65, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorTaffyPatron, kClueMcCoyIsABladeRunner, 70, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorTyrell, kClueMcCoyIsKind, 65, false, false, -1);
-	Actor_Clue_Add_To_Database(kActorTyrell, kClueMcCoyShotZubenintheback, 40, false, false, -1);
+	Actor_Clue_Add_To_Database(kActorTyrell, kClueMcCoyShotZubenInTheBack, 40, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorTyrell, kClueMcCoyKilledRunciter1, 55, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorTyrell, kClueMcCoyLetZubenEscape, 65, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorTyrell, kClueMcCoyWarnedIzo, 65, false, false, -1);
@@ -1436,7 +1436,7 @@ void InitScript::Init_Clues2() {
 	Actor_Clue_Add_To_Database(kActorGaff, kClueCar, 90, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorGaff, kClueMcCoyHelpedLucy, 90, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorGaff, kClueMcCoyIsKind, 90, false, false, -1);
-	Actor_Clue_Add_To_Database(kActorGaff, kClueMcCoyShotZubenintheback, 70, false, false, -1);
+	Actor_Clue_Add_To_Database(kActorGaff, kClueMcCoyShotZubenInTheBack, 70, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorGaff, kClueMcCoyKilledRunciter1, 55, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorGaff, kClueMcCoyKilledRunciter2, 65, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorGaff, kClueMcCoyLetZubenEscape, 70, false, false, -1);
@@ -1465,7 +1465,7 @@ void InitScript::Init_Clues2() {
 	Actor_Clue_Add_To_Database(kActorTaffy, kClueMcCoyIsKind, 65, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorTaffy, kClueMcCoyIsInsane, 65, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorTaffy, kClueMcCoyRetiredZuben, 50, false, false, -1);
-	Actor_Clue_Add_To_Database(kActorTaffy, kClueMcCoyShotZubenintheback, 50, false, false, -1);
+	Actor_Clue_Add_To_Database(kActorTaffy, kClueMcCoyShotZubenInTheBack, 50, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorTaffy, kClueMcCoyKilledRunciter1, 50, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorTaffy, kClueMcCoyLetZubenEscape, 50, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorTaffy, kClueMcCoyWarnedIzo, 50, false, false, -1);
@@ -1490,7 +1490,7 @@ void InitScript::Init_Clues2() {
 	Actor_Clue_Add_To_Database(kActorTaffy, kClueCrystalArrestedCrazylegs, 55, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorTaffy, kClueSightingMcCoyRuncitersShop, 65, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorSebastian, kClueMcCoyRetiredZuben, 60, false, false, -1);
-	Actor_Clue_Add_To_Database(kActorSebastian, kClueMcCoyShotZubenintheback, 65, false, false, -1);
+	Actor_Clue_Add_To_Database(kActorSebastian, kClueMcCoyShotZubenInTheBack, 65, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorSebastian, kClueMcCoyIsAnnoying, 45, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorSebastian, kClueMcCoyIsKind, 70, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorSebastian, kClueMcCoyIsInsane, 65, false, false, -1);
@@ -1535,7 +1535,7 @@ void InitScript::Init_Clues2() {
 	Actor_Clue_Add_To_Database(kActorSebastian, kClueCrystalArrestedCrazylegs, 55, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorSebastian, kClueSightingMcCoyRuncitersShop, 65, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorRachael, kClueMcCoyIsKind, 65, false, false, -1);
-	Actor_Clue_Add_To_Database(kActorRachael, kClueMcCoyShotZubenintheback, 40, false, false, -1);
+	Actor_Clue_Add_To_Database(kActorRachael, kClueMcCoyShotZubenInTheBack, 40, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorRachael, kClueMcCoyLetZubenEscape, 65, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorRachael, kClueMcCoyWarnedIzo, 65, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorRachael, kClueMcCoyHelpedIzoIzoIsAReplicant, 65, false, false, -1);
@@ -1559,7 +1559,7 @@ void InitScript::Init_Clues2() {
 	Actor_Clue_Add_To_Database(kActorGeneralDoll, kClueMcCoyIsInsane, 65, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorGeneralDoll, kClueMcCoyIsStupid, 65, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorGeneralDoll, kClueMcCoyIsABladeRunner, 65, false, false, -1);
-	Actor_Clue_Add_To_Database(kActorIsabella, kClueMcCoyShotZubenintheback, 55, false, false, -1);
+	Actor_Clue_Add_To_Database(kActorIsabella, kClueMcCoyShotZubenInTheBack, 55, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorIsabella, kClueMcCoyIsAnnoying, 55, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorIsabella, kClueMcCoyIsKind, 70, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorIsabella, kClueMcCoyIsInsane, 55, false, false, -1);
@@ -1598,7 +1598,7 @@ void InitScript::Init_Clues2() {
 	Actor_Clue_Add_To_Database(kActorLeon, kClueMcCoyIsKind, 55, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorLeon, kClueMcCoyIsInsane, 65, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorLeon, kClueMcCoyRetiredZuben, 65, false, false, -1);
-	Actor_Clue_Add_To_Database(kActorLeon, kClueMcCoyShotZubenintheback, 70, false, false, -1);
+	Actor_Clue_Add_To_Database(kActorLeon, kClueMcCoyShotZubenInTheBack, 70, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorLeon, kClueMcCoyKilledRunciter1, 40, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorLeon, kClueMcCoyLetZubenEscape, 65, false, false, -1);
 	Actor_Clue_Add_To_Database(kActorLeon, kClueMcCoyWarnedIzo, 65, false, false, -1);
diff --git a/engines/bladerunner/script/scene/ct01.cpp b/engines/bladerunner/script/scene/ct01.cpp
index e0af940..5a30809 100644
--- a/engines/bladerunner/script/scene/ct01.cpp
+++ b/engines/bladerunner/script/scene/ct01.cpp
@@ -125,7 +125,7 @@ bool SceneScriptCT01::ClickedOnActor(int actorId) {
 				Game_Flag_Set(26);
 				Actor_Set_Goal_Number(kActorHowieLee, 0);
 			} else if (!Game_Flag_Query(30) && Actor_Query_Friendliness_To_Other(kActorHowieLee, kActorMcCoy) >= 40) {
-				sub_40269C();
+				dialogueWithHowieLee();
 				Actor_Set_Goal_Number(kActorHowieLee, 0);
 			} else {
 				if (Game_Flag_Query(31)) {
@@ -395,7 +395,7 @@ void SceneScriptCT01::PlayerWalkedIn() {
 }
 
 void SceneScriptCT01::PlayerWalkedOut() {
-	Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+	Ambient_Sounds_Remove_All_Non_Looping_Sounds(true);
 	if (Game_Flag_Query(123)) {
 		Ambient_Sounds_Remove_Looping_Sound(55, true);
 		Ambient_Sounds_Remove_Looping_Sound(56, true);
@@ -403,8 +403,8 @@ void SceneScriptCT01::PlayerWalkedOut() {
 		Ambient_Sounds_Remove_All_Looping_Sounds(1);
 	}
 	Music_Stop(5);
-	if (!Game_Flag_Query(176) && Global_Variable_Query(kVariableChapter)) {
-		Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+	if (!Game_Flag_Query(176) && Global_Variable_Query(kVariableChapter) == 1) {
+		Ambient_Sounds_Remove_All_Non_Looping_Sounds(true);
 		Ambient_Sounds_Remove_All_Looping_Sounds(1);
 		Outtake_Play(kOuttakeTowards3, true, -1);
 	}
@@ -413,7 +413,7 @@ void SceneScriptCT01::PlayerWalkedOut() {
 void SceneScriptCT01::DialogueQueueFlushed(int a1) {
 }
 
-void SceneScriptCT01::sub_40269C() {
+void SceneScriptCT01::dialogueWithHowieLee() {
 	Dialogue_Menu_Clear_List();
 	if (Actor_Clue_Query(kActorMcCoy, kClueLucy)) {
 		DM_Add_To_List_Never_Repeat_Once_Selected(40, 4, 5, 6);
diff --git a/engines/bladerunner/script/scene/ct02.cpp b/engines/bladerunner/script/scene/ct02.cpp
index 499ad13..ca17d78 100644
--- a/engines/bladerunner/script/scene/ct02.cpp
+++ b/engines/bladerunner/script/scene/ct02.cpp
@@ -105,7 +105,7 @@ bool SceneScriptCT02::ClickedOn3DObject(const char *objectName, bool a2) {
 	return false;
 }
 
-void SceneScriptCT02::sub_401ACC() {
+void SceneScriptCT02::dialogueWithZuben() {
 	Dialogue_Menu_Clear_List();
 	if (Actor_Clue_Query(kActorMcCoy, kClueLucy)) {
 		DM_Add_To_List_Never_Repeat_Once_Selected(270, 8, 5, 3);
@@ -209,7 +209,7 @@ bool SceneScriptCT02::ClickedOnActor(int actorId) {
 				Actor_Says(kActorMcCoy, 375, 9);
 				Game_Flag_Set(59);
 			}
-			sub_401ACC();
+			dialogueWithZuben();
 			return true;
 		}
 	}
diff --git a/engines/bladerunner/script/scene_script.h b/engines/bladerunner/script/scene_script.h
index 086388c..a1167c9 100644
--- a/engines/bladerunner/script/scene_script.h
+++ b/engines/bladerunner/script/scene_script.h
@@ -119,11 +119,11 @@ DECLARE_SCRIPT(BB51)
 END_SCRIPT
 
 DECLARE_SCRIPT(CT01)
-	void sub_40269C();
+	void dialogueWithHowieLee();
 END_SCRIPT
 
 DECLARE_SCRIPT(CT02)
-	void sub_401ACC();
+	void dialogueWithZuben();
 END_SCRIPT
 
 DECLARE_SCRIPT(CT03)
diff --git a/engines/bladerunner/script/script.cpp b/engines/bladerunner/script/script.cpp
index b7b6e47..528dc2f 100644
--- a/engines/bladerunner/script/script.cpp
+++ b/engines/bladerunner/script/script.cpp
@@ -755,9 +755,8 @@ void ScriptBase::Sound_Play(int id, int volume, int panFrom, int panTo, int prio
 	_vm->_audioPlayer->playAud(name, volume, panFrom, panTo, priority);
 }
 
-void ScriptBase::Sound_Play_Speech_Line(int actorId, int speechId, int a3, int a4, int a5) {
-	//TODO
-	warning("Sound_Play_Speech_Line(%d, %d, %d, %d, %d)", actorId, speechId, a3, a4, a5);
+void ScriptBase::Sound_Play_Speech_Line(int actorId, int sentenceId, int volume, int a4, int priority) {
+	_vm->_audioSpeech->playSpeechLine(actorId, sentenceId, volume, a4, priority);
 }
 
 void ScriptBase::Sound_Left_Footstep_Walk(int actorId) {
@@ -835,7 +834,7 @@ bool ScriptBase::Music_Is_Playing() {
 	return _vm->_music->isPlaying();
 }
 
-void ScriptBase::Overlay_Play(const char *overlay, int loopId, int loopForever, int startNow, int a5) {
+void ScriptBase::Overlay_Play(const char *overlay, int loopId, bool loopForever, bool startNow, int a5) {
 	_vm->_overlays->play(overlay, loopId, loopForever, startNow, a5);
 }
 
diff --git a/engines/bladerunner/script/script.h b/engines/bladerunner/script/script.h
index 8ec9575..ae6e6ee 100644
--- a/engines/bladerunner/script/script.h
+++ b/engines/bladerunner/script/script.h
@@ -153,7 +153,7 @@ protected:
 	int Global_Variable_Decrement(int, int);
 	int Random_Query(int min, int max);
 	void Sound_Play(int id, int volume, int panFrom, int panTo, int priority);
-	void Sound_Play_Speech_Line(int actorId, int speechId, int a3, int a4, int a5);
+	void Sound_Play_Speech_Line(int actorId, int sentenceId, int volume, int a4, int priority);
 	void Sound_Left_Footstep_Walk(int actorId);
 	void Sound_Right_Footstep_Walk(int actorId);
 	void Sound_Left_Footstep_Run(int actorId);
@@ -166,7 +166,7 @@ protected:
 	void Music_Adjust(int volume, int pan, int delay);
 	void Music_Stop(int delay);
 	bool Music_Is_Playing();
-	void Overlay_Play(const char *overlay, int loopId, int loopForever, int startNow, int a5);
+	void Overlay_Play(const char *overlay, int loopId, bool loopForever, bool startNow, int a5);
 	void Overlay_Remove(const char *overlay);
 	void Scene_Loop_Set_Default(int loopId);
 	void Scene_Loop_Start_Special(int sceneLoopMode, int loopId, bool immediately);
diff --git a/engines/bladerunner/vqa_decoder.cpp b/engines/bladerunner/vqa_decoder.cpp
index ac3cadf..07df325 100644
--- a/engines/bladerunner/vqa_decoder.cpp
+++ b/engines/bladerunner/vqa_decoder.cpp
@@ -246,13 +246,13 @@ void VQADecoder::readPacket(uint readFlags) {
 	IFFChunkHeader chd;
 
 	if (remain(_s) < 8) {
-		warning("remain: %d", remain(_s));
+		warning("VQADecoder::readPacket: remain: %d", remain(_s));
 		assert(remain(_s) < 8);
 	}
 
 	do {
 		if (!readIFFChunkHeader(_s, &chd)) {
-			warning("Error reading chunk header");
+			error("VQADecoder::readPacket: Error reading chunk header");
 			return;
 		}
 
@@ -274,7 +274,7 @@ void VQADecoder::readPacket(uint readFlags) {
 		}
 
 		if (!rc) {
-			warning("Error handling chunk %s", strTag(chd.id));
+			warning("VQADecoder::readPacket: Error handling chunk %s", strTag(chd.id));
 			return;
 		}
 	} while (chd.id != kVQFR);
@@ -282,7 +282,7 @@ void VQADecoder::readPacket(uint readFlags) {
 
 void VQADecoder::readFrame(int frame, uint readFlags) {
 	if (frame < 0 || frame >= numFrames()) {
-		error("frame %d out of bounds, frame count is %d", frame, numFrames());
+		error("VQADecoder::readFrame: frame %d out of bounds, frame count is %d", frame, numFrames());
 	}
 
 	uint32 frameOffset = 2 * (_frameInfo[frame] & 0x0FFFFFFF);





More information about the Scummvm-git-logs mailing list