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

mduggan mgithub at guarana.org
Sat May 29 12:37:56 UTC 2021


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

Summary:
08ae7420c3 ULTIMA8: Fix Crusader new battery type order
b82669a7ad ULTIMA8: Don't destroy and recreate camera on map switch


Commit: 08ae7420c363583b2e6d58efa57d51c3bdeb2019
    https://github.com/scummvm/scummvm/commit/08ae7420c363583b2e6d58efa57d51c3bdeb2019
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2021-05-29T21:31:55+09:00

Commit Message:
ULTIMA8: Fix Crusader new battery type order

Changed paths:
    engines/ultima/ultima8/world/actors/main_actor.cpp


diff --git a/engines/ultima/ultima8/world/actors/main_actor.cpp b/engines/ultima/ultima8/world/actors/main_actor.cpp
index 05b9809b0f..6787cdb89f 100644
--- a/engines/ultima/ultima8/world/actors/main_actor.cpp
+++ b/engines/ultima/ultima8/world/actors/main_actor.cpp
@@ -233,14 +233,14 @@ int16 MainActor::addItemCru(Item *item, bool showtoast) {
 					plusenergy = 0x9c4;
 				}
 			} else if (shapeno == 0x3a4) {
-				if (oldbattery < FusionBattery) {
-					setBatteryType(FusionBattery);
+				if (oldbattery < FissionBattery) {
+					setBatteryType(FissionBattery);
 				} else {
 					plusenergy = 5000;
 				}
 			} else if (shapeno == 0x3a3) {
-				if (oldbattery < FissionBattery) {
-					setBatteryType(FissionBattery);
+				if (oldbattery < FusionBattery) {
+					setBatteryType(FusionBattery);
 				} else {
 					plusenergy = 10000;
 				}


Commit: b82669a7add46f95efc7bbed22650af7f81052dd
    https://github.com/scummvm/scummvm/commit/b82669a7add46f95efc7bbed22650af7f81052dd
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2021-05-29T21:31:55+09:00

Commit Message:
ULTIMA8: Don't destroy and recreate camera on map switch

This bug was a bit complex.

This change ensures that cacheIn events get called before enterFastArea.  In
Ultima 8 only a couple of classes have cacheIn events, so it makes no real
difference. In Crusader, this bug caused extra people in the rebel base because
they got the wrong mission number during enterFastArea (the mission number is
updated in a cacheIn event).

The previous map switch code was re-making the CameraProcess as needed, but
after the cacheIn usecode processes were created - so the new camera went to
the front of the process queue.  The first execution of the camera process then
updates the fast area, and enterFastArea processes get added to the front of
the queue again (in front of the cacheIn events).  Switch to only updating the
existing camera process where possible instead of creating a new one, so the
execution order does not change.

Changed paths:
    engines/ultima/ultima8/gumps/game_map_gump.cpp
    engines/ultima/ultima8/world/actors/main_actor.cpp
    engines/ultima/ultima8/world/camera_process.cpp
    engines/ultima/ultima8/world/camera_process.h
    engines/ultima/ultima8/world/item.cpp
    engines/ultima/ultima8/world/world.cpp


diff --git a/engines/ultima/ultima8/gumps/game_map_gump.cpp b/engines/ultima/ultima8/gumps/game_map_gump.cpp
index 7f5d604ac7..eeb937bde5 100644
--- a/engines/ultima/ultima8/gumps/game_map_gump.cpp
+++ b/engines/ultima/ultima8/gumps/game_map_gump.cpp
@@ -100,7 +100,7 @@ void GameMapGump::PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled)
 		av->getFootpadWorld(axd, ayd, azd);
 		map->isValidPosition(ax, ay, az, 32, 32, 8, 0, 1, 0, &roofid);
 	} else
-		roofid = camera->FindRoof(lerp_factor);
+		roofid = camera->findRoof(lerp_factor);
 
 	const Item *roof = getItem(roofid);
 	if (roof) {
diff --git a/engines/ultima/ultima8/world/actors/main_actor.cpp b/engines/ultima/ultima8/world/actors/main_actor.cpp
index 6787cdb89f..caae02630a 100644
--- a/engines/ultima/ultima8/world/actors/main_actor.cpp
+++ b/engines/ultima/ultima8/world/actors/main_actor.cpp
@@ -352,6 +352,8 @@ const ShapeInfo *MainActor::getShapeInfoFromGameInstance() const {
 void MainActor::teleport(int mapNum, int32 x, int32 y, int32 z) {
 	World *world = World::get_instance();
 
+	uint16 oldmap = getMapNum();
+
 	// (attempt to) load the new map
 	if (!world->switchMap(mapNum)) {
 		perr << "MainActor::teleport(): switchMap(" << mapNum << ") failed!" << Std::endl;
@@ -360,9 +362,9 @@ void MainActor::teleport(int mapNum, int32 x, int32 y, int32 z) {
 
 	Actor::teleport(mapNum, x, y, z);
 
-	if (GAME_IS_CRUSADER && (x || y)) {
+	if (GAME_IS_CRUSADER && (x || y) && oldmap == mapNum) {
 		// Keep the camera on the avatar (the snap process will update on next move)
-		CameraProcess::SetCameraProcess(new CameraProcess(x, y, z));
+		CameraProcess::GetCameraProcess()->moveToLocation(x, y, z);
 	}
 
 	_justTeleported = true;
@@ -405,13 +407,15 @@ void MainActor::teleport(int mapNum, int teleport_id) {
 	pout << "Found destination: " << xv << "," << yv << "," << zv << Std::endl;
 	egg->dumpInfo();
 
-	Actor::teleport(mapNum, xv, yv, zv);
-
 	if (GAME_IS_CRUSADER) {
 		// Keep the camera on the avatar (the snap process will update on next move)
-		CameraProcess::SetCameraProcess(new CameraProcess(xv, yv, zv));
+		// We don't add a new camera process here, as that would update the fast area
+		// before the cachein calls above have run.
+		CameraProcess::GetCameraProcess()->moveToLocation(xv, yv, zv);
 	}
 
+	Actor::teleport(mapNum, xv, yv, zv);
+
 	_justTeleported = true;
 }
 
diff --git a/engines/ultima/ultima8/world/camera_process.cpp b/engines/ultima/ultima8/world/camera_process.cpp
index 44221fc0fb..f03af7820c 100644
--- a/engines/ultima/ultima8/world/camera_process.cpp
+++ b/engines/ultima/ultima8/world/camera_process.cpp
@@ -63,6 +63,20 @@ void CameraProcess::ResetCameraProcess() {
 	_camera = nullptr;
 }
 
+void CameraProcess::moveToLocation(int32 x, int32 y, int32 z) {
+	if (_itemNum) {
+		Item *item = getItem(_itemNum);
+		if (item) item->clearExtFlag(Item::EXT_CAMERA);
+	}
+
+	_sx = _sy = _sz = _time = _elapsed = _lastFrameNum = _itemNum = 0;
+	_eqX = _eqY = _earthquake = 0;
+	_ex = x;
+	_ey = y;
+	_ez = z;
+	GetCameraLocation(_sx, _sy, _sz);
+}
+
 void CameraProcess::GetCameraLocation(int32 &x, int32 &y, int32 &z) {
 	if (!_camera) {
 		World *world = World::get_instance();
@@ -157,7 +171,7 @@ void CameraProcess::run() {
 	_elapsed++;
 }
 
-void CameraProcess::ItemMoved() {
+void CameraProcess::itemMoved() {
 	if (!_itemNum)
 		return;
 
@@ -260,7 +274,7 @@ void CameraProcess::GetLerped(int32 &x, int32 &y, int32 &z, int32 factor, bool n
 	}
 }
 
-uint16 CameraProcess::FindRoof(int32 factor) {
+uint16 CameraProcess::findRoof(int32 factor) {
 	int32 x, y, z;
 	int32 earthquake_old = _earthquake;
 	_earthquake = 0;
diff --git a/engines/ultima/ultima8/world/camera_process.h b/engines/ultima/ultima8/world/camera_process.h
index f6433baf35..b84963ef01 100644
--- a/engines/ultima/ultima8/world/camera_process.h
+++ b/engines/ultima/ultima8/world/camera_process.h
@@ -57,7 +57,16 @@ public:
 	//! Find the roof above the camera.
 	//! \param factor Interpolation factor for this frame
 	//! \return 0 if no roof found, objid of roof if found
-	uint16 FindRoof(int32 factor);
+	uint16 findRoof(int32 factor);
+
+	/**
+	 * Move the existing camera process to a new location.  If the current process is focused on
+	 * an item, remove that focus.
+	 *
+	 * This is not the same as setting a new process, because execution order will not change,
+	 * so other pending events will all happen before the fast area is updated
+	 */
+	void moveToLocation(int32 x, int32 y, int32 z);
 
 	INTRINSIC(I_setCenterOn);
 	INTRINSIC(I_moveTo);
@@ -72,7 +81,13 @@ public:
 	static CameraProcess   *GetCameraProcess() {
 		return _camera;
 	}
-	static uint16           SetCameraProcess(CameraProcess *);  // Set the current camera process. Adds process. Return PID
+
+	/**
+	 * Set the current camera process. Adds process and returns PID.
+	 * The new process will go on the front of the process queue, so the fast area
+	 * will be updated before any other pending actions occur.
+	 */
+	static uint16           SetCameraProcess(CameraProcess *);
 	static void             ResetCameraProcess();
 
 	static void             SetEarthquake(int32 e) {
@@ -80,7 +95,8 @@ public:
 		if (!e)  _eqX = _eqY = 0;
 	}
 
-	void                    ItemMoved();
+	/** Notify the Camera that the target item has moved */
+	void itemMoved();
 
 	void terminate() override;   // Terminate NOW!
 
diff --git a/engines/ultima/ultima8/world/item.cpp b/engines/ultima/ultima8/world/item.cpp
index 6ee684d337..d390b1bbbf 100644
--- a/engines/ultima/ultima8/world/item.cpp
+++ b/engines/ultima/ultima8/world/item.cpp
@@ -232,7 +232,7 @@ void Item::move(int32 X, int32 Y, int32 Z) {
 	if (!dest_fast && (_flags & Item::FLG_FASTAREA)) {
 		_extendedFlags |= EXT_LERP_NOPREV;
 		if (_extendedFlags & EXT_CAMERA)
-			CameraProcess::GetCameraProcess()->ItemMoved();
+			CameraProcess::GetCameraProcess()->itemMoved();
 		else
 			leaveFastArea();
 
@@ -247,7 +247,7 @@ void Item::move(int32 X, int32 Y, int32 Z) {
 	// If we are being followed, notify the camera that we moved
 	// Note that we don't need to
 	if (_extendedFlags & EXT_CAMERA)
-		CameraProcess::GetCameraProcess()->ItemMoved();
+		CameraProcess::GetCameraProcess()->itemMoved();
 
 	if (_extendedFlags & EXT_TARGET)
 		TargetReticleProcess::get_instance()->itemMoved(this);
diff --git a/engines/ultima/ultima8/world/world.cpp b/engines/ultima/ultima8/world/world.cpp
index 28e524ecbb..142325f845 100644
--- a/engines/ultima/ultima8/world/world.cpp
+++ b/engines/ultima/ultima8/world/world.cpp
@@ -110,10 +110,9 @@ bool World::switchMap(uint32 newmap) {
 
 	// Map switching procedure:
 
-	// get rid of camera
 	// stop all sound effects (except speech, such as Guardian barks)
 	// notify all gumps of a map change
-	// delete any _ethereal objects
+	// delete any ethereal objects
 	// write back CurrentMap to the old map, which
 	//   deletes all disposable items
 	//   deletes the EggHatcher
@@ -126,11 +125,7 @@ bool World::switchMap(uint32 newmap) {
 	//   assigns objIDs to nonfixed items
 	//   creates an EggHatcher and notifies it of all eggs
 	//   sets up all NPCs in the new map
-	// reset camera
-
-
-	// kill camera
-	CameraProcess::ResetCameraProcess();
+	// update camera if needed
 
 	AudioProcess *ap = AudioProcess::get_instance();
 	if (ap) ap->stopAllExceptSpeech();
@@ -174,9 +169,16 @@ bool World::switchMap(uint32 newmap) {
 
 	_currentMap->loadMap(_maps[newmap]);
 
-	// reset camera
-	CameraProcess::SetCameraProcess(new CameraProcess(1));
-	CameraProcess::SetEarthquake(0);
+	// update camera if needed (u8 only)
+	// TODO: This may not even be needed, but do it just in case the
+	// camera was looking at something else during teleport.
+	if (GAME_IS_U8) {
+		CameraProcess *camera = CameraProcess::GetCameraProcess();
+		if (camera && camera->getItemNum() != 1) {
+			CameraProcess::SetCameraProcess(new CameraProcess(1));
+		}
+		CameraProcess::SetEarthquake(0);
+	}
 
 	return true;
 }




More information about the Scummvm-git-logs mailing list