[Scummvm-git-logs] scummvm branch-2-6 -> 4ffd401945dcac9b4449402bd35eec2a19ccd63b

mduggan noreply at scummvm.org
Sun Jun 26 07:04:52 UTC 2022


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:
4ffd401945 ULTIMA8: Terminate more processes on Crusader level change


Commit: 4ffd401945dcac9b4449402bd35eec2a19ccd63b
    https://github.com/scummvm/scummvm/commit/4ffd401945dcac9b4449402bd35eec2a19ccd63b
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2022-06-26T16:02:31+09:00

Commit Message:
ULTIMA8: Terminate more processes on Crusader level change

Previously we used the Ultima 8 behavior of not terminating any obj id 0
processes on level change, but that occasionally left never ending "alarm has
been activated" background audio and similar problems.

This changes so that all but the "persistent" processes are terminated.

At the same time, also correctly clean up the snap egg and target lists when
changing maps - previously these were left sitting around.

Changed paths:
    engines/ultima/ultima8/graphics/cycle_process.cpp
    engines/ultima/ultima8/kernel/kernel.cpp
    engines/ultima/ultima8/kernel/kernel.h
    engines/ultima/ultima8/world/crosshair_process.cpp
    engines/ultima/ultima8/world/current_map.cpp
    engines/ultima/ultima8/world/item_selection_process.cpp
    engines/ultima/ultima8/world/snap_process.cpp
    engines/ultima/ultima8/world/snap_process.h
    engines/ultima/ultima8/world/target_reticle_process.cpp
    engines/ultima/ultima8/world/world.cpp


diff --git a/engines/ultima/ultima8/graphics/cycle_process.cpp b/engines/ultima/ultima8/graphics/cycle_process.cpp
index e3d01fa10ad..e3e4a828532 100644
--- a/engines/ultima/ultima8/graphics/cycle_process.cpp
+++ b/engines/ultima/ultima8/graphics/cycle_process.cpp
@@ -134,6 +134,8 @@ bool CycleProcess::loadData(Common::ReadStream *rs, uint32 version) {
 
 	_running = rs->readByte();
 	_instance = this; //static
+
+	_type = 1; // should be persistant but older savegames may not know that.
 	return true;
 }
 
diff --git a/engines/ultima/ultima8/kernel/kernel.cpp b/engines/ultima/ultima8/kernel/kernel.cpp
index 51da4447063..16930c87895 100644
--- a/engines/ultima/ultima8/kernel/kernel.cpp
+++ b/engines/ultima/ultima8/kernel/kernel.cpp
@@ -323,6 +323,8 @@ void Kernel::killProcessesNotOfType(ObjId objid, uint16 processtype, bool fail)
 	for (ProcessIterator it = _processes.begin(); it != _processes.end(); ++it) {
 		Process *p = *it;
 
+		// * If objid is 0, terminate procs for all objects.
+		// * Never terminate procs with objid 0
 		if (p->_itemNum != 0 && (objid == 0 || objid == p->_itemNum) &&
 		        (p->_type != processtype) &&
 		        !(p->_flags & Process::PROC_TERMINATED) &&
@@ -335,6 +337,26 @@ void Kernel::killProcessesNotOfType(ObjId objid, uint16 processtype, bool fail)
 	}
 }
 
