[Scummvm-git-logs] scummvm master -> ad01f082649137f755b287854764556410f98b50

mduggan mgithub at guarana.org
Fri Jan 8 09:20:06 UTC 2021


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

Summary:
fedc73f9f2 ULTIMA8: Add more anims to crusdaer table. Fix z-values for Crusader anims
27c35abb44 ULTIMA8: Fix many small Cruader movement issues
ac6c4add3a ULTIMA8: Avoid wait/wake-up tight loops in attack process
7542d278a6 ULTIMA8: Call hit usecode multiple times in Crusader
b4e50e21ef ULTIMA8: Hold last Crusader target reticle frame
ff910b0d91 ULTIMA8: Tone down Crusader splash damage
5d7b662538 ULTIMA8: Don't update fast area when getting item location
bd00ab28a0 ULTIMA8: Avoid corner-case of Crusader mover failing
ad01f08264 ULTIMA8: More tweaks for Crusader mover to bring closer to original


Commit: fedc73f9f27531bb1ab71ac9e9a9c8757781796d
    https://github.com/scummvm/scummvm/commit/fedc73f9f27531bb1ab71ac9e9a9c8757781796d
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2021-01-08T18:18:37+09:00

Commit Message:
ULTIMA8: Add more anims to crusdaer table. Fix z-values for Crusader anims

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


diff --git a/engines/ultima/ultima8/graphics/anim_dat.cpp b/engines/ultima/ultima8/graphics/anim_dat.cpp
index d05e5be74b..57bc81fb68 100644
--- a/engines/ultima/ultima8/graphics/anim_dat.cpp
+++ b/engines/ultima/ultima8/graphics/anim_dat.cpp
@@ -137,6 +137,10 @@ uint32 AnimDat::getActionNumberForSequence(Animation::Sequence action, const Act
 			return 0;
 		case Animation::lookRight:
 			return 0;
+		case Animation::jump:
+			return 58; // 58 is a shorter jump?
+		case Animation::startRunWithLargeWeapon:
+			return (smallwpn ? 34 : 35);
 		default:
 			return action_int;
 		}
@@ -238,7 +242,7 @@ void AnimDat::load(Common::SeekableReadStream *rs) {
 						const uint8 x = rs->readByte();
 						f._frame += (x & 0xF) << 8;
 						// byte 2: delta z
-						f._deltaZ = rs->readByte();
+						f._deltaZ = rs->readSByte();
 						// byte 3: sfx
 						f._sfx = rs->readByte();
 						// byte 4: deltadir (signed) - convert to pixels


Commit: 27c35abb4442a73ada2c7248167394e84b92b604
    https://github.com/scummvm/scummvm/commit/27c35abb4442a73ada2c7248167394e84b92b604
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2021-01-08T18:18:37+09:00

Commit Message:
ULTIMA8: Fix many small Cruader movement issues

Changed paths:
    engines/ultima/ultima8/world/actors/actor.cpp
    engines/ultima/ultima8/world/actors/actor.h
    engines/ultima/ultima8/world/actors/animation.cpp
    engines/ultima/ultima8/world/actors/animation.h
    engines/ultima/ultima8/world/actors/cru_avatar_mover_process.cpp
    engines/ultima/ultima8/world/actors/main_actor.cpp
    engines/ultima/ultima8/world/current_map.cpp
    engines/ultima/ultima8/world/item.cpp
    engines/ultima/ultima8/world/item.h


diff --git a/engines/ultima/ultima8/world/actors/actor.cpp b/engines/ultima/ultima8/world/actors/actor.cpp
index 33025ed4b3..63a5c81ae3 100644
--- a/engines/ultima/ultima8/world/actors/actor.cpp
+++ b/engines/ultima/ultima8/world/actors/actor.cpp
@@ -487,15 +487,20 @@ uint16 Actor::doAnim(Animation::Sequence anim, Direction dir, unsigned int steps
 		// 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)
+
+		if (anim == Animation::readyWeapon || anim == Animation::stopRunningAndDrawWeapon ||
+				anim == Animation::combatStand || anim == Animation::attack || anim == Animation::kneel ||
+				anim == Animation::kneelAndFire)
 			setActorFlag(ACT_WEAPONREADY);
-		else if (anim == Animation::unreadyWeapon)
+		else
 			clearActorFlag(ACT_WEAPONREADY);
-		else if (anim == Animation::startKneeling || anim == Animation::kneelAndFire ||
-				 anim == Animation::kneelAndFireSmallWeapon ||
-				 anim == Animation::kneelAndFireLargeWeapon)
+
+		if (anim == Animation::startKneeling || anim == Animation::kneelAndFire ||
+				anim == Animation::kneelAndFireSmallWeapon ||
+				anim == Animation::kneelAndFireLargeWeapon ||
+				anim == Animation::kneel)
 			setActorFlag(ACT_KNEELING);
-		else if (anim == Animation::stopKneeling)
+		else
 			clearActorFlag(ACT_KNEELING);
 	}
 
@@ -2387,7 +2392,7 @@ uint32 Actor::I_isKneeling(const uint8 *args, unsigned int /*argsize*/) {
 	ARG_ACTOR_FROM_PTR(actor);
 	if (!actor) return 0;
 
-	return actor->hasFlags(ACT_KNEELING) ? 1 : 0;
+	return actor->isKneeling() ? 1 : 0;
 }
 
 } // End of namespace Ultima8
