[Scummvm-git-logs] scummvm master -> 3c61365692a31f80e2ebb7253f9be8e7d1fa6ac1

antoniou79 a.antoniou79 at gmail.com
Fri Apr 16 22:49:30 UTC 2021


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

Summary:
c0bcc5438f BLADERUNNER: Fix logic for asking Crazylegs about Dektora
f69fe5ee0b BLADERUNNER: JANITORIAL: Comment alignment fix
3c61365692 BLADERUNNER: Fix bad boundbox for corpses


Commit: c0bcc5438f285fb43b40889c53118ba4fa4a5959
    https://github.com/scummvm/scummvm/commit/c0bcc5438f285fb43b40889c53118ba4fa4a5959
Author: antoniou79 (a.antoniou79 at gmail.com)
Date: 2021-04-17T01:45:38+03:00

Commit Message:
BLADERUNNER: Fix logic for asking Crazylegs about Dektora

Changed paths:
    engines/bladerunner/game_constants.h
    engines/bladerunner/script/scene/hf05.cpp
    engines/bladerunner/script/scene/nr05.cpp


diff --git a/engines/bladerunner/game_constants.h b/engines/bladerunner/game_constants.h
index 373586534d..7b8f040b82 100644
--- a/engines/bladerunner/game_constants.h
+++ b/engines/bladerunner/game_constants.h
@@ -216,11 +216,11 @@ enum Clues {
 	kClueHoldensBadge                      = 110,
 	kClueCar                               = 111,
 	kClueCarIdentified                     = 112,
-	kClueCarRegistration1                  = 113,
-	kClueCarRegistration2                  = 114,
-	kClueCarRegistration3                  = 115,
-	kClueCrazylegsInterview1               = 116,
-	kClueCrazylegsInterview2               = 117,
+	kClueCarRegistration1                  = 113, // Dektora bought the car
+	kClueCarRegistration2                  = 114, // Gavin Kelly bought the car
+	kClueCarRegistration3                  = 115, // Blake Williams bought the car
+	kClueCrazylegsInterview1               = 116, // new: acquired after bug fix. Original: Never acquired
+	kClueCrazylegsInterview2               = 117, // original: Never acquired
 	kClueLichenDogWrapper                  = 118,
 	kClueRequisitionForm                   = 119, // original: Never acquired
 	kClueScaryChair                        = 120,
diff --git a/engines/bladerunner/script/scene/hf05.cpp b/engines/bladerunner/script/scene/hf05.cpp
index b1937f5091..f1208c6f78 100644
--- a/engines/bladerunner/script/scene/hf05.cpp
+++ b/engines/bladerunner/script/scene/hf05.cpp
@@ -152,6 +152,10 @@ bool SceneScriptHF05::ClickedOn3DObject(const char *objectName, bool a2) {
 
 bool SceneScriptHF05::ClickedOnActor(int actorId) {
 	if (actorId == kActorCrazylegs) {
+		// Note: dialogueWithCrazylegs1() makes sense only for Acts 3 and 4.
+		//      by Act 5, McCoy is done interrogating, and it would also be weird
+		//      if he is asking questions about Lucy or Dektora, with them standing next to him.
+		// TODO Recheck: Is McCoy allowed to click on CrazyLegs in Act5 while Dektora or Lucy are there too?
 #if BLADERUNNER_ORIGINAL_BUGS
 		if (!Loop_Actor_Walk_To_Actor(kActorMcCoy, kActorCrazylegs, 60, true, false)) {
 			Actor_Face_Actor(kActorMcCoy, kActorCrazylegs, true);
@@ -395,11 +399,24 @@ void SceneScriptHF05::dialogueWithCrazylegs1() {
 		DM_Add_To_List_Never_Repeat_Once_Selected(1180, 3, 6, 7); // ADVERTISEMENT
 	}
 	if (Actor_Clue_Query(kActorMcCoy, kClueCrazylegsInterview1)) {
+		// kClueCrazylegsInterview1 is acquired (after bug fix)
+		// only when Dektora has bought the car (kClueCarRegistration1)
+		// and McCoy has asked Crazylegs for the CAR REGISTRATION topic already
 		DM_Add_To_List_Never_Repeat_Once_Selected(1190, 2, 7, 4); // WOMAN
 	}
+#if BLADERUNNER_ORIGINAL_BUGS
 	if (Actor_Clue_Query(kActorMcCoy, kClueDektorasDressingRoom)) {
 		DM_Add_To_List_Never_Repeat_Once_Selected(1200, 5, 5, 3); // WOMAN'S PHOTO
 	}
+#else
+	if ((Actor_Clue_Query(kActorMcCoy, kClueDektorasDressingRoom)
+	    && Actor_Clue_Query(kActorMcCoy, kClueCrazylegsInterview1))
+	) {
+		// kClueDektorasDressingRoom is acquired from EarlyQ at his office (nr04)
+		// McCoy should only ask about this if CrazyLegs already told him at least about the sexy blonde (kClueCrazylegsInterview1)
+		DM_Add_To_List_Never_Repeat_Once_Selected(1200, 5, 5, 3); // WOMAN'S PHOTO
+	}
+#endif // BLADERUNNER_ORIGINAL_BUGS
 	if (Actor_Clue_Query(kActorMcCoy, kClueLucy)
 	 && Actor_Query_Goal_Number(kActorLucy) != kGoalLucyGone
 	) {
@@ -410,11 +427,15 @@ void SceneScriptHF05::dialogueWithCrazylegs1() {
 	  && Global_Variable_Query(kVariableChapter) == 3
 	 )
 	) {
+		// TODO recheck the condition here. The chapter check should probably be done in both cases
+		//      either McCoy has kClueGrigoriansResources or kClueGrigoriansNote
 		DM_Add_To_List_Never_Repeat_Once_Selected(1220, -1, 2, 8); // GRIGORIAN
 	}
 	if (Actor_Clue_Query(kActorMcCoy, kClueCarRegistration1)
 	 || Actor_Clue_Query(kActorMcCoy, kClueCarRegistration3)
 	) {
+		// Dektora bought the car or Blake Williams (which is an alias, that Clovis used)
+		// Gordo is with Dektora when making the car purchase (as revealed by CrazyLegs in the "WOMAN" question).
 		DM_Add_To_List_Never_Repeat_Once_Selected(1230, 4, 7, -1); // CAR REGISTRATION
 	}
 
@@ -515,6 +536,13 @@ void SceneScriptHF05::dialogueWithCrazylegs1() {
 			Actor_Says(kActorMcCoy, 2080, kAnimationModeTalk);
 			Actor_Says(kActorCrazylegs, 860, 16);
 			Actor_Says(kActorCrazylegs, 870, kAnimationModeTalk);
+#if BLADERUNNER_ORIGINAL_BUGS
+#else
+			// This clue was never acquired, even though it is checked in KIA
+			// (so that it appears as a recording in KIA if acquired)
+			// It also enables the "WOMAN" conversation option with CrazyLegs.
+			Actor_Clue_Acquire(kActorMcCoy, kClueCrazylegsInterview1, true, kActorCrazylegs);
+#endif // BLADERUNNER_ORIGINAL_BUGS
 		} else if (Actor_Clue_Query(kActorMcCoy, kClueCarRegistration3)) {
 			Actor_Says(kActorCrazylegs, 880, 12);
 			Actor_Says(kActorCrazylegs, 890, 14);
diff --git a/engines/bladerunner/script/scene/nr05.cpp b/engines/bladerunner/script/scene/nr05.cpp
index 9151ae2acf..e294f9ab2d 100644
--- a/engines/bladerunner/script/scene/nr05.cpp
+++ b/engines/bladerunner/script/scene/nr05.cpp
@@ -305,6 +305,12 @@ void SceneScriptNR05::talkToEarlyQ() {
 			DM_Add_To_List_Never_Repeat_Once_Selected(900, 5, 6, 5); // LUCY
 		}
 		if (Actor_Clue_Query(kActorMcCoy, kClueDektorasDressingRoom)) {
+			// TODO A bug? kClueDektorasDressingRoom is acquired from EarlyQ
+			// at his office (nr04) while being threatened by McCoy.
+			// At which point EarlyQ already tells McCoy who the people on the photograph are.
+			// It makes no sense that McCoy will next find EarlyQ at the VIP area (this area, nr05)
+			// and casually ask him about who the woman is in this photo.
+			// (McCoy won't be able to even find EarlyQ there again).
 			DM_Add_To_List_Never_Repeat_Once_Selected(910, 5, 5, 5); // BLOND WOMAN
 		}
 	}
@@ -356,6 +362,8 @@ void SceneScriptNR05::talkToEarlyQ() {
 		Actor_Says(kActorMcCoy, 3515, 14);
 		Actor_Modify_Friendliness_To_Other(kActorEarlyQ, kActorMcCoy, -1);
 		if (Actor_Clue_Query(kActorMcCoy, kClueGrigoriansNote)) { // cut content? this clue is unobtanium
+			// TODO why is Grigorian's Note needed here, for EarlyQ to reveal who Hecuba is?
+			//      maybe another clue should be required in its place or some additional ones?
 			Actor_Says(kActorEarlyQ, 580, 12);
 			Actor_Says(kActorMcCoy, 3560, 13);
 			Actor_Says(kActorEarlyQ, 590, 16);


Commit: f69fe5ee0b44f911b65edd4e8625517ef4d197a2
    https://github.com/scummvm/scummvm/commit/f69fe5ee0b44f911b65edd4e8625517ef4d197a2
Author: antoniou79 (a.antoniou79 at gmail.com)
Date: 2021-04-17T01:45:38+03:00

Commit Message:
BLADERUNNER: JANITORIAL: Comment alignment fix

Changed paths:
    engines/bladerunner/script/scene/rc03.cpp


diff --git a/engines/bladerunner/script/scene/rc03.cpp b/engines/bladerunner/script/scene/rc03.cpp
index d55e944321..e173901fdb 100644
--- a/engines/bladerunner/script/scene/rc03.cpp
+++ b/engines/bladerunner/script/scene/rc03.cpp
@@ -54,7 +54,7 @@ void SceneScriptRC03::InitializeScene() {
 #if BLADERUNNER_ORIGINAL_BUGS
 		Scene_Exit_Add_2D_Exit(2, 524, 350, 573, 359, 2);
 #else
-	// prevent Izo's corpse from blocking the exit hot-spot area
+		// prevent Izo's corpse from blocking the exit hot-spot area
 		Scene_Exit_Add_2D_Exit(2, 524, 340, 573, 359, 2);
 #endif // BLADERUNNER_ORIGINAL_BUGS
 	}


Commit: 3c61365692a31f80e2ebb7253f9be8e7d1fa6ac1
    https://github.com/scummvm/scummvm/commit/3c61365692a31f80e2ebb7253f9be8e7d1fa6ac1
Author: antoniou79 (a.antoniou79 at gmail.com)
Date: 2021-04-17T01:45:38+03:00

Commit Message:
BLADERUNNER: Fix bad boundbox for corpses

Some of these issues were caused by commit 186de62ffb575a6c7fe5c27e1b6980364390e678

Others were original bugs (mutants 2 and 3), and both rats.
This commit includes a fix for Grayford's death animation when shot (in Act 4)

Changed paths:
    engines/bladerunner/actor.cpp
    engines/bladerunner/actor.h
    engines/bladerunner/boundingbox.cpp
    engines/bladerunner/debugger.cpp
    engines/bladerunner/game_constants.h
    engines/bladerunner/scene_objects.cpp
    engines/bladerunner/scene_objects.h
    engines/bladerunner/script/ai/free_slot_a.cpp
    engines/bladerunner/script/ai/free_slot_b.cpp
    engines/bladerunner/script/ai/mutant1.cpp
    engines/bladerunner/script/ai/mutant2.cpp
    engines/bladerunner/script/ai/mutant3.cpp
    engines/bladerunner/script/ai/officer_grayford.cpp


diff --git a/engines/bladerunner/actor.cpp b/engines/bladerunner/actor.cpp
index 4b9dad1c3d..8898eb3431 100644
--- a/engines/bladerunner/actor.cpp
+++ b/engines/bladerunner/actor.cpp
@@ -202,6 +202,10 @@ void Actor::changeAnimationMode(int animationMode, bool force) {
 	}
 }
 
+int Actor::getFPS() const {
+	return _fps;
+}
+
 void Actor::setFPS(int fps) {
 	_fps = fps;
 
@@ -398,6 +402,7 @@ void Actor::movementTrackNext(bool omitAiScript) {
 			}
 		} else {
 			setSetId(waypointSetId);
+
 			setAtXYZ(waypointPosition, angle, true, false, false);
 
 			if (!delay) {
@@ -682,6 +687,13 @@ bool Actor::tick(bool forceDraw, Common::Rect *screenRect) {
 	int32 timeLeft = 0;
 	bool needsUpdate = false;
 	if (_fps > 0) {
+		// Note that when (some?) actors are retired (eg. Zuben)
+		// their _fps is still > 0 so they will periodically set needsUpdate to true in their tick() (here)
+		// Also, the moment an actor is retired does not necessarily means their death animation finished playing
+		// Their death animation may finish a while later.
+		// Thus, until it finished, their screen rectangle will be likely changing at the draw() operation.
+		// Typically at the end of a death animation, the actor keeps updating for the same frame
+		// (ie the last of the death animation). At that point their screen rectangle won't change at the draw() operation.
 		timerUpdate(kActorTimerAnimationFrame);
 		timeLeft = timerLeft(kActorTimerAnimationFrame);
 		needsUpdate = (timeLeft <= 0);
@@ -803,6 +815,9 @@ bool Actor::tick(bool forceDraw, Common::Rect *screenRect) {
 
 	bool isVisible = false;
 	if (!_isInvisible) {
+		// draw() will set the new screenRect for the actor
+		// based on the current animation frame
+		// the new screenRect may be empty, in which case draw returns false (thus isVisible will be false then).
 		isVisible = draw(screenRect);
 		if (isVisible) {
 			_screenRectangle = *screenRect;
@@ -813,19 +828,28 @@ bool Actor::tick(bool forceDraw, Common::Rect *screenRect) {
 	// For consistency we need to init the screen rectangle and bbox for the actor's *scene object*
 	// in a new scene (since we also reset the screen rectangle at Scene::open())
 	// for the case of the actor not moving
+
 	if (_vm->_scene->getSetId() == _setId
 	    && !_isInvisible
-	    && _vm->_sceneObjects->findById(_id + kSceneObjectOffsetActors) != -1
-	    && (_vm->_sceneObjects->isEmptyScreenRectangle(_id + kSceneObjectOffsetActors)
-	        || _vm->_sceneObjects->compareScreenRectangle(_id + kSceneObjectOffsetActors, _screenRectangle) != 0)
-	) {
-		if (isVisible) {
-			Vector3 pos = getPosition();
-			int facing = getFacing();
-			setAtXYZ(pos, facing, false, _isMoving, false);
-		} else {
-			resetScreenRectangleAndBbox();
-			_vm->_sceneObjects->resetScreenRectangleAndBbox(_id + kSceneObjectOffsetActors);
+	    && _vm->_sceneObjects->findById(_id + kSceneObjectOffsetActors) != -1) {
+		if (_vm->_sceneObjects->isEmptyScreenRectangle(_id + kSceneObjectOffsetActors)) {
+			if (isVisible) {
+				Vector3 pos = getPosition();
+				int facing = getFacing();
+				setAtXYZ(pos, facing, true, _isMoving, _isRetired);
+			} else {
+				resetScreenRectangleAndBbox();
+				_vm->_sceneObjects->resetScreenRectangleAndBbox(_id + kSceneObjectOffsetActors);
+			}
+		} else if (_vm->_sceneObjects->compareScreenRectangle(_id + kSceneObjectOffsetActors, _screenRectangle) != 0) {
+			if (isVisible) {
+				// keep actor's _screenRectangle synched with sceneObject's actor's screen rectange
+				// don't do a setAtXYZ here though
+				_vm->_sceneObjects->synchScreenRectangle(_id + kSceneObjectOffsetActors, _screenRectangle);
+			} else {
+				resetScreenRectangleAndBbox();
+				_vm->_sceneObjects->resetScreenRectangleAndBbox(_id + kSceneObjectOffsetActors);
+			}
 		}
 	}
 
@@ -965,7 +989,7 @@ void Actor::setFacing(int facing, bool halfOrSet) {
 }
 
 void Actor::setBoundingBox(const Vector3 &position, bool retired) {
-	if (retired) {
+	if (retired || _isRetired) {
 		_bbox.setXYZ(position.x - (_retiredWidth / 2.0f),
 		             position.y,
 		             position.z - (_retiredWidth / 2.0f),
diff --git a/engines/bladerunner/actor.h b/engines/bladerunner/actor.h
index 1e7169dccf..36bfde8e32 100644
--- a/engines/bladerunner/actor.h
+++ b/engines/bladerunner/actor.h
@@ -140,6 +140,7 @@ public:
 	Vector3 getPosition() const { return _position; }
 
 	void changeAnimationMode(int animationMode, bool force = false);
+	int  getFPS() const;
 	void setFPS(int fps);
 	void increaseFPS();
 
diff --git a/engines/bladerunner/boundingbox.cpp b/engines/bladerunner/boundingbox.cpp
index 40b7d4285a..eceac7b255 100644
--- a/engines/bladerunner/boundingbox.cpp
+++ b/engines/bladerunner/boundingbox.cpp
@@ -26,6 +26,11 @@
 
 namespace BladeRunner {
 
+// TO VERIFY
+// First vertex is typically the bottom left point (x0, y0, z0)
+// and second vertex is the top right (x1, y1, z1)
+// Hence, we also assume that x0 < x1, y0 < y1 and z0 < z1 (ie. see how the inside() method makes its calculation)
+// TODO Maybe add a check here to catch any exceptions?
 BoundingBox::BoundingBox(float x0, float y0, float z0, float x1, float y1, float z1) {
 	_vertices[0].x = x0;
 	_vertices[0].y = y0;
diff --git a/engines/bladerunner/debugger.cpp b/engines/bladerunner/debugger.cpp
index c0ac863dc2..7247e95da6 100644
--- a/engines/bladerunner/debugger.cpp
+++ b/engines/bladerunner/debugger.cpp
@@ -2056,11 +2056,12 @@ bool Debugger::cmdList(int argc, const char **argv) {
 						             sceneObject->isPresent?   "T" : "F",
 						             sceneObject->isObstacle?  "T" : "F",
 						             sceneObject->isMoving?    "T" : "F");
-						debugPrintf("    Goal: %d, Set: %d, Anim mode: %d id:%d showDmg: %s inCombat: %s\n",
+						debugPrintf("    Goal: %d, Set: %d, Anim mode: %d id:%d fps: %d showDmg: %s inCombat: %s\n",
 						             actor->getGoal(),
 						             actor->getSetId(),
 						             actor->getAnimationMode(),
 						             actor->getAnimationId(),
+						             actor->getFPS(),
 						             actor->getFlagDamageAnimIfMoving()? "T" : "F",
 						             actor->inCombat()? "T" : "F");
 						debugPrintf("    Pos(%02.2f,%02.2f,%02.2f)\n",
diff --git a/engines/bladerunner/game_constants.h b/engines/bladerunner/game_constants.h
index 7b8f040b82..951e9784fd 100644
--- a/engines/bladerunner/game_constants.h
+++ b/engines/bladerunner/game_constants.h
@@ -3496,17 +3496,19 @@ enum GoalFreeSlotA { // Rat A
 	kGoalFreeSlotAAct5Default        = 400,
 	kGoalFreeSlotAAct5Prepare        = 405,
 	kGoalFreeSlotAAct5KP02Attack     = 406,
+	kGoalFreeSlotAGoneIntermediate   = 411,
 	kGoalFreeSlotAGone               = 599
 };
 
 enum GoalFreeSlotB { // Rat B
-	kGoalFreeSlotBAct4Default     = 300,
-	kGoalFreeSlotBAct4WalkAround  = 301,
-	kGoalFreeSlotBAct4AttackMcCoy = 302,
-	kGoalFreeSlotBAct5Default     = 400,
-	kGoalFreeSlotBAct5Prepare     = 405,
-	kGoalFreeSlotBAct5KP02Attack  = 406,
-	kGoalFreeSlotBGone            = 599
+	kGoalFreeSlotBAct4Default      = 300,
+	kGoalFreeSlotBAct4WalkAround   = 301,
+	kGoalFreeSlotBAct4AttackMcCoy  = 302,
+	kGoalFreeSlotBAct5Default      = 400,
+	kGoalFreeSlotBAct5Prepare      = 405,
+	kGoalFreeSlotBAct5KP02Attack   = 406,
+	kGoalFreeSlotBGoneIntermediate = 411,
+	kGoalFreeSlotBGone             = 599
 };
 
 enum GoalMaggie {
diff --git a/engines/bladerunner/scene_objects.cpp b/engines/bladerunner/scene_objects.cpp
index 6f091c21d2..d19ed41ef8 100644
--- a/engines/bladerunner/scene_objects.cpp
+++ b/engines/bladerunner/scene_objects.cpp
@@ -373,6 +373,17 @@ void SceneObjects::resetScreenRectangleAndBbox(int sceneObjectId) {
 	}
 }
 
+void SceneObjects::synchScreenRectangle(int sceneObjectId, const Common::Rect &targetScreenRect) {
+	int index = findById(sceneObjectId);
+	if (index != -1) {
+		SceneObject *sceneObject = &_sceneObjects[index];
+		sceneObject->screenRectangle.left   = targetScreenRect.left;
+		sceneObject->screenRectangle.top    = targetScreenRect.top;
+		sceneObject->screenRectangle.right  = targetScreenRect.right;
+		sceneObject->screenRectangle.bottom = targetScreenRect.bottom;
+	}
+}
+
 void SceneObjects::save(SaveFileWriteStream &f) {
 	f.writeInt(_count);
 	for (int i = 0; i < kSceneObjectCount; ++i) {
diff --git a/engines/bladerunner/scene_objects.h b/engines/bladerunner/scene_objects.h
index a4471162e7..10b1b1d2d1 100644
--- a/engines/bladerunner/scene_objects.h
+++ b/engines/bladerunner/scene_objects.h
@@ -93,6 +93,7 @@ public:
 	bool isEmptyScreenRectangle(int sceneObjectId);
 	int compareScreenRectangle(int sceneObjectId, const Common::Rect &rectangle);
 	void resetScreenRectangleAndBbox(int sceneObjectId);
+	void synchScreenRectangle(int sceneObjectId, const Common::Rect &targetScreenRect);
 
 	void save(SaveFileWriteStream &f);
 	void load(SaveFileReadStream &f);
diff --git a/engines/bladerunner/script/ai/free_slot_a.cpp b/engines/bladerunner/script/ai/free_slot_a.cpp
index 2cd9df1259..7cc0e59580 100644
--- a/engines/bladerunner/script/ai/free_slot_a.cpp
+++ b/engines/bladerunner/script/ai/free_slot_a.cpp
@@ -106,7 +106,11 @@ bool AIScriptFreeSlotA::Update() {
 			if (Actor_Query_Which_Set_In(kActorFreeSlotA) != Player_Query_Current_Set()) {
 				Game_Flag_Reset(kFlagRatWalkingAround);
 				Game_Flag_Reset(kFlagUG15BridgeWillBreak);
+#if BLADERUNNER_ORIGINAL_BUGS
 				Actor_Set_Goal_Number(kActorFreeSlotA, kGoalFreeSlotADefault);
+#else
+				Actor_Set_Goal_Number(kActorFreeSlotA, kGoalFreeSlotAGoneIntermediate);
+#endif
 			}
 			break;
 
@@ -143,7 +147,11 @@ bool AIScriptFreeSlotA::Update() {
 				if (Actor_Query_Goal_Number(kActorFreeSlotA) == kGoalFreeSlotAGone) {
 					if (Actor_Query_Which_Set_In(kActorFreeSlotA) != Player_Query_Current_Set()) {
 						Non_Player_Actor_Combat_Mode_Off(kActorFreeSlotA);
+#if BLADERUNNER_ORIGINAL_BUGS
 						Actor_Set_Goal_Number(kActorFreeSlotA, kGoalFreeSlotAAct5Default);
+#else
+						Actor_Set_Goal_Number(kActorFreeSlotA, kGoalFreeSlotAGoneIntermediate);
+#endif
 						return true;
 					}
 				}
@@ -244,11 +252,10 @@ void AIScriptFreeSlotA::OtherAgentExitedThisSet(int otherActorId) {
 		if (Global_Variable_Query(kVariableChapter) == 4) {
 			Game_Flag_Reset(kFlagRatWalkingAround);
 			Game_Flag_Reset(kFlagUG15BridgeWillBreak);
-			Actor_Set_Goal_Number(kActorFreeSlotA, kGoalFreeSlotADefault);
 		} else if (Global_Variable_Query(kVariableChapter) == 5) {
 			Non_Player_Actor_Combat_Mode_Off(kActorFreeSlotA);
-			Actor_Set_Goal_Number(kActorFreeSlotA, kGoalFreeSlotAAct5Default);
 		}
+		Actor_Set_Goal_Number(kActorFreeSlotA, kGoalFreeSlotAGoneIntermediate);
 	}
 #endif // BLADERUNNER_ORIGINAL_BUGS
 	// return false;
@@ -267,6 +274,12 @@ void AIScriptFreeSlotA::ShotAtAndMissed() {
 bool AIScriptFreeSlotA::ShotAtAndHit() {
 	if (Actor_Query_In_Set(kActorFreeSlotA, kSetUG15)) {
 		checkIfOnBridge();
+		// This goal "kGoalFreeSlotAUG15Die" circumvents the proper process
+		// a proper combat with the rat and it dying when its health reaches <= 0
+		// ie. being "retired".
+		// Thus, since the rat never actually 'dies' from being shot,
+		// its Actor::retire() is not called in this case (UG15 bridge rat),
+		// and so its bounding box is not affected. Thus, the rat corpse remains clickable.
 		Actor_Set_Goal_Number(kActorFreeSlotA, kGoalFreeSlotAUG15Die);
 		return true;
 	}
@@ -385,8 +398,23 @@ bool AIScriptFreeSlotA::GoalChanged(int currentGoalNumber, int newGoalNumber) {
 		AI_Movement_Track_Repeat(kActorFreeSlotA);
 		break;
 
+#if BLADERUNNER_ORIGINAL_BUGS
+#else
+	case kGoalFreeSlotAGoneIntermediate:
+		Actor_Set_Health(kActorFreeSlotA, 20, 20);
+		if (Global_Variable_Query(kVariableChapter) == 4) {
+			Actor_Set_Goal_Number(kActorFreeSlotA, kGoalFreeSlotADefault);
+		} else if (Global_Variable_Query(kVariableChapter) == 5) {
+			Actor_Set_Goal_Number(kActorFreeSlotA, kGoalFreeSlotAAct5Default);
+		}
+		break;
+#endif
+
 	case kGoalFreeSlotAGone:
+#if BLADERUNNER_ORIGINAL_BUGS
 		Actor_Set_Health(kActorFreeSlotA, 20, 20);
+#endif
+		// A bug? What does this friendliness affect?
 		Actor_Set_Friendliness_To_Other(kActorFreeSlotA, kActorMcCoy, 40);
 		break;
 
diff --git a/engines/bladerunner/script/ai/free_slot_b.cpp b/engines/bladerunner/script/ai/free_slot_b.cpp
index 3093bc32ae..639d3d8c91 100644
--- a/engines/bladerunner/script/ai/free_slot_b.cpp
+++ b/engines/bladerunner/script/ai/free_slot_b.cpp
@@ -81,7 +81,11 @@ bool AIScriptFreeSlotB::Update() {
 
 		case kGoalFreeSlotBGone:
 			if (Actor_Query_Which_Set_In(kActorFreeSlotB) != Player_Query_Current_Set()) {
+#if BLADERUNNER_ORIGINAL_BUGS
 				Actor_Set_Goal_Number(kActorFreeSlotB, kGoalFreeSlotBAct4Default);
+#else
+				Actor_Set_Goal_Number(kActorFreeSlotB, kGoalFreeSlotBGoneIntermediate);
+#endif
 			}
 			break;
 
@@ -104,7 +108,11 @@ bool AIScriptFreeSlotB::Update() {
 			if (Actor_Query_Goal_Number(kActorFreeSlotB) == kGoalFreeSlotBGone) {
 				if (Actor_Query_Which_Set_In(kActorFreeSlotB) != Player_Query_Current_Set()) {
 					Non_Player_Actor_Combat_Mode_Off(kActorFreeSlotB);
+#if BLADERUNNER_ORIGINAL_BUGS
 					Actor_Set_Goal_Number(kActorFreeSlotB, kGoalFreeSlotBAct5Default);
+#else
+					Actor_Set_Goal_Number(kActorFreeSlotB, kGoalFreeSlotBGoneIntermediate);
+#endif
 					return true;
 				}
 			}
@@ -184,12 +192,10 @@ void AIScriptFreeSlotB::OtherAgentEnteredThisSet(int otherActorId) {
 void AIScriptFreeSlotB::OtherAgentExitedThisSet(int otherActorId) {
 #if !BLADERUNNER_ORIGINAL_BUGS
 	if (otherActorId == kActorMcCoy && Actor_Query_Goal_Number(kActorFreeSlotB) == kGoalFreeSlotBGone) {
-		if (Global_Variable_Query(kVariableChapter) == 4) {
-			Actor_Set_Goal_Number(kActorFreeSlotB, kGoalFreeSlotBAct4Default);
-		} else if (Global_Variable_Query(kVariableChapter) == 5) {
+		if (Global_Variable_Query(kVariableChapter) == 5) {
 			Non_Player_Actor_Combat_Mode_Off(kActorFreeSlotB);
-			Actor_Set_Goal_Number(kActorFreeSlotB, kGoalFreeSlotBAct5Default);
 		}
+		Actor_Set_Goal_Number(kActorFreeSlotB, kGoalFreeSlotBGoneIntermediate);
 	}
 
 #endif // BLADERUNNER_ORIGINAL_BUGS
@@ -250,8 +256,22 @@ bool AIScriptFreeSlotB::GoalChanged(int currentGoalNumber, int newGoalNumber) {
 		AI_Movement_Track_Repeat(kActorFreeSlotB);
 		break;
 
+#if BLADERUNNER_ORIGINAL_BUGS
+#else
+	case kGoalFreeSlotBGoneIntermediate:
+		Actor_Set_Health(kActorFreeSlotB, 20, 20);
+		if (Global_Variable_Query(kVariableChapter) == 4) {
+			Actor_Set_Goal_Number(kActorFreeSlotB, kGoalFreeSlotBAct4Default);
+		} else if (Global_Variable_Query(kVariableChapter) == 5) {
+			Actor_Set_Goal_Number(kActorFreeSlotB, kGoalFreeSlotBAct5Default);
+		}
+		break;
+#endif
+
 	case kGoalFreeSlotBGone:
+#if BLADERUNNER_ORIGINAL_BUGS
 		Actor_Set_Health(kActorFreeSlotB, 20, 20);
+#endif
 		break;
 
 	default:
diff --git a/engines/bladerunner/script/ai/mutant1.cpp b/engines/bladerunner/script/ai/mutant1.cpp
index f88f741275..fd6f518163 100644
--- a/engines/bladerunner/script/ai/mutant1.cpp
+++ b/engines/bladerunner/script/ai/mutant1.cpp
@@ -372,6 +372,9 @@ bool AIScriptMutant1::GoalChanged(int currentGoalNumber, int newGoalNumber) {
 			Actor_Set_Friendliness_To_Other(kActorMutant1, kActorMcCoy, 45);
 		}
 
+		// code repeated also in case 599 which precedes this one
+		// redundant?
+		// results in additional reduction in friendliness and increase of aggressiveness for the other two mutants
 		Actor_Modify_Friendliness_To_Other(kActorMutant2, kActorMcCoy, -10);
 		Actor_Modify_Friendliness_To_Other(kActorMutant3, kActorMcCoy, -20);
 		Actor_Modify_Combat_Aggressiveness(kActorMutant2, 10);
@@ -387,7 +390,8 @@ bool AIScriptMutant1::GoalChanged(int currentGoalNumber, int newGoalNumber) {
 
 	case 599:
 		AI_Movement_Track_Flush(kActorMutant1);
-		Actor_Change_Animation_Mode(kActorMutant1, 48);
+		Actor_Change_Animation_Mode(kActorMutant1, kAnimationModeDie);
+		// results in additional reduction in friendlinees and increase of aggressiveness for the other two mutants
 		Actor_Modify_Friendliness_To_Other(kActorMutant2, kActorMcCoy, -10);
 		Actor_Modify_Friendliness_To_Other(kActorMutant3, kActorMcCoy, -20);
 		Actor_Modify_Combat_Aggressiveness(kActorMutant2, 10);
diff --git a/engines/bladerunner/script/ai/mutant2.cpp b/engines/bladerunner/script/ai/mutant2.cpp
index 0a6e85f293..76de5e6ee5 100644
--- a/engines/bladerunner/script/ai/mutant2.cpp
+++ b/engines/bladerunner/script/ai/mutant2.cpp
@@ -71,7 +71,12 @@ bool AIScriptMutant2::Update() {
 
 		case 599:
 			if (Actor_Query_Which_Set_In(kActorMutant2) != Player_Query_Current_Set()) {
+#if BLADERUNNER_ORIGINAL_BUGS
 				Actor_Set_Goal_Number(kActorMutant2, 403);
+#else
+				// intermediate goal to set new Health (revive for reuse)
+				Actor_Set_Goal_Number(kActorMutant2, 411);
+#endif // BLADERUNNER_ORIGINAL_BUGS
 			}
 			break;
 		}
@@ -337,6 +342,38 @@ bool AIScriptMutant2::GoalChanged(int currentGoalNumber, int newGoalNumber) {
 		}
 		return true;
 
+#if BLADERUNNER_ORIGINAL_BUGS
+#else
+	case 411:
+		// We need the additional intermediate goal 411 (as mutant1 has)
+		// so that we set the health here, instead of the when the goal is set to 599 (dying)
+		// Setting the health "revives" the mutant, which would result in their bound box being reduced to a point
+		// (see Actor::setHealth() call to retire(false, 0, 0, -1))
+		// and thus their corpse being unclickable after McCoy shot them.
+		// Goal 411 does this, but is set only when McCoy is no longer present in the scene/set.
+		AI_Movement_Track_Flush(kActorMutant2);
+		Actor_Set_Intelligence(kActorMutant2, 20);
+		Actor_Set_Health(kActorMutant2, 10 * Query_Difficulty_Level() + 50, 10 * Query_Difficulty_Level() + 50);
+
+		if (Game_Flag_Query(kFlagCT04HomelessKilledByMcCoy)) {
+			Actor_Set_Combat_Aggressiveness(kActorMutant2, 60);
+			Actor_Set_Friendliness_To_Other(kActorMutant2, kActorMcCoy, 30);
+		} else {
+			Actor_Set_Combat_Aggressiveness(kActorMutant2, 40);
+			Actor_Set_Friendliness_To_Other(kActorMutant2, kActorMcCoy, 50);
+		}
+
+		// code repeated also in case 599 which precedes this one
+		// redundant? 
+		// results in additional reduction in friendliness and increase of aggressiveness for the other two mutants
+		Actor_Modify_Friendliness_To_Other(kActorMutant1, kActorMcCoy, -15);
+		Actor_Modify_Friendliness_To_Other(kActorMutant3, kActorMcCoy, -20);
+		Actor_Modify_Combat_Aggressiveness(kActorMutant1, 10);
+		Actor_Modify_Combat_Aggressiveness(kActorMutant3, 15);
+		Actor_Set_Goal_Number(kActorMutant2, 403);
+		return true;
+#endif // BLADERUNNER_ORIGINAL_BUGS
+
 	case 590:
 		AI_Movement_Track_Flush(kActorMutant2);
 		AI_Movement_Track_Append(kActorMutant2, 39, 100);
@@ -345,9 +382,10 @@ bool AIScriptMutant2::GoalChanged(int currentGoalNumber, int newGoalNumber) {
 
 	case 599:
 		AI_Movement_Track_Flush(kActorMutant2);
-		Actor_Change_Animation_Mode(kActorMutant2, 48);
+		Actor_Change_Animation_Mode(kActorMutant2, kAnimationModeDie);
+#if BLADERUNNER_ORIGINAL_BUGS
 		Actor_Set_Intelligence(kActorMutant2, 20);
-		Actor_Set_Health(71, 10 * Query_Difficulty_Level() + 50, 10 * Query_Difficulty_Level() + 50);
+		Actor_Set_Health(kActorMutant2, 10 * Query_Difficulty_Level() + 50, 10 * Query_Difficulty_Level() + 50);
 
 		if (Game_Flag_Query(kFlagCT04HomelessKilledByMcCoy)) {
 			Actor_Set_Combat_Aggressiveness(kActorMutant2, 60);
@@ -356,7 +394,8 @@ bool AIScriptMutant2::GoalChanged(int currentGoalNumber, int newGoalNumber) {
 			Actor_Set_Combat_Aggressiveness(kActorMutant2, 40);
 			Actor_Set_Friendliness_To_Other(kActorMutant2, kActorMcCoy, 50);
 		}
-
+#endif // BLADERUNNER_ORIGINAL_BUGS
+		// results in additional reduction in friendliness and increase of aggressiveness for the other two mutants
 		Actor_Modify_Friendliness_To_Other(kActorMutant1, kActorMcCoy, -15);
 		Actor_Modify_Friendliness_To_Other(kActorMutant3, kActorMcCoy, -20);
 		Actor_Modify_Combat_Aggressiveness(kActorMutant1, 10);
diff --git a/engines/bladerunner/script/ai/mutant3.cpp b/engines/bladerunner/script/ai/mutant3.cpp
index b7aca072ee..f435754172 100644
--- a/engines/bladerunner/script/ai/mutant3.cpp
+++ b/engines/bladerunner/script/ai/mutant3.cpp
@@ -71,7 +71,12 @@ bool AIScriptMutant3::Update() {
 
 		case 599:
 			if (Actor_Query_Which_Set_In(kActorMutant3) != Player_Query_Current_Set()) {
+#if BLADERUNNER_ORIGINAL_BUGS
 				Actor_Set_Goal_Number(kActorMutant3, 403);
+#else
+				// intermediate goal to set new Health (revive for reuse)
+				Actor_Set_Goal_Number(kActorMutant3, 411);
+#endif // BLADERUNNER_ORIGINAL_BUGS
 			}
 			break;
 		}
@@ -348,6 +353,38 @@ bool AIScriptMutant3::GoalChanged(int currentGoalNumber, int newGoalNumber) {
 		}
 		break;
 
+#if BLADERUNNER_ORIGINAL_BUGS
+#else
+	case 411:
+		// We need the additional intermediate goal 411 (as mutant1 has)
+		// so that we set the health here, instead of the when the goal is set to 599 (dying)
+		// Setting the health "revives" the mutant, which would result in their bound box being reduced to a point
+		// (see Actor::setHealth() call to retire(false, 0, 0, -1))
+		// and thus their corpse being unclickable after McCoy shot them.
+		// Goal 411 does this, but is set only when McCoy is no longer present in the scene/set.
+		AI_Movement_Track_Flush(kActorMutant3);
+		Actor_Set_Intelligence(kActorMutant3, 40);
+		Actor_Set_Health(kActorMutant3, 10 * Query_Difficulty_Level() + 50, 10 * Query_Difficulty_Level() + 50);
+
+		if (Game_Flag_Query(kFlagCT04HomelessKilledByMcCoy)) {
+			Actor_Set_Combat_Aggressiveness(kActorMutant3, 80);
+			Actor_Set_Friendliness_To_Other(kActorMutant3, kActorMcCoy, 20);
+		} else {
+			Actor_Set_Combat_Aggressiveness(kActorMutant3, 50);
+			Actor_Set_Friendliness_To_Other(kActorMutant3, kActorMcCoy, 40);
+		}
+
+		// code repeated also in case 599 which precedes this one
+		// redundant? 
+		// results in additional reduction in friendliness and increase of aggressiveness for the other two mutants
+		Actor_Modify_Friendliness_To_Other(kActorMutant1, kActorMcCoy, 20);
+		Actor_Modify_Friendliness_To_Other(kActorMutant2, kActorMcCoy, 15);
+		Actor_Modify_Combat_Aggressiveness(kActorMutant1, 10);
+		Actor_Modify_Combat_Aggressiveness(kActorMutant2, 10);
+		Actor_Set_Goal_Number(kActorMutant3, 403);
+		return true;
+#endif // BLADERUNNER_ORIGINAL_BUGS
+
 	case 590:
 		AI_Movement_Track_Flush(kActorMutant3);
 		AI_Movement_Track_Append(kActorMutant3, 39, 100);
@@ -356,7 +393,8 @@ bool AIScriptMutant3::GoalChanged(int currentGoalNumber, int newGoalNumber) {
 
 	case 599:
 		AI_Movement_Track_Flush(kActorMutant3);
-		Actor_Change_Animation_Mode(kActorMutant3, 48);
+		Actor_Change_Animation_Mode(kActorMutant3, kAnimationModeDie);
+#if BLADERUNNER_ORIGINAL_BUGS
 		Actor_Set_Intelligence(kActorMutant3, 40);
 		Actor_Set_Health(kActorMutant3, 10 * Query_Difficulty_Level() + 50, 10 * Query_Difficulty_Level() + 50);
 
@@ -367,7 +405,8 @@ bool AIScriptMutant3::GoalChanged(int currentGoalNumber, int newGoalNumber) {
 			Actor_Set_Combat_Aggressiveness(kActorMutant3, 50);
 			Actor_Set_Friendliness_To_Other(kActorMutant3, kActorMcCoy, 40);
 		}
-
+#endif // BLADERUNNER_ORIGINAL_BUGS
+		// results in additional reduction in friendliness and increase of aggressiveness for the other two mutants
 		Actor_Modify_Friendliness_To_Other(kActorMutant1, kActorMcCoy, 20);
 		Actor_Modify_Friendliness_To_Other(kActorMutant2, kActorMcCoy, 15);
 		Actor_Modify_Combat_Aggressiveness(kActorMutant1, 10);
diff --git a/engines/bladerunner/script/ai/officer_grayford.cpp b/engines/bladerunner/script/ai/officer_grayford.cpp
index c92790be78..5efcf6abaf 100644
--- a/engines/bladerunner/script/ai/officer_grayford.cpp
+++ b/engines/bladerunner/script/ai/officer_grayford.cpp
@@ -914,10 +914,22 @@ bool AIScriptOfficerGrayford::GoalChanged(int currentGoalNumber, int newGoalNumb
 		return true;
 
 	case kGoalOfficerGrayfordDead:
+#if BLADERUNNER_ORIGINAL_BUGS
 		_animationState = 32;
 		_animationFrame = Slice_Animation_Query_Number_Of_Frames(kModelAnimationOfficerGrayfordShotDead) - 1;
-		return true;
-
+#else
+		// The original code sets Grayford flat "dead" immediately when he is "retired"
+		// His full death animation will not play, only the last frame.
+		// This is useful for Act5, where he should lie dying down (underground railway UG05),
+		// but looks bad in Act4 if McCoy shoots a Grayford cop hunting him
+		if (Game_Flag_Query(kFlagHF07Hole)
+		    && Actor_Query_In_Set(kActorOfficerGrayford, kSetUG05)) {
+			_animationState = 32;
+			_animationFrame = Slice_Animation_Query_Number_Of_Frames(kModelAnimationOfficerGrayfordShotDead) - 1;
+			return true;
+		}
+		return false;
+#endif
 	}
 	return false;
 }
@@ -1549,6 +1561,7 @@ bool AIScriptOfficerGrayford::ChangeAnimationMode(int mode) {
 		break;
 
 	case kAnimationModeDie:
+#if BLADERUNNER_ORIGINAL_BUGS
 		switch (_animationState) {
 		case 0:
 			// fall through
@@ -1575,6 +1588,44 @@ bool AIScriptOfficerGrayford::ChangeAnimationMode(int mode) {
 			_animationFrame = 0;
 			break;
 		}
+#else
+		switch (_animationState) {
+		case 5:
+			// fall through
+		case 6:
+			// fall through
+		case 18:
+			// fall through
+		case 19:
+			// fall through
+		case 20:
+			// fall through
+		case 21:
+			// fall through
+		case 22:
+			// fall through
+		case 23:
+			// fall through
+		case 24:
+			// fall through
+		case 27:
+			// fall through
+		case 28:
+			// fall through
+		case 29:
+			// fall through
+		case 30:
+			// For all the states using combat animation (incl. holster/unholster gun)
+			_animationState = 31; // combat shot dead
+			_animationFrame = 0;
+			break;
+
+		default:
+			_animationState = 32; // shot dead
+			_animationFrame = 0;
+			break;
+		}
+#endif // BLADERUNNER_ORIGINAL_BUGS
 		break;
 
 	case 58:




More information about the Scummvm-git-logs mailing list