+void Kernel::killAllProcessesNotOfTypeExcludeCurrent(uint16 processtype, bool fail) {
+	for (ProcessIterator it = _processes.begin(); it != _processes.end(); ++it) {
+		Process *p = *it;
+
+		// Don't kill the running process
+		if (p == _runningProcess)
+			continue;
+
+		if ((p->_type != processtype) &&
+				!(p->_flags & Process::PROC_TERMINATED) &&
+				!(p->_flags & Process::PROC_TERM_DEFERRED)) {
+			if (fail)
+				p->fail();
+			else
+				p->terminate();
+		}
+	}
+}
+
+
 void Kernel::save(Common::WriteStream *ws) {
 	ws->writeUint32LE(_tickNum);
 	_pIDs->save(ws);
diff --git a/engines/ultima/ultima8/kernel/kernel.h b/engines/ultima/ultima8/kernel/kernel.h
index e6a9315b11b..c2f384cda6a 100644
--- a/engines/ultima/ultima8/kernel/kernel.h
+++ b/engines/ultima/ultima8/kernel/kernel.h
@@ -83,6 +83,12 @@ public:
 	//! \param fail if true, fail the processes instead of terminating them
 	void killProcessesNotOfType(ObjId objid, uint16 processtype, bool fail);
 
+	//! kill (fail) processes not of a certain type, regardless of object ID
+	//! except for the current running process (for switching levels in Crusader)
+	//! \param type the type not to kill
+	//! \param fail if true, fail the processes instead of terminating them
+	void killAllProcessesNotOfTypeExcludeCurrent(uint16 processtype, bool fail);
+
 	//! get an iterator of the process list.
 	ProcessIter getProcessBeginIterator() {
 		return _processes.begin();
diff --git a/engines/ultima/ultima8/world/crosshair_process.cpp b/engines/ultima/ultima8/world/crosshair_process.cpp
index 97c562139ea..a101626b6f6 100644
--- a/engines/ultima/ultima8/world/crosshair_process.cpp
+++ b/engines/ultima/ultima8/world/crosshair_process.cpp
@@ -108,7 +108,9 @@ void CrosshairProcess::saveData(Common::WriteStream *ws) {
 }
 
 bool CrosshairProcess::loadData(Common::ReadStream *rs, uint32 version) {
-	return Process::loadData(rs, version);
+	if (!Process::loadData(rs, version)) return false;
+	_type = 1; // should be persistant but older savegames may not know that.
+	return true;
 }
 
 } // End of namespace Ultima8
diff --git a/engines/ultima/ultima8/world/current_map.cpp b/engines/ultima/ultima8/world/current_map.cpp
index 82fe1f38b26..09b49011810 100644
--- a/engines/ultima/ultima8/world/current_map.cpp
+++ b/engines/ultima/ultima8/world/current_map.cpp
@@ -194,6 +194,11 @@ void CurrentMap::loadMap(Map *map) {
 	_fastXMax = -1;
 	_fastYMax = -1;
 
+	// Clear target items
+	for (unsigned int i = 0; i < MAP_NUM_TARGET_ITEMS; i++) {
+		_targets[i] = 0;
+	}
+
 	loadItems(map->_fixedItems, callCacheIn);
 	loadItems(map->_dynamicItems, callCacheIn);
 
@@ -1378,11 +1383,16 @@ uint32 CurrentMap::I_canExistAt(const uint8 *args, unsigned int argsize) {
 }
 
 uint32 CurrentMap::I_canExistAtPoint(const uint8 *args, unsigned int /*argsize*/) {
-	ARG_NULL16(); // unknown
-	ARG_NULL16(); // unknown
+	ARG_ITEM_FROM_PTR(other);
 	ARG_UINT16(shape);
 	ARG_WORLDPOINT(pt);
 
+	if (other) {
+		debug("I_canExistAtPoint other object: ");
+		other->dumpInfo();
+	} else {
+		debug("I_canExistAtPoint other object null.");
+	}
 	if (shape > 0x800)
 		return 0;
 
diff --git a/engines/ultima/ultima8/world/item_selection_process.cpp b/engines/ultima/ultima8/world/item_selection_process.cpp
index fa6648c5b51..4969b2fdc53 100644
--- a/engines/ultima/ultima8/world/item_selection_process.cpp
+++ b/engines/ultima/ultima8/world/item_selection_process.cpp
@@ -220,6 +220,7 @@ bool ItemSelectionProcess::loadData(Common::ReadStream *rs, uint32 version) {
 	_ax = rs->readSint32LE();
 	_ay = rs->readSint32LE();
 	_az = rs->readSint32LE();
+	_type = 1; // should be persistant but older savegames may not know that.
 	return true;
 }
 
diff --git a/engines/ultima/ultima8/world/snap_process.cpp b/engines/ultima/ultima8/world/snap_process.cpp
index cd1fc0232cd..697ae6fbab8 100644
--- a/engines/ultima/ultima8/world/snap_process.cpp
+++ b/engines/ultima/ultima8/world/snap_process.cpp
@@ -128,6 +128,13 @@ void SnapProcess::removeEgg(Item *item) {
 	}
 }
 
+void SnapProcess::clearEggs() {
+	_snapEggs.clear();
+	_currentSnapEgg = 0;
+	_currentSnapEggRange = Rect();
+}
+
+
 bool SnapProcess::isNpcInRangeOfCurrentEgg() const {
 	if (!_currentSnapEgg)
 		return false;
@@ -191,6 +198,8 @@ bool SnapProcess::loadData(Common::ReadStream *rs, uint32 version) {
 		_snapEggs.push_back(rs->readUint16LE());
 	}
 
+	_type = 1; // should be persistant but older savegames may not know that.
+
 	return true;
 }
 
diff --git a/engines/ultima/ultima8/world/snap_process.h b/engines/ultima/ultima8/world/snap_process.h
index cf13cb1251f..6b44fc4116b 100644
--- a/engines/ultima/ultima8/world/snap_process.h
+++ b/engines/ultima/ultima8/world/snap_process.h
@@ -44,6 +44,7 @@ public:
 
 	void addEgg(Item *item);
 	void removeEgg(Item *item);
+	void clearEggs();
 
 	static SnapProcess *get_instance();
 
diff --git a/engines/ultima/ultima8/world/target_reticle_process.cpp b/engines/ultima/ultima8/world/target_reticle_process.cpp
index 48fa5e4a7e5..a1de56cc530 100644
--- a/engines/ultima/ultima8/world/target_reticle_process.cpp
+++ b/engines/ultima/ultima8/world/target_reticle_process.cpp
@@ -238,6 +238,8 @@ bool TargetReticleProcess::loadData(Common::ReadStream *rs, uint32 version) {
 	if (GAME_IS_REGRET)
 		_reticleStyle = rs->readUint16LE();
 
+	_type = 1; // should be persistant but older savegames may not know that.
+
 	return true;
 }
 
diff --git a/engines/ultima/ultima8/world/world.cpp b/engines/ultima/ultima8/world/world.cpp
index d1d90c0f220..432c5556fc3 100644
--- a/engines/ultima/ultima8/world/world.cpp
+++ b/engines/ultima/ultima8/world/world.cpp
@@ -27,6 +27,7 @@
 #include "ultima/ultima8/filesys/raw_archive.h"
 #include "ultima/ultima8/world/item_factory.h"
 #include "ultima/ultima8/world/actors/main_actor.h"
+#include "ultima/ultima8/world/actors/scheduler_process.h"
 #include "ultima/ultima8/world/loop_script.h"
 #include "ultima/ultima8/usecode/uc_list.h"
 #include "ultima/ultima8/misc/direction_util.h"
@@ -167,8 +168,17 @@ bool World::switchMap(uint32 newmap) {
 		_maps[oldmap]->unloadFixed();
 	}
 
-	// Kill any processes that need killing (those with type != 1 && item != 0)
-	Kernel::get_instance()->killProcessesNotOfType(0, 1, true);
+	// Kill any processes that need killing
+	if (GAME_IS_U8) {
+		// U8 doesn't kill processes of object 0 *or* type 1 when changing map.
+		Kernel::get_instance()->killProcessesNotOfType(0, 1, true);
+	} else {
+		// Crusader kills processes even for object 0 when switching.
+		SnapProcess::get_instance()->clearEggs();
+		CameraProcess::ResetCameraProcess();
+		Kernel::get_instance()->killAllProcessesNotOfTypeExcludeCurrent(1, true);
+		Kernel::get_instance()->addProcess(new SchedulerProcess());
+	}
 
 	pout << "Loading Fixed items in map " << newmap << Std::endl;
 	Common::SeekableReadStream *items = GameData::get_instance()->getFixed()
@@ -178,15 +188,19 @@ bool World::switchMap(uint32 newmap) {
 
 	_currentMap->loadMap(_maps[newmap]);
 
-	// 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.
+	// Update camera
 	if (GAME_IS_U8) {
+		// TODO: This may not even be needed for U8, but reset in case camera
+		// was looking at something other than the avatar during teleport.
 		CameraProcess *camera = CameraProcess::GetCameraProcess();
 		if (camera && camera->getItemNum() != 1) {
 			CameraProcess::SetCameraProcess(new CameraProcess(1));
 		}
 		CameraProcess::SetEarthquake(0);
+	} else {
+		// In Crusader, snap the camera to the avatar.  The snap process will
+		// then find the right snap egg in the next frame.
+		CameraProcess::SetCameraProcess(new CameraProcess(1));
 	}
 
 	return true;




More information about the Scummvm-git-logs mailing list