[Scummvm-git-logs] scummvm master -> 5cf57339c152171e28df0b0da68764b7aaabcf1f

mduggan noreply at scummvm.org
Thu Dec 30 08:51:33 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:
31a2797e42 ULTIMA8: Ensure escape closes videos correctly
b036b127fe ULTIMA8: Implement No Regret specific intrinsic I_setVolumeForObjectSFX
5cf57339c1 ULTIMA8: Add No Regret sounds in SurrenderProcess


Commit: 31a2797e426338b1bbc135eb6a1395d902d76ef0
    https://github.com/scummvm/scummvm/commit/31a2797e426338b1bbc135eb6a1395d902d76ef0
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2021-12-30T17:11:04+09:00

Commit Message:
ULTIMA8: Ensure escape closes videos correctly

There are some rare cases where modals can stack (eg, credits playing on top of
menu).  In this case we want to close the credits first, then the menu.

Add a little hack to ensure the order is right.

This also fixes #12995.

Changed paths:
    engines/ultima/ultima8/misc/debugger.cpp
    engines/ultima/ultima8/ultima8.cpp


diff --git a/engines/ultima/ultima8/misc/debugger.cpp b/engines/ultima/ultima8/misc/debugger.cpp
index 967dddee21a..5eca7d1e712 100644
--- a/engines/ultima/ultima8/misc/debugger.cpp
+++ b/engines/ultima/ultima8/misc/debugger.cpp
@@ -1862,6 +1862,12 @@ bool Debugger::cmdShowMenu(int argc, const char **argv) {
 		debugPrintf("Not opening menu: cruStasis\n");
 		return false;
 	}
+	Gump *gump = Ultima8Engine::get_instance()->getDesktopGump()->FindGump<ModalGump>();
+	if (gump) {
+		// ensure any modal gump gets the message to close before we open the menu.
+		gump->Close();
+		return false;
+	}
 	MenuGump::showMenu();
 	return false;
 }
