[Scummvm-git-logs] scummvm master -> 8329f5280b5a87eaaf5f2a181bed749c0d3df424

mduggan mgithub at guarana.org
Mon Dec 28 08:57:38 UTC 2020


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

Summary:
fb8e638e5a ULTIMA8: Correct comment
5ca7f7dfd1 ULTIMA8: Fix splash damage in Crusader
c5ed838bb9 ULTIMA8: Check for terminated state of old fader
296fc3662c ULTIMA8: Small refactor for gump finder function
c6920d258a ULTIMA8: Refactor Crusader pickup gumps to recycle existing gumps
b3ced0b190 ULTIMA8: Ensure dir is corrected when switching dirmodes
fabfa02b8b ULTIMA8: Use correct dirmode functions in attack process
b4330e0aae ULTIMA8: Small pathfinder optimizations
1bd9936f37 ULTIMA8: Small const correctness improvement
606afd7e54 ULTIMA8: Remove magic number
9abb14326e ULTIMA8: Intrinsic improvements for Crusader
b7c5ad8a95 ULTIMA8: Remove TODO comments that are done
8329f5280b ULTIMA8: Avoid duplicate weapon-ready animations


Commit: fb8e638e5ab786e06c83bdd77e4bfb35d485e7bb
    https://github.com/scummvm/scummvm/commit/fb8e638e5ab786e06c83bdd77e4bfb35d485e7bb
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-12-28T17:56:32+09:00

Commit Message:
ULTIMA8: Correct comment

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


diff --git a/engines/ultima/ultima8/world/crosshair_process.cpp b/engines/ultima/ultima8/world/crosshair_process.cpp
index f395085f0d..00af5317aa 100644
--- a/engines/ultima/ultima8/world/crosshair_process.cpp
+++ b/engines/ultima/ultima8/world/crosshair_process.cpp
@@ -59,7 +59,7 @@ void CrosshairProcess::run() {
 		cz += az / 4;
 		// TODO: Get the fine angle of the avatar once that is implemented.
 		uint16 dir = (mainactor->getDir() + 4) % 16;
-		// Dir is 0~7, convert to 0~15/8*pi
+		// Dir is 0~15, convert to 0~15/8*pi
 		float angle = (3.14 * dir / 8.0);
 		float xoff = CROSSHAIR_DIST * cos(angle);
 		float yoff = CROSSHAIR_DIST * sin(angle);


Commit: 5ca7f7dfd161e2811d82826ff09c3cacd101876b
    https://github.com/scummvm/scummvm/commit/5ca7f7dfd161e2811d82826ff09c3cacd101876b
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-12-28T17:56:32+09:00

Commit Message:
ULTIMA8: Fix splash damage in Crusader

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


diff --git a/engines/ultima/ultima8/world/fire_type.cpp b/engines/ultima/ultima8/world/fire_type.cpp
index 6c6ca3674c..a0c0014bd8 100644
--- a/engines/ultima/ultima8/world/fire_type.cpp
+++ b/engines/ultima/ultima8/world/fire_type.cpp
@@ -49,6 +49,8 @@ FireType::FireType(uint16 typeNo, uint16 minDamage, uint16 maxDamage, uint8 rang
 }
 
 uint16 FireType::getRandomDamage() const {
+	if (_minDamage == _maxDamage)
+		return _minDamage;
 	return _minDamage + (getRandom() % (_maxDamage - _minDamage));
 }
 
@@ -173,15 +175,20 @@ void FireType::applySplashDamageAround(const Point3 &pt, int damage, const Item
 	CurrentMap *currentmap = World::get_instance()->getCurrentMap();
 
 	//
-	// Find items in range and apply splash damage
+	// Find items in range and apply splash damage.  Coordinates here are 2x the
+	// original game code (in line with our other x2 multipliers for game coords)
 	//
 	UCList uclist(2);
 	LOOPSCRIPT(script, LS_TOKEN_TRUE); // we want all items
 	currentmap->areaSearch(&uclist, script, sizeof(script), nullptr,
-						   getRange() * 16, true);
+						   getRange() * 32, true, pt.x, pt.y);
 	for (unsigned int i = 0; i < uclist.getSize(); ++i) {
 		Item *splashitem = getItem(uclist.getuint16(i));
-		assert(splashitem);
+		if (!splashitem) {
+			// already gone - probably got destroyed by some chain-reaction?
+			continue;
+		}
+
 		//
 		// Other items don't get splash damage from their own fire.. but the
 		// player does.  Life is not fair..
@@ -194,7 +201,7 @@ void FireType::applySplashDamageAround(const Point3 &pt, int damage, const Item
 			Point3 pt2;
 			splashitem->getLocation(pt2);
 			int splashrange = pt.maxDistXYZ(pt2);
-			splashrange = (splashrange / 16) / 3;
+			splashrange = (splashrange / 32) / 3;
 			if (splashrange)
 				splashitemdamage /= splashrange;
 		}
diff --git a/engines/ultima/ultima8/world/item.cpp b/engines/ultima/ultima8/world/item.cpp
index 99e4610b7c..d8a5e6ecfe 100644
--- a/engines/ultima/ultima8/world/item.cpp
+++ b/engines/ultima/ultima8/world/item.cpp
@@ -2055,21 +2055,29 @@ void Item::explode(int explosion_type, bool destroy_item, bool cause_damage) {
 	if (!cause_damage)
 		return;
 
-	UCList itemlist(2);
-	LOOPSCRIPT(script, LS_TOKEN_TRUE); // we want all items
-	CurrentMap *currentmap = World::get_instance()->getCurrentMap();
-	currentmap->areaSearch(&itemlist, script, sizeof(script), 0,
-	                       160, false, xv, yv); //! CHECKME: 128?
-
-	for (unsigned int i = 0; i < itemlist.getSize(); ++i) {
-		Item *item = getItem(itemlist.getuint16(i));
-		if (!item) continue;
-		if (getRange(*item, true) > 160) continue; // check vertical distance
+	if (GAME_IS_U8) {
+		UCList itemlist(2);
+		LOOPSCRIPT(script, LS_TOKEN_TRUE); // we want all items
+		CurrentMap *currentmap = World::get_instance()->getCurrentMap();
+		currentmap->areaSearch(&itemlist, script, sizeof(script), 0,
+							   160, false, xv, yv); //! CHECKME: 128?
+
+		for (unsigned int i = 0; i < itemlist.getSize(); ++i) {
+			Item *item = getItem(itemlist.getuint16(i));
+			if (!item) continue;
+			if (getRange(*item, true) > 160) continue; // check vertical distance
 
-		item->getLocation(xv, yv, zv);
-		Direction dir = Direction_GetWorldDir(xv - xv, yv - yv, dirmode_8dirs); //!! CHECKME
-		item->receiveHit(0, dir, 6 + (getRandom() % 6),
-		                 WeaponInfo::DMG_BLUNT | WeaponInfo::DMG_FIRE);
+			item->getLocation(xv, yv, zv);
+			Direction dir = Direction_GetWorldDir(xv - xv, yv - yv, dirmode_8dirs); //!! CHECKME
+			item->receiveHit(0, dir, 6 + (getRandom() % 6),
+							 WeaponInfo::DMG_BLUNT | WeaponInfo::DMG_FIRE);
+		}
+	} else {
+		Point3 pt;
+		getLocation(pt);
+		const FireType *firetypedat = GameData::get_instance()->getFireType(4);
+		int damage = firetypedat->getRandomDamage();
+		firetypedat->applySplashDamageAround(pt, damage, this, this);
 	}
 }
 


Commit: c5ed838bb90ef11ceebacda0c2b7d29fefc54f1f
    https://github.com/scummvm/scummvm/commit/c5ed838bb90ef11ceebacda0c2b7d29fefc54f1f
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-12-28T17:56:32+09:00

Commit Message:
ULTIMA8: Check for terminated state of old fader

Fixes a corner case if old global fader finishes on the same frame a new one is
created.

Changed paths:
    engines/ultima/ultima8/graphics/palette_fader_process.cpp


diff --git a/engines/ultima/ultima8/graphics/palette_fader_process.cpp b/engines/ultima/ultima8/graphics/palette_fader_process.cpp
index 2a04af64e2..2d6cb9a5c9 100644
--- a/engines/ultima/ultima8/graphics/palette_fader_process.cpp
+++ b/engines/ultima/ultima8/graphics/palette_fader_process.cpp
@@ -133,8 +133,10 @@ uint32 PaletteFaderProcess::I_fadeToPaletteTransform(const uint8 *args,
 	ARG_UINT16(priority);
 
 	// If current _fader has higher _priority, we do nothing
-	if (_fader && _fader->_priority > priority) return 0;
-	else if (_fader) _fader->terminate();
+	if (_fader && _fader->_priority > priority)
+		return 0;
+	else if (_fader && !_fader->is_terminated())
+		_fader->terminate();
 
 	_fader = new PaletteFaderProcess(static_cast<PalTransforms>(transform),
 	                                priority, 45);
@@ -144,8 +146,10 @@ uint32 PaletteFaderProcess::I_fadeToPaletteTransform(const uint8 *args,
 
 uint32 PaletteFaderProcess::I_fadeToBlack(const uint8 *args,
         unsigned int argsize) {
-	if (_fader && _fader->_priority > 0x7FFF) return 0;
-	else if (_fader) _fader->terminate();
+	if (_fader && _fader->_priority > 0x7FFF)
+		return 0;
+	else if (_fader && !_fader->is_terminated())
+		_fader->terminate();
 
 	int nsteps = (GAME_IS_U8 ? 30 : 40);
 	if (argsize > 0) {
@@ -163,8 +167,10 @@ uint32 PaletteFaderProcess::I_fadeToBlack(const uint8 *args,
 
 uint32 PaletteFaderProcess::I_fadeFromBlack(const uint8 *args,
         unsigned int argsize) {
-	if (_fader && _fader->_priority > 0x7FFF) return 0;
-	else if (_fader) _fader->terminate();
+	if (_fader && _fader->_priority > 0x7FFF)
+		return 0;
+	else if (_fader && !_fader->is_terminated())
+		_fader->terminate();
 
 	int nsteps = (GAME_IS_U8 ? 30 : 40);
 	if (argsize > 0) {
@@ -182,8 +188,10 @@ uint32 PaletteFaderProcess::I_fadeFromBlack(const uint8 *args,
 
 uint32 PaletteFaderProcess::I_fadeToWhite(const uint8 * /*args*/,
         unsigned int /*argsize*/) {
-	if (_fader && _fader->_priority > 0x7FFF) return 0;
-	else if (_fader) _fader->terminate();
+	if (_fader && _fader->_priority > 0x7FFF)
+		return 0;
+	else if (_fader && !_fader->is_terminated())
+		_fader->terminate();
 
 	_fader = new PaletteFaderProcess(0x00FFFFFF, false, 0x7FFF, 30, true);
 	return Kernel::get_instance()->addProcess(_fader);
@@ -191,8 +199,10 @@ uint32 PaletteFaderProcess::I_fadeToWhite(const uint8 * /*args*/,
 
 uint32 PaletteFaderProcess::I_fadeFromWhite(const uint8 * /*args*/,
         unsigned int /*argsize*/) {
-	if (_fader && _fader->_priority > 0x7FFF) return 0;
-	else if (_fader) _fader->terminate();
+	if (_fader && _fader->_priority > 0x7FFF)
+		return 0;
+	else if (_fader && !_fader->is_terminated())
+		_fader->terminate();
 
 	_fader = new PaletteFaderProcess(0x00FFFFFF, true, 0x7FFF, 30, false);
 	return Kernel::get_instance()->addProcess(_fader);
@@ -200,8 +210,10 @@ uint32 PaletteFaderProcess::I_fadeFromWhite(const uint8 * /*args*/,
 
 uint32 PaletteFaderProcess::I_lightningBolt(const uint8 * /*args*/,
         unsigned int /*argsize*/) {
-	if (_fader && _fader->_priority > -1) return 0;
-	else if (_fader) _fader->terminate();
+	if (_fader && _fader->_priority > -1)
+		return 0;
+	else if (_fader && !_fader->is_terminated())
+		_fader->terminate();
 
 	_fader = new PaletteFaderProcess(0x3FCFCFCF, true, -1, 10, false);
 	return Kernel::get_instance()->addProcess(_fader);


Commit: 296fc3662c02707ffc05851e57b0872f73238d88
    https://github.com/scummvm/scummvm/commit/296fc3662c02707ffc05851e57b0872f73238d88
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-12-28T17:56:32+09:00

Commit Message:
ULTIMA8: Small refactor for gump finder function

Changed paths:
    engines/ultima/ultima8/gumps/gump.h
    engines/ultima/ultima8/gumps/keypad_gump.cpp
    engines/ultima/ultima8/gumps/weasel_gump.cpp


diff --git a/engines/ultima/ultima8/gumps/gump.h b/engines/ultima/ultima8/gumps/gump.h
index 93f8e8c88a..4e48e5ea02 100644
--- a/engines/ultima/ultima8/gumps/gump.h
+++ b/engines/ultima/ultima8/gumps/gump.h
@@ -124,6 +124,9 @@ public:
 		return FindGump(&IsOfType<T>, recursive);
 	}
 
+	//! A predicate to find a ui element by its index
+	template<int T> static bool FindByIndex(const Gump *g) { return g->GetIndex() == T; }
+
 	//! Find gump (this, child or NULL) at parent coordinates (mx,my)
 	//! \return the Gump at these coordinates, or NULL if none
 	virtual Gump       *FindGump(int mx, int my);
diff --git a/engines/ultima/ultima8/gumps/keypad_gump.cpp b/engines/ultima/ultima8/gumps/keypad_gump.cpp
index d2e71e79e2..bacdeaaede 100644
--- a/engines/ultima/ultima8/gumps/keypad_gump.cpp
+++ b/engines/ultima/ultima8/gumps/keypad_gump.cpp
@@ -40,8 +40,6 @@ namespace Ultima8 {
 
 DEFINE_RUNTIME_CLASSTYPE_CODE(KeypadGump)
 
-template<int T> bool FindUiElem(const Gump *g) { return g->GetIndex() == T; }
-
 static const int TXT_CONTAINER_IDX = 0x100;
 // Actually the max val where we will allow another digit to be entered
 static const int MAX_CODE_VAL = 9999999;
@@ -167,7 +165,7 @@ void KeypadGump::ChildNotify(Gump *child, uint32 message) {
 }
 
 void KeypadGump::updateDigitDisplay() {
-	Gump *txt = Gump::FindGump(&FindUiElem<TXT_CONTAINER_IDX>);
+	Gump *txt = Gump::FindGump(&FindByIndex<TXT_CONTAINER_IDX>);
 	if (txt)
 		txt->Close();
 	txt = new Gump(25, 12, 200, 12);
diff --git a/engines/ultima/ultima8/gumps/weasel_gump.cpp b/engines/ultima/ultima8/gumps/weasel_gump.cpp
index 317abbf443..4ebacd525b 100644
--- a/engines/ultima/ultima8/gumps/weasel_gump.cpp
+++ b/engines/ultima/ultima8/gumps/weasel_gump.cpp
@@ -84,7 +84,6 @@ static const char *CANCELLED_PURCHASE_MOVIES[] = {"19C", "19D"};
 static const char *COMPLETED_PURCHASE_MOVIES[] = {"21C", "21D"};
 static const char *INSUFFICIENT_FUND_MOVIES[] = {"20C", "20D"};
 
-template<int T> bool FindUiElem(const Gump *g) { return g->GetIndex() == T; }
 
 namespace {
 // A small container gump that doesn't do anything except pass notifications to the parent
@@ -342,8 +341,8 @@ void WeaselGump::onButtonClick(int entry) {
 
 void WeaselGump::updateAmmoButtons() {
 	_ammoMode = !_ammoMode;
-	Gump *ammobtn = _ui->FindGump(&FindUiElem<kBtnAmmo>);
-	Gump *wpnbtn = _ui->FindGump(&FindUiElem<kBtnWeapons>);
+	Gump *ammobtn = _ui->FindGump(&FindByIndex<kBtnAmmo>);
+	Gump *wpnbtn = _ui->FindGump(&FindByIndex<kBtnWeapons>);
 	assert(ammobtn && wpnbtn);
 	ammobtn->SetVisibility(_ammoMode);
 	wpnbtn->SetVisibility(!_ammoMode);
@@ -415,7 +414,7 @@ void WeaselGump::checkBuyMore() {
 
 void WeaselGump::setYesNoQuestion(const Std::string &msg) {
 	browsingMode(false);
-	_closeIfExists(_ui->FindGump(&FindUiElem<kTxtQuestion>));
+	_closeIfExists(_ui->FindGump(&FindByIndex<kTxtQuestion>));
 	TextWidget *textWidget = new TextWidget(30, 100, msg, true, WEASEL_FONT, 150);
 	textWidget->InitGump(_ui);
 	textWidget->SetIndex(kTxtQuestion);
@@ -429,23 +428,23 @@ void WeaselGump::browsingMode(bool browsing) {
 
 	// Note: all these searches are not super effieient but it's
 	// not a time-sensitive function and the search is relatively short
-	Gump *yesbtn = _ui->FindGump(&FindUiElem<kBtnYes>);
-	Gump *nobtn = _ui->FindGump(&FindUiElem<kBtnNo>);
-	Gump *qtxt = _ui->FindGump(&FindUiElem<kTxtQuestion>);
-
-	Gump *buybtn = _ui->FindGump(&FindUiElem<kBtnBuy>);
-	Gump *wpnbtn = _ui->FindGump(&FindUiElem<kBtnWeapons>);
-	Gump *ammobtn = _ui->FindGump(&FindUiElem<kBtnAmmo>);
-	Gump *exitbtn = _ui->FindGump(&FindUiElem<kBtnExit>);
-	Gump *blankbtn = _ui->FindGump(&FindUiElem<kBtnBlank>);
-	Gump *leftbtn = _ui->FindGump(&FindUiElem<kBtnLeft>);
-	Gump *rightbtn = _ui->FindGump(&FindUiElem<kBtnRight>);
-	Gump *credtxt = _ui->FindGump(&FindUiElem<kTxtCredits>);
-	Gump *nametxt = _ui->FindGump(&FindUiElem<kTxtItemName>);
-	Gump *costtxt = _ui->FindGump(&FindUiElem<kTxtItemCost>);
-	Gump *purchtxt = _ui->FindGump(&FindUiElem<kTxtItemPurch>);
-	Gump *ownedtxt = _ui->FindGump(&FindUiElem<kTxtItemOwned>);
-	Gump *icon = _ui->FindGump(&FindUiElem<kIconItem>);
+	Gump *yesbtn = _ui->FindGump(&FindByIndex<kBtnYes>);
+	Gump *nobtn = _ui->FindGump(&FindByIndex<kBtnNo>);
+	Gump *qtxt = _ui->FindGump(&FindByIndex<kTxtQuestion>);
+
+	Gump *buybtn = _ui->FindGump(&FindByIndex<kBtnBuy>);
+	Gump *wpnbtn = _ui->FindGump(&FindByIndex<kBtnWeapons>);
+	Gump *ammobtn = _ui->FindGump(&FindByIndex<kBtnAmmo>);
+	Gump *exitbtn = _ui->FindGump(&FindByIndex<kBtnExit>);
+	Gump *blankbtn = _ui->FindGump(&FindByIndex<kBtnBlank>);
+	Gump *leftbtn = _ui->FindGump(&FindByIndex<kBtnLeft>);
+	Gump *rightbtn = _ui->FindGump(&FindByIndex<kBtnRight>);
+	Gump *credtxt = _ui->FindGump(&FindByIndex<kTxtCredits>);
+	Gump *nametxt = _ui->FindGump(&FindByIndex<kTxtItemName>);
+	Gump *costtxt = _ui->FindGump(&FindByIndex<kTxtItemCost>);
+	Gump *purchtxt = _ui->FindGump(&FindByIndex<kTxtItemPurch>);
+	Gump *ownedtxt = _ui->FindGump(&FindByIndex<kTxtItemOwned>);
+	Gump *icon = _ui->FindGump(&FindByIndex<kIconItem>);
 
 	yesbtn->SetVisibility(!browsing);
 	nobtn->SetVisibility(!browsing);
@@ -510,12 +509,12 @@ void WeaselGump::updateItemDisplay() {
 	}
 	Shape *shape = GameData::get_instance()->getGumps()->getShape(shapeinfo->_weaponInfo->_displayGumpShape);
 
-	_closeIfExists(_ui->FindGump(&FindUiElem<kTxtCredits>));
-	_closeIfExists(_ui->FindGump(&FindUiElem<kTxtItemName>));
-	_closeIfExists(_ui->FindGump(&FindUiElem<kTxtItemCost>));
-	_closeIfExists(_ui->FindGump(&FindUiElem<kTxtItemPurch>));
-	_closeIfExists(_ui->FindGump(&FindUiElem<kTxtItemOwned>));
-	_closeIfExists(_ui->FindGump(&FindUiElem<kIconItem>));
+	_closeIfExists(_ui->FindGump(&FindByIndex<kTxtCredits>));
+	_closeIfExists(_ui->FindGump(&FindByIndex<kTxtItemName>));
+	_closeIfExists(_ui->FindGump(&FindByIndex<kTxtItemCost>));
+	_closeIfExists(_ui->FindGump(&FindByIndex<kTxtItemPurch>));
+	_closeIfExists(_ui->FindGump(&FindByIndex<kTxtItemOwned>));
+	_closeIfExists(_ui->FindGump(&FindByIndex<kIconItem>));
 
 	Std::string credstr = Std::string::format("Credits:%d", _credits);
 	TextWidget *textWidget = new TextWidget(30, 57, credstr, true, WEASEL_FONT);


Commit: c6920d258a90a4fd717224b1de43cca4987f8325
    https://github.com/scummvm/scummvm/commit/c6920d258a90a4fd717224b1de43cca4987f8325
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-12-28T17:56:32+09:00

Commit Message:
ULTIMA8: Refactor Crusader pickup gumps to recycle existing gumps

Changed paths:
    engines/ultima/ultima8/gumps/cru_pickup_area_gump.cpp
    engines/ultima/ultima8/gumps/cru_pickup_area_gump.h
    engines/ultima/ultima8/gumps/cru_pickup_gump.cpp
    engines/ultima/ultima8/gumps/cru_pickup_gump.h


diff --git a/engines/ultima/ultima8/gumps/cru_pickup_area_gump.cpp b/engines/ultima/ultima8/gumps/cru_pickup_area_gump.cpp
index 6b8894fcd2..0d607c1fb4 100644
--- a/engines/ultima/ultima8/gumps/cru_pickup_area_gump.cpp
+++ b/engines/ultima/ultima8/gumps/cru_pickup_area_gump.cpp
@@ -42,39 +42,32 @@ CruPickupAreaGump::CruPickupAreaGump() : Gump(PICKUP_GUMP_GAP, PICKUP_GUMP_GAP,
     _instance = this;
 }
 
-CruPickupAreaGump::~CruPickupAreaGump() {
-}
-
-void CruPickupAreaGump::addPickup(Item *item) {
+void CruPickupAreaGump::addPickup(const Item *item) {
 	if (!item)
 		return;
 
 	uint32 shapeno = item->getShape();
 
 	Std::list<Gump *>::iterator it;
-	int32 yoff = 0;
-	uint16 qval = 0;
+
 	for (it = _children.begin(); it != _children.end(); it++) {
 		CruPickupGump *pug = dynamic_cast<CruPickupGump *>(*it);
 		if (!pug)
 			return;
-		int32 x;
-		pug->getLocation(x, yoff);
 		if (pug->getShapeNo() == shapeno) {
-			// Already a notification for this object, close it
-			// and make a new one in the same spot.
-			qval = pug->getQ();
-			pug->Close();
+			// Already a notification for this object, update it
+			pug->updateForNewItem(item);
 			break;
 		}
 	}
 	if (it == _children.end()) {
-		yoff += PICKUP_GUMP_GAP;
+		int32 yoff = PICKUP_GUMP_GAP;
 		if (_children.size() > 0)
 			yoff += PICKUP_GUMP_HEIGHT;
+
+		Gump *newgump = new CruPickupGump(item, yoff);
+		newgump->InitGump(this, false);
 	}
-	Gump *newgump = new CruPickupGump(item, yoff, qval);
-	newgump->InitGump(this, false);
 }
 
 CruPickupAreaGump *CruPickupAreaGump::get_instance() {
diff --git a/engines/ultima/ultima8/gumps/cru_pickup_area_gump.h b/engines/ultima/ultima8/gumps/cru_pickup_area_gump.h
index 9b3bc66f17..2138cbb334 100644
--- a/engines/ultima/ultima8/gumps/cru_pickup_area_gump.h
+++ b/engines/ultima/ultima8/gumps/cru_pickup_area_gump.h
@@ -40,10 +40,8 @@ public:
 	ENABLE_RUNTIME_CLASSTYPE()
 
 	CruPickupAreaGump();
-	CruPickupAreaGump(Item *item, int y);
-	~CruPickupAreaGump() override;
 
-	void addPickup(Item *item);
+	void addPickup(const Item *item);
 
 	static CruPickupAreaGump *get_instance();
 private:
diff --git a/engines/ultima/ultima8/gumps/cru_pickup_gump.cpp b/engines/ultima/ultima8/gumps/cru_pickup_gump.cpp
index 3919101e46..4d95a26e9d 100644
--- a/engines/ultima/ultima8/gumps/cru_pickup_gump.cpp
+++ b/engines/ultima/ultima8/gumps/cru_pickup_gump.cpp
@@ -42,20 +42,19 @@ static const int COUNT_TEXT_FONT = 12;
 static const int ITEM_TEXT_FONT = 13;
 static const int ITEM_AREA_WIDTH = 60;
 
+// A high "random" index so we can always find this..
+static const int COUNT_TEXT_INDEX = 0x100;
+
 DEFINE_RUNTIME_CLASSTYPE_CODE(CruPickupGump)
 CruPickupGump::CruPickupGump() : Gump(), _startFrame(0), _itemShapeNo(0), _q(0),
 	_gumpShapeNo(0), _gumpFrameNo(0) {
 }
 
-CruPickupGump::CruPickupGump(const Item *item, int y, uint16 currentq) : Gump(0, y, 5, 5, 0), _startFrame(0) {
+CruPickupGump::CruPickupGump(const Item *item, int y) : Gump(0, y, 5, 5, 0), _startFrame(0) {
 	const WeaponInfo *weaponInfo = item->getShapeInfo()->_weaponInfo;
 	if (weaponInfo) {
 		_itemShapeNo = item->getShape();
 		_q = item->getQuality();
-		// TODO: should we add current q? + currentq;
-		// It seems like the items are hacked to give the right "q" for
-		// this gump from the last item, which is why the add process
-		// uses q + 1 instead of adding the new q.
 		_itemName = weaponInfo->_name;
 		_gumpShapeNo = weaponInfo->_displayGumpShape;
 		_gumpFrameNo = weaponInfo->_displayGumpFrame;
@@ -67,9 +66,6 @@ CruPickupGump::CruPickupGump(const Item *item, int y, uint16 currentq) : Gump(0,
 	}
 }
 
-CruPickupGump::~CruPickupGump() {
-}
-
 void CruPickupGump::InitGump(Gump *newparent, bool take_focus) {
 	Gump::InitGump(newparent, take_focus);
 
@@ -115,11 +111,7 @@ void CruPickupGump::InitGump(Gump *newparent, bool take_focus) {
 	text->InitGump(this, false);
 
 	// Paint the count if needed
-	if (_q > 1) {
-		Std::string qstr = Std::string::format("%d", _q);
-		TextWidget *count = new TextWidget(ITEM_AREA_WIDTH / 2 + 22, _dims.height() / 2 + 3, qstr, true, COUNT_TEXT_FONT);
-		count->InitGump(this, false);
-	}
+	addCountText();
 
 	// Paint the item in the mid-left item area.
 	const ShapeFrame *itemframe = itemshape->getFrame(_gumpFrameNo);
@@ -130,6 +122,30 @@ void CruPickupGump::InitGump(Gump *newparent, bool take_focus) {
 	itemgump->Move(ITEM_AREA_WIDTH / 2 - itemframe->_width / 2, _dims.height() / 2 - itemframe->_height / 2);
 }
 
+void CruPickupGump::updateForNewItem(const Item *item) {
+	assert(item);
+	assert(item->getShape() == _itemShapeNo);
+	TextWidget *oldtext = dynamic_cast<TextWidget *>(FindGump(&FindByIndex<COUNT_TEXT_INDEX>));
+	if (oldtext)
+		oldtext->Close();
+	// TODO: should we add current q? + currentq;
+	// It seems like the items are hacked to give the right "q" for
+	// this gump from the last item, which is why the add process
+	// uses q + 1 instead of adding the new q.
+	_q = item->getQuality();
+	addCountText();
+}
+
+void CruPickupGump::addCountText() {
+	if (_q <= 1)
+		return;
+	Std::string qstr = Std::string::format("%d", _q);
+	TextWidget *count = new TextWidget(ITEM_AREA_WIDTH / 2 + 22, _dims.height() / 2 + 3, qstr, true, COUNT_TEXT_FONT);
+	count->InitGump(this, false);
+	count->SetIndex(COUNT_TEXT_INDEX);
+}
+
+
 void CruPickupGump::PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled) {
 	uint32 frameno = Kernel::get_instance()->getFrameNum();
 	if (!_itemShapeNo || frameno - _startFrame > 90) {
diff --git a/engines/ultima/ultima8/gumps/cru_pickup_gump.h b/engines/ultima/ultima8/gumps/cru_pickup_gump.h
index db27debdf9..5ffc050af6 100644
--- a/engines/ultima/ultima8/gumps/cru_pickup_gump.h
+++ b/engines/ultima/ultima8/gumps/cru_pickup_gump.h
@@ -39,10 +39,7 @@ public:
 	ENABLE_RUNTIME_CLASSTYPE()
 
 	CruPickupGump();
-	//! Create a new gump for an item pickup. CurrentQ is the value of an existing gump
-	//! so they can be combined (eg, pick up one medikit then another -> show medikit 2)
-	CruPickupGump(const Item *item, int y, uint16 currentq);
-	~CruPickupGump() override;
+	CruPickupGump(const Item *item, int y);
 
 	// Init the gump, call after construction
 	void InitGump(Gump *newparent, bool take_focus = true) override;
@@ -58,6 +55,10 @@ public:
 		return _q;
 	}
 
+	//! Update for a second item pickup - generally just replace existing count text.
+	void updateForNewItem(const Item *item);
+	void addCountText();
+
 	bool loadData(Common::ReadStream *rs, uint32 version);
 	void saveData(Common::WriteStream *ws) override;
 


Commit: b3ced0b190927ce583bf7aedc09ef92a09409e5f
    https://github.com/scummvm/scummvm/commit/b3ced0b190927ce583bf7aedc09ef92a09409e5f
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-12-28T17:56:32+09:00

Commit Message:
ULTIMA8: Ensure dir is corrected when switching dirmodes

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


diff --git a/engines/ultima/ultima8/world/actors/actor.cpp b/engines/ultima/ultima8/world/actors/actor.cpp
index 9628ab4fc7..9866ea5002 100644
--- a/engines/ultima/ultima8/world/actors/actor.cpp
+++ b/engines/ultima/ultima8/world/actors/actor.cpp
@@ -30,6 +30,7 @@
 #include "ultima/ultima8/misc/direction.h"
 #include "ultima/ultima8/misc/direction_util.h"
 #include "ultima/ultima8/games/game_data.h"
+#include "ultima/ultima8/graphics/anim_dat.h"
 #include "ultima/ultima8/graphics/main_shape_archive.h"
 #include "ultima/ultima8/graphics/shape_info.h"
 #include "ultima/ultima8/graphics/shape.h"
@@ -470,6 +471,9 @@ uint16 Actor::doAnim(Animation::Sequence anim, Direction dir, unsigned int steps
 		return 0;
 	}
 
+	if (dir == dir_current)
+		dir = getDir();
+
 #if 0
 	if (tryAnim(anim, dir)) {
 		perr << "Actor::doAnim: tryAnim = Ok!" << Std::endl;
@@ -480,9 +484,8 @@ uint16 Actor::doAnim(Animation::Sequence anim, Direction dir, unsigned int steps
 
 	if (GAME_IS_CRUSADER) {
 		// Crusader sets some flags on animation start
-		// HACK: When switching from 16-dir combat to 8-dir walking,
-		// fix the direction to only 8 dirs
-		if (anim == Animation::stand)
+		// Small hack: When switching from 16-dir to 8-dir, fix the direction
+		if (animDirMode(anim) == dirmode_8dirs)
 			dir = static_cast<Direction>(dir - (static_cast<uint32>(dir) % 2));
 		else if (anim == Animation::readyWeapon)
 			setActorFlag(ACT_WEAPONREADY);
@@ -566,8 +569,9 @@ Animation::Result Actor::tryAnim(Animation::Sequence anim, Direction dir,
 }
 
 DirectionMode Actor::animDirMode(Animation::Sequence anim) const {
-	const AnimAction *action = GameData::get_instance()->getMainShapes()->
-	getAnim(getShape(), anim);
+	int32 actionno = AnimDat::getActionNumberForSequence(anim, this);
+	const AnimAction *action = GameData::get_instance()->getMainShapes()->getAnim(getShape(), actionno);
+
 	if (!action)
 		return dirmode_8dirs;
 	return action->getDirCount() == 8 ? dirmode_8dirs : dirmode_16dirs;


Commit: fabfa02b8b13aebf00b51775c77a51969a623313
    https://github.com/scummvm/scummvm/commit/fabfa02b8b13aebf00b51775c77a51969a623313
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-12-28T17:56:32+09:00

Commit Message:
ULTIMA8: Use correct dirmode functions in attack process

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


diff --git a/engines/ultima/ultima8/world/actors/attack_process.cpp b/engines/ultima/ultima8/world/actors/attack_process.cpp
index 8f6bfa7887..645d051d35 100644
--- a/engines/ultima/ultima8/world/actors/attack_process.cpp
+++ b/engines/ultima/ultima8/world/actors/attack_process.cpp
@@ -213,14 +213,14 @@ void AttackProcess::run() {
 		case 0x88:
 		{
 			// Turn 90 degrees left
-			Direction newdir = Direction_OneLeft(Direction_OneLeft(curdir, dirmode_8dirs), dirmode_8dirs);
+			Direction newdir = Direction_TurnByDelta(curdir, -2, dirmode_8dirs);
 			a->turnTowardDir(newdir);
 			return;
 		}
 		case 0x89:
 		{
 			// Turn 90 degrees right
-			Direction newdir = Direction_OneRight(Direction_OneLeft(curdir, dirmode_8dirs), dirmode_8dirs);
+			Direction newdir = Direction_TurnByDelta(curdir, 2, dirmode_8dirs);
 			a->turnTowardDir(newdir);
 			return;
 		}
@@ -563,15 +563,13 @@ void AttackProcess::genericAttack() {
 			return;
 		}
 	} else {
-		// TODO: Get directions anim has (8 or 16)
-		DirectionMode standDirMode = dirmode_8dirs;
-		/*
 		Animation::Sequence anim;
 		if (a->isInCombat()) {
 			anim = Animation::combatStand;
 		} else {
 			anim = Animation::stand;
-		}*/
+		}
+		DirectionMode standDirMode = a->animDirMode(anim);
 		if (_timer3set) {
 			if (_timer3 >= now) {
 				if (a->isInCombat()) {


Commit: b4330e0aae20c10f296c147253a5157092427385
    https://github.com/scummvm/scummvm/commit/b4330e0aae20c10f296c147253a5157092427385
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-12-28T17:56:32+09:00

Commit Message:
ULTIMA8: Small pathfinder optimizations

Changed paths:
    engines/ultima/ultima8/world/actors/animation_tracker.cpp
    engines/ultima/ultima8/world/actors/pathfinder.cpp
    engines/ultima/ultima8/world/actors/pathfinder.h


diff --git a/engines/ultima/ultima8/world/actors/animation_tracker.cpp b/engines/ultima/ultima8/world/actors/animation_tracker.cpp
index fc1954e581..68d1d12eb3 100644
--- a/engines/ultima/ultima8/world/actors/animation_tracker.cpp
+++ b/engines/ultima/ultima8/world/actors/animation_tracker.cpp
@@ -168,9 +168,6 @@ void AnimationTracker::evaluateMaxAnimTravel(int32 &max_endx, int32 &max_endy, D
 bool AnimationTracker::step() {
 	if (_done) return false;
 
-	Actor *a = getActor(_actor);
-	assert(a);
-
 	if (_firstFrame)
 		_currentFrame = _startFrame;
 	else
@@ -231,6 +228,9 @@ bool AnimationTracker::step() {
 	}
 
 	// determine footpad
+	Actor *a = getActor(_actor);
+	assert(a);
+
 	bool actorflipped = a->hasFlags(Item::FLG_FLIPPED);
 	int32 xd, yd, zd;
 	a->getFootpadWorld(xd, yd, zd);
@@ -239,6 +239,7 @@ bool AnimationTracker::step() {
 		xd = yd;
 		yd = t;
 	}
+
 	CurrentMap *cm = World::get_instance()->getCurrentMap();
 
 	// TODO: check if this step is allowed
diff --git a/engines/ultima/ultima8/world/actors/pathfinder.cpp b/engines/ultima/ultima8/world/actors/pathfinder.cpp
index c3b59d5e03..547ee9828d 100644
--- a/engines/ultima/ultima8/world/actors/pathfinder.cpp
+++ b/engines/ultima/ultima8/world/actors/pathfinder.cpp
@@ -120,11 +120,13 @@ Pathfinder::Pathfinder() : _actor(nullptr), _targetItem(nullptr),
 		_hitMode(false), _expandTime(0), _targetX(0), _targetY(0),
 		_targetZ(0), _actorXd(0), _actorYd(0), _actorZd(0) {
 	expandednodes = 0;
+	_visited.reserve(1800);
 }
 
 Pathfinder::~Pathfinder() {
-#if 1
-	pout << "~Pathfinder: " << _cleanupNodes.size() << " nodes to clean up, "
+#if 0
+	pout << "~Pathfinder: " << _cleanupNodes.size() << " nodes to clean up, visited "
+		 << _visited.size() << " and "
 	     << expandednodes << " expanded nodes in " << _expandTime << "ms." << Std::endl;
 #endif
 
@@ -180,8 +182,7 @@ bool Pathfinder::canReach() {
 bool Pathfinder::alreadyVisited(int32 x, int32 y, int32 z) const {
 	//! this may need optimization
 
-	Std::list<PathfindingState>::const_iterator iter;
-
+	Std::vector<PathfindingState>::const_iterator iter;
 	for (iter = _visited.begin(); iter != _visited.end(); ++iter)
 		if (iter->checkPoint(x, y, z, 8))
 			return true;
@@ -204,7 +205,7 @@ bool Pathfinder::checkTarget(const PathNode *node) const {
 	}
 }
 
-unsigned int Pathfinder::costHeuristic(PathNode *node) {
+unsigned int Pathfinder::costHeuristic(PathNode *node) const {
 	unsigned int cost = node->cost;
 
 #if 0
@@ -441,12 +442,6 @@ void Pathfinder::expandNode(PathNode *node) {
 		state._lastAnim = walkanim;
 		state._direction = dir;
 		state._combat = _actor->isInCombat();
-		uint32 steps = 0, beststeps = 0;
-		int bestsqdist;
-		bestsqdist = (_targetX - node->state._x + _actorXd / 2) *
-		             (_targetX - node->state._x + _actorXd / 2);
-		bestsqdist += (_targetY - node->state._y + _actorYd / 2) *
-		              (_targetY - node->state._y + _actorYd / 2);
 
 		if (!tracker.init(_actor, walkanim, dir, &state)) continue;
 
@@ -454,21 +449,28 @@ void Pathfinder::expandNode(PathNode *node) {
 		int32 max_endx, max_endy;
 		tracker.evaluateMaxAnimTravel(max_endx, max_endy, dir);
 		if (alreadyVisited(max_endx, max_endy, state._z)) continue;
-		int sqrddist;
+
 		const int x_travel = ABS(max_endx - state._x);
-		int xy_maxtravel = x_travel;    // don't have the max(a,b) macro...
 		const int y_travel = ABS(max_endy - state._y);
-		if (y_travel > xy_maxtravel) xy_maxtravel = y_travel;
+		const int xy_maxtravel = MAX(x_travel, y_travel);
 
-		sqrddist = x_travel * x_travel + y_travel * y_travel;
+		int sqrddist = x_travel * x_travel + y_travel * y_travel;
 		if (sqrddist > 400) {
-			// range is greater than 20; see if a node has been _visited at range 10
+			// range is greater than 20; see if a node has been visited at range 10
 			if (alreadyVisited(state._x + x_travel * 10 / xy_maxtravel,
 			                   state._y + y_travel * 10 / xy_maxtravel,
 			                   state._z)) {
 				continue;
 			}
 		}
+
+		uint32 steps = 0, beststeps = 0;
+		int bestsqdist;
+		bestsqdist = (_targetX - node->state._x + _actorXd / 2) *
+					 (_targetX - node->state._x + _actorXd / 2);
+		bestsqdist += (_targetY - node->state._y + _actorYd / 2) *
+					  (_targetY - node->state._y + _actorYd / 2);
+
 		while (tracker.step()) {
 			steps++;
 			tracker.updateState(state);
@@ -492,7 +494,7 @@ void Pathfinder::expandNode(PathNode *node) {
 				_visited.push_back(state);
 			}
 		} else {
-			// an obstruction was encountered, so generate a _visited node to block
+			// an obstruction was encountered, so generate a visited node to block
 			// future evaluation at the endpoint.
 			_visited.push_back(state);
 		}
diff --git a/engines/ultima/ultima8/world/actors/pathfinder.h b/engines/ultima/ultima8/world/actors/pathfinder.h
index e1e1f05b5c..689f2a6e9f 100644
--- a/engines/ultima/ultima8/world/actors/pathfinder.h
+++ b/engines/ultima/ultima8/world/actors/pathfinder.h
@@ -93,7 +93,7 @@ protected:
 
 	int32 _actorXd, _actorYd, _actorZd;
 
-	Std::list<PathfindingState> _visited;
+	Std::vector<PathfindingState> _visited;
 	Std::priority_queue<PathNode *, Std::vector<PathNode *>, PathNodeCmp> _nodes;
 
 	/** List of nodes for garbage collection later and order is not important */
@@ -103,7 +103,7 @@ protected:
 	void newNode(PathNode *oldnode, PathfindingState &state,
 				 unsigned int steps);
 	void expandNode(PathNode *node);
-	unsigned int costHeuristic(PathNode *node);
+	unsigned int costHeuristic(PathNode *node) const;
 	bool checkTarget(const PathNode *node) const;
 };
 


Commit: 1bd9936f372e24c19c089ca407fe53ed7009b99b
    https://github.com/scummvm/scummvm/commit/1bd9936f372e24c19c089ca407fe53ed7009b99b
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-12-28T17:56:32+09:00

Commit Message:
ULTIMA8: Small const correctness improvement

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


diff --git a/engines/ultima/ultima8/world/item_sorter.cpp b/engines/ultima/ultima8/world/item_sorter.cpp
index de83050bdb..beaa2d84a9 100644
--- a/engines/ultima/ultima8/world/item_sorter.cpp
+++ b/engines/ultima/ultima8/world/item_sorter.cpp
@@ -147,10 +147,10 @@ struct SortItem {
 			}
 		};
 
-		iterator begin() {
+		iterator begin() const {
 			return iterator(list);
 		}
-		iterator end() {
+		iterator end() const {
 			return iterator(nullptr);
 		}
 


Commit: 606afd7e544c5e551c43d17cb059036e3fba0dcd
    https://github.com/scummvm/scummvm/commit/606afd7e544c5e551c43d17cb059036e3fba0dcd
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-12-28T17:56:32+09:00

Commit Message:
ULTIMA8: Remove magic number

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


diff --git a/engines/ultima/ultima8/world/current_map.h b/engines/ultima/ultima8/world/current_map.h
index c0726a8164..ecefeca23e 100644
--- a/engines/ultima/ultima8/world/current_map.h
+++ b/engines/ultima/ultima8/world/current_map.h
@@ -239,7 +239,7 @@ private:
 
 	//! Items that are "targetable" in Crusader. It might be faster to store
 	//! this in a more fancy data structure, but this works fine.
-	ObjId _targets[200];
+	ObjId _targets[MAP_NUM_TARGET_ITEMS];
 
 	void setChunkFast(int32 cx, int32 cy);
 	void unsetChunkFast(int32 cx, int32 cy);


Commit: 9abb14326e50da8f5dec446af38d9c334314e6aa
    https://github.com/scummvm/scummvm/commit/9abb14326e50da8f5dec446af38d9c334314e6aa
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-12-28T17:56:32+09:00

Commit Message:
ULTIMA8: Intrinsic improvements for Crusader

Changed paths:
    engines/ultima/ultima8/world/actors/actor.cpp
    engines/ultima/ultima8/world/current_map.cpp
    engines/ultima/ultima8/world/item.cpp


diff --git a/engines/ultima/ultima8/world/actors/actor.cpp b/engines/ultima/ultima8/world/actors/actor.cpp
index 9866ea5002..098c3cbb2c 100644
--- a/engines/ultima/ultima8/world/actors/actor.cpp
+++ b/engines/ultima/ultima8/world/actors/actor.cpp
@@ -499,6 +499,16 @@ uint16 Actor::doAnim(Animation::Sequence anim, Direction dir, unsigned int steps
 			clearActorFlag(ACT_KNEELING);
 	}
 
+#if 0
+	if (_objId == 1) {
+		int32 x, y, z;
+		getLocation(x, y, z);
+		int32 actionno = AnimDat::getActionNumberForSequence(anim, this);
+		const AnimAction *action = GameData::get_instance()->getMainShapes()->getAnim(getShape(), actionno);
+		debug(6, "Actir::doAnim(%d, %d, %d) from (%d, %d, %d) frame repeat %d", anim, dir, steps, x, y, z, action->getFrameRepeat());
+	}
+#endif
+
 	Process *p = new ActorAnimProcess(this, anim, dir, steps);
 
 	return Kernel::get_instance()->addProcess(p);
@@ -585,11 +595,13 @@ uint16 Actor::turnTowardDir(Direction targetdir) {
 	bool surrendered = hasActorFlags(Actor::ACT_SURRENDERED);
 
 	int stepDelta = Direction_GetShorterTurnDelta(curdir, targetdir);
-	Animation::Sequence turnanim;
-	if (stepDelta == -1) {
-		turnanim = Animation::lookLeft;
-	} else {
-		turnanim = Animation::lookRight;
+	Animation::Sequence turnanim = Animation::stand;
+	if (GAME_IS_U8) {
+		if (stepDelta == -1) {
+			turnanim = Animation::lookLeft;
+		} else {
+			turnanim = Animation::lookRight;
+		}
 	}
 
 	if (combat) {
@@ -1643,6 +1655,11 @@ uint32 Actor::I_teleport(const uint8 *args, unsigned int /*argsize*/) {
 	ARG_UINT16(newmap);
 	if (!actor) return 0;
 
+	if (GAME_IS_CRUSADER) {
+		newx *= 2;
+		newy *= 2;
+	}
+
 	actor->teleport(newmap, newx, newy, newz);
 	return 0;
 }
diff --git a/engines/ultima/ultima8/world/current_map.cpp b/engines/ultima/ultima8/world/current_map.cpp
index fcf9307dd1..5f27a6a7f8 100644
--- a/engines/ultima/ultima8/world/current_map.cpp
+++ b/engines/ultima/ultima8/world/current_map.cpp
@@ -1324,13 +1324,17 @@ uint32 CurrentMap::I_canExistAtPoint(const uint8 *args, unsigned int /*argsize*/
 	if (shape > 0x800)
 		return 0;
 
+	int32 x = pt.getX();
+	int32 y = pt.getY();
+	int32 z = pt.getZ();
+
 	if (GAME_IS_CRUSADER) {
-		pt.setX(pt.getX() * 2);
-		pt.setY(pt.getY() * 2);
+		x *= 2;
+		y *= 2;
 	}
 
 	const CurrentMap *cm = World::get_instance()->getCurrentMap();
-	bool valid = cm->isValidPosition(pt.getX(), pt.getY(), pt.getZ(), shape, 0, 0, 0);
+	bool valid = cm->isValidPosition(x, y, z, shape, 0, 0, 0);
 
 	if (valid)
 		return 1;
diff --git a/engines/ultima/ultima8/world/item.cpp b/engines/ultima/ultima8/world/item.cpp
index d8a5e6ecfe..2b49f3baf1 100644
--- a/engines/ultima/ultima8/world/item.cpp
+++ b/engines/ultima/ultima8/world/item.cpp
@@ -1802,6 +1802,10 @@ void Item::leaveFastArea() {
 		if (g) g->Close();
 	}
 
+	if (_objId == 1) {
+		debug(6, "avatar leaving fast area");
+	}
+
 	// Unset the flag
 	_flags &= ~FLG_FASTAREA;
 
@@ -2075,9 +2079,14 @@ void Item::explode(int explosion_type, bool destroy_item, bool cause_damage) {
 	} else {
 		Point3 pt;
 		getLocation(pt);
+		// Note: same FireType number used in both Remorse and Regret
 		const FireType *firetypedat = GameData::get_instance()->getFireType(4);
-		int damage = firetypedat->getRandomDamage();
-		firetypedat->applySplashDamageAround(pt, damage, this, this);
+		if (firetypedat) {
+			int damage = firetypedat->getRandomDamage();
+			firetypedat->applySplashDamageAround(pt, damage, this, this);
+		} else {
+			warning("couldn't explode properly - no firetype 4 data");
+		}
 	}
 }
 
@@ -2513,7 +2522,11 @@ uint32 Item::I_getCX(const uint8 *args, unsigned int /*argsize*/) {
 	int32 x, y, z;
 	item->getLocationAbsolute(x, y, z);
 
-	int mul = ((GAME_IS_CRUSADER) ? 8 : 16);
+	int mul = 16;
+	if (GAME_IS_CRUSADER) {
+		x /= 2;
+		mul /= 2;
+	}
 
 	if (item->_flags & FLG_FLIPPED)
 		return x - item->getShapeInfo()->_y * mul;
@@ -2528,7 +2541,11 @@ uint32 Item::I_getCY(const uint8 *args, unsigned int /*argsize*/) {
 	int32 x, y, z;
 	item->getLocationAbsolute(x, y, z);
 
-	int mul = ((GAME_IS_CRUSADER) ? 8 : 16);
+	int mul = 16;
+	if (GAME_IS_CRUSADER) {
+		y /= 2;
+		mul /= 2;
+	}
 
 	if (item->_flags & FLG_FLIPPED)
 		return y - item->getShapeInfo()->_x * mul;
@@ -2946,10 +2963,18 @@ uint32 Item::I_legalCreateAtPoint(const uint8 *args, unsigned int /*argsize*/) {
 	ARG_UINT16(frame);
 	ARG_WORLDPOINT(point);
 
+	int32 x = point.getX();
+	int32 y = point.getY();
+	int32 z = point.getZ();
+
+	if (GAME_IS_CRUSADER) {
+		x *= 2;
+		y *= 2;
+	}
+
 	// check if item can exist
 	CurrentMap *cm = World::get_instance()->getCurrentMap();
-	bool valid = cm->isValidPosition(point.getX(), point.getY(), point.getZ(),
-	                                 shape, 0, 0, 0);
+	bool valid = cm->isValidPosition(x, y, z, shape, 0, 0, 0);
 	if (!valid)
 		return 0;
 
@@ -2960,7 +2985,7 @@ uint32 Item::I_legalCreateAtPoint(const uint8 *args, unsigned int /*argsize*/) {
 		return 0;
 	}
 	uint16 objID = newitem->getObjId();
-	newitem->move(point.getX(), point.getY(), point.getZ());
+	newitem->move(x, y, z);
 
 	uint8 buf[2];
 	buf[0] = static_cast<uint8>(objID);
@@ -3357,21 +3382,21 @@ uint32 Item::I_legalMoveToPoint(const uint8 *args, unsigned int argsize) {
 	ARG_UINT16(force); // 0/1
 	ARG_UINT16(unknown2); // always 0
 
+	int32 x = point.getX();
+	int32 y = point.getY();
+	int32 z = point.getZ();
+
 	if (GAME_IS_CRUSADER) {
-		point.setX(point.getX() * 2);
-		point.setY(point.getY() * 2);
+		x *= 2;
+		y *= 2;
 	}
 
 	if (!item)
 		return 0;
 	//! What should this do to ethereal items?
-
-//	if (item->canExistAt(point.getX(), point.getY(), point.getZ())) {
-//		item->move(point.getX(), point.getY(), point.getZ());
-//		return 1;
-//	} else {
-	return item->collideMove(point.getX(), point.getY(), point.getZ(), false, force == 1) == 0x4000;
-//	}
+	if (item->collideMove(x, y, z, false, force == 1) == 0x4000)
+		return 1;
+	return 0;
 }
 
 uint32 Item::I_legalMoveToContainer(const uint8 *args, unsigned int /*argsize*/) {
@@ -3537,6 +3562,7 @@ uint32 Item::I_shoot(const uint8 *args, unsigned int /*argsize*/) {
 	ARG_UINT16(gravity); // either 2 (fish) or 1 (death disk, dart)
 	if (!item) return 0;
 
+	assert(GAME_IS_U8);
 	MissileTracker tracker(item, point.getX(), point.getY(), point.getZ(),
 	                       speed, gravity);
 	tracker.launchItem();
@@ -3708,6 +3734,8 @@ uint32 Item::I_getRange(const uint8 *args, unsigned int /*argsize*/) {
 	if (!item) return 0;
 	if (!other) return 0;
 
+	assert(GAME_IS_U8);
+
 	return item->getRange(*other);
 }
 


Commit: b7c5ad8a95f7dd92863c4af93a1d1beb9b991eb9
    https://github.com/scummvm/scummvm/commit/b7c5ad8a95f7dd92863c4af93a1d1beb9b991eb9
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-12-28T17:56:32+09:00

Commit Message:
ULTIMA8: Remove TODO comments that are done

Changed paths:
    engines/ultima/ultima8/audio/sound_flex.cpp
    engines/ultima/ultima8/world/camera_process.cpp


diff --git a/engines/ultima/ultima8/audio/sound_flex.cpp b/engines/ultima/ultima8/audio/sound_flex.cpp
index 116281670a..9322a67cf2 100644
--- a/engines/ultima/ultima8/audio/sound_flex.cpp
+++ b/engines/ultima/ultima8/audio/sound_flex.cpp
@@ -94,8 +94,7 @@ void SoundFlex::cache(uint32 index) {
 	if (!buf || !size) return;
 
 	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 if No Regret is Stereo and/or 16 bit?
+		// After the 32 byte header, ASFX (crusader audio) is just raw 11025 data
 		const SoundFlexEntry &entry = _index[index];
 		debug(6, "SoundFlex: Playing sfx %d (%s) with data 0x%04X", index, entry._name.c_str(), entry._data);
 		_samples[index] = new RawAudioSample(buf + 32, size - 32, 11025, true, false);
diff --git a/engines/ultima/ultima8/world/camera_process.cpp b/engines/ultima/ultima8/world/camera_process.cpp
index 3d971dd1f3..370c2fb292 100644
--- a/engines/ultima/ultima8/world/camera_process.cpp
+++ b/engines/ultima/ultima8/world/camera_process.cpp
@@ -187,9 +187,6 @@ void CameraProcess::ItemMoved() {
 }
 
 void CameraProcess::GetLerped(int32 &x, int32 &y, int32 &z, int32 factor, bool noupdate) {
-	// TODO: For Crusader, only update the camera position if the
-	// distance to the target object passes a threshold.
-
 	if (_time == 0) {
 		if (!noupdate) {
 


Commit: 8329f5280b5a87eaaf5f2a181bed749c0d3df424
    https://github.com/scummvm/scummvm/commit/8329f5280b5a87eaaf5f2a181bed749c0d3df424
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-12-28T17:56:40+09:00

Commit Message:
ULTIMA8: Avoid duplicate weapon-ready animations

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


diff --git a/engines/ultima/ultima8/world/actors/cru_avatar_mover_process.cpp b/engines/ultima/ultima8/world/actors/cru_avatar_mover_process.cpp
index ab06a9d42f..799fa9786b 100644
--- a/engines/ultima/ultima8/world/actors/cru_avatar_mover_process.cpp
+++ b/engines/ultima/ultima8/world/actors/cru_avatar_mover_process.cpp
@@ -369,7 +369,8 @@ void CruAvatarMoverProcess::tryAttack() {
 	Direction dir = avatar->getDir();
 	if (!avatar->isInCombat()) {
 		avatar->setInCombat(0);
-		waitFor(avatar->doAnim(Animation::readyWeapon, dir));
+		if (!avatar->hasActorFlags(Actor::ACT_WEAPONREADY))
+			waitFor(avatar->doAnim(Animation::readyWeapon, dir));
 	} else {
 		if (canAttack()) {
 			// Fire event happens from animation




More information about the Scummvm-git-logs mailing list