[Scummvm-git-logs] scummvm master -> 749214ce61d9f24d1ec2f769ae32d842a4ef41da

mduggan mgithub at guarana.org
Mon Jul 13 04:19:29 UTC 2020


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

Summary:
6e99e85407 ULTIMA8: Play correct SFX when Silencer dies in Crusader
ac0f52b028 ULTIMA8: Make intrinsics behave more correctly in Crusader
c58c235249 ULTIMA8: Remember actor activity numbers in Crusader
754c415016 ULTIMA8: Always have camera follow avatar in quick mover
a037987282 ULTIMA8: Fix typo in comment
c8d1a017f5 ULTIMA8: Add some useful warp points for debugging
bb7638917e ULTIMA8: Fix usecode dump output
427d653683 ULTIMA8: Add loader for Crusader damage flex
749214ce61 ULTIMA8: Correct comment and variable name


Commit: 6e99e85407f6b574b2fcf5c4f6dd233ff2d12994
    https://github.com/scummvm/scummvm/commit/6e99e85407f6b574b2fcf5c4f6dd233ff2d12994
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-07-13T12:55:21+09:00

Commit Message:
ULTIMA8: Play correct SFX when Silencer dies in Crusader

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


diff --git a/engines/ultima/ultima8/world/actors/avatar_death_process.cpp b/engines/ultima/ultima8/world/actors/avatar_death_process.cpp
index 8aec052e22..95b6dfd227 100644
--- a/engines/ultima/ultima8/world/actors/avatar_death_process.cpp
+++ b/engines/ultima/ultima8/world/actors/avatar_death_process.cpp
@@ -28,10 +28,12 @@
 #include "ultima/ultima8/games/game_data.h"
 #include "ultima/ultima8/kernel/kernel.h"
 #include "ultima/ultima8/kernel/core_app.h"
+#include "ultima/ultima8/kernel/delay_process.h"
 #include "ultima/ultima8/gumps/main_menu_process.h"
 #include "ultima/ultima8/gumps/gump_notify_process.h"
 #include "ultima/ultima8/graphics/palette_manager.h"
 #include "ultima/ultima8/audio/music_process.h"
+#include "ultima/ultima8/audio/audio_process.h"
 #include "ultima/ultima8/world/get_object.h"
 
 namespace Ultima {
@@ -69,13 +71,21 @@ void AvatarDeathProcess::run() {
 	Kernel::get_instance()->addProcess(menuproc);
 
 	if (GAME_IS_U8) {
-		// TODO: What should this do in crusader?
+		// Show the avatar gravestone
 		ReadableGump *gump = new ReadableGump(1, 27, 11,
 											  _TL_("HERE LIES*THE AVATAR*REST IN PEACE"));
 		gump->InitGump(0);
 		gump->setRelativePosition(Gump::CENTER);
 		Process *gumpproc = gump->GetNotifyProcess();
 		menuproc->waitFor(gumpproc);
+	} else {
+		// Play "Silencer Terminated" audio and wait
+		// a couple of seconds before showing menu
+		AudioProcess *ap = AudioProcess::get_instance();
+		ap->playSFX(9, 0x10, 0, 1);
+		DelayProcess *delayproc = new DelayProcess(60);
+		Kernel::get_instance()->addProcess(delayproc);
+		menuproc->waitFor(delayproc);
 	}
 
 	// done


Commit: ac0f52b02853f7fd6d5e1985c2c8d8ddd047cd22
    https://github.com/scummvm/scummvm/commit/ac0f52b02853f7fd6d5e1985c2c8d8ddd047cd22
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-07-13T12:55:21+09:00

Commit Message:
ULTIMA8: Make intrinsics behave more correctly in Crusader

Changed paths:
    engines/ultima/ultima8/world/item.cpp


diff --git a/engines/ultima/ultima8/world/item.cpp b/engines/ultima/ultima8/world/item.cpp
index 84d1c14426..351faadafc 100644
--- a/engines/ultima/ultima8/world/item.cpp
+++ b/engines/ultima/ultima8/world/item.cpp
@@ -538,8 +538,9 @@ bool Item::isOn(const Item &item2) const {
 }
 
 bool Item::isCompletelyOn(const Item &item2) const {
-	warning("TODO: Properly implement Item::isCompletelyOn");
-	// FIXME: this is just a copy of isOn at the moment
+	if (hasFlags(FLG_CONTAINED) || item2.hasFlags(FLG_CONTAINED))
+		return false;
+
 	int32 x1a, y1a, z1a, x1b, y1b;
 	int32 x2a, y2a, z2a, x2b, y2b, z2b;
 	getLocation(x1b, y1b, z1a);
@@ -555,10 +556,9 @@ bool Item::isCompletelyOn(const Item &item2) const {
 	y2a = y2b - yd;
 	z2b = z2a + zd;
 
-	if (x1b <= x2a || x2b <= x1a) return false;
-	if (y1b <= y2a || y2b <= y1a) return false;
-	if (z2b == z1a) return true;
-	return false;
+	return ((x1b <= x2b && x2a <= x1a) &&
+			(y1b <= y2b && y2a <= y1a) &&
+			(z2b == z1a));
 }
 
 bool Item::isCentreOn(const Item &item2) const {
@@ -1279,11 +1279,13 @@ uint32 Item::use() {
 	Actor *actor = dynamic_cast<Actor *>(this);
 	if (actor) {
 		if (actor->isDead()) {
-			// dead actor, so open/close the dead-body-_gump
-			if (hasFlags(FLG_GUMP_OPEN)) {
-				closeGump();
-			} else {
-				openGump(12); // CONSTANT!!
+			if (GAME_IS_U8) {
+				// dead actor, so open/close the dead-body-gump
+				if (hasFlags(FLG_GUMP_OPEN)) {
+					closeGump();
+				} else {
+					openGump(12); // CONSTANT!!
+				}
 			}
 			return 0;
 		}
@@ -1457,11 +1459,17 @@ void Item::enterFastArea() {
 
 	// Call usecode
 	if (!(_flags & FLG_FASTAREA)) {
-
 		Actor *actor = dynamic_cast<Actor *>(this);
-		if (actor && actor->isDead()) {
+		// Crusader special-cases a few shapes even when they are dead.
+		bool call_even_if_dead = (_shape == 0x576 || _shape == 0x596 ||
+								  _shape == 0x59c || _shape == 0x58f) && GAME_IS_CRUSADER;
+		if (actor && actor->isDead() && !call_even_if_dead) {
 			// dead actor, don't call the usecode
 		} else {
+			if (actor && GAME_IS_CRUSADER) {
+				actor->clearLastActivityNo();
+				actor->clearInCombat();
+			}
 			callUsecodeEvent_enterFastArea();
 		}
 	}


Commit: c58c235249536ce6728e2cadfde47bb9cdda0406
    https://github.com/scummvm/scummvm/commit/c58c235249536ce6728e2cadfde47bb9cdda0406
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-07-13T12:55:21+09:00

Commit Message:
ULTIMA8: Remember actor activity numbers in Crusader

Changed paths:
    engines/ultima/ultima8/usecode/remorse_intrinsics.h
    engines/ultima/ultima8/world/actors/actor.cpp
    engines/ultima/ultima8/world/actors/actor.h


diff --git a/engines/ultima/ultima8/usecode/remorse_intrinsics.h b/engines/ultima/ultima8/usecode/remorse_intrinsics.h
index ed987f054e..c8b3a81c42 100644
--- a/engines/ultima/ultima8/usecode/remorse_intrinsics.h
+++ b/engines/ultima/ultima8/usecode/remorse_intrinsics.h
@@ -120,7 +120,7 @@ Intrinsic RemorseIntrinsics[] = {
 	Item::I_isOn,
 	Item::I_getQHi,  // based on same coff set as 026
 	// 0x050
-	0, // TODO: int16 Actor::I_getCurrentActivityNo // void Intrinsic050(4 bytes)
+	Actor::I_getCurrentActivityNo, // void Intrinsic050(4 bytes)
 	Actor::I_clrInCombat, // void Intrinsic051(4 bytes)
 	Actor::I_setDefaultActivity0, // void Intrinsic052(6 bytes)
 	Actor::I_setDefaultActivity1, // void Intrinsic053(6 bytes)
@@ -269,7 +269,7 @@ Intrinsic RemorseIntrinsics[] = {
 	0, // TODO: PaletteFaderProcess::I_setPalToAllGrey // sets all colors to 0x3F3F3F
 	Actor::I_setActivity, // void Intrinsic0DB(6 bytes)
 	Item::I_isOn,
-	0, // TODO: Actor::I_getLastActivityNo void Intrinsic0DD(4 bytes)
+	Actor::I_getLastActivityNo, // void Intrinsic0DD(4 bytes)
 	Actor::I_setCombatTactic, // void Intrinsic0DE(6 bytes)
 	Actor::I_getEquip, // void Intrinsic0DF(6 bytes)
 	// 0x0E0
diff --git a/engines/ultima/ultima8/world/actors/actor.cpp b/engines/ultima/ultima8/world/actors/actor.cpp
index 0865328c23..9f1eef5240 100644
--- a/engines/ultima/ultima8/world/actors/actor.cpp
+++ b/engines/ultima/ultima8/world/actors/actor.cpp
@@ -69,7 +69,8 @@ Actor::Actor() : _strength(0), _dexterity(0), _intelligence(0),
 		_hitPoints(0), _mana(0), _alignment(0), _enemyAlignment(0),
 		_lastAnim(Animation::stand), _animFrame(0), _direction(0),
 		_fallStart(0), _unkByte(0), _actorFlags(0), _combatTactic(0),
-		_homeX(0), _homeY(0), _homeZ(0) {
+		_homeX(0), _homeY(0), _homeZ(0), _currentActivityNo(0),
+		_lastActivityNo(0) {
 	_defaultActivity[0] = 0;
 	_defaultActivity[1] = 0;
 	_defaultActivity[2] = 0;
@@ -573,6 +574,9 @@ uint16 Actor::setActivityCru(int activity) {
 	if (isDead())
 		return 0;
 
+	_lastActivityNo = _currentActivityNo;
+	_currentActivityNo = activity;
+
 	switch (activity) {
 	case 1: // stand
 		return doAnim(Animation::stand, 8);
@@ -1241,6 +1245,8 @@ void Actor::saveData(Common::WriteStream *ws) {
 		ws->writeUint32LE(_homeX);
 		ws->writeUint32LE(_homeY);
 		ws->writeUint32LE(_homeZ);
+		ws->writeUint16LE(_currentActivityNo);
+		ws->writeUint16LE(_lastActivityNo);
 	}
 }
 
@@ -1269,6 +1275,8 @@ bool Actor::loadData(Common::ReadStream *rs, uint32 version) {
 		_homeX = rs->readUint32LE();
 		_homeY = rs->readUint32LE();
 		_homeZ = rs->readUint32LE();
+		_currentActivityNo = rs->readUint16LE();
+		_lastActivityNo = rs->readUint16LE();
 	}
 
 	return true;
@@ -1959,7 +1967,19 @@ uint32 Actor::I_setCombatTactic(const uint8 *args, unsigned int /*argsize*/) {
 	return 0;
 }
 
+uint32 Actor::I_getCurrentActivityNo(const uint8 *args, unsigned int /*argsize*/) {
+	ARG_ACTOR_FROM_PTR(actor);
+	if (!actor) return 0;
+
+	return actor->getCurrentActivityNo();
+}
 
+uint32 Actor::I_getLastActivityNo(const uint8 *args, unsigned int /*argsize*/) {
+	ARG_ACTOR_FROM_PTR(actor);
+	if (!actor) return 0;
+
+	return actor->getLastActivityNo();
+}
 
 } // End of namespace Ultima8
 } // End of namespace Ultima
diff --git a/engines/ultima/ultima8/world/actors/actor.h b/engines/ultima/ultima8/world/actors/actor.h
index 1b7a77e7ac..5729f9824b 100644
--- a/engines/ultima/ultima8/world/actors/actor.h
+++ b/engines/ultima/ultima8/world/actors/actor.h
@@ -210,6 +210,18 @@ public:
 	//! \return processID of process handling the activity or zero
 	uint16 setActivity(int activity);
 
+	uint16 getCurrentActivityNo() const {
+		return _currentActivityNo;
+	}
+
+	uint16 getLastActivityNo() const {
+		return _lastActivityNo;
+	}
+
+	void clearLastActivityNo() {
+		_lastActivityNo = 0;
+	}
+
 	//! run the given animation
 	//! \return the PID of the ActorAnimProcess
 	uint16 doAnim(Animation::Sequence anim, int dir, unsigned int steps = 0);
@@ -302,6 +314,8 @@ public:
 	INTRINSIC(I_setCombatTactic);
 	INTRINSIC(I_setUnkByte);
 	INTRINSIC(I_getUnkByte);
+	INTRINSIC(I_getLastActivityNo);
+	INTRINSIC(I_getCurrentActivityNo);
 
 	enum ActorFlags {
 		ACT_INVINCIBLE     = 0x000001, // flags from npcdata byte 0x1B
@@ -355,6 +369,10 @@ protected:
 	int32 _homeY;
 	int32 _homeZ;
 
+	//! Current and last activity (only used in Crusader)
+	uint16 _currentActivityNo;
+	uint16 _lastActivityNo;
+
 	//! starts an activity (Ultima 8 version)
 	//! \return processID of process handling the activity or zero
 	uint16 setActivityU8(int activity);


Commit: 754c415016a5e708cf3097bb39e12024941a8621
    https://github.com/scummvm/scummvm/commit/754c415016a5e708cf3097bb39e12024941a8621
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-07-13T13:14:36+09:00

Commit Message:
ULTIMA8: Always have camera follow avatar in quick mover

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


diff --git a/engines/ultima/ultima8/world/actors/quick_avatar_mover_process.cpp b/engines/ultima/ultima8/world/actors/quick_avatar_mover_process.cpp
index 0320fa2ab9..c3e6007ad2 100644
--- a/engines/ultima/ultima8/world/actors/quick_avatar_mover_process.cpp
+++ b/engines/ultima/ultima8/world/actors/quick_avatar_mover_process.cpp
@@ -26,8 +26,10 @@
 #include "ultima/ultima8/world/world.h"
 #include "ultima/ultima8/world/current_map.h"
 #include "ultima/ultima8/kernel/kernel.h"
+#include "ultima/ultima8/kernel/core_app.h"
 #include "ultima/ultima8/ultima8.h"
 #include "ultima/ultima8/graphics/shape_info.h"
+#include "ultima/ultima8/world/camera_process.h"
 #include "ultima/ultima8/world/get_object.h"
 #include "ultima/ultima8/world/actors/avatar_mover_process.h"
 
@@ -124,6 +126,10 @@ void QuickAvatarMoverProcess::run() {
 	// Yes, i know, not entirely correct
 	avatar->collideMove(x + dxv, y + dyv, z + dzv, false, true);
 
+	if (GAME_IS_CRUSADER) {
+		// Keep the camera on the avatar while we're quick-moving.
+		CameraProcess::SetCameraProcess(new CameraProcess(x + dxv, y + dyv, z + dzv));
+	}
 
 	// Prevent avatar from running an idle animation while moving around
 	Ultima8Engine::get_instance()->getAvatarMoverProcess()->resetIdleTime();


Commit: a0379872822b6ff3474e7e2f294f14f429e5ac16
    https://github.com/scummvm/scummvm/commit/a0379872822b6ff3474e7e2f294f14f429e5ac16
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-07-13T13:14:41+09:00

Commit Message:
ULTIMA8: Fix typo in comment

Changed paths:
    engines/ultima/ultima8/world/item.h


diff --git a/engines/ultima/ultima8/world/item.h b/engines/ultima/ultima8/world/item.h
index 0f4bf761f6..dec7d85a45 100644
--- a/engines/ultima/ultima8/world/item.h
+++ b/engines/ultima/ultima8/world/item.h
@@ -226,7 +226,7 @@ public:
 		return _mapNum;
 	}
 
-	//! Set the 'NpcNum' of this Item. Note that this can represent various
+	//! Set the 'MapNum' of this Item. Note that this can represent various
 	//! things depending on the family of this Item.
 	void setMapNum(uint16 mapnum_) {
 		_mapNum = mapnum_;


Commit: c8d1a017f545fb2bc59e442fd9ab3195d81cb759
    https://github.com/scummvm/scummvm/commit/c8d1a017f545fb2bc59e442fd9ab3195d81cb759
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-07-13T13:14:41+09:00

Commit Message:
ULTIMA8: Add some useful warp points for debugging

Changed paths:
    engines/ultima/ultima8/games/remorse_game.cpp


diff --git a/engines/ultima/ultima8/games/remorse_game.cpp b/engines/ultima/ultima8/games/remorse_game.cpp
index 9dfd65623c..97ef21150d 100644
--- a/engines/ultima/ultima8/games/remorse_game.cpp
+++ b/engines/ultima/ultima8/games/remorse_game.cpp
@@ -122,7 +122,18 @@ bool RemorseGame::startGame() {
 	ObjectManager::get_instance()->assignActorObjId(actor, 1);
 
 	if (GAME_IS_REMORSE) {
-		actor->setLocation(60716, 59400, 16);
+		// Some useful points to warp into for testing..
+		actor->setLocation(60716, 59400, 16); // Map 1 (mission 1)
+		//actor->setLocation(42493, 26621, 16); // Map 2 (mission 1 / level 4)
+		//actor->setLocation(34302, 32254, 16); // Map 3 (mission 2)
+		//actor->setLocation(34813, 33789, 16); // Map 4
+		//actor->setLocation(37373, 30205, 16); // Map 5
+		//actor->setLocation(37373, 30205, 16); // Map 6
+		//actor->setLocation(35070, 26142, 96); // Map 7
+		//actor->setLocation(29693, 32253, 0); // Map 8 - unfinished area?
+		//actor->setLocation(2046, 2046, 0); // Map 9
+		//actor->setLocation(14845, 6141, 0); // Map 22 - debugging map
+		//actor->setLocation(34302, 32254, 16); // Map 40 (Rebel base)
 	} else {
 		actor->setLocation(58174, 56606, 16);
 	}
@@ -165,7 +176,7 @@ ProcId RemorseGame::playEndgameMovie(bool fade) {
 }
 
 void RemorseGame::playCredits() {
-
+	warning("TODO: Implement Crusader credits..");
 }
 
 void RemorseGame::writeSaveInfo(Common::WriteStream *ws) {


Commit: bb7638917e5095bd07045d15a326b77ad51e5eca
    https://github.com/scummvm/scummvm/commit/bb7638917e5095bd07045d15a326b77ad51e5eca
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-07-13T13:14:59+09:00

Commit Message:
ULTIMA8: Fix usecode dump output

Changed paths:
    engines/ultima/ultima8/usecode/uc_machine.cpp


diff --git a/engines/ultima/ultima8/usecode/uc_machine.cpp b/engines/ultima/ultima8/usecode/uc_machine.cpp
index 9e3d5bfc2e..cd2cf1c498 100644
--- a/engines/ultima/ultima8/usecode/uc_machine.cpp
+++ b/engines/ultima/ultima8/usecode/uc_machine.cpp
@@ -2027,6 +2027,7 @@ void UCMachine::execProcess(UCProcess *p) {
 		case 0x5B: {
 			ui16a = cs.readUint16LE(); // source line number
 			debug(10, "ignore debug opcode %02X: line offset %d", opcode, ui16a);
+			LOGPF(("line number %d\n", ui16a));
 			break;
 		}
 		case 0x5C: {
@@ -2036,6 +2037,7 @@ void UCMachine::execProcess(UCProcess *p) {
 				// skip over class name and null terminator
 				name[x] = cs.readByte();
 			}
+			LOGPF(("line number %s %d\n", name, ui16a));
 			debug(10, "ignore debug opcode %02X: %s line offset %d", opcode, name, ui16a);
 			break;
 		}
@@ -2454,8 +2456,8 @@ uint32 UCMachine::I_rndRange(const uint8 *args, unsigned int /*argsize*/) {
 	ARG_SINT16(hi);
 
 	// return random integer between lo (incl.) to hi (incl.)
-
-	if (hi <= lo) return lo;
+	if (hi <= lo)
+		return lo;
 
 	return (lo + (getRandom() % (hi - lo + 1)));
 }


Commit: 427d65368310d50f8ae00a619b41ab8feed40a07
    https://github.com/scummvm/scummvm/commit/427d65368310d50f8ae00a619b41ab8feed40a07
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-07-13T13:16:10+09:00

Commit Message:
ULTIMA8: Add loader for Crusader damage flex

Changed paths:
  A engines/ultima/ultima8/world/damage_info.cpp
  A engines/ultima/ultima8/world/damage_info.h
    engines/ultima/module.mk
    engines/ultima/ultima8/games/game_data.cpp
    engines/ultima/ultima8/graphics/main_shape_archive.cpp
    engines/ultima/ultima8/graphics/main_shape_archive.h
    engines/ultima/ultima8/graphics/shape_info.h
    engines/ultima/ultima8/graphics/type_flags.cpp
    engines/ultima/ultima8/graphics/type_flags.h


diff --git a/engines/ultima/module.mk b/engines/ultima/module.mk
index 56632f4933..d419906744 100644
--- a/engines/ultima/module.mk
+++ b/engines/ultima/module.mk
@@ -528,6 +528,7 @@ MODULE_OBJS := \
 	ultima8/world/create_item_process.o \
 	ultima8/world/crosshair_process.o \
 	ultima8/world/current_map.o \
+	ultima8/world/damage_info.o \
 	ultima8/world/destroy_item_process.o \
 	ultima8/world/egg.o \
 	ultima8/world/egg_hatcher_process.o \
diff --git a/engines/ultima/ultima8/games/game_data.cpp b/engines/ultima/ultima8/games/game_data.cpp
index e3e307d1e1..6a90cde653 100644
--- a/engines/ultima/ultima8/games/game_data.cpp
+++ b/engines/ultima/ultima8/games/game_data.cpp
@@ -633,11 +633,10 @@ void GameData::loadRemorseData() {
 		error("Unable to load static/damage.flx");
 
 	RawArchive *damageflex = new RawArchive(damageds);
+	if (damageflex->getCount() != 1)
+		error("static/damage.flx appears corrupted");
 
-	// TODO: What's in this flex file?
-	// 1 object of 12288 bytes, mostly 0s
-	//_damage = new DamageDat();
-	//_damage->load(damageflex);
+	_mainShapes->loadDamageDat(damageflex->get_datasource(0));
 
 	delete damageflex;
 
diff --git a/engines/ultima/ultima8/graphics/main_shape_archive.cpp b/engines/ultima/ultima8/graphics/main_shape_archive.cpp
index c79af9dde4..e20ea63dfe 100644
--- a/engines/ultima/ultima8/graphics/main_shape_archive.cpp
+++ b/engines/ultima/ultima8/graphics/main_shape_archive.cpp
@@ -49,6 +49,11 @@ void MainShapeArchive::loadTypeFlags(Common::SeekableReadStream *rs) {
 	_typeFlags->load(rs);
 }
 
+void MainShapeArchive::loadDamageDat(Common::SeekableReadStream *rs) {
+	assert(_typeFlags);
+	_typeFlags->loadDamageDat(rs);
+}
+
 ShapeInfo *MainShapeArchive::getShapeInfo(uint32 shapenum) {
 	assert(_typeFlags);
 
diff --git a/engines/ultima/ultima8/graphics/main_shape_archive.h b/engines/ultima/ultima8/graphics/main_shape_archive.h
index 8fa93ede77..73041670c9 100644
--- a/engines/ultima/ultima8/graphics/main_shape_archive.h
+++ b/engines/ultima/ultima8/graphics/main_shape_archive.h
@@ -50,6 +50,7 @@ public:
 	~MainShapeArchive() override;
 
 	void loadTypeFlags(Common::SeekableReadStream *rs);
+	void loadDamageDat(Common::SeekableReadStream *rs);
 	ShapeInfo *getShapeInfo(uint32 shapenum);
 
 	void loadAnimDat(Common::SeekableReadStream *rs);
diff --git a/engines/ultima/ultima8/graphics/shape_info.h b/engines/ultima/ultima8/graphics/shape_info.h
index 3b95765694..3b6c06565e 100644
--- a/engines/ultima/ultima8/graphics/shape_info.h
+++ b/engines/ultima/ultima8/graphics/shape_info.h
@@ -25,6 +25,7 @@
 
 #include "ultima/ultima8/world/weapon_info.h"
 #include "ultima/ultima8/world/armour_info.h"
+#include "ultima/ultima8/world/damage_info.h"
 #include "ultima/ultima8/world/actors/monster_info.h"
 
 namespace Ultima {
@@ -97,6 +98,7 @@ public:
 	WeaponInfo *_weaponInfo;
 	ArmourInfo *_armourInfo;
 	MonsterInfo *_monsterInfo;
+	DamageInfo *_damageInfo;
 
 	inline bool is_fixed() const {
 		return (_flags & SI_FIXED) != 0;
@@ -145,6 +147,10 @@ public:
 		return (_family == SF_QUANTITY || _family == SF_REAGENT);
 	}
 
+	bool takesDamage() const {
+		return (_damageInfo && _damageInfo->takesDamage());
+	}
+
 	bool getTypeFlag(int typeFlag);
 	bool getTypeFlagU8(int typeFlag);
 	bool getTypeFlagCrusader(int typeFlag);
@@ -156,12 +162,13 @@ public:
 		_family(0), _equipType(0), _animType(0), _animData(0),
 		_unknown(0), _weight(0), _volume(0),
 		_weaponInfo(nullptr), _armourInfo(nullptr),
-		_monsterInfo(nullptr) { }
+		_monsterInfo(nullptr), _damageInfo(nullptr) { }
 
 	~ShapeInfo() {
 		delete _weaponInfo;
 		delete[] _armourInfo;
 		delete _monsterInfo;
+		delete _damageInfo;
 	}
 
 };
diff --git a/engines/ultima/ultima8/graphics/type_flags.cpp b/engines/ultima/ultima8/graphics/type_flags.cpp
index 2297a2ddc2..590553679b 100644
--- a/engines/ultima/ultima8/graphics/type_flags.cpp
+++ b/engines/ultima/ultima8/graphics/type_flags.cpp
@@ -51,10 +51,6 @@ ShapeInfo *TypeFlags::getShapeInfo(uint32 shapenum) {
 
 
 void TypeFlags::load(Common::SeekableReadStream *rs) {
-	// TODO: detect U8/crusader format somehow?!
-	// (Or probably pass it as parameter)
-	// The 'parsing' below is only for U8
-
 	unsigned int blocksize = 8;
 	if (GAME_IS_CRUSADER) {
 		blocksize = 9;
@@ -266,7 +262,12 @@ void TypeFlags::loadWeaponInfo() {
 		else
 			wi->_displayGumpShape = 3;
 
-		assert(wi->_shape < _shapeInfo.size());
+		if (wi->_shape > _shapeInfo.size()) {
+			warning("ignoring weapon info for shape %d beyond size %d.",
+					wi->_shape, _shapeInfo.size());
+			delete wi;
+			continue;
+		}
 		_shapeInfo[wi->_shape]._weaponInfo = wi;
 	}
 }
@@ -416,5 +417,23 @@ void TypeFlags::loadMonsterInfo() {
 	}
 }
 
+void TypeFlags::loadDamageDat(Common::SeekableReadStream *rs) {
+	uint32 count = rs->size() / 6;
+	if (_shapeInfo.size() < count) {
+		warning("more damage info than shape info");
+		return;
+	}
+	for (uint32 i = 0; i < count; i++) {
+		byte damagedata[6];
+		rs->read(damagedata, 6);
+		if (damagedata[0] == 0)
+			continue;
+
+		DamageInfo *di = new DamageInfo(damagedata);
+		_shapeInfo[i]._damageInfo = di;
+	}
+}
+
+
 } // End of namespace Ultima8
 } // End of namespace Ultima
diff --git a/engines/ultima/ultima8/graphics/type_flags.h b/engines/ultima/ultima8/graphics/type_flags.h
index d5512de15f..27f1f350df 100644
--- a/engines/ultima/ultima8/graphics/type_flags.h
+++ b/engines/ultima/ultima8/graphics/type_flags.h
@@ -35,6 +35,7 @@ public:
 	~TypeFlags();
 
 	void load(Common::SeekableReadStream *rs);
+	void loadDamageDat(Common::SeekableReadStream *rs);
 	ShapeInfo *getShapeInfo(uint32 shape);
 
 private:
diff --git a/engines/ultima/ultima8/world/damage_info.cpp b/engines/ultima/ultima8/world/damage_info.cpp
new file mode 100644
index 0000000000..473cb3905f
--- /dev/null
+++ b/engines/ultima/ultima8/world/damage_info.cpp
@@ -0,0 +1,87 @@
+/* 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 "ultima/ultima8/misc/pent_include.h"
+#include "ultima/ultima8/world/damage_info.h"
+#include "ultima/ultima8/world/item.h"
+#include "ultima/ultima8/world/item_factory.h"
+#include "ultima/ultima8/audio/audio_process.h"
+#include "ultima/ultima8/kernel/kernel.h"
+
+namespace Ultima {
+namespace Ultima8 {
+
+DamageInfo::DamageInfo(uint8 data[6]) {
+	_flags = data[0];
+	_sound = data[1];
+	_data[0] = data[2];
+	_data[1] = data[3];
+	_data[2] = data[4];
+	_data[3] = data[5];
+}
+
+void DamageInfo::applyToItem(Item *item) {
+	if (!item)
+		return;
+	if (explode()) {
+		item->explode(explosionType(), explodeDestroysItem());
+	}
+	if (_sound) {
+		AudioProcess *audio = AudioProcess::get_instance();
+		if (audio) {
+			audio->playSFX(_sound, 0x10, item->getObjId(), 1, true);
+		}
+	}
+	if (replaceItem()) {
+		uint16 q = item->getQuality();
+		int32 x, y, z;
+		item->getLocation(x, y, z);
+		uint16 replacementShape = getReplacementShape();
+		uint8 replacementFrame = getReplacementFrame();
+		Item *newitem = ItemFactory::createItem(replacementShape, replacementFrame, q, 0, 0, 0, 0, true);
+		newitem->setLocation(x, y, z);
+	} else {
+		if (frameDataIsAbsolute()) {
+			int frameval = 1;
+			if (_data[1])
+				frameval++;
+			if (_data[2])
+				frameval++;
+			item->setFrame(_data[getRandom() % frameval]);
+		} else {
+			int frameoff = 0;
+			for (int i = 0; i < 3; i++)
+				if (_data[i])
+					frameoff++;
+			if (!frameoff) {
+				item->destroy();
+			} else {
+				uint32 frame = item->getFrame();
+				item->setFrame(frame + _data[getRandom() % frameoff]);
+			}
+		}
+	}
+}
+
+
+} // End of namespace Ultima8
+} // End of namespace Ultima
diff --git a/engines/ultima/ultima8/world/damage_info.h b/engines/ultima/ultima8/world/damage_info.h
new file mode 100644
index 0000000000..0760699f40
--- /dev/null
+++ b/engines/ultima/ultima8/world/damage_info.h
@@ -0,0 +1,89 @@
+/* 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.
+ *
+ */
+
+#ifndef WORLD_DAMAGE_INFO_H
+#define WORLD_DAMAGE_INFO_H
+
+#include "common/stream.h"
+
+#include "ultima/shared/std/string.h"
+
+namespace Ultima {
+namespace Ultima8 {
+
+class Item;
+
+/**
+ * The damage.dat flex contains data about each shape and how it should be damaged
+ */
+class DamageInfo {
+public:
+	DamageInfo(uint8 data[6]);
+	~DamageInfo() {};
+	
+	void applyToItem(Item *item);
+	
+	bool takesDamage() {
+		return _flags != 0;
+	}
+
+protected:
+	bool replaceItem() const {
+		return (_flags & 0x40) != 0;
+	}
+	bool explode() const {
+		return (_flags & 0x06) != 0;
+	}
+	bool explosionType() const{
+		assert(explode());
+		return ((_flags & 0x06) >> 1) - 1;
+	}
+	bool explodeDestroysItem() const {
+		return (_flags >> 5) & 1;
+	}
+	bool explodeWithDamage() const {
+		return (_flags >> 3) & 1;
+	}
+	
+	uint16 getReplacementShape() const {
+		assert(replaceItem());
+		return static_cast<uint16>(_data[1]) << 16 | _data[0];
+	}
+	
+	uint16 getReplacementFrame() const {
+		assert(replaceItem());
+		return static_cast<uint16>(_data[2]);
+	}
+	
+	bool frameDataIsAbsolute() const {
+		return (_flags & 0x80) != 0;
+	}
+
+	uint8 _flags;
+	uint8 _sound;
+	uint8 _data[4];
+};
+
+} // End of namespace Ultima8
+} // End of namespace Ultima
+
+#endif


Commit: 749214ce61d9f24d1ec2f769ae32d842a4ef41da
    https://github.com/scummvm/scummvm/commit/749214ce61d9f24d1ec2f769ae32d842a4ef41da
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-07-13T13:16:22+09:00

Commit Message:
ULTIMA8: Correct comment and variable name

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 23d0517de3..3327d337d0 100644
--- a/engines/ultima/ultima8/world/actors/main_actor.cpp
+++ b/engines/ultima/ultima8/world/actors/main_actor.cpp
@@ -693,15 +693,15 @@ uint32 MainActor::I_teleportToEgg(const uint8 *args, unsigned int argsize) {
 		ARG_UINT16(map);
 		mapnum = map;
 	} else {
-		// TODO: Confirm this works right.
-		// Crusader teleport uses main actor map.
+		// Crusader teleport intrinsic 096 uses main actor map.
+		// Intrinsic 079 provides a map argument.
 		assert(argsize == 8);
 		MainActor *av = getMainActor();
 		mapnum = av->getMapNum();
 	}
 
 	ARG_UINT16(teleport_id);
-	ARG_UINT16(unknown); // 0/1
+	ARG_UINT16(put_in_stasis); // 0/1
 
 	return Kernel::get_instance()->addProcess(
 	           new TeleportToEggProcess(mapnum, teleport_id));




More information about the Scummvm-git-logs mailing list