diff --git a/engines/ultima/ultima8/ultima8.cpp b/engines/ultima/ultima8/ultima8.cpp
index 83e39478b78..45a44773a0f 100644
--- a/engines/ultima/ultima8/ultima8.cpp
+++ b/engines/ultima/ultima8/ultima8.cpp
@@ -726,17 +726,21 @@ void Ultima8Engine::changeVideoMode(int width, int height) {
 }
 
 void Ultima8Engine::handleEvent(const Common::Event &event) {
-	Gump *gump = _desktopGump->FindGump<ModalGump>();
-	if (gump) {
+	// Handle the fact that we can get 2 modals stacking.
+	// We want the focussed one preferrably.
+	Gump *modal = dynamic_cast<ModalGump *>(_desktopGump->GetFocusChild());
+	if (!modal)
+		modal = _desktopGump->FindGump<ModalGump>();
+	if (modal) {
 		_avatarMoverProcess->resetMovementFlags();
 	}
 
 	Common::Keymapper *const keymapper = _eventMan->getKeymapper();
-	keymapper->setEnabledKeymapType(gump ? Common::Keymap::kKeymapTypeGui : Common::Keymap::kKeymapTypeGame);
+	keymapper->setEnabledKeymapType(modal ? Common::Keymap::kKeymapTypeGui : Common::Keymap::kKeymapTypeGame);
 
 	switch (event.type) {
 	case Common::EVENT_KEYDOWN:
-		if (gump) {
+		if (modal) {
 			// Paste from Clip-Board on Ctrl-V - Note this should be a flag of some sort
 			if (event.kbd.keycode == Common::KEYCODE_v && (event.kbd.flags & Common::KBD_CTRL)) {
 				if (!g_system->hasTextInClipboard())
@@ -746,7 +750,7 @@ void Ultima8Engine::handleEvent(const Common::Event &event) {
 
 				// Only read the first line of text
 				while (!text.empty() && text.firstChar() >= ' ')
-					gump->OnTextInput(text.firstChar());
+					modal->OnTextInput(text.firstChar());
 
 				return;
 			}
@@ -755,15 +759,15 @@ void Ultima8Engine::handleEvent(const Common::Event &event) {
 				event.kbd.ascii <= 255 &&
 				!(event.kbd.ascii >= 0x7F && // control chars
 					event.kbd.ascii <= 0x9F)) {
-				gump->OnTextInput(event.kbd.ascii);
+				modal->OnTextInput(event.kbd.ascii);
 			}
 
-			gump->OnKeyDown(event.kbd.keycode, event.kbd.flags);
+			modal->OnKeyDown(event.kbd.keycode, event.kbd.flags);
 		}
 		break;
 	case Common::EVENT_KEYUP:
-		if (gump) {
-			gump->OnKeyUp(event.kbd.keycode);
+		if (modal) {
+			modal->OnKeyUp(event.kbd.keycode);
 		}
 		break;
 


Commit: b036b127fe6778b6c98477f28c3cfe446b3cca59
    https://github.com/scummvm/scummvm/commit/b036b127fe6778b6c98477f28c3cfe446b3cca59
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2021-12-30T17:11:32+09:00

Commit Message:
ULTIMA8: Implement No Regret specific intrinsic I_setVolumeForObjectSFX

Changed paths:
    engines/ultima/ultima8/audio/audio_process.cpp
    engines/ultima/ultima8/audio/audio_process.h
    engines/ultima/ultima8/usecode/regret_intrinsics.h


diff --git a/engines/ultima/ultima8/audio/audio_process.cpp b/engines/ultima/ultima8/audio/audio_process.cpp
index 6325eef0b11..2dc7e6244f1 100644
--- a/engines/ultima/ultima8/audio/audio_process.cpp
+++ b/engines/ultima/ultima8/audio/audio_process.cpp
@@ -339,6 +339,23 @@ void AudioProcess::setVolumeSFX(int sfxNum, uint8 volume) {
 	}
 }
 
+void AudioProcess::setVolumeForObjectSFX(ObjId objId, int sfxNum, uint8 volume) {
+	AudioMixer *mixer = AudioMixer::get_instance();
+
+	Std::list<SampleInfo>::iterator it;
+	for (it = _sampleInfo.begin(); it != _sampleInfo.end(); ++it) {
+		if (it->_sfxNum == sfxNum && it->_sfxNum != -1 && objId == it->_objId) {
+			it->_volume = volume;
+
+			int lVol = 256, _rVol = 256;
+			// TODO: does the original recalculate relative volume or just set abosolute?
+			calculateSoundVolume(it->_objId, it->_lVol, it->_rVol);
+			mixer->setVolume(it->_channel, (lVol * it->_volume) / 256, (_rVol * it->_volume) / 256);
+		}
+	}
+}
+
+
 //
 // Speech
 //
@@ -596,6 +613,25 @@ uint32 AudioProcess::I_setVolumeSFX(const uint8 *args, unsigned int /*argsize*/)
 	return 0;
 }
 
+uint32 AudioProcess::I_setVolumeForObjectSFX(const uint8 *args, unsigned int /*argsize*/) {
+	// Sets volume for last played instances of sfxNum on object
+	ARG_ITEM_FROM_PTR(item);
+	ARG_SINT16(sfxNum);
+	ARG_UINT8(volume);
+
+	if (!item) {
+		warning("I_setVolumeForObjectSFX: Couldn't get item");
+	} else {
+		AudioProcess *ap = AudioProcess::get_instance();
+		if (ap)
+			ap->setVolumeForObjectSFX(item->getObjId(), sfxNum, volume);
+		else
+			warning("I_setVolumeForObjectSFX: No AudioProcess");
+	}
+
+	return 0;
+}
+
 uint32 AudioProcess::I_stopSFX(const uint8 *args, unsigned int argsize) {
 	ARG_SINT16(sfxNum);
 
diff --git a/engines/ultima/ultima8/audio/audio_process.h b/engines/ultima/ultima8/audio/audio_process.h
index 7eb52c15067..56c7dc6e7cc 100644
--- a/engines/ultima/ultima8/audio/audio_process.h
+++ b/engines/ultima/ultima8/audio/audio_process.h
@@ -83,6 +83,7 @@ public:
 	INTRINSIC(I_isSFXPlaying);
 	INTRINSIC(I_isSFXPlayingForObject);
 	INTRINSIC(I_setVolumeSFX);
+	INTRINSIC(I_setVolumeForObjectSFX);
 	INTRINSIC(I_stopSFX);
 	INTRINSIC(I_stopSFXCru);
 	INTRINSIC(I_stopAllSFX);
@@ -105,6 +106,7 @@ public:
 	bool isSFXPlaying(int sfxNum);
 	bool isSFXPlayingForObject(int sfxNum, ObjId objId);
 	void setVolumeSFX(int sfxNum, uint8 volume);
+	void setVolumeForObjectSFX(ObjId objId, int sfxNum, uint8 volume);
 
 	bool playSpeech(const Std::string &barked, int shapenum, ObjId objId,
 					uint32 pitchShift = PITCH_SHIFT_NONE, uint16 volume = 255);
diff --git a/engines/ultima/ultima8/usecode/regret_intrinsics.h b/engines/ultima/ultima8/usecode/regret_intrinsics.h
index 6e632a68ab9..a6ff4fdbc2c 100644
--- a/engines/ultima/ultima8/usecode/regret_intrinsics.h
+++ b/engines/ultima/ultima8/usecode/regret_intrinsics.h
@@ -85,7 +85,7 @@ Intrinsic RegretIntrinsics[] = {
 	MainActor::I_getMana, // Intrinsic030()
 	Item::I_getFamily, // Intrinsic031()
 	Actor::I_destroyContents, // Intrinsic032()
-	0, // Intrinsic033() AudioProcess::I_setVolumeForItemSFX
+	AudioProcess::I_setVolumeForObjectSFX, // Intrinsic033()
 	Item::I_getDirToItem, // Intrinsic034()
 	AudioProcess::I_isSFXPlayingForObject, // Intrinsic035()
 	Item::I_getRangeIfVisible, // Intrinsic036()
@@ -389,7 +389,7 @@ Intrinsic RegretIntrinsics[] = {
 	Egg::I_getEggXRange, // Intrinsic14F()
 	// 0150
 	Actor::I_clrInCombat, // Intrinsic150()
-	PaletteFaderProcess::I_jumpToAllGivenColor, // Intrinsic151() PaletteFaderProcess::I_jumpToColor
+	PaletteFaderProcess::I_jumpToAllGivenColor, // Intrinsic151()
 	Item::I_setFrame, // Intrinsic152()
 	UCMachine::I_numToStr, // Intrinsic153()
 	Actor::I_getDir, // Intrinsic154()
@@ -465,7 +465,7 @@ Intrinsic RegretDemoIntrinsics[] = {
 	MainActor::I_getMana,           // Intrinsic030 10f8:3b4a
 	Item::I_getFamily,              // Intrinsic031 10b0:1036
 	Actor::I_destroyContents,       // Intrinsic032 10b0:14f3
-	0, // AudioProcess::I_setVolumeForItemSFX, // Intrinsic033 10b0:3a33
+	AudioProcess::I_setVolumeForObjectSFX, // Intrinsic033 10b0:3a33
 	Item::I_getDirToItem,           // Intrinsic034 10b0:1ab8
 	AudioProcess::I_isSFXPlayingForObject, // Intrinsic035 10b0:3a0b
 	Item::I_touch,                  // Intrinsic036 10b0:2558
@@ -839,7 +839,7 @@ Intrinsic RegretDeIntrinsics[] = {
 	MainActor::I_getMana,           // Intrinsic030 10f8:3b4a
 	Item::I_getFamily,              // Intrinsic031 10b0:1036
 	Actor::I_destroyContents,       // Intrinsic032 10b0:14f3
-	0, // AudioProcess::I_setVolumeForItemSFX,  // Intrinsic033 10b0:3a33
+	AudioProcess::I_setVolumeForObjectSFX,  // Intrinsic033 10b0:3a33
 	Item::I_getDirToItem,           // Intrinsic034 10b0:1ab8
 	AudioProcess::I_isSFXPlayingForObject, // Intrinsic035 10b0:3a0b
 	Item::I_getRangeIfVisible,      // Intrinsic036 1140:258e


Commit: 5cf57339c152171e28df0b0da68764b7aaabcf1f
    https://github.com/scummvm/scummvm/commit/5cf57339c152171e28df0b0da68764b7aaabcf1f
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2021-12-30T17:15:50+09:00

Commit Message:
ULTIMA8: Add No Regret sounds in SurrenderProcess

This also fixes the fact that attack sounds in both Crusader games were never
repeated because the timing check was reversed.

Changed paths:
    engines/ultima/ultima8/world/actors/attack_process.cpp
    engines/ultima/ultima8/world/actors/attack_process.h
    engines/ultima/ultima8/world/actors/surrender_process.cpp
    engines/ultima/ultima8/world/actors/surrender_process.h


diff --git a/engines/ultima/ultima8/world/actors/attack_process.cpp b/engines/ultima/ultima8/world/actors/attack_process.cpp
index 13db6140fc0..f707663c302 100644
--- a/engines/ultima/ultima8/world/actors/attack_process.cpp
+++ b/engines/ultima/ultima8/world/actors/attack_process.cpp
@@ -90,10 +90,15 @@ _tacticDatReadStream(nullptr), _tacticDatStartOffset(0), _soundNo(-1), _playedSt
 _npcInitialDir(dir_invalid), _field57(0), _field59(0), _field7f(false), _field96(false), _field97(false),
 _isActivity9orB(false), _isActivityAorB(false), _timer3set(false), _timer2set(false),
 _doubleDelay(false), _wpnField8(1), _wpnBasedTimeout(0), _difficultyBasedTimeout(0), _timer2(0),
-_timer3(0), _timer4(0), _timer5(0), _soundTimestamp(0), _fireTimestamp(0) {
+_timer3(0), _timer4(0), _timer5(0), _soundTimestamp(0), _soundDelayTicks(480), _fireTimestamp(0) {
 	for (int i = 0; i < ARRAYSIZE(_dataArray); i++) {
 		_dataArray[i] = 0;
 	}
+	if (GAME_IS_REGRET) {
+		_soundDelayTicks = (10 + randomOf(15)) * 60;
+		if (randomOf(3) == 0)
+			_soundTimestamp = Kernel::get_instance()->getTickNum();
+	}
 }
 
 AttackProcess::AttackProcess(Actor *actor) : _block(0), _target(1), _tactic(0), _tacticDat(nullptr),
@@ -101,7 +106,7 @@ _tacticDatReadStream(nullptr), _tacticDatStartOffset(0), _soundNo(-1), _playedSt
 _field57(0), _field59(0), _field7f(false), _field96(false), _field97(false), _isActivity9orB(false),
 _isActivityAorB(false), _timer3set(false), _timer2set(false), _doubleDelay(false), _wpnField8(1),
 _wpnBasedTimeout(0), _difficultyBasedTimeout(0), _timer2(0), _timer3(0), _timer4(0), _timer5(0),
-_soundTimestamp(0), _fireTimestamp(0) {
+_soundTimestamp(0), _soundDelayTicks(480), _fireTimestamp(0) {
 	assert(actor);
 	_itemNum = actor->getObjId();
 	_npcInitialDir = actor->getDir();
@@ -113,6 +118,12 @@ _soundTimestamp(0), _fireTimestamp(0) {
 		_dataArray[i] = 0;
 	}
 
+	if (GAME_IS_REGRET) {
+		_soundDelayTicks = (10 + randomOf(15)) * 60;
+		if (randomOf(3) == 0)
+			_soundTimestamp = Kernel::get_instance()->getTickNum();
+	}
+
 	actor->setAttackAimFlag(false);
 
 	const Item *wpn = getItem(actor->getActiveWeapon());
@@ -778,18 +789,33 @@ void AttackProcess::genericAttack() {
 }
 
 void AttackProcess::checkRandomAttackSoundRegret(const Actor *actor) {
+	if (!readyForNextSound(Kernel::get_instance()->getTickNum()))
+		return;
+
 	AudioProcess *audio = AudioProcess::get_instance();
+	if (audio->isSFXPlayingForObject(-1, actor->getObjId()))
+		return;
+
+	int16 sndno = getRandomAttackSoundRegret(actor);
+
+	if (sndno != -1 && _lastAttackSound != sndno && _lastLastAttackSound != sndno) {
+		_lastLastAttackSound = _lastAttackSound;
+		_lastAttackSound = sndno;
+		_soundNo = sndno;
+		audio->playSFX(sndno, 0x80, actor->getObjId(), 1);
+	}
+}
 
+/* static */
+int16 AttackProcess::getRandomAttackSoundRegret(const Actor *actor) {
 	if (World::get_instance()->getControlledNPCNum() != 1)
-		return;
+		return -1;
 
 	if (actor->isDead())
-		return;
-
-	if (audio->isSFXPlayingForObject(-1, actor->getObjId()))
-		return;
+		return -1;
 
 	uint32 shapeno = actor->getShape();
+
 	int16 sndno = -1;
 	// The order here is pretty random, how it comes out of the disasm.
 	switch (shapeno) {
@@ -849,12 +875,7 @@ void AttackProcess::checkRandomAttackSoundRegret(const Actor *actor) {
 		  break;
 	}
 
-	if (sndno != -1 && _lastAttackSound != sndno && _lastLastAttackSound != sndno) {
-		_lastLastAttackSound = _lastAttackSound;
-		_lastAttackSound = sndno;
-		_soundNo = sndno;
-		audio->playSFX(sndno, 0x80, actor->getObjId(), 1);
-	}
+	return sndno;
 }
 
 void AttackProcess::checkRandomAttackSound(int now, uint32 shapeno) {
@@ -904,8 +925,8 @@ void AttackProcess::checkRandomAttackSound(int now, uint32 shapeno) {
 	}
 }
 
-bool AttackProcess::readyForNextSound(int now) {
-	if (_soundTimestamp == 0 || _soundTimestamp - now >= 480) {
+bool AttackProcess::readyForNextSound(uint32 now) {
+	if (_soundTimestamp == 0 || now - _soundTimestamp >= _soundDelayTicks) {
 		_soundTimestamp = now;
 		return true;
 	}
@@ -1077,7 +1098,10 @@ void AttackProcess::saveData(Common::WriteStream *ws) {
 	ws->writeSint32LE(_timer3);
 	ws->writeSint32LE(_timer4);
 	ws->writeSint32LE(_timer5);
-	ws->writeSint32LE(_soundTimestamp);
+	ws->writeSint32LE(_soundTimestamp); // bug: this should ideally be unsigned, probably won't make any difference.
+	// Don't write the sound delay because it only affects
+	// No Regret, adding it now would need a version bump, and
+	// and it doesn't make much difference to re-randomize it.
 	ws->writeSint32LE(_fireTimestamp);
 }
 
diff --git a/engines/ultima/ultima8/world/actors/attack_process.h b/engines/ultima/ultima8/world/actors/attack_process.h
index 76970862ea6..5407d810fa2 100644
--- a/engines/ultima/ultima8/world/actors/attack_process.h
+++ b/engines/ultima/ultima8/world/actors/attack_process.h
@@ -76,6 +76,11 @@ public:
 		_target = target;
 	}
 
+	/** Get the right "attack" sound for No Regret for the
+	 given actor.  This is actually used for surrender sounds too, hence
+	 being public static so it can be used from SurrenderProcess. */
+	static int16 getRandomAttackSoundRegret(const Actor *actor);
+
 	bool loadData(Common::ReadStream *rs, uint32 version);
 	void saveData(Common::WriteStream *ws) override;
 
@@ -106,7 +111,7 @@ private:
 	void sleep(int ticks);
 
 	/// Check the sound timer and return if we are ready for a new sound
-	bool readyForNextSound(int now);
+	bool readyForNextSound(uint32 now);
 
 	bool checkTimer2PlusDelayElapsed(int now);
 	void pathfindToItemInNPCData();
@@ -160,7 +165,8 @@ private:
 	int32 _timer4; // 0x6f/0x71 in orig
 	int32 _timer5; // 0x8a/0x8c in orig
 
-	int32 _soundTimestamp; /// 0x84/0x86 in orig - time a sound was last played
+	uint32 _soundTimestamp; /// 0x84/0x86 in orig - time a sound was last played
+	uint32 _soundDelayTicks; /// Delay between playing sounds, always 480 in No Remorse - Not saved.
 	int32 _fireTimestamp; /// 0x90/0x92 in orig - time NPC last fired
 
 	// Used in No Regret only, to avoid replaying the same sfx for attack twice in a row.
diff --git a/engines/ultima/ultima8/world/actors/surrender_process.cpp b/engines/ultima/ultima8/world/actors/surrender_process.cpp
index 6194d01a522..2c3c6cd32d7 100644
--- a/engines/ultima/ultima8/world/actors/surrender_process.cpp
+++ b/engines/ultima/ultima8/world/actors/surrender_process.cpp
@@ -21,9 +21,11 @@
 
 #include "ultima/ultima8/audio/audio_process.h"
 #include "ultima/ultima8/world/actors/surrender_process.h"
+#include "ultima/ultima8/world/actors/attack_process.h"
 #include "ultima/ultima8/world/actors/main_actor.h"
 #include "ultima/ultima8/kernel/kernel.h"
 #include "ultima/ultima8/world/get_object.h"
+#include "ultima/ultima8/ultima8.h"
 
 namespace Ultima {
 namespace Ultima8 {
@@ -36,24 +38,38 @@ static const uint16 SCIENTIST_SUR_SNDS[] = {0xe3, 0xe4, 0xec, 0xf6};
 static const uint16 HARDHAT_SUR_SNDS[] = {0xde, 0xdf, 0x8a, 0x8b};
 static const uint16 FEMALE_SUR_SNDS[] = {0xd6, 0xff, 0xd7};
 
+static inline int32 randomOf(int32 max) {
+	return (max > 0 ? getRandom() % max : 0);
+}
+
 #define RANDOM_ELEM(array) (array[getRandom() % ARRAYSIZE(array)])
 
-SurrenderProcess::SurrenderProcess() : Process(), _playedSound(false) {
+SurrenderProcess::SurrenderProcess() :
+	_playedSound(false), _soundDelayTicks(480), _soundTimestamp(0)
+{
 }
 
-SurrenderProcess::SurrenderProcess(Actor *actor) : _playedSound(false) {
+SurrenderProcess::SurrenderProcess(Actor *actor) :
+	_playedSound(false), _soundDelayTicks(480), _soundTimestamp(0)
+{
 	assert(actor);
 	_itemNum = actor->getObjId();
 
 	if (!actor->hasActorFlags(Actor::ACT_SURRENDERED))
 		actor->doAnim(Animation::surrender, actor->getDir());
 
+	if (GAME_IS_REGRET) {
+		_soundDelayTicks = (10 + randomOf(15)) * 60;
+		if (randomOf(3) == 0)
+			_soundTimestamp = Kernel::get_instance()->getTickNum();
+	}
+
 	_type = 0x25f; // CONSTANT!
 }
 
 void SurrenderProcess::run() {
 	Actor *a = getActor(_itemNum);
-	MainActor *main = getMainActor();
+	const MainActor *main = getMainActor();
 	if (!a || a->isDead() || !main) {
 		// dead
 		terminate();
@@ -73,13 +89,30 @@ void SurrenderProcess::run() {
 		uint16 animpid = a->turnTowardDir(direction);
 		if (animpid) {
 			waitFor(animpid);
-			return;
 		}
+		return;
+	}
+
+	int16 soundno;
+	if (GAME_IS_REMORSE)
+		soundno = checkRandomSoundRemorse();
+	else
+		soundno = checkRandomSoundRegret();
+
+	AudioProcess *audio = AudioProcess::get_instance();
+	if (soundno != -1 && audio) {
+		audio->playSFX(soundno, 0x80, _itemNum, 1);
 	}
+}
 
+int16 SurrenderProcess::checkRandomSoundRemorse() {
+	const Actor *a = getActor(_itemNum);
+	const MainActor *main = getMainActor();
 	if (_playedSound || a->getRangeIfVisible(*main) == 0)
 		// Nothing to do.
-		return;
+		return - 1;
+
+	_playedSound = true;
 
 	int16 soundno = -1;
 
@@ -101,21 +134,56 @@ void SurrenderProcess::run() {
 		break;
 	}
 
+	return soundno;
+}
+
+int16 SurrenderProcess::checkRandomSoundRegret() {
 	AudioProcess *audio = AudioProcess::get_instance();
-	if (audio && soundno != -1) {
-		audio->playSFX(soundno, 0x80, _itemNum, 1);
-		_playedSound = true;
+
+	const Actor *a = getActor(_itemNum);
+
+	if (!readyForNextSoundRegret())
+		return -1;
+
+	if (audio->isSFXPlayingForObject(-1, a->getObjId()))
+		return -1;
+
+	return AttackProcess::getRandomAttackSoundRegret(a);
+}
+
+//
+// This and the initializer in the constructor are duplicated logic from
+// AttackProcess.  In the original No Regret code they inherit from the same
+// type, but that makes the No Remorse code more messy for us since we support
+// both, so just live with a bit of mess in the code.
+//
+bool SurrenderProcess::readyForNextSoundRegret() {
+	uint32 now = Kernel::get_instance()->getTickNum();
+	if (_soundTimestamp == 0 || now - _soundTimestamp >= _soundDelayTicks) {
+		_soundTimestamp = now;
+		return true;
 	}
+	return false;
 }
 
 void SurrenderProcess::saveData(Common::WriteStream *ws) {
 	Process::saveData(ws);
-	ws->writeByte(_playedSound ? 1 : 0);
+	if (GAME_IS_REMORSE) {
+		ws->writeByte(_playedSound ? 1 : 0);
+	} else {
+		ws->writeUint32LE(_soundDelayTicks);
+		ws->writeUint32LE(_soundTimestamp);
+	}
 }
 
 bool SurrenderProcess::loadData(Common::ReadStream *rs, uint32 version) {
 	if (!Process::loadData(rs, version)) return false;
-	_playedSound = rs->readByte() != 0;
+	if (GAME_IS_REMORSE) {
+		_playedSound = rs->readByte() != 0;
+	} else {
+		_soundDelayTicks = rs->readUint32LE();
+		_soundTimestamp = rs->readUint32LE();
+	}
 	return true;
 }
 
diff --git a/engines/ultima/ultima8/world/actors/surrender_process.h b/engines/ultima/ultima8/world/actors/surrender_process.h
index 916cd16fd4c..77fb60de86b 100644
--- a/engines/ultima/ultima8/world/actors/surrender_process.h
+++ b/engines/ultima/ultima8/world/actors/surrender_process.h
@@ -43,6 +43,15 @@ public:
 
 protected:
 	bool _playedSound;
+
+	uint32 _soundDelayTicks; // Time between playing a sound
+	uint32 _soundTimestamp;  // Last timestamp when a sound was played
+
+private:
+	int16 checkRandomSoundRemorse();
+	int16 checkRandomSoundRegret();
+	bool readyForNextSoundRegret();
+
 };
 
 } // End of namespace Ultima8




More information about the Scummvm-git-logs mailing list