diff --git a/engines/ultima/ultima8/world/actors/actor.h b/engines/ultima/ultima8/world/actors/actor.h
index 7358e69c34..868c20e65d 100644
--- a/engines/ultima/ultima8/world/actors/actor.h
+++ b/engines/ultima/ultima8/world/actors/actor.h
@@ -84,6 +84,10 @@ public:
 		return (_actorFlags & ACT_INCOMBAT) != 0;
 	}
 
+	bool isKneeling() const {
+		return (_actorFlags & ACT_KNEELING) != 0;
+	}
+
 	CombatProcess *getCombatProcess(); 	// in U8
 	AttackProcess *getAttackProcess();	// in Crusader
 	virtual void setInCombat(int activity);
diff --git a/engines/ultima/ultima8/world/actors/animation.cpp b/engines/ultima/ultima8/world/actors/animation.cpp
index bb26236237..e7b0da2a2a 100644
--- a/engines/ultima/ultima8/world/actors/animation.cpp
+++ b/engines/ultima/ultima8/world/actors/animation.cpp
@@ -60,12 +60,18 @@ bool isCombatAnimCru(const Sequence anim) {
 	case attack:
 	case kick:
 	case kneel:
-	case kneelStart:
+	case startKneeling:
+	case stopKneeling:
+	case kneelAndFire:
 	case fire2:
 	case combatRollLeft:
 	case combatRollRight:
 	case slideLeft:
 	case slideRight:
+	case startRun:
+	case startRunWithLargeWeapon:
+	case run:
+	case stopRunningAndDrawWeapon:
 		return true;
 	default:
 		return false;
diff --git a/engines/ultima/ultima8/world/actors/animation.h b/engines/ultima/ultima8/world/actors/animation.h
index 84c6d3ab36..dea6764120 100644
--- a/engines/ultima/ultima8/world/actors/animation.h
+++ b/engines/ultima/ultima8/world/actors/animation.h
@@ -112,8 +112,8 @@ enum Sequence {
 	halfStep = 37,
 	startRun = 38,
 	stopRunningAndDrawWeapon = 39,
-	kneelStart = 40,
-	kneelEnd = 41,
+	kneelStartCru = 40,
+	kneelEndCru = 41,
 	kneelAndFireSmallWeapon = 42,
 	kneelAndFireLargeWeapon = 43,
 	advanceWithLargeWeapon = 44,
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 a9c8aecaa2..c4117e71d9 100644
--- a/engines/ultima/ultima8/world/actors/cru_avatar_mover_process.cpp
+++ b/engines/ultima/ultima8/world/actors/cru_avatar_mover_process.cpp
@@ -106,23 +106,26 @@ void CruAvatarMoverProcess::handleCombatMode() {
 	} else if (hasMovementFlags(MOVE_FORWARD)) {
 		Animation::Sequence nextanim;
 		if (hasMovementFlags(MOVE_STEP)) {
-			nextanim = avatar->hasActorFlags(Actor::ACT_KNEELING) ?
+			nextanim = avatar->isKneeling() ?
 							Animation::kneelingAdvance : Animation::advance;
 		} else if (hasMovementFlags(MOVE_RUN)) {
 			// Take a step before running
-			avatar->toggleInCombat();
-			if (lastanim != Animation::startRun)
-				nextanim = Animation::startRun;
+			if (lastanim != Animation::startRunWithLargeWeapon && lastanim != Animation::run)
+				nextanim = Animation::startRunWithLargeWeapon;
 			else
 				nextanim = Animation::run;
 		} else if (hasMovementFlags(MOVE_JUMP)) {
-			avatar->toggleInCombat();
-			nextanim = Animation::jumpForward;
-		} else if (avatar->hasActorFlags(Actor::ACT_KNEELING)) {
+			if (lastanim == Animation::walk || lastanim == Animation::run)
+				nextanim = Animation::jumpForward;
+			else
+				nextanim = Animation::jump;
+			// Jump always ends out of combat
+			avatar->clearInCombat();
+		} else if (avatar->isKneeling()) {
 			nextanim = Animation::stopKneeling;
 			avatar->clearActorFlag(Actor::ACT_KNEELING);
 		} else {
-			// moving from combat stows weapon
+			// moving forward from combat stows weapon
 			nextanim = Animation::walk;
 			avatar->toggleInCombat();
 		}
@@ -133,30 +136,43 @@ void CruAvatarMoverProcess::handleCombatMode() {
 	} else if (hasMovementFlags(MOVE_BACK)) {
 		Animation::Sequence nextanim;
 		if (hasMovementFlags(MOVE_JUMP)) {
-			nextanim = Animation::startKneeling;
-			avatar->setActorFlag(Actor::ACT_KNEELING);
+			if (!avatar->isKneeling()) {
+				nextanim = Animation::startKneeling;
+				avatar->setActorFlag(Actor::ACT_KNEELING);
+			} else {
+				// Do nothing if already kneeling
+				return;
+			}
 		} else {
-			nextanim = avatar->hasActorFlags(Actor::ACT_KNEELING) ?
-							Animation::kneelingRetreat : Animation::retreat;
+			nextanim = Animation::retreat;
 		}
 		waitFor(avatar->doAnim(nextanim, direction));
 		return;
 	} else if (hasMovementFlags(MOVE_STEP)) {
-		if (hasMovementFlags(MOVE_TURN_LEFT)) {
-			avatar->doAnim(Animation::slideLeft, direction);
-			return;
-		} else if (hasMovementFlags(MOVE_TURN_RIGHT)) {
-			avatar->doAnim(Animation::slideRight, direction);
+		if (avatar->isKneeling()) {
+			avatar->doAnim(Animation::stopKneeling, direction);
 			return;
+		} else {
+			if (hasMovementFlags(MOVE_TURN_LEFT)) {
+				avatar->doAnim(Animation::slideLeft, direction);
+				return;
+			} else if (hasMovementFlags(MOVE_TURN_RIGHT)) {
+				avatar->doAnim(Animation::slideRight, direction);
+				return;
+			}
 		}
 	} else if (hasMovementFlags(MOVE_JUMP)) {
 		if (hasMovementFlags(MOVE_TURN_LEFT)) {
-			//direction = Direction_TurnByDelta(direction, 4, dirmode_16dirs);
-			avatar->doAnim(Animation::combatRollLeft, direction);
+			if (avatar->isKneeling())
+				avatar->doAnim(Animation::slowCombatRollLeft, direction);
+			else
+				avatar->doAnim(Animation::combatRollLeft, direction);
 			return;
 		} else if (hasMovementFlags(MOVE_TURN_RIGHT)) {
-			//direction = Direction_TurnByDelta(direction, -4, dirmode_16dirs);
-			avatar->doAnim(Animation::combatRollRight, direction);
+			if (avatar->isKneeling())
+				avatar->doAnim(Animation::slowCombatRollRight, direction);
+			else
+				avatar->doAnim(Animation::combatRollRight, direction);
 			return;
 		}
 	}
@@ -170,19 +186,18 @@ void CruAvatarMoverProcess::handleCombatMode() {
 			return;
 
 		Animation::Sequence nextanim = Animation::combatStand;
-		if (lastanim == Animation::run) {
-			// want to run while in combat mode?
-			// first sheath weapon
-			nextanim = Animation::readyWeapon;
-		} else if (Direction_Invert(direction) == nextdir) {
+		if (lastanim == Animation::run && !hasMovementFlags(MOVE_RUN)) {
+			// want to go back to combat mode from run
+			nextanim = Animation::stopRunningAndDrawWeapon;
+		} else if (hasMovementFlags(MOVE_BACK)) {
 			nextanim = Animation::retreat;
-			nextdir = direction;
+			nextdir = Direction_Invert(direction);
 		}
 
 		if (hasMovementFlags(MOVE_RUN)) {
-			// Take a step before running
-			nextanim = Animation::startRun;
-			avatar->toggleInCombat();
+			// Take a step before running.  Don't clear combat mode in Cruasder
+			// - running always finishes with drawing weapon
+			nextanim = Animation::run;
 		}
 
 		nextanim = Animation::checkWeapon(nextanim, lastanim);
@@ -190,7 +205,7 @@ void CruAvatarMoverProcess::handleCombatMode() {
 		return;
 	}
 
-	Animation::Sequence idleanim = avatar->hasActorFlags(Actor::ACT_KNEELING) ?
+	Animation::Sequence idleanim = avatar->isKneeling() ?
 						Animation::kneel : Animation::combatStand;
 
 	if (curdir != direction) {
@@ -214,6 +229,14 @@ void CruAvatarMoverProcess::handleNormalMode() {
 	Direction direction = avatar->getDir();
 	const bool stasis = Ultima8Engine::get_instance()->isAvatarInStasis();
 
+	if (hasMovementFlags(MOVE_STEP | MOVE_JUMP) && hasMovementFlags(MOVE_ANY_DIRECTION | MOVE_TURN_LEFT | MOVE_TURN_RIGHT)) {
+		// All jump and step movements in crusader are handled identically
+		// whether starting from combat mode or not.
+		avatar->setInCombat(0);
+		handleCombatMode();
+		return;
+	}
+
 	// Store current idle time. (Also see end of function.)
 	uint32 currentIdleTime = _idleTime;
 	_idleTime = 0;
@@ -231,16 +254,12 @@ void CruAvatarMoverProcess::handleNormalMode() {
 	if (standUpIfNeeded(direction))
 		return;
 
-	// If still in combat stance, sheathe weapon
-	if (!stasis && Animation::isCombatAnimU8(lastanim)) {
-		putAwayWeapon(direction);
-		return;
-	}
-
 	if (!hasMovementFlags(MOVE_ANY_DIRECTION) && lastanim == Animation::run) {
 		// if we were running, slow to a walk before stopping
 		// (even in stasis)
-		slowFromRun(direction);
+		waitFor(avatar->doAnim(Animation::stopRunningAndDrawWeapon, direction));
+		avatar->setInCombat(0);
+		avatar->clearActorFlag(Actor::ACT_COMBATRUN);
 		return;
 	}
 
@@ -248,13 +267,6 @@ void CruAvatarMoverProcess::handleNormalMode() {
 	if (stasis)
 		return;
 
-	if (hasMovementFlags(MOVE_JUMP) && hasMovementFlags(MOVE_FORWARD)) {
-		Animation::Sequence nextanim = Animation::jump;
-		nextanim = Animation::checkWeapon(nextanim, lastanim);
-		waitFor(avatar->doAnim(nextanim, direction));
-		return;
-	}
-
 	bool moving = (lastanim == Animation::step || lastanim == Animation::run || lastanim == Animation::walk);
 
 	DirectionMode dirmode = avatar->animDirMode(Animation::step);
@@ -266,15 +278,19 @@ void CruAvatarMoverProcess::handleNormalMode() {
 
 	Animation::Sequence nextanim = Animation::walk;
 
-	if (hasMovementFlags(MOVE_STEP)) {
-		nextanim = Animation::step;
-	} else if (hasMovementFlags(MOVE_RUN)) {
+	if (hasMovementFlags(MOVE_RUN)) {
 		if (lastanim == Animation::run
-			    || lastanim == Animation::runningJump
-			    || lastanim == Animation::walk)
+			|| lastanim == Animation::startRun
+			|| lastanim == Animation::startRunWithLargeWeapon
+			|| lastanim == Animation::walk) {
+			// keep running
 			nextanim = Animation::run;
-		else
-			nextanim = Animation::walk;
+			avatar->setActorFlag(Actor::ACT_COMBATRUN);
+		} else {
+			// start running
+			nextanim = Animation::startRun;
+			avatar->setActorFlag(Actor::ACT_COMBATRUN);
+		}
 	}
 
 	if (hasMovementFlags(MOVE_FORWARD)) {
@@ -283,10 +299,8 @@ void CruAvatarMoverProcess::handleNormalMode() {
 	}
 
 	if (hasMovementFlags(MOVE_BACK)) {
-		step(nextanim, Direction_Invert(direction));
-
-		// flip to move forward once turned
-		setMovementFlag(MOVE_FORWARD);
+		avatar->toggleInCombat();
+		step(Animation::retreat, direction);
 		return;
 	}
 
@@ -306,12 +320,6 @@ void CruAvatarMoverProcess::handleNormalMode() {
 	if (Kernel::get_instance()->getNumProcesses(1, ActorAnimProcess::ACTOR_ANIM_PROC_TYPE))
 		return;
 
-	// if we were running, slow to a walk before stopping
-	if (lastanim == Animation::run) {
-		waitFor(avatar->doAnim(Animation::walk, direction));
-		return;
-	}
-
 	// not doing anything in particular? stand
 	if (lastanim != Animation::stand && currentIdleTime == 0) {
 		waitFor(avatar->doAnim(Animation::stand, direction));
@@ -325,13 +333,12 @@ void CruAvatarMoverProcess::handleNormalMode() {
 void CruAvatarMoverProcess::step(Animation::Sequence action, Direction direction,
                               bool adjusted) {
 	MainActor *avatar = getMainActor();
-	Animation::Sequence lastanim = avatar->getLastAnim();
 
 	Animation::Result res = avatar->tryAnim(action, direction);
 
 	if (res != Animation::SUCCESS) {
 		World *world = World::get_instance();
-		CurrentMap *currentmap = world->getCurrentMap();
+		const CurrentMap *currentmap = world->getCurrentMap();
 
 		// Search right/left gradually increasing distance to see if we can make the move work.
 
@@ -378,7 +385,6 @@ void CruAvatarMoverProcess::step(Animation::Sequence action, Direction direction
 		return;
 
 	debug(6, "Cru avatar step: picked action %d dir %d (test result %d)", action, direction, res);
-	action = Animation::checkWeapon(action, lastanim);
 	waitFor(avatar->doAnim(action, direction));
 }
 
@@ -397,7 +403,9 @@ void CruAvatarMoverProcess::tryAttack() {
 	} else {
 		if (canAttack()) {
 			// Fire event happens from animation
-			waitFor(avatar->doAnim(Animation::attack, dir));
+			Animation::Sequence fireanim = (avatar->isKneeling() ?
+											Animation::kneelAndFire : Animation::attack);
+			waitFor(avatar->doAnim(fireanim, dir));
 		}
 	}
 }
diff --git a/engines/ultima/ultima8/world/actors/main_actor.cpp b/engines/ultima/ultima8/world/actors/main_actor.cpp
index d97a3adc16..cfc8796799 100644
--- a/engines/ultima/ultima8/world/actors/main_actor.cpp
+++ b/engines/ultima/ultima8/world/actors/main_actor.cpp
@@ -689,7 +689,7 @@ void MainActor::nextInvItem() {
 
 void MainActor::addFireAnimOffsets(int32 &x, int32 &y, int32 &z) {
 	assert(GAME_IS_CRUSADER);
-	Animation::Sequence fireanim = (hasActorFlags(ACT_KNEELING) ? Animation::kneelAndFire : Animation::attack);
+	Animation::Sequence fireanim = (isKneeling() ? Animation::kneelAndFire : Animation::attack);
 	uint32 actionno = AnimDat::getActionNumberForSequence(fireanim, this);
 	Direction dir = getDir();
 
diff --git a/engines/ultima/ultima8/world/current_map.cpp b/engines/ultima/ultima8/world/current_map.cpp
index 5f27a6a7f8..945db6d2e2 100644
--- a/engines/ultima/ultima8/world/current_map.cpp
+++ b/engines/ultima/ultima8/world/current_map.cpp
@@ -343,7 +343,7 @@ Item *CurrentMap::findBestTargetItem(int32 x, int32 y, Direction dir, DirectionM
 			continue;
 
 		const Actor *actor = dynamic_cast<const Actor *>(item);
-		if ((bestisoccl && !isoccl) || (bestisnpc && !actor) || !item->isOnScreen())
+		if ((bestisoccl && !isoccl) || (bestisnpc && !actor) || !item->isPartlyOnScreen())
 			continue;
 
 		int xdiff = abs(x - ix);
diff --git a/engines/ultima/ultima8/world/item.cpp b/engines/ultima/ultima8/world/item.cpp
index 5241c909eb..6bd94628b0 100644
--- a/engines/ultima/ultima8/world/item.cpp
+++ b/engines/ultima/ultima8/world/item.cpp
@@ -616,6 +616,28 @@ bool Item::isOnScreen() const {
 	return false;
 }
 
+bool Item::isPartlyOnScreen() const {
+	GameMapGump *game_map = Ultima8Engine::get_instance()->getGameMapGump();
+
+	if (!game_map)
+		return false;
+
+	Rect game_map_dims;
+	int32 screenx = -1;
+	int32 screeny = -1;
+	game_map->GetLocationOfItem(_objId, screenx, screeny);
+	game_map->GetDims(game_map_dims);
+	int32 xd, yd, zd;
+	getFootpadWorld(xd, yd, zd);
+
+	if (game_map_dims.contains(screenx, screeny) ||
+		game_map_dims.contains(screenx + xd, screeny + yd)) {
+		return true;
+	}
+
+	return false;
+}
+
 bool Item::canExistAt(int32 x, int32 y, int32 z, bool needsupport) const {
 	CurrentMap *cm = World::get_instance()->getCurrentMap();
 	const Item *support;
@@ -1302,7 +1324,7 @@ uint16 Item::fireDistance(Item *other, Direction dir, int16 xoff, int16 yoff, in
 	Actor *a = dynamic_cast<Actor *>(this);
 	if (a) {
 		Animation::Sequence anim;
-		bool kneeling = a->hasActorFlags(Actor::ACT_KNEELING);
+		bool kneeling = a->isKneeling();
 		bool smallwpn = true;
 		MainActor *ma = dynamic_cast<MainActor *>(this);
 		Item *wpn = getItem(a->getActiveWeapon());
diff --git a/engines/ultima/ultima8/world/item.h b/engines/ultima/ultima8/world/item.h
index 7119a1af1d..2a4a7c3570 100644
--- a/engines/ultima/ultima8/world/item.h
+++ b/engines/ultima/ultima8/world/item.h
@@ -285,9 +285,12 @@ public:
 	//! Check if the centre of this item is on top of another item
 	bool isCentreOn(const Item &item2) const;
 
-	//! Check if the item is currently visible on screen
+	//! Check if the item is currently entirely visible on screen
 	bool isOnScreen() const;
 
+	//! Check if the item is currently partly visible on screen
+	bool isPartlyOnScreen() const;
+
 	//! Check if this item can exist at the given coordinates
 	bool canExistAt(int32 x, int32 y, int32 z, bool needsupport = false) const;
 


Commit: ac6c4add3a21cb4984198d9e15493c8669e82481
    https://github.com/scummvm/scummvm/commit/ac6c4add3a21cb4984198d9e15493c8669e82481
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2021-01-08T18:18:37+09:00

Commit Message:
ULTIMA8: Avoid wait/wake-up tight loops 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 9a26a4aae1..3bdeb732ee 100644
--- a/engines/ultima/ultima8/world/actors/attack_process.cpp
+++ b/engines/ultima/ultima8/world/actors/attack_process.cpp
@@ -887,6 +887,8 @@ void AttackProcess::setTimer3() {
 }
 
 void AttackProcess::sleep(int ticks) {
+	// waiting less than 2 ticks can cause a tight loop
+	ticks = MAX(ticks, 2);
 	Process *delayProc = new DelayProcess(ticks);
 	ProcId pid = Kernel::get_instance()->addProcess(delayProc);
 	waitFor(pid);


Commit: 7542d278a6f4bb3c84d403b7ac76d3f4c139daa4
    https://github.com/scummvm/scummvm/commit/7542d278a6f4bb3c84d403b7ac76d3f4c139daa4
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2021-01-08T18:18:37+09:00

Commit Message:
ULTIMA8: Call hit usecode multiple times in Crusader

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


diff --git a/engines/ultima/ultima8/world/item.cpp b/engines/ultima/ultima8/world/item.cpp
index 6bd94628b0..161a027442 100644
--- a/engines/ultima/ultima8/world/item.cpp
+++ b/engines/ultima/ultima8/world/item.cpp
@@ -1142,8 +1142,11 @@ int32 Item::collideMove(int32 dx, int32 dy, int32 dz, bool teleport, bool force,
 			uint16 proc_gothit = 0, proc_rel = 0;
 
 			// If hitting at start, we should have already
-			// called gotHit and hit.
-			if ((!it->_touching || it->_touchingFloor) && it->_hitTime >= 0) {
+			// called gotHit and hit.  In Crusader we call
+			// hit for every hitting frame to make sickbays
+			// and teleporters work.
+			bool call_hit = it->_hitTime >= 0 || GAME_IS_CRUSADER;
+			if ((!it->_touching || it->_touchingFloor) && call_hit) {
 				if (_objId == 1 && guiapp->isShowTouchingItems())
 					item->setExtFlag(Item::EXT_HIGHLIGHT);
 
@@ -1790,6 +1793,7 @@ void Item::enterFastArea() {
 			if (actor && GAME_IS_CRUSADER) {
 				actor->clearLastActivityNo();
 				actor->clearInCombat();
+				actor->clearActorFlag(Actor::ACT_WEAPONREADY);
 			}
 			callUsecodeEvent_enterFastArea();
 		}


Commit: b4e50e21ef61d5ed6dde1d5c6655e07b03a9cd4f
    https://github.com/scummvm/scummvm/commit/b4e50e21ef61d5ed6dde1d5c6655e07b03a9cd4f
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2021-01-08T18:18:37+09:00

Commit Message:
ULTIMA8: Hold last Crusader target reticle frame

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


diff --git a/engines/ultima/ultima8/world/target_reticle_process.cpp b/engines/ultima/ultima8/world/target_reticle_process.cpp
index 3a686a0436..0b214fe4b9 100644
--- a/engines/ultima/ultima8/world/target_reticle_process.cpp
+++ b/engines/ultima/ultima8/world/target_reticle_process.cpp
@@ -64,14 +64,23 @@ void TargetReticleProcess::run() {
 		return;
 	}
 
+	if (_reticleSpriteProcess && (!spriteProc || spriteProc->is_terminated())) {
+		// The sprite proc has finished but the target is still valid - replace
+		// with one that just holds the last frame.
+		Item *target = getItem(_lastTargetItem);
+		if (target)
+			putTargetReticleOnItem(target, true);
+	}
+
 	if (frameno - _lastUpdate < 2 * Kernel::FRAMES_PER_SECOND) {
 		return;
 	}
 
 	bool changed = findTargetItem();
-	if (spriteProc && changed)
+	if (spriteProc && changed) {
 		// Terminate the old process.
 		spriteProc->terminate();
+	}
 	_lastUpdate = frameno;
 }
 
@@ -94,7 +103,7 @@ bool TargetReticleProcess::findTargetItem() {
 		Item *lastItem = getItem(_lastTargetItem);
 		if (lastItem)
 			lastItem->clearExtFlag(Item::EXT_TARGET);
-		putTargetReticleOnItem(item);
+		putTargetReticleOnItem(item, false);
 		_lastTargetDir = dir;
 		changed = true;
 	} else if (!item) {
@@ -115,7 +124,7 @@ void TargetReticleProcess::avatarMoved() {
 	_lastUpdate = 0;
 }
 
-void TargetReticleProcess::putTargetReticleOnItem(Item *item) {
+void TargetReticleProcess::putTargetReticleOnItem(Item *item, bool last_frame) {
 	int32 x, y, z;
 
 	// TODO: the game does a bunch of other maths here to pick the right location.
@@ -124,7 +133,11 @@ void TargetReticleProcess::putTargetReticleOnItem(Item *item) {
 	item->getCentre(x, y, z);
 	z -= 8;
 
-	Process *p = new SpriteProcess(0x59a, 0, 5, 1, 10, x, y, z, false);
+	Process *p;
+	if (!last_frame)
+		p = new SpriteProcess(0x59a, 0, 5, 1, 10, x, y, z, false);
+	else
+		p = new SpriteProcess(0x59a, 5, 5, 1, 1000, x, y, z, false);
 
 	_reticleSpriteProcess = Kernel::get_instance()->addProcess(p);
 	_lastTargetItem = item->getObjId();
@@ -155,6 +168,7 @@ void TargetReticleProcess::itemMoved(Item *item) {
 	if (spriteproc) {
 		if (actordir != _lastTargetDir || dirtoitem != _lastTargetDir) {
 			spriteproc->terminate();
+			_reticleSpriteProcess = 0;
 			clearSprite();
 		} else {
 			spriteproc->move(x, y, z);
diff --git a/engines/ultima/ultima8/world/target_reticle_process.h b/engines/ultima/ultima8/world/target_reticle_process.h
index d16942b282..e7d45590ec 100644
--- a/engines/ultima/ultima8/world/target_reticle_process.h
+++ b/engines/ultima/ultima8/world/target_reticle_process.h
@@ -68,7 +68,7 @@ public:
 
 private:
 	bool findTargetItem();
-	void putTargetReticleOnItem(Item *);
+	void putTargetReticleOnItem(Item *, bool last_frame);
 	void clearSprite();
 
     bool _reticleEnabled;


Commit: ff910b0d915b94157102361047e1e87556e7de2e
    https://github.com/scummvm/scummvm/commit/ff910b0d915b94157102361047e1e87556e7de2e
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2021-01-08T18:18:37+09:00

Commit Message:
ULTIMA8: Tone down Crusader splash damage

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


diff --git a/engines/ultima/ultima8/world/fire_type.cpp b/engines/ultima/ultima8/world/fire_type.cpp
index a0c0014bd8..5780a5643f 100644
--- a/engines/ultima/ultima8/world/fire_type.cpp
+++ b/engines/ultima/ultima8/world/fire_type.cpp
@@ -201,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 / 32) / 3;
+			splashrange = (splashrange / 16) / 3;
 			if (splashrange)
 				splashitemdamage /= splashrange;
 		}


Commit: 5d7b6625387ff62b1869b4567c1e456c6cc00f98
    https://github.com/scummvm/scummvm/commit/5d7b6625387ff62b1869b4567c1e456c6cc00f98
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2021-01-08T18:18:37+09:00

Commit Message:
ULTIMA8: Don't update fast area when getting item location

Changed paths:
    engines/ultima/ultima8/gumps/game_map_gump.cpp


diff --git a/engines/ultima/ultima8/gumps/game_map_gump.cpp b/engines/ultima/ultima8/gumps/game_map_gump.cpp
index ded60fbcd2..1bfc4d13c4 100644
--- a/engines/ultima/ultima8/gumps/game_map_gump.cpp
+++ b/engines/ultima/ultima8/gumps/game_map_gump.cpp
@@ -264,7 +264,7 @@ bool GameMapGump::GetLocationOfItem(uint16 itemid, int32 &gx, int32 &gy,
 	int32 cx, cy, cz;
 	CameraProcess *cam = CameraProcess::GetCameraProcess();
 	if (!cam) CameraProcess::GetCameraLocation(cx, cy, cz);
-	else cam->GetLerped(cx, cy, cz, lerp_factor);
+	else cam->GetLerped(cx, cy, cz, lerp_factor, true);
 
 	// Screenspace bounding box bottom x coord (RNB x coord)
 	gx = (ix - iy) / 4;


Commit: bd00ab28a0c7f61268ca70bc195f34742456bba4
    https://github.com/scummvm/scummvm/commit/bd00ab28a0c7f61268ca70bc195f34742456bba4
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2021-01-08T18:18:37+09:00

Commit Message:
ULTIMA8: Avoid corner-case of Crusader mover failing

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 c4117e71d9..56e57e8762 100644
--- a/engines/ultima/ultima8/world/actors/cru_avatar_mover_process.cpp
+++ b/engines/ultima/ultima8/world/actors/cru_avatar_mover_process.cpp
@@ -335,6 +335,7 @@ void CruAvatarMoverProcess::step(Animation::Sequence action, Direction direction
 	MainActor *avatar = getMainActor();
 
 	Animation::Result res = avatar->tryAnim(action, direction);
+	Animation::Result initialres = res;
 
 	if (res != Animation::SUCCESS) {
 		World *world = World::get_instance();
@@ -367,13 +368,16 @@ void CruAvatarMoverProcess::step(Animation::Sequence action, Direction direction
 		}
 
 		if (res != Animation::SUCCESS) {
-			// reset location, couldn't move.
+			// reset location and result (in case it's END_OFF_LAND now)
+			// couldn't find a better move.
 			avatar->setLocation(origpt.x, origpt.y, origpt.z);
+			res = initialres;
 		}
 	}
 
 	if ((action == Animation::step || action == Animation::advance ||
 		 action == Animation::retreat || action == Animation::run ||
+		 action == Animation::startRunWithLargeWeapon ||
 		 action == Animation::startRun || action == Animation::walk)
 		&& res == Animation::FAILURE) {
 		action = Animation::stand;


Commit: ad01f082649137f755b287854764556410f98b50
    https://github.com/scummvm/scummvm/commit/ad01f082649137f755b287854764556410f98b50
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2021-01-08T18:18:37+09:00

Commit Message:
ULTIMA8: More tweaks for Crusader mover to bring closer to original

Changed paths:
    engines/ultima/ultima8/world/actors/avatar_mover_process.h
    engines/ultima/ultima8/world/actors/cru_avatar_mover_process.cpp
    engines/ultima/ultima8/world/actors/cru_avatar_mover_process.h
    engines/ultima/ultima8/world/actors/u8_avatar_mover_process.cpp
    engines/ultima/ultima8/world/actors/u8_avatar_mover_process.h
    engines/ultima/ultima8/world/crosshair_process.cpp


diff --git a/engines/ultima/ultima8/world/actors/avatar_mover_process.h b/engines/ultima/ultima8/world/actors/avatar_mover_process.h
index 4c245655f2..96ee244684 100644
--- a/engines/ultima/ultima8/world/actors/avatar_mover_process.h
+++ b/engines/ultima/ultima8/world/actors/avatar_mover_process.h
@@ -89,8 +89,6 @@ protected:
 	virtual void handleCombatMode() = 0;
 	virtual void handleNormalMode() = 0;
 
-	virtual bool canAttack() = 0;
-
 	void turnToDirection(Direction direction);
 	bool checkTurn(Direction direction, bool moving);
 
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 56e57e8762..aef2c65732 100644
--- a/engines/ultima/ultima8/world/actors/cru_avatar_mover_process.cpp
+++ b/engines/ultima/ultima8/world/actors/cru_avatar_mover_process.cpp
@@ -57,25 +57,33 @@ void CruAvatarMoverProcess::run() {
 	const MainActor *avatar = getMainActor();
 	assert(avatar);
 
-	if (avatar->isInCombat() && !hasMovementFlags(MOVE_FORWARD | MOVE_BACK | MOVE_JUMP | MOVE_STEP)) {
-		// See comment on _avatarAngle in header about these constants
-		if (hasMovementFlags(MOVE_TURN_LEFT)) {
-			if (hasMovementFlags(MOVE_RUN))
-				_avatarAngle -= 375;
-			else
-				_avatarAngle -= 150;
-
-			if (_avatarAngle < 0)
-				_avatarAngle += 36000;
+	// When not in combat the angle is kept as -1
+	if (avatar->isInCombat()) {
+		if (_avatarAngle < 0) {
+			_avatarAngle = Direction_ToCentidegrees(avatar->getDir());
 		}
-		if (hasMovementFlags(MOVE_TURN_RIGHT)) {
-			if (hasMovementFlags(MOVE_RUN))
-				_avatarAngle += 375;
-			else
-				_avatarAngle += 150;
+		if (!hasMovementFlags(MOVE_FORWARD | MOVE_BACK | MOVE_JUMP | MOVE_STEP)) {
+			// See comment on _avatarAngle in header about these constants
+			if (hasMovementFlags(MOVE_TURN_LEFT)) {
+				if (hasMovementFlags(MOVE_RUN))
+					_avatarAngle -= 375;
+				else
+					_avatarAngle -= 150;
+
+				if (_avatarAngle < 0)
+					_avatarAngle += 36000;
+			}
+			if (hasMovementFlags(MOVE_TURN_RIGHT)) {
+				if (hasMovementFlags(MOVE_RUN))
+					_avatarAngle += 375;
+				else
+					_avatarAngle += 150;
 
-			_avatarAngle = _avatarAngle % 36000;
+				_avatarAngle = _avatarAngle % 36000;
+			}
 		}
+	} else {
+		_avatarAngle = -1;
 	}
 
 	// Now do the regular process
@@ -91,7 +99,7 @@ void CruAvatarMoverProcess::handleHangingMode() {
 void CruAvatarMoverProcess::handleCombatMode() {
 	MainActor *avatar = getMainActor();
 	const Animation::Sequence lastanim = avatar->getLastAnim();
-	Direction direction = Direction_FromCentidegrees(_avatarAngle);
+	Direction direction = (_avatarAngle >= 0 ? Direction_FromCentidegrees(_avatarAngle) : avatar->getDir());
 	const Direction curdir = avatar->getDir();
 	const bool stasis = Ultima8Engine::get_instance()->isAvatarInStasis();
 
@@ -180,7 +188,7 @@ void CruAvatarMoverProcess::handleCombatMode() {
 	int x, y;
 	getMovementFlagAxes(x, y);
 	if (x != 0 || y != 0) {
-		Direction nextdir = Direction_FromCentidegrees(_avatarAngle);
+		Direction nextdir = (_avatarAngle >= 0 ? Direction_FromCentidegrees(_avatarAngle) : avatar->getDir());
 
 		if (checkTurn(nextdir, true))
 			return;
@@ -247,9 +255,6 @@ void CruAvatarMoverProcess::handleNormalMode() {
 		avatar->toggleInCombat();
 	}
 
-	// In normal mode the internal angle is set based on the avatar direction
-	_avatarAngle = Direction_ToCentidegrees(direction);
-
 	// If Avatar has fallen down and not dead, get up!
 	if (standUpIfNeeded(direction))
 		return;
@@ -392,26 +397,16 @@ void CruAvatarMoverProcess::step(Animation::Sequence action, Direction direction
 	waitFor(avatar->doAnim(action, direction));
 }
 
-bool CruAvatarMoverProcess::canAttack() {
-	MainActor *avatar = getMainActor();
-	return avatar->isInCombat();
-}
-
 void CruAvatarMoverProcess::tryAttack() {
 	MainActor *avatar = getMainActor();
 	Direction dir = avatar->getDir();
 	if (!avatar->isInCombat()) {
 		avatar->setInCombat(0);
-		if (!avatar->hasActorFlags(Actor::ACT_WEAPONREADY))
-			waitFor(avatar->doAnim(Animation::readyWeapon, dir));
-	} else {
-		if (canAttack()) {
-			// Fire event happens from animation
-			Animation::Sequence fireanim = (avatar->isKneeling() ?
-											Animation::kneelAndFire : Animation::attack);
-			waitFor(avatar->doAnim(fireanim, dir));
-		}
 	}
+	// Fire event happens from animation
+	Animation::Sequence fireanim = (avatar->isKneeling() ?
+									Animation::kneelAndFire : Animation::attack);
+	waitFor(avatar->doAnim(fireanim, dir));
 }
 
 void CruAvatarMoverProcess::saveData(Common::WriteStream *ws) {
diff --git a/engines/ultima/ultima8/world/actors/cru_avatar_mover_process.h b/engines/ultima/ultima8/world/actors/cru_avatar_mover_process.h
index e99ce27628..1f8ee22a12 100644
--- a/engines/ultima/ultima8/world/actors/cru_avatar_mover_process.h
+++ b/engines/ultima/ultima8/world/actors/cru_avatar_mover_process.h
@@ -67,7 +67,6 @@ private:
 	void handleHangingMode() override;
 	void handleCombatMode() override;
 	void handleNormalMode() override;
-	bool canAttack() override;
 
 	void step(Animation::Sequence action, Direction direction, bool adjusted = false);
 
diff --git a/engines/ultima/ultima8/world/actors/u8_avatar_mover_process.cpp b/engines/ultima/ultima8/world/actors/u8_avatar_mover_process.cpp
index bc771ee72f..f4b2ae73d6 100644
--- a/engines/ultima/ultima8/world/actors/u8_avatar_mover_process.cpp
+++ b/engines/ultima/ultima8/world/actors/u8_avatar_mover_process.cpp
@@ -754,16 +754,7 @@ bool U8AvatarMoverProcess::canAttack() {
 }
 
 void U8AvatarMoverProcess::tryAttack() {
-	MainActor *avatar = getMainActor();
-	Direction dir = avatar->getDir();
-	if (!avatar->isInCombat()) {
-		avatar->setInCombat(0);
-		waitFor(avatar->doAnim(Animation::readyWeapon, dir));
-	} else {
-		if (canAttack()) {
-			waitFor(avatar->doAnim(Animation::attack, dir));
-		}
-	}
+	error("tryAttack should only be called in Crusader");
 }
 
 void U8AvatarMoverProcess::saveData(Common::WriteStream *ws) {
diff --git a/engines/ultima/ultima8/world/actors/u8_avatar_mover_process.h b/engines/ultima/ultima8/world/actors/u8_avatar_mover_process.h
index 81fd454068..3cf988b787 100644
--- a/engines/ultima/ultima8/world/actors/u8_avatar_mover_process.h
+++ b/engines/ultima/ultima8/world/actors/u8_avatar_mover_process.h
@@ -52,7 +52,7 @@ protected:
 	void handleHangingMode() override;
 	void handleCombatMode() override;
 	void handleNormalMode() override;
-	bool canAttack() override;
+	bool canAttack();
 
 	void step(Animation::Sequence action, Direction direction, bool adjusted = false);
 	void jump(Animation::Sequence action, Direction direction);
diff --git a/engines/ultima/ultima8/world/crosshair_process.cpp b/engines/ultima/ultima8/world/crosshair_process.cpp
index 132c42b356..74c4cfc4f8 100644
--- a/engines/ultima/ultima8/world/crosshair_process.cpp
+++ b/engines/ultima/ultima8/world/crosshair_process.cpp
@@ -65,6 +65,10 @@ void CrosshairProcess::run() {
 			return;
 		}
 		double angle = mover->getAvatarAngleDegrees() + 90.0;
+		if (angle < 90.0) {
+			// -1 is used to record the avatar is not in combat, so shouldn't happen?
+			return;
+		}
 		// Convert angle to 0~2pi
 		double rads = Common::deg2rad(angle);
 		float xoff = CROSSHAIR_DIST * cos(rads);




More information about the Scummvm-git-logs mailing list