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

mduggan mgithub at guarana.org
Mon Jul 20 05:49:58 UTC 2020


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

Summary:
4ab93b0aaa ULTIMA8: Add intrinsic I_canExistAtPoint
d72dd113bb ULTIMA8: Implement game difficulty intrinsic for Crusader
2cc3964f94 ULTIMA8: JANITORIAL: Remove whitespace
e2965a8d31 ULTIMA8: Replace family ids with enum names for nicer code
7bc2eef4de ULTIMA8: Add direction deltas for 16 dirs
d01a7432c4 ULTIMA8: Use item damage data for receiving hits in Crusader
5ce876b92a ULTIMA8: JANITORIAL: Remove some TODOs which are out-of-date.
bd642b73ca ULTIMA8: Add intrinsics for getting/setting controlled NPC
84eebe3e7d ULTIMA8: Add Crusader fire type data
601e996678 ULTIMA8: Add helper to get controlled actor
4641ec2304 ULTIMA8: Force target reticle update when avatar dies
3bcb0fe8ed ULTIMA8: Fix some coverity-identified issues


Commit: 4ab93b0aaaf36b62a48114d67cda36e7ee6c9986
    https://github.com/scummvm/scummvm/commit/4ab93b0aaaf36b62a48114d67cda36e7ee6c9986
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-07-20T14:23:50+09:00

Commit Message:
ULTIMA8: Add intrinsic I_canExistAtPoint

Changed paths:
    engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h
    engines/ultima/ultima8/usecode/remorse_intrinsics.h
    engines/ultima/ultima8/world/current_map.cpp
    engines/ultima/ultima8/world/current_map.h


diff --git a/engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h b/engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h
index 1fc06333db..1520575b73 100644
--- a/engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h
+++ b/engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h
@@ -103,8 +103,8 @@ const char* const ConvertUsecodeCrusader::_intrinsics[] = {
 	// 0020
 	"void Item::I_popToCoords(Item *, uint16 x, uint16 y, uint16 z)", // set coords, used after creating blood spills in NPCDEATH
 	"void Actor::I_setDead(4 bytes)", // part of same coff set 021, 060, 073, 0A0, 0A8, 0D8, 0E7, 135
-	"void I_push(Item *)", // same code as U8
-	"int16 Item::I_getEtherealTop(void)", // from disasmww
+	"void Item::I_push(Item *)", // same code as U8
+	"int16 Item::I_getEtherealTop(void)", // based on disasm
 	"void Item::I_setShape(Item *, int16 shapeno)", // probably. See PEPSIEW::gotHit.
 	"void Item::I_touch(Item *)", // same code as U8
 	"int16 Item::I_getQHi(Item *)", // guess, based on variable name in BOUNCBOX::gotHit
@@ -115,8 +115,8 @@ const char* const ConvertUsecodeCrusader::_intrinsics[] = {
 	"int16 Item::I_getQLo(Item *)", // guess, based on variable name in BOUNCBOX::gotHit
 	"byte Item::I_inFastArea(Item *)",
 	"void Item::I_setQHi(Item *, uint16 qhi)", // probably setQHi, see usage in FREE::ordinal2E where object position is copied
-	"byte I_legalMoveToPoint(Item *, Point *, int16 force)", // based on disasm
-	"byte Intrinsic02F(int, int, shapeno, Point *)", // no idea what this does..
+	"byte Item::I_legalMoveToPoint(Item *, Point *, int16 force)", // based on disasm
+	"byte CurrentMap::I_canExistAtPoint(int, int, shapeno, Point *)",
 	// 0030
 	"void Item::I_pop(Item *)", // same code as U8
 	"void Item::I_andStatus(Item *, uint16 status)", // part of same coff set 01A, 031, 069, 06E, 099, 0B2, 0BF, 0C1, 0C3, 0E9, 0FC, 101, 104, 106, 108, 10A, 10C, 10E, 110, 114, 117, 11A, 128, 132
@@ -247,7 +247,7 @@ const char* const ConvertUsecodeCrusader::_intrinsics[] = {
 	"int16 Egg::I_getEggXRange(Egg *)", // based on disasm
 	"void Actor::I_setDead(Actor *)", // part of same coff set 021, 060, 073, 0A0, 0A8, 0D8, 0E7, 135
 	"void I_playFlic0A9(char *)", // same coff as 092
-	"void I_playSFX(2 bytes)", // same coff as 0D4
+	"void AudioProcess::I_playSFX(2 bytes)", // same coff as 0D4
 	"byte Actor::I_NPCGetField0x59Flag1_0AB(Actor *)",
 	"int16 Item::I_getFamilyOfType(Item *)", // per pentagram notes, matches disasm.
 	"int16 Item::I_getNPCNum(Item *)", // part of same coff set 067, 06D, 089, 08E, 0AD, 0F8, 100, 102, 105, 107, 109, 10B, 10D, 10F, 111, 115, 11C, 123, 129
diff --git a/engines/ultima/ultima8/usecode/remorse_intrinsics.h b/engines/ultima/ultima8/usecode/remorse_intrinsics.h
index f94f700a97..953739ff69 100644
--- a/engines/ultima/ultima8/usecode/remorse_intrinsics.h
+++ b/engines/ultima/ultima8/usecode/remorse_intrinsics.h
@@ -84,7 +84,7 @@ Intrinsic RemorseIntrinsics[] = {
 	Item::I_inFastArea, // byte Intrinsic02C(4 bytes) // based on disassembly - checks for flag 0x2000
 	Item::I_setQHi,
 	Item::I_legalMoveToPoint, // byte Intrinsic02E(12 bytes)
-	0, // byte Intrinsic02F(10 bytes)
+	CurrentMap::I_canExistAtPoint, // byte Intrinsic02F(10 bytes)
 	// 0x030
 	Item::I_pop,
 	Item::I_andStatus,
diff --git a/engines/ultima/ultima8/world/current_map.cpp b/engines/ultima/ultima8/world/current_map.cpp
index 8b8d69251f..2bb616e631 100644
--- a/engines/ultima/ultima8/world/current_map.cpp
+++ b/engines/ultima/ultima8/world/current_map.cpp
@@ -28,9 +28,11 @@
 #include "ultima/ultima8/world/egg.h"
 #include "ultima/ultima8/world/actors/actor.h"
 #include "ultima/ultima8/world/world.h"
+#include "ultima/ultima8/world/world_point.h"
 #include "ultima/ultima8/misc/rect.h"
 #include "ultima/ultima8/world/container.h"
 #include "ultima/ultima8/usecode/uc_list.h"
+#include "ultima/ultima8/usecode/uc_machine.h"
 #include "ultima/ultima8/graphics/shape_info.h"
 #include "ultima/ultima8/world/teleport_egg.h"
 #include "ultima/ultima8/world/egg_hatcher_process.h"
@@ -1299,5 +1301,29 @@ uint32 CurrentMap::I_canExistAt(const uint8 *args, unsigned int /*argsize*/) {
 		return 0;
 }
 
+uint32 CurrentMap::I_canExistAtPoint(const uint8 *args, unsigned int /*argsize*/) {
+	ARG_UINT16(unk1);
+	ARG_UINT16(unk2);
+	ARG_UINT16(shape);
+	ARG_WORLDPOINT(pt);
+
+	if (shape > 0x800)
+		return 0;
+
+	if (GAME_IS_CRUSADER) {
+		pt.setX(pt.getX());
+		pt.setY(pt.getY());
+	}
+
+	const CurrentMap *cm = World::get_instance()->getCurrentMap();
+	bool valid = cm->isValidPosition(pt.getX(), pt.getY(), pt.getZ(), shape, 0, 0, 0);
+
+	if (valid)
+		return 1;
+	else
+		return 0;
+}
+
+
 } // End of namespace Ultima8
 } // End of namespace Ultima
diff --git a/engines/ultima/ultima8/world/current_map.h b/engines/ultima/ultima8/world/current_map.h
index d814006761..7f24f23e7d 100644
--- a/engines/ultima/ultima8/world/current_map.h
+++ b/engines/ultima/ultima8/world/current_map.h
@@ -210,6 +210,7 @@ public:
 	bool load(Common::ReadStream *rs, uint32 version);
 
 	INTRINSIC(I_canExistAt);
+	INTRINSIC(I_canExistAtPoint);
 
 private:
 	void loadItems(Std::list<Item *> itemlist, bool callCacheIn);


Commit: d72dd113bb31e548c380674e8638faecce12c74a
    https://github.com/scummvm/scummvm/commit/d72dd113bb31e548c380674e8638faecce12c74a
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-07-20T14:23:50+09:00

Commit Message:
ULTIMA8: Implement game difficulty intrinsic for Crusader

Changed paths:
    engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h
    engines/ultima/ultima8/usecode/remorse_intrinsics.h
    engines/ultima/ultima8/world/world.cpp
    engines/ultima/ultima8/world/world.h


diff --git a/engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h b/engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h
index 1520575b73..e45c5241c5 100644
--- a/engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h
+++ b/engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h
@@ -110,7 +110,7 @@ const char* const ConvertUsecodeCrusader::_intrinsics[] = {
 	"int16 Item::I_getQHi(Item *)", // guess, based on variable name in BOUNCBOX::gotHit
 	"int16 I_getClosestDirectionInRange(x1, y1, x2, y2, numdirs, mindir, maxdir)",
 	"int16 Item::I_hurl(Item *,8 bytes)", // part of same coff set 028, 08D, 0BD, 0C0, 0C2, 0C8, 0F7, 0F9, 118, 11D
-	"int16 Game::I_getDifficultyLevel(void)",
+	"int16 World::I_gameDifficulty(void)",
 	"void AudioProcess::I_playAmbientSFXCru(Item *, sndno)",
 	"int16 Item::I_getQLo(Item *)", // guess, based on variable name in BOUNCBOX::gotHit
 	"byte Item::I_inFastArea(Item *)",
diff --git a/engines/ultima/ultima8/usecode/remorse_intrinsics.h b/engines/ultima/ultima8/usecode/remorse_intrinsics.h
index 953739ff69..70ff18052d 100644
--- a/engines/ultima/ultima8/usecode/remorse_intrinsics.h
+++ b/engines/ultima/ultima8/usecode/remorse_intrinsics.h
@@ -78,7 +78,7 @@ Intrinsic RemorseIntrinsics[] = {
 	Item::I_getQHi, // int16 Intrinsic026(Item *)
 	Item::I_getClosestDirectionInRange, // int Intrinsic027(14 bytes)
 	Item::I_hurl, // int Intrinsic028(12 bytes)
-	UCMachine::I_true, // TODO: This is actually game difficulty level.  Make an intrinsic for that once it's implemented (for now return 1, easiest difficulty).
+	World::I_gameDifficulty,
 	AudioProcess::I_playAmbientSFXCru,
 	Item::I_getQLo, // int16 Intrinsic02B(4 bytes)
 	Item::I_inFastArea, // byte Intrinsic02C(4 bytes) // based on disassembly - checks for flag 0x2000
diff --git a/engines/ultima/ultima8/world/world.cpp b/engines/ultima/ultima8/world/world.cpp
index e62dcf5efa..f7192823ec 100644
--- a/engines/ultima/ultima8/world/world.cpp
+++ b/engines/ultima/ultima8/world/world.cpp
@@ -50,7 +50,7 @@ namespace Ultima8 {
 
 World *World::_world = nullptr;
 
-World::World() : _currentMap(nullptr),  _alertActive(false) {
+World::World() : _currentMap(nullptr), _alertActive(false), _difficulty(1) {
 	debugN(MM_INFO, "Creating World...\n");
 
 	_world = this;
@@ -341,6 +341,7 @@ void World::save(Common::WriteStream *ws) {
 
 	if (GAME_IS_CRUSADER) {
 		ws->writeByte(_alertActive ? 0 : 1);
+		ws->writeByte(_difficulty);
 	}
 
 	uint16 es = static_cast<uint16>(_ethereal.size());
@@ -370,6 +371,7 @@ bool World::load(Common::ReadStream *rs, uint32 version) {
 
 	if (GAME_IS_CRUSADER) {
 		_alertActive = (rs->readByte() != 0);
+		_difficulty = rs->readByte();
 	}
 
 	uint32 etherealcount = rs->readUint32LE();
@@ -457,6 +459,10 @@ uint32 World::I_clrAlertActive(const uint8 * /*args*/,
 	return 0;
 }
 
+uint32 World::I_gameDifficulty(const uint8 * /*args*/,
+	unsigned int /*argsize*/) {
+	return get_instance()->_world->getGameDifficulty();
+}
 
 } // End of namespace Ultima8
 } // End of namespace Ultima
diff --git a/engines/ultima/ultima8/world/world.h b/engines/ultima/ultima8/world/world.h
index 60a2a48ff4..9dcdb71c15 100644
--- a/engines/ultima/ultima8/world/world.h
+++ b/engines/ultima/ultima8/world/world.h
@@ -139,15 +139,23 @@ public:
 	//! load World data
 	bool load(Common::ReadStream *rs, uint32 version);
 
-	bool isAlertActive() {
+	bool isAlertActive() const {
 		return _alertActive;
 	}
 
 	void setAlertActive(bool active);
 
+	uint8 getGameDifficulty() const {
+		return _difficulty;
+	}
+	void setGameDifficulty(uint8 difficulty) {
+		_difficulty = difficulty;
+	}
+
 	INTRINSIC(I_getAlertActive); // for Crusader
 	INTRINSIC(I_setAlertActive); // for Crusader
 	INTRINSIC(I_clrAlertActive); // for Crusader
+	INTRINSIC(I_gameDifficulty); // for Crusader
 
 private:
 	static World *_world;
@@ -158,6 +166,7 @@ private:
 	Std::list<ObjId> _ethereal;
 
 	bool _alertActive; //!< is intruder alert active (Crusader)
+	uint8 _difficulty; //!< game difficulty level (Crusader)
 
 };
 


Commit: 2cc3964f9446f2487bcb0a2d7eda8e1217520922
    https://github.com/scummvm/scummvm/commit/2cc3964f9446f2487bcb0a2d7eda8e1217520922
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-07-20T14:23:51+09:00

Commit Message:
ULTIMA8: JANITORIAL: Remove whitespace

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


diff --git a/engines/ultima/ultima8/world/actors/avatar_mover_process.cpp b/engines/ultima/ultima8/world/actors/avatar_mover_process.cpp
index f36c332db1..abe958e9a0 100644
--- a/engines/ultima/ultima8/world/actors/avatar_mover_process.cpp
+++ b/engines/ultima/ultima8/world/actors/avatar_mover_process.cpp
@@ -595,7 +595,7 @@ void AvatarMoverProcess::handleNormalMode() {
 		}
 		return;
 	}
-	
+
 	if (hasMovementFlags(MOVE_MOUSE_DIRECTION)) {
 		Animation::Sequence nextanim = Animation::step;
 


Commit: e2965a8d31f4e3dfaee58d7674a3158ff18b3e42
    https://github.com/scummvm/scummvm/commit/e2965a8d31f4e3dfaee58d7674a3158ff18b3e42
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-07-20T14:23:51+09:00

Commit Message:
ULTIMA8: Replace family ids with enum names for nicer code

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


diff --git a/engines/ultima/ultima8/world/item_selection_process.cpp b/engines/ultima/ultima8/world/item_selection_process.cpp
index 5319626283..7445f63e26 100644
--- a/engines/ultima/ultima8/world/item_selection_process.cpp
+++ b/engines/ultima/ultima8/world/item_selection_process.cpp
@@ -82,7 +82,11 @@ bool ItemSelectionProcess::selectNextItem() {
 		// but this is how the game does it..
 		if (item->hasFlags(Actor::FLG_HANGING))
 			continue;
-		if (item->getShape() == 0x4ed || item->getFamily() == 10 || item->getFamily() == 11 || item->getFamily() == 12 || item->getFamily() == 13 || (info && info->_flags & ShapeInfo::SI_SELECTABLE)) {
+		uint16 family = item->getFamily();
+		if (item->getShape() == 0x4ed || family == ShapeInfo::SF_CRUWEAPON ||
+			family == ShapeInfo::SF_CRUAMMO || family == ShapeInfo::SF_CRUBOMB ||
+			family == ShapeInfo::SF_CRUINVITEM ||
+			(info && info->_flags & ShapeInfo::SI_SELECTABLE)) {
 
 			int32 cx, cy, cz;
 			item->getCentre(cx, cy, cz);


Commit: 7bc2eef4de4e0357fee8e824c68523ea29393de4
    https://github.com/scummvm/scummvm/commit/7bc2eef4de4e0357fee8e824c68523ea29393de4
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-07-20T14:23:51+09:00

Commit Message:
ULTIMA8: Add direction deltas for 16 dirs

Changed paths:
    engines/ultima/ultima8/misc/direction.h


diff --git a/engines/ultima/ultima8/misc/direction.h b/engines/ultima/ultima8/misc/direction.h
index 2fa3ec145d..a81db522f6 100644
--- a/engines/ultima/ultima8/misc/direction.h
+++ b/engines/ultima/ultima8/misc/direction.h
@@ -43,8 +43,11 @@ enum Direction {
 /*
  * Tables to map a Direction to x/y deltas
  */
-const int x_fact[] = {  0, +1, +1, +1,  0, -1, -1, -1 };
-const int y_fact[] = { -1, -1,  0, +1, +1, +1,  0, -1 };
+static const int x_fact[] = {  0, +1, +1, +1,  0, -1, -1, -1 };
+static const int y_fact[] = { -1, -1,  0, +1, +1, +1,  0, -1 };
+
+static const int x_fact16[] = {  0, +1, +2, +2, +2, +2, +2, +1, 0, -1, -2, -2, -2, -2, -2, -1 };
+static const int y_fact16[] = { -2, -2, -2, -1,  0, +1, +2, +2, +2, +2, +2, +1, 0, -1, -2, -2 };
 
 /*
  *  Return the direction for a given slope (0-7).


Commit: d01a7432c41bc15ba85d1f2ba498a1a881163cde
    https://github.com/scummvm/scummvm/commit/d01a7432c41bc15ba85d1f2ba498a1a881163cde
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-07-20T14:23:51+09:00

Commit Message:
ULTIMA8: Use item damage data for receiving hits in Crusader

Changed paths:
    engines/ultima/ultima8/world/damage_info.cpp
    engines/ultima/ultima8/world/damage_info.h
    engines/ultima/ultima8/world/item.cpp
    engines/ultima/ultima8/world/item.h
    engines/ultima/ultima8/world/item_factory.cpp


diff --git a/engines/ultima/ultima8/world/damage_info.cpp b/engines/ultima/ultima8/world/damage_info.cpp
index 473cb3905f..fbbc394473 100644
--- a/engines/ultima/ultima8/world/damage_info.cpp
+++ b/engines/ultima/ultima8/world/damage_info.cpp
@@ -36,12 +36,26 @@ DamageInfo::DamageInfo(uint8 data[6]) {
 	_data[0] = data[2];
 	_data[1] = data[3];
 	_data[2] = data[4];
-	_data[3] = data[5];
+	_damagePoints = data[5];
 }
 
-void DamageInfo::applyToItem(Item *item) {
+bool DamageInfo::applyToItem(Item *item, uint16 points) const {
 	if (!item)
-		return;
+		return false;
+
+	// The game does this.. it seems to be used to mean
+	// "destroyed" (as distinct from broken?)
+	if (item->hasFlags(Item::FLG_GUMP_OPEN))
+		return false;
+
+	uint8 itemPts = item->getDamagePoints();
+	if (points < itemPts) {
+		item->setDamagePoints(itemPts - points);
+		return false;
+	}
+	item->setDamagePoints(0);
+	item->setFlag(Item::FLG_GUMP_OPEN | Item::FLG_BROKEN);
+
 	if (explode()) {
 		item->explode(explosionType(), explodeDestroysItem());
 	}
@@ -80,6 +94,7 @@ void DamageInfo::applyToItem(Item *item) {
 			}
 		}
 	}
+	return true;
 }
 
 
diff --git a/engines/ultima/ultima8/world/damage_info.h b/engines/ultima/ultima8/world/damage_info.h
index 0760699f40..aaa72c590e 100644
--- a/engines/ultima/ultima8/world/damage_info.h
+++ b/engines/ultima/ultima8/world/damage_info.h
@@ -39,48 +39,61 @@ class DamageInfo {
 public:
 	DamageInfo(uint8 data[6]);
 	~DamageInfo() {};
-	
-	void applyToItem(Item *item);
-	
-	bool takesDamage() {
-		return _flags != 0;
-	}
 
-protected:
+	//! apply this damage info to the given item.  Returns true if the item was destroyed in the process.
+	bool applyToItem(Item *item, uint16 points) const;
+
+	bool frameDataIsAbsolute() const {
+		return (_flags >> 7) & 1;
+	}
+	bool explodeDestroysItem() const {
+		return (_flags >> 6) & 1;
+	}
 	bool replaceItem() const {
-		return (_flags & 0x40) != 0;
+		return (_flags >> 4) & 1;
+	}
+	bool explodeWithDamage() const {
+		return (_flags >> 3) & 1;
+	}
+	bool takesDamage() const {
+		return _flags & 1;
+	}
+
+	uint8 damagePoints() const {
+		return _damagePoints;
 	}
+
+protected:
 	bool explode() const {
 		return (_flags & 0x06) != 0;
 	}
-	bool explosionType() const{
+	int 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];
+		return static_cast<uint16>(_data[1]) << 8 | _data[0];
 	}
-	
+
 	uint16 getReplacementFrame() const {
 		assert(replaceItem());
 		return static_cast<uint16>(_data[2]);
 	}
-	
-	bool frameDataIsAbsolute() const {
-		return (_flags & 0x80) != 0;
-	}
 
+
+	// Flags are ABxCDEEF
+	// A = frame data is absolute (not relative to current)
+	// B = item destroyed after explosion
+	// C = item is replaced when destroyed
+	// D = explosion damages surrounding items
+	// EE = 2 bits for explosion type
+	// F = item takes damage
 	uint8 _flags;
 	uint8 _sound;
-	uint8 _data[4];
+	uint8 _data[3];
+	uint8 _damagePoints;
 };
 
 } // End of namespace Ultima8
diff --git a/engines/ultima/ultima8/world/item.cpp b/engines/ultima/ultima8/world/item.cpp
index 6c17c62e3d..5e52cda7c4 100644
--- a/engines/ultima/ultima8/world/item.cpp
+++ b/engines/ultima/ultima8/world/item.cpp
@@ -78,7 +78,7 @@ Item::Item()
 	  _extendedFlags(0), _parent(0),
 	  _cachedShape(nullptr), _cachedShapeInfo(nullptr),
 	  _gump(0), _gravityPid(0), _lastSetup(0),
-	  _ix(0), _iy(0), _iz(0) {
+	  _ix(0), _iy(0), _iz(0), _damagePoints(1) {
 }
 
 
@@ -1777,6 +1777,13 @@ uint16 Item::getDamageType() const {
 }
 
 void Item::receiveHit(uint16 other, int dir, int damage, uint16 type) {
+	if (GAME_IS_U8)
+		receiveHitU8(other, dir, damage, type);
+	else
+		receiveHitCru(other, dir, damage, type);
+}
+
+void Item::receiveHitU8(uint16 other, int dir, int damage, uint16 type) {
 	// first, check if the item has a 'gotHit' usecode event
 	if (callUsecodeEvent_gotHit(other, 0)) //!! TODO: what should the 0 be??
 		return;
@@ -1804,6 +1811,41 @@ void Item::receiveHit(uint16 other, int dir, int damage, uint16 type) {
 	hurl(-16 * x_fact[dir], -16 * y_fact[dir], 16, 4); //!! constants
 }
 
+
+void Item::receiveHitCru(uint16 other, int dir, int damage, uint16 type) {
+	damage = scaleReceivedDamageCru(damage, type);
+	const ShapeInfo *shapeInfo = getShapeInfo();
+	if (!shapeInfo)
+		return;
+	const DamageInfo *damageInfo = shapeInfo->_damageInfo;
+
+	// TODO: work out how this flag is decided.
+	uint8 shouldCallUsecode = 1;
+
+	if (shouldCallUsecode)
+		callUsecodeEvent_gotHit(other, 0);
+
+	if (damageInfo) {
+		bool wasbroken = damageInfo->applyToItem(this, damage);
+		if (wasbroken) {
+			Kernel::get_instance()->killProcesses(_objId, 0xc, true);
+		}
+	}
+
+	if (shapeInfo->is_fixed() || shapeInfo->_weight == 0) {
+		// can't move
+		return;
+	}
+
+	int xhurl = 10 + getRandom() % 15;
+	int yhurl = 10 + getRandom() % 15;
+
+	// nothing special, so just hurl the item
+	// TODO: hurl item in direction, with speed depending on damage
+	hurl(-xhurl * x_fact[dir], -yhurl * y_fact[dir], 16, 4); //!! constants
+}
+
+
 bool Item::canDrag() {
 	ShapeInfo *si = getShapeInfo();
 	if (si->is_fixed()) return false;
@@ -2016,6 +2058,44 @@ bool Item::canMergeWith(Item *other) {
 	return false;
 }
 
+bool Item::isRobotCru() const {
+	uint32 shape = getShape();
+	return (shape == 0x4c8 || shape == 0x338 || shape == 0x45d ||
+			shape == 0x2cb || shape == 0x4e6 || shape == 899 ||
+			shape == 0x385);
+}
+
+int Item::scaleReceivedDamageCru(int damage, uint16 type) const {
+	uint8 difficulty = World::get_instance()->getGameDifficulty();
+	const Actor *actor = dynamic_cast<const Actor *>(this);
+	//
+	// TODO: this should check for current controlled NPC *or* avatar.
+	//
+	// For difficulty 1 and 2, we scale damage to others *up* and damage
+	// to avatar *down*.
+	//
+	if (!actor || getObjId() != 1) {
+		if (difficulty == 1) {
+			damage *= 5;
+		} else if (difficulty == 2) {
+			damage *= 3;
+		}
+	} else {
+		if (difficulty == 1) {
+			damage /= 5;
+		} else if (difficulty == 2) {
+			damage /= 3;
+		}
+	}
+
+	if (isRobotCru() && (type == 1 || type == 2 || type == 0xb || type == 0xd)) {
+		damage /= 3;
+	}
+
+	damage = CLIP(damage, 1, 0xfa);
+	return damage;
+}
+
 
 void Item::saveData(Common::WriteStream *ws) {
 	Object::saveData(ws);
diff --git a/engines/ultima/ultima8/world/item.h b/engines/ultima/ultima8/world/item.h
index ce365201f7..c28c9d9862 100644
--- a/engines/ultima/ultima8/world/item.h
+++ b/engines/ultima/ultima8/world/item.h
@@ -375,6 +375,16 @@ public:
 	//! \param type The type of damage done. Zero for default
 	virtual void receiveHit(ObjId other, int dir, int damage, uint16 type);
 
+	//! get damage points, used in Crusader for item damage.
+	uint8 getDamagePoints() const {
+		return _damagePoints;
+	}
+
+	//! set damage points, used in Crusader for item damage.
+	void setDamagePoints(uint8 points) {
+		_damagePoints = points;
+	}
+
 	//! count nearby objects of a given shape
 	unsigned int countNearby(uint32 shape_, uint16 range);
 
@@ -597,6 +607,15 @@ protected:
 	ObjId _gump;             // Item's gump
 	ProcId _gravityPid;      // Item's GravityTracker (or 0)
 
+	uint8 _damagePoints;	// Damage points, used for item damage in Crusader
+
+	//! True if this is a Robot shape (in a fixed list)
+	bool isRobotCru() const;
+
+	//! Scale a received damage value based on the current difficulty level
+	//! and the type of object this is.
+	int scaleReceivedDamageCru(int damage, uint16 type) const;
+
 private:
 
 	//! Call a Usecode Event. Use the separate functions instead!
@@ -608,6 +627,12 @@ private:
 	//! Animate the item (called by setupLerp)
 	void animateItem();
 
+	//! The U8 version of receiveHit
+	void receiveHitU8(ObjId other, int dir, int damage, uint16 type);
+
+	//! The Crusader version of receiveHit
+	void receiveHitCru(ObjId other, int dir, int damage, uint16 type);
+
 public:
 	enum statusflags {
 		FLG_DISPOSABLE   = 0x0002,  //!< Item is discarded on map change
diff --git a/engines/ultima/ultima8/world/item_factory.cpp b/engines/ultima/ultima8/world/item_factory.cpp
index 40241bc3a5..dfdebbad3a 100644
--- a/engines/ultima/ultima8/world/item_factory.cpp
+++ b/engines/ultima/ultima8/world/item_factory.cpp
@@ -79,7 +79,7 @@ static Item *getItemForFamily(uint32 family) {
 
 Item *ItemFactory::createItem(uint32 shape, uint32 frame, uint16 quality,
                               uint16 flags, uint16 npcnum, uint16 mapnum,
-                              uint32 extendedflags, bool _objId) {
+                              uint32 extendedflags, bool objId) {
 	// check what class to create
 	ShapeInfo *info = GameData::get_instance()->getMainShapes()->
 	                  getShapeInfo(shape);
@@ -101,8 +101,14 @@ Item *ItemFactory::createItem(uint32 shape, uint32 frame, uint16 quality,
 		item->_npcNum = npcnum;
 		item->_mapNum = mapnum;
 		item->_extendedFlags = extendedflags;
-		if (_objId)
+		if (objId)
 			item->assignObjId();
+		if (GAME_IS_CRUSADER) {
+			ShapeInfo *info = item->getShapeInfo();
+			if (info && info->_damageInfo && info->_damageInfo->takesDamage()) {
+				item->setDamagePoints(info->_damageInfo->damagePoints());
+			}
+		}
 	}
 
 	return item;
@@ -118,7 +124,7 @@ static Actor *getActorForNpcNum(uint32 npcnum) {
 
 Actor *ItemFactory::createActor(uint32 shape, uint32 frame, uint16 quality,
                                 uint16 flags, uint16 npcnum, uint16 mapnum,
-                                uint32 extendedflags, bool _objId) {
+                                uint32 extendedflags, bool objId) {
 	/*
 	    // This makes it rather hard to create new NPCs...
 	    if (npcnum == 0) // or do monsters have npcnum 0? we'll see...
@@ -137,7 +143,7 @@ Actor *ItemFactory::createActor(uint32 shape, uint32 frame, uint16 quality,
 	actor->_mapNum = mapnum;
 	if (npcnum != 0) {
 		actor->_objId = static_cast<uint16>(npcnum);
-	} else if (_objId) {
+	} else if (objId) {
 		actor->assignObjId();
 	}
 	actor->_extendedFlags = extendedflags;


Commit: 5ce876b92a3b469e10b0ae73aba9cb04bf3ebc1d
    https://github.com/scummvm/scummvm/commit/5ce876b92a3b469e10b0ae73aba9cb04bf3ebc1d
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-07-20T14:27:37+09:00

Commit Message:
ULTIMA8: JANITORIAL: Remove some TODOs which are out-of-date.

Changed paths:
    engines/ultima/ultima8/audio/sound_flex.cpp
    engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h
    engines/ultima/ultima8/games/remorse_game.cpp
    engines/ultima/ultima8/graphics/base_soft_render_surface.cpp
    engines/ultima/ultima8/gumps/cru_pickup_gump.cpp
    engines/ultima/ultima8/gumps/keypad_gump.cpp
    engines/ultima/ultima8/kernel/core_app.cpp
    engines/ultima/ultima8/usecode/uc_machine.cpp


diff --git a/engines/ultima/ultima8/audio/sound_flex.cpp b/engines/ultima/ultima8/audio/sound_flex.cpp
index 020635936b..3e35c95709 100644
--- a/engines/ultima/ultima8/audio/sound_flex.cpp
+++ b/engines/ultima/ultima8/audio/sound_flex.cpp
@@ -94,7 +94,6 @@ void SoundFlex::cache(uint32 index) {
 
 	if (Std::strncmp(reinterpret_cast<const char *>(buf), "ASFX", 4) == 0) {
 		// After the 32 byte header, ASFX (crusader audio) is just raw data
-		// TODO: Check that 11025 is correct (seems like it?)
 		// TODO: Check if No Regret is Stereo and/or 16 bit?
 		const SoundFlexEntry &entry = _index[index];
 		debug(6, "SoundFlex: Playing sfx %d (%s) with data 0x%04X", index, entry._name.c_str(), entry._data);
diff --git a/engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h b/engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h
index e45c5241c5..d7fce24aa6 100644
--- a/engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h
+++ b/engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h
@@ -95,10 +95,10 @@ const char* const ConvertUsecodeCrusader::_intrinsics[] = {
 	"int16 UCMachine::I_rndRange(uint16 x, uint16 y)", // // probably.. always called with 2 constants, then result often compared to some number between
 	"byte Item::I_legalCreateAtCoords(Item *, int16 shapeno, int16 frame, int16 x, int16 y, int16 z)", // probably, see usage in DOOR2::ordinal37
 	"void Item::I_andStatus(Item *, uint16 status)", // part of same coff set 01A, 031, 069, 06E, 099, 0B2, 0BF, 0C1, 0C3, 0E9, 0FC, 101, 104, 106, 108, 10A, 10C, 10E, 110, 114, 117, 11A, 128, 132. Always associated with a bitwise-not or bitmask
-	"int16 I_getTargetNPCNumMaybe(void)",
+	"int16 World::I_getControlledNPCNum()",
 	"byte Actor::I_getDir(4 bytes)", // based on disasm. same coff as 112, 121
 	"int16 Actor::I_getLastAnimSet(4 bytes)", // based on disasm. part of same coff set 01D, 05A, 0B9, 0D7, 0E4, 124
-	"int16 Actor::I_maybeFire(Actor *, x, y, z, byte, int, byte)", // TODO: investigate more
+	"int16 Actor::I_maybeFire(Actor *, x, y, z, byte, int, byte)",
 	"byte Item::I_create(Item *, uint16 shapenum, uint16 framenum)", // probably - used in MISS1EGG referencing keycards and NPCDEATH in creating blood spills
 	// 0020
 	"void Item::I_popToCoords(Item *, uint16 x, uint16 y, uint16 z)", // set coords, used after creating blood spills in NPCDEATH
@@ -158,7 +158,7 @@ const char* const ConvertUsecodeCrusader::_intrinsics[] = {
 	"void Actor::I_setDefaultActivity1(Actor *, int)",
 	"void Actor::I_setDefaultActivity2(Actor *, int)",
 	"void Actor::I_setActivity(Actor *, int)", // part of same coff set 055, 07D, 0CD, 0DB, 0F2, 131
-	"void I_setControlledNPCTo(int itemno)", // when you take over the Thermatron etc.
+	"void World::I_setControlledNPCNum(int itemno)", // when you take over the Thermatron etc.
 	"int16 Item::I_getSurfaceWeight(Item *)",
 	"byte Item::I_isCentreOn(Item *, uint16 other)",
 	"void Item::I_setFrame(Item *, frame)", // based on same coff as 002
@@ -198,7 +198,7 @@ const char* const ConvertUsecodeCrusader::_intrinsics[] = {
 	"int16 MainActor::I_teleportToEgg(int, int, int)",
 	"int16 PaletteFaderProcess::I_fadeFromBlack(void)", // from black, no arg (40 frames)
 	"void Actor::I_clrImmortal(Actor *)", // same coff as 130
-	"int16 Actor::I_getHp(Actor *)", // TODO: double-check whether field 0 of NPC data is HP or *max* HP.
+	"int16 Actor::I_getHp(Actor *)",
 	"void Actor::I_setActivity(Actor *, int)", // part of same coff set 055, 07D, 0CD, 0DB, 0F2, 131
 	"int16 Item::I_getQuality(Item *)", // based on disassembly
 	"void Item::I_setQuality(Item *, int)", // based on disassembly. same coff as 0BA, 125
diff --git a/engines/ultima/ultima8/games/remorse_game.cpp b/engines/ultima/ultima8/games/remorse_game.cpp
index 7ff3fa8ed1..91c19256ef 100644
--- a/engines/ultima/ultima8/games/remorse_game.cpp
+++ b/engines/ultima/ultima8/games/remorse_game.cpp
@@ -177,7 +177,7 @@ ProcId RemorseGame::playEndgameMovie(bool fade) {
 }
 
 void RemorseGame::playCredits() {
-	warning("TODO: Implement Crusader credits..");
+	warning("TODO: RemorseGame::playCredits: Implement Crusader credits");
 }
 
 void RemorseGame::writeSaveInfo(Common::WriteStream *ws) {
diff --git a/engines/ultima/ultima8/graphics/base_soft_render_surface.cpp b/engines/ultima/ultima8/graphics/base_soft_render_surface.cpp
index b3cd772686..46a5a33d0c 100644
--- a/engines/ultima/ultima8/graphics/base_soft_render_surface.cpp
+++ b/engines/ultima/ultima8/graphics/base_soft_render_surface.cpp
@@ -267,8 +267,7 @@ bool BaseSoftRenderSurface::BeginPainting() {
 	_lockCount++;
 
 	if (_pixels00 == nullptr) {
-		// TODO: SetLastError(GR_SOFT_ERROR_LOCKED_NULL_PIXELS, "Surface Locked with NULL BaseSoftRenderSurface::_pixels pointer!");
-		perr << "Error: Surface Locked with NULL BaseSoftRenderSurface::_pixels pointer!" << Std::endl;
+		error("Error: Surface Locked with NULL BaseSoftRenderSurface::_pixels pointer!");
 		return false;
 	}
 
@@ -289,8 +288,7 @@ bool BaseSoftRenderSurface::BeginPainting() {
 bool BaseSoftRenderSurface::EndPainting() {
 	// Already Unlocked
 	if (!_lockCount) {
-		// TODO: SetLastError(GR_SOFT_ERROR_BEGIN_END_MISMATCH, "BeginPainting()/EndPainting() Mismatch!");
-		perr << "Error: BeginPainting()/EndPainting() Mismatch!" << Std::endl;
+		error("Error: BeginPainting()/EndPainting() Mismatch!");
 		return false;
 	}
 
diff --git a/engines/ultima/ultima8/gumps/cru_pickup_gump.cpp b/engines/ultima/ultima8/gumps/cru_pickup_gump.cpp
index 36fe39dab7..9e01a9fbf9 100644
--- a/engines/ultima/ultima8/gumps/cru_pickup_gump.cpp
+++ b/engines/ultima/ultima8/gumps/cru_pickup_gump.cpp
@@ -101,6 +101,7 @@ void CruPickupGump::InitGump(Gump *newparent, bool take_focus) {
 	// Paint a semi-transparent background
 	const FrameID bfgrameid(GameData::GUMPS, PICKUP_GUMP_SHAPE, 0);
 	// TODO: The game uses a variable number of these depending on the text length
+	// For now 5 is ok.
 	for (int i = 0; i < 5; i++) {
 		Gump *gump = new TranslucentGump(i * bgframe->_width, 0, bgframe->_width, bgframe->_height);
 		gump->SetShape(bfgrameid, false);
diff --git a/engines/ultima/ultima8/gumps/keypad_gump.cpp b/engines/ultima/ultima8/gumps/keypad_gump.cpp
index ebb3cf96c0..6da1599677 100644
--- a/engines/ultima/ultima8/gumps/keypad_gump.cpp
+++ b/engines/ultima/ultima8/gumps/keypad_gump.cpp
@@ -129,14 +129,13 @@ void KeypadGump::ChildNotify(Gump *child, uint32 message) {
 bool KeypadGump::OnTextInput(int unicode) {
 	if (!(unicode & 0xFF80)) {
 		//char c = unicode & 0x7F;
-		// TODO: Accept numeric inputs
+		// TODO: Accept numeric keyboard inputs
 	}
 	return true;
 }
 
 uint32 KeypadGump::I_showKeypad(const uint8 *args, unsigned int /*argsize*/) {
 	ARG_UINT16(target)
-	 // TODO: what's this parameter?
 	ModalGump *gump = new KeypadGump(target);
 	gump->InitGump(0);
 	gump->setRelativePosition(CENTER);
diff --git a/engines/ultima/ultima8/kernel/core_app.cpp b/engines/ultima/ultima8/kernel/core_app.cpp
index 07997e22db..a14e3be5db 100644
--- a/engines/ultima/ultima8/kernel/core_app.cpp
+++ b/engines/ultima/ultima8/kernel/core_app.cpp
@@ -264,22 +264,6 @@ void CoreApp::setupGamePaths(GameInfo *ginfo) {
 	if (!_settingMan->get("work", work, SettingManager::DOM_GAME))
 		work = "@home/" + game + "-work";
 
-#if 0
-	// force creation if it doesn't exist
-
-	// TODO: I don't like these being created here.
-	//       I'd prefer them to be created when needed. (-wjp)
-
-	_fileSystem->AddVirtualPath("@work", work, true);
-	debugN(MM_INFO, "U8 Workdir: %s\n", work.c_str()); //!!FIXME (u8)
-
-	// make sure we've got a minimal sane _fileSystem under there...
-	_fileSystem->MkDir("@work/usecode");
-	_fileSystem->MkDir("@work/usecode/obj");
-	_fileSystem->MkDir("@work/usecode/src");
-	_fileSystem->MkDir("@work/usecode/asm");
-#endif
-
 	// load savegame path. Default is @home/game-save
 	Std::string save;
 	if (!_settingMan->get("save", save, SettingManager::DOM_GAME))
diff --git a/engines/ultima/ultima8/usecode/uc_machine.cpp b/engines/ultima/ultima8/usecode/uc_machine.cpp
index 4c117c6829..3b0f86c306 100644
--- a/engines/ultima/ultima8/usecode/uc_machine.cpp
+++ b/engines/ultima/ultima8/usecode/uc_machine.cpp
@@ -366,7 +366,6 @@ void UCMachine::execProcess(UCProcess *p) {
 			// (includes this pointer, if present)
 			// NB: do not actually pop these argument bytes
 		{
-			//! TODO
 			uint16 arg_bytes = cs.readByte();
 			uint16 func = cs.readUint16LE();
 			LOGPF(("calli\t\t%04Xh (%02Xh arg bytes) %s\n", func, arg_bytes, _convUse->intrinsics()[func]));
@@ -1235,8 +1234,6 @@ void UCMachine::execProcess(UCProcess *p) {
 			// push global xxxx size yy bits
 			ui16a = cs.readUint16LE();
 			ui16b = cs.readByte();
-			// TODO: get flagname for output?
-
 			ui32a = _globals->getEntries(ui16a, ui16b);
 			p->_stack.push2(static_cast<uint16>(ui32a));
 			LOGPF(("push\t\tglobal [%04X %02X] = %02X\n", ui16a, ui16b, ui32a));
@@ -1247,7 +1244,6 @@ void UCMachine::execProcess(UCProcess *p) {
 			// pop value into global xxxx size yy bits
 			ui16a = cs.readUint16LE();
 			ui16b = cs.readByte();
-			// TODO: get flagname for output?
 			ui32a = p->_stack.pop2();
 			_globals->setEntries(ui16a, ui16b, ui32a);
 
@@ -1271,7 +1267,6 @@ void UCMachine::execProcess(UCProcess *p) {
 			// return from function
 
 			if (p->ret()) { // returning from process
-				// TODO
 				LOGPF(("ret\t\tfrom process\n"));
 				p->terminateDeferred();
 


Commit: bd642b73ca2f57a686121d405402fdf28c210941
    https://github.com/scummvm/scummvm/commit/bd642b73ca2f57a686121d405402fdf28c210941
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-07-20T14:29:22+09:00

Commit Message:
ULTIMA8: Add intrinsics for getting/setting controlled NPC

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


diff --git a/engines/ultima/ultima8/usecode/remorse_intrinsics.h b/engines/ultima/ultima8/usecode/remorse_intrinsics.h
index 70ff18052d..8a3672032c 100644
--- a/engines/ultima/ultima8/usecode/remorse_intrinsics.h
+++ b/engines/ultima/ultima8/usecode/remorse_intrinsics.h
@@ -63,7 +63,7 @@ Intrinsic RemorseIntrinsics[] = {
 	UCMachine::I_rndRange, // int16 Intrinsic018(4 bytes) // probably.. always called with 2 constants, then result compared to some number between
 	Item::I_legalCreateAtCoords, // byte Intrinsic019(14 bytes)
 	Item::I_andStatus, // void Intrinsic01A(6 bytes)
-	UCMachine::I_true, // FIXME: get the num of some npc - maybe currently controlled NPC? For now default to 1 (avatar).
+	World::I_getControlledNPCNum,  // int16 Intrinsic01B(void)
 	Actor::I_getDir, // byte Intrinsic01C(4 bytes)
 	Actor::I_getLastAnimSet, // int Intrinsic01D(4 bytes)
 	0, // int Intrinsic01E(16 bytes)
@@ -126,7 +126,7 @@ Intrinsic RemorseIntrinsics[] = {
 	Actor::I_setDefaultActivity1, // void Intrinsic053(6 bytes)
 	Actor::I_setDefaultActivity2, // void Intrinsic054(6 bytes)
 	Actor::I_setActivity, // void Intrinsic055(6 bytes)
-	0, // void Intrinsic056(2 bytes)
+	World::I_setControlledNPCNum, // void Intrinsic056(2 bytes)
 	Item::I_getSurfaceWeight, // void Intrinsic057(4 bytes)
 	Item::I_isCentreOn, // int Intrinsic058(6 bytes)
 	Item::I_setFrame, // based on same coff as 002
diff --git a/engines/ultima/ultima8/world/world.cpp b/engines/ultima/ultima8/world/world.cpp
index f7192823ec..537005a18b 100644
--- a/engines/ultima/ultima8/world/world.cpp
+++ b/engines/ultima/ultima8/world/world.cpp
@@ -42,6 +42,7 @@
 #include "ultima/ultima8/world/get_object.h"
 #include "ultima/ultima8/audio/audio_process.h"
 #include "ultima/ultima8/filesys/idata_source.h"
+#include "ultima/ultima8/usecode/intrinsics.h"
 
 namespace Ultima {
 namespace Ultima8 {
@@ -50,7 +51,8 @@ namespace Ultima8 {
 
 World *World::_world = nullptr;
 
-World::World() : _currentMap(nullptr), _alertActive(false), _difficulty(1) {
+World::World() : _currentMap(nullptr), _alertActive(false), _difficulty(1),
+				 _controlledNPCNum(1) {
 	debugN(MM_INFO, "Creating World...\n");
 
 	_world = this;
@@ -442,6 +444,10 @@ void World::setAlertActive(bool active)
 	}
 }
 
+void World::setControlledNPCNum(uint16 num) {
+	warning("TODO: World::setControlledNPCNum(%d): IMPLEMENT ME", num);
+}
+
 uint32 World::I_getAlertActive(const uint8 * /*args*/,
 	unsigned int /*argsize*/) {
 	return get_instance()->_world->isAlertActive() ? 1 : 0;
@@ -464,5 +470,17 @@ uint32 World::I_gameDifficulty(const uint8 * /*args*/,
 	return get_instance()->_world->getGameDifficulty();
 }
 
+uint32 World::I_getControlledNPCNum(const uint8 * /*args*/,
+	unsigned int /*argsize*/) {
+	return get_instance()->_world->getControlledNPCNum();
+}
+
+uint32 World::I_setControlledNPCNum(const uint8 *args,
+	unsigned int /*argsize*/) {
+	ARG_UINT16(num);
+	get_instance()->_world->setControlledNPCNum(num);
+	return 0;
+}
+
 } // End of namespace Ultima8
 } // End of namespace Ultima
diff --git a/engines/ultima/ultima8/world/world.h b/engines/ultima/ultima8/world/world.h
index 9dcdb71c15..2baf2ce6a6 100644
--- a/engines/ultima/ultima8/world/world.h
+++ b/engines/ultima/ultima8/world/world.h
@@ -152,10 +152,17 @@ public:
 		_difficulty = difficulty;
 	}
 
+	uint16 getControlledNPCNum() const {
+		return _controlledNPCNum;
+	}
+	void setControlledNPCNum(uint16 num);
+
 	INTRINSIC(I_getAlertActive); // for Crusader
 	INTRINSIC(I_setAlertActive); // for Crusader
 	INTRINSIC(I_clrAlertActive); // for Crusader
 	INTRINSIC(I_gameDifficulty); // for Crusader
+	INTRINSIC(I_getControlledNPCNum); // for Crusader
+	INTRINSIC(I_setControlledNPCNum); // for Crusader
 
 private:
 	static World *_world;
@@ -167,6 +174,7 @@ private:
 
 	bool _alertActive; //!< is intruder alert active (Crusader)
 	uint8 _difficulty; //!< game difficulty level (Crusader)
+	uint16 _controlledNPCNum; //!< Current controlled NPC (normally 1, the avatar)
 
 };
 


Commit: 84eebe3e7d83d2e8957320b3035b52de572341fd
    https://github.com/scummvm/scummvm/commit/84eebe3e7d83d2e8957320b3035b52de572341fd
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-07-20T14:33:20+09:00

Commit Message:
ULTIMA8: Add Crusader fire type data

Changed paths:
  A engines/ultima/ultima8/world/fire_type.cpp
  A engines/ultima/ultima8/world/fire_type.h
  A engines/ultima/ultima8/world/fire_type_table.cpp
  A engines/ultima/ultima8/world/fire_type_table.h
    engines/ultima/module.mk
    engines/ultima/ultima8/games/game_data.cpp
    engines/ultima/ultima8/games/game_data.h


diff --git a/engines/ultima/module.mk b/engines/ultima/module.mk
index 277af7252d..fa9af239a8 100644
--- a/engines/ultima/module.mk
+++ b/engines/ultima/module.mk
@@ -533,6 +533,8 @@ MODULE_OBJS := \
 	ultima8/world/egg.o \
 	ultima8/world/egg_hatcher_process.o \
 	ultima8/world/fireball_process.o \
+	ultima8/world/fire_type.o \
+	ultima8/world/fire_type_table.o \
 	ultima8/world/get_object.o \
 	ultima8/world/glob_egg.o \
 	ultima8/world/gravity_process.o \
diff --git a/engines/ultima/ultima8/games/game_data.cpp b/engines/ultima/ultima8/games/game_data.cpp
index 6a90cde653..9e93aa478e 100644
--- a/engines/ultima/ultima8/games/game_data.cpp
+++ b/engines/ultima/ultima8/games/game_data.cpp
@@ -31,6 +31,7 @@
 #include "ultima/ultima8/graphics/fonts/font_shape_archive.h"
 #include "ultima/ultima8/graphics/gump_shape_archive.h"
 #include "ultima/ultima8/world/map_glob.h"
+#include "ultima/ultima8/world/fire_type_table.h"
 #include "ultima/ultima8/world/actors/npc_dat.h"
 #include "ultima/ultima8/world/actors/combat_dat.h"
 #include "ultima/ultima8/graphics/palette_manager.h"
@@ -503,6 +504,10 @@ const CombatDat *GameData::getCombatDat(uint16 entry) const {
 	return nullptr;
 }
 
+const FireType *GameData::getFireType(uint16 type) const {
+	return FireTypeTable::get(type);
+}
+
 void GameData::loadRemorseData() {
 	FileSystem *filesystem = FileSystem::get_instance();
 
@@ -655,14 +660,6 @@ void GameData::loadRemorseData() {
 		}
 		delete combatflexrs;
 	}
-	// TODO: What's in this flex file?  Descriptions of combat tactics?
-	// 14 objects with contents:
-	// [ 16 Byte Name ]
-	// [ 4 * 16 bit numbers, alway 44, xx, 77, 78 ]
-	// [ 20 bytes of 0s ]
-	// [ variable number of bytes of data ]
-	//_combat = new CombatDat();
-	//_combat->load(combatflex);
 
 	delete combatflex;
 
diff --git a/engines/ultima/ultima8/games/game_data.h b/engines/ultima/ultima8/games/game_data.h
index 3a8d11d514..d0a54f9814 100644
--- a/engines/ultima/ultima8/games/game_data.h
+++ b/engines/ultima/ultima8/games/game_data.h
@@ -41,6 +41,7 @@ class MusicFlex;
 class WpnOvlayDat;
 class NPCDat;
 class CombatDat;
+class FireType;
 class ShapeFrame;
 class SoundFlex;
 class SpeechFlex;
@@ -98,6 +99,8 @@ public:
 
 	const CombatDat *getCombatDat(uint16 entry) const;
 
+	const FireType *getFireType(uint16 type) const;
+
 	Std::string translate(const Std::string &text);
 	FrameID translate(FrameID frame);
 
diff --git a/engines/ultima/ultima8/world/fire_type.cpp b/engines/ultima/ultima8/world/fire_type.cpp
new file mode 100644
index 0000000000..44622eb7cc
--- /dev/null
+++ b/engines/ultima/ultima8/world/fire_type.cpp
@@ -0,0 +1,156 @@
+/* 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/sprite_process.h"
+#include "ultima/ultima8/world/fire_type.h"
+#include "ultima/ultima8/kernel/kernel.h"
+#include "ultima/ultima8/audio/audio_process.h"
+
+namespace Ultima {
+namespace Ultima8 {
+
+FireType::FireType(uint16 typeNo, uint16 minDamage, uint16 maxDamage, uint8 range,
+				 uint8 numShots, uint16 shieldCost, uint8 shieldMask, uint8 accurate,
+				 uint16 cellsPerRound, uint16 roundDuration, uint8 nearSprite) :
+	_typeNo(typeNo), _minDamage(minDamage), _maxDamage(maxDamage),
+	_range(range), _numShots(numShots), _shieldCost(shieldCost),
+	_shieldMask(shieldMask), _accurate(accurate),
+	_cellsPerRound(cellsPerRound), _roundDuration(roundDuration),
+	_nearSprite(nearSprite) {
+}
+
+uint16 FireType::getRandomDamage() const {
+	return _minDamage + (getRandom() % (_maxDamage - _minDamage));
+}
+
+
+// TODO: This is all hard coded values for No Remorse. These should probably
+// be moved into ini file settings so that it can be swapped out for No Regret.
+static const int16 FIRESOUND_1[] = { 0x26, 0x27, 0x41, 0x42, 0x45, 0x46 };
+static const int16 FIRESOUND_3[] = { 0x1c, 0x6c, 0x3e };
+static const int16 FIRESOUND_7[] = { 0x48, 0x5 };
+
+static const int16 FIRESHAPE_3[] = { 0x326, 0x320, 0x321 };
+static const int16 FIRESHAPE_10[] = { 0x31c, 0x31f, 0x322 };
+
+void FireType::makeBulletSplashShapeAndPlaySound(int32 x, int32 y, int32 z) const {
+	int16 sfxno = 0;
+	int16 shape = 0;
+
+	// First randomize the sprite and sound
+	switch (_typeNo) {
+		case 1:
+		case 0xb:
+			shape = 0x1d8;
+			sfxno = FIRESOUND_1[getRandom() % 6];
+			break;
+		case 2:
+			shape = 0x1d8;
+			break;
+		case 3:
+		case 4:
+			shape = FIRESHAPE_3[getRandom() % 3];
+			sfxno = FIRESOUND_3[getRandom() % 3];
+			break;
+		case 5:
+			shape = 0x573;
+			break;
+		case 6:
+			shape = 0x578;
+			break;
+		case 7:
+			shape = 0x537;
+			sfxno = FIRESOUND_7[getRandom() % 2];
+			break;
+		case 10:
+			shape = FIRESHAPE_10[getRandom() % 3];
+			sfxno = FIRESOUND_3[getRandom() % 3];
+			break;
+		case 0xd:
+			shape = 0x1d8;
+			sfxno = FIRESOUND_1[getRandom() % 6];
+			break;
+		case 0xe:
+			shape = 0x56b;
+			break;
+		case 0xf:
+			shape = 0x59b;
+			sfxno = FIRESOUND_7[getRandom() % 2];
+			break;
+		case 9:
+		default:
+			shape = 0x537;
+			break;
+	}
+
+	int16 firstframe = 0;
+	int16 lastframe = 0x27;
+
+	// now randomize frames
+	switch (shape) {
+	case 0x56b:
+		firstframe = (getRandom() % 3) * 6;
+		lastframe = firstframe + 5;
+			break;
+	case 0x537:
+		lastframe = 10;
+	case 0x578:
+		firstframe = (getRandom() % 3) * 6;
+		lastframe = firstframe + 4;
+	case 0x59b:
+		firstframe = (getRandom() % 2) * 4;
+		lastframe = firstframe + 3;
+	case 0x1d8: {
+		switch (getRandom() % 4) {
+			case 0:
+				lastframe = 4;
+				break;
+			case 1:
+				firstframe = 5;
+				lastframe = 8;
+				break;
+			case 2:
+				firstframe = 9;
+				lastframe = 0xc;
+				break;
+			case 3:
+				firstframe = 0xd;
+				lastframe = 0x10;
+				break;
+		}
+		break;
+	}
+	}
+
+	SpriteProcess *sprite = new SpriteProcess(shape, firstframe, lastframe, 1, 3, x, y, z);
+	Kernel::get_instance()->addProcess(sprite);
+
+	AudioProcess *audio = AudioProcess::get_instance();
+	if (sfxno && audio) {
+		audio->playSFX(sfxno, 0x10, 0, 1, false);
+	}
+}
+
+}
+}
diff --git a/engines/ultima/ultima8/world/fire_type.h b/engines/ultima/ultima8/world/fire_type.h
new file mode 100644
index 0000000000..b31d8a1d5e
--- /dev/null
+++ b/engines/ultima/ultima8/world/fire_type.h
@@ -0,0 +1,103 @@
+/* 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 ULTIMA8_WORLD_FIRETYPE_H
+#define ULTIMA8_WORLD_FIRETYPE_H
+
+namespace Ultima {
+namespace Ultima8 {
+
+/**
+ * A structure to hold data about the fire that comes from various weapons
+ */
+class FireType {
+public:
+	FireType(uint16 typeNo, uint16 minDamage, uint16 maxDamage, uint8 range,
+			 uint8 numShots, uint16 shieldCost, uint8 shieldMask, uint8 accurate,
+			 uint16 cellsPerRound, uint16 roundDuration, uint8 nearSprite);
+
+	uint16 getTypeNo() const {
+		return _typeNo;
+	}
+
+	uint16 getMinDamage() const {
+		return _minDamage;
+	}
+
+	uint16 getMaxDamage() const {
+		return _maxDamage;
+	}
+
+	uint8 getRange() const {
+		return _range;
+	}
+
+	uint8 getNumShots() const {
+		return _numShots;
+	}
+
+	uint16 getShieldCost() const {
+		return _shieldCost;
+	}
+
+	uint8 getShieldMask() const {
+		return _shieldMask;
+	}
+
+	uint8 getAccurate() const {
+		return _accurate;
+	}
+
+	uint16 getCellsPerRound() const {
+		return _cellsPerRound;
+	}
+
+	uint16 getRoundDuration() const {
+		return _roundDuration;
+	}
+
+	uint8 getNearSprite() const {
+		return _nearSprite;
+	}
+
+	uint16 getRandomDamage() const;
+
+	void makeBulletSplashShapeAndPlaySound(int32 x, int32 y, int32 z) const;
+
+private:
+	uint16 _typeNo;
+	uint16 _minDamage;
+	uint16 _maxDamage;
+	uint8 _range;
+	uint8 _numShots;
+	uint16 _shieldCost;
+	uint8 _shieldMask;
+	uint8 _accurate;
+	uint16 _cellsPerRound;
+	uint16 _roundDuration;
+	uint8 _nearSprite;
+};
+
+}
+}
+
+#endif
diff --git a/engines/ultima/ultima8/world/fire_type_table.cpp b/engines/ultima/ultima8/world/fire_type_table.cpp
new file mode 100644
index 0000000000..132ecd7c4d
--- /dev/null
+++ b/engines/ultima/ultima8/world/fire_type_table.cpp
@@ -0,0 +1,60 @@
+/* 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/fire_type_table.h"
+#include "ultima/ultima8/world/fire_type.h"
+
+namespace Ultima {
+namespace Ultima8 {
+
+static FireType FIRE_TYPE_TABLE_REM[] = {
+	// Extracted from CRUSADER.EXE 1478:252a
+	FireType(0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0),
+	FireType(0x1, 0x12, 0x19, 0x0, 0x1, 0x82, 0x7, 0x0, 0xc, 0x3e8, 0x0),
+	FireType(0x2, 0xa, 0x11, 0x0, 0x8, 0x50, 0x7, 0x0, 0xc, 0x3e8, 0x0),
+	FireType(0x3, 0xc8, 0xc8, 0xa, 0x1, 0x0, 0x0, 0x1, 0x3, 0x3e8, 0x1),
+	FireType(0x4, 0x96, 0x96, 0xa, 0x1, 0x0, 0x0, 0x0, 0x1, 0x3e8, 0x1),
+	FireType(0x5, 0x19, 0x2d, 0x0, 0x1, 0x190, 0x6, 0x0, 0x4, 0x3e8, 0x1),
+	FireType(0x6, 0xf, 0x23, 0x0, 0x1, 0x177, 0x6, 0x1, 0x4, 0x3e8, 0x1),
+	FireType(0x7, 0x5, 0x5, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x3e8, 0x1),
+	FireType(0x8, 0x5, 0x5, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x3e8, 0x0),
+	FireType(0x9, 0xa, 0xf, 0x0, 0x1, 0x12c, 0x6, 0x1, 0x1, 0x64, 0x1),
+	FireType(0xa, 0x2d, 0x50, 0xa, 0x3, 0x0, 0x0, 0x0, 0x3, 0x64, 0x1),
+	FireType(0xb, 0xe, 0x14, 0x0, 0x1, 0x50, 0x7, 0x0, 0xc, 0x3e8, 0x0),
+	FireType(0xc, 0x5, 0x5, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x3e8, 0x0),
+	FireType(0xd, 0xa, 0x11, 0x0, 0x5, 0x50, 0x7, 0x0, 0xc, 0x3e8, 0x0),
+	FireType(0xe, 0xfa, 0xfa, 0x4, 0x1, 0x9c4, 0x4, 0x1, 0x3, 0x3e8, 0x1),
+	FireType(0xf, 0x23, 0x37, 0x4, 0x1, 0x2ee, 0x4, 0x0, 0x3, 0x3e8, 0x1),
+};
+
+static const int FIRE_TYPE_TABLE_LEN = 16;
+
+const FireType *FireTypeTable::get(uint16 type) {
+	if (type >= FIRE_TYPE_TABLE_LEN)
+		return nullptr;
+	return &FIRE_TYPE_TABLE_REM[type];
+}
+
+} // End of namespace Ultima8
+} // End of namespace Ultima
diff --git a/engines/ultima/ultima8/world/fire_type_table.h b/engines/ultima/ultima8/world/fire_type_table.h
new file mode 100644
index 0000000000..fecb8a3dd7
--- /dev/null
+++ b/engines/ultima/ultima8/world/fire_type_table.h
@@ -0,0 +1,39 @@
+/* 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 ULTIMA8_WORLD_FIRETYPETABLE_H
+#define ULTIMA8_WORLD_FIRETYPETABLE_H
+
+namespace Ultima {
+namespace Ultima8 {
+
+class FireType;
+
+class FireTypeTable {
+public:
+	static const FireType *get(uint16 firetype);
+};
+
+}
+}
+
+#endif


Commit: 601e996678cebbd9d1547d4c6472db2eea47e872
    https://github.com/scummvm/scummvm/commit/601e996678cebbd9d1547d4c6472db2eea47e872
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-07-20T14:34:48+09:00

Commit Message:
ULTIMA8: Add helper to get controlled actor

Changed paths:
    engines/ultima/ultima8/world/get_object.cpp
    engines/ultima/ultima8/world/get_object.h


diff --git a/engines/ultima/ultima8/world/get_object.cpp b/engines/ultima/ultima8/world/get_object.cpp
index f81ad8ea4a..5b9e15ff7b 100644
--- a/engines/ultima/ultima8/world/get_object.cpp
+++ b/engines/ultima/ultima8/world/get_object.cpp
@@ -26,6 +26,7 @@
 #include "ultima/ultima8/kernel/object_manager.h"
 #include "ultima/ultima8/world/actors/main_actor.h"
 #include "ultima/ultima8/gumps/gump.h"
+#include "ultima/ultima8/world/world.h"
 
 namespace Ultima {
 namespace Ultima8 {
@@ -52,6 +53,11 @@ MainActor *getMainActor() {
 	return dynamic_cast<MainActor *>(ObjectManager::get_instance()->getObject(1));
 }
 
+Actor *getControlledActor() {
+	uint16 num = World::get_instance()->getControlledNPCNum();
+	return dynamic_cast<Actor *>(ObjectManager::get_instance()->getObject(num));
+}
+
 Gump *getGump(ObjId id) {
 	return dynamic_cast<Gump *>(ObjectManager::get_instance()->getObject(id));
 }
diff --git a/engines/ultima/ultima8/world/get_object.h b/engines/ultima/ultima8/world/get_object.h
index 6ef6e648f2..da6b4997d0 100644
--- a/engines/ultima/ultima8/world/get_object.h
+++ b/engines/ultima/ultima8/world/get_object.h
@@ -40,6 +40,7 @@ Item *getItem(ObjId id);
 Container *getContainer(ObjId id);
 Actor *getActor(ObjId id);
 MainActor *getMainActor();
+Actor *getControlledActor();
 
 Gump *getGump(ObjId id);
 


Commit: 4641ec23048193bad3b7fdf776ea0e09aa6f5fad
    https://github.com/scummvm/scummvm/commit/4641ec23048193bad3b7fdf776ea0e09aa6f5fad
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-07-20T14:36:09+09:00

Commit Message:
ULTIMA8: Force target reticle update when avatar dies

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 3327d337d0..17425aa2b4 100644
--- a/engines/ultima/ultima8/world/actors/main_actor.cpp
+++ b/engines/ultima/ultima8/world/actors/main_actor.cpp
@@ -27,6 +27,7 @@
 #include "ultima/ultima8/kernel/process.h"
 #include "ultima/ultima8/kernel/kernel.h"
 #include "ultima/ultima8/world/actors/teleport_to_egg_process.h"
+#include "ultima/ultima8/world/target_reticle_process.h"
 #include "ultima/ultima8/world/camera_process.h"
 #include "ultima/ultima8/world/actors/animation.h"
 #include "ultima/ultima8/ultima8.h"
@@ -506,10 +507,15 @@ ProcId MainActor::die(uint16 damageType) {
 	deathproc->waitFor(delayproc);
 
 	MusicProcess *music = MusicProcess::get_instance();
-	if (music) {
+	if (GAME_IS_U8 && music) {
 		music->unqueueMusic();
 		music->playCombatMusic(44); // CONSTANT!!
-	};
+	}
+
+	if (GAME_IS_CRUSADER) {
+		// Force a reticle update
+		TargetReticleProcess::get_instance()->avatarMoved();
+	}
 
 	return animprocid;
 }


Commit: 3bcb0fe8ed8a10e46092dc96dc3392edd6060131
    https://github.com/scummvm/scummvm/commit/3bcb0fe8ed8a10e46092dc96dc3392edd6060131
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-07-20T14:45:22+09:00

Commit Message:
ULTIMA8: Fix some coverity-identified issues

Changed paths:
    engines/ultima/ultima8/world/item_selection_process.cpp
    engines/ultima/ultima8/world/item_selection_process.h


diff --git a/engines/ultima/ultima8/world/item_selection_process.cpp b/engines/ultima/ultima8/world/item_selection_process.cpp
index 7445f63e26..a30bd2aa7d 100644
--- a/engines/ultima/ultima8/world/item_selection_process.cpp
+++ b/engines/ultima/ultima8/world/item_selection_process.cpp
@@ -74,10 +74,11 @@ bool ItemSelectionProcess::selectNextItem() {
 	for (unsigned int i = 0; i < uclist.getSize(); ++i) {
 		ObjId itemid = uclist.getuint16(i);
 		Item *item = getItem(itemid);
-		const ShapeInfo *info = item->getShapeInfo();
-
 		if (!item)
 			continue;
+
+		const ShapeInfo *info = item->getShapeInfo();
+
 		// Maybe this can be done with a loopscript,
 		// but this is how the game does it..
 		if (item->hasFlags(Actor::FLG_HANGING))
diff --git a/engines/ultima/ultima8/world/item_selection_process.h b/engines/ultima/ultima8/world/item_selection_process.h
index 8dc47f94b0..afd3a86919 100644
--- a/engines/ultima/ultima8/world/item_selection_process.h
+++ b/engines/ultima/ultima8/world/item_selection_process.h
@@ -67,10 +67,6 @@ private:
 	void putItemSelectionOnItem(Item *item);
 
 	uint16 _selectedItem;
-    int32 _ax;
-    int32 _ay;
-    int32 _az;
-    uint16 _adir;
 
 	static ItemSelectionProcess *_instance;
 };




More information about the Scummvm-git-logs mailing list