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

mduggan mgithub at guarana.org
Wed Jul 29 05:10:27 UTC 2020


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

Summary:
1c36ddfae5 ULTIMA8: Eliminate more use of direction as int.
08c987843a ULTIMA8: Better encapsulate AnimAction and make ShapeInfo const.
4ac5cdc5cf ULTIMA8: More const improvements
3cae01c410 ULTIMA8: Plumbing for 16 dir support (still only uses 8 dirs)


Commit: 1c36ddfae5609bda3d8edcbf78c5ccbaccc0e02c
    https://github.com/scummvm/scummvm/commit/1c36ddfae5609bda3d8edcbf78c5ccbaccc0e02c
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-07-29T14:10:15+09:00

Commit Message:
ULTIMA8: Eliminate more use of direction as int.

Changed paths:
    engines/ultima/ultima8/misc/direction.h
    engines/ultima/ultima8/misc/direction_util.h
    engines/ultima/ultima8/world/actors/actor.cpp
    engines/ultima/ultima8/world/actors/actor_anim_process.cpp
    engines/ultima/ultima8/world/actors/animation_tracker.cpp
    engines/ultima/ultima8/world/actors/pathfinder_process.cpp
    engines/ultima/ultima8/world/current_map.cpp
    engines/ultima/ultima8/world/current_map.h
    engines/ultima/ultima8/world/fireball_process.cpp
    engines/ultima/ultima8/world/item.cpp
    engines/ultima/ultima8/world/super_sprite_process.cpp


diff --git a/engines/ultima/ultima8/misc/direction.h b/engines/ultima/ultima8/misc/direction.h
index 3812e15310..6286cecde6 100644
--- a/engines/ultima/ultima8/misc/direction.h
+++ b/engines/ultima/ultima8/misc/direction.h
@@ -38,7 +38,15 @@ enum Direction {
 	dir_southwest = 5,
 	dir_west = 6,
 	dir_northwest = 7,
-	dir_current = 16
+	dir_current = 16,
+	dir_nne,
+	dir_ene,
+	dir_ese,
+	dir_sse,
+	dir_ssw,
+	dir_wsw,
+	dir_wnw,
+	dir_nnw
 };
 
 } // End of namespace Ultima8
diff --git a/engines/ultima/ultima8/misc/direction_util.h b/engines/ultima/ultima8/misc/direction_util.h
index c29600a70d..7da658f898 100644
--- a/engines/ultima/ultima8/misc/direction_util.h
+++ b/engines/ultima/ultima8/misc/direction_util.h
@@ -32,11 +32,19 @@ namespace Ultima8 {
 /*
  * Tables to map a Direction to x/y deltas
  */
-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 };
+
+inline int Direction_XFactor(Direction dir) {
+	static const int _x_fact[] = {  0, +1, +1, +1,  0, -1, -1, -1 };
+	//static const int _x_fact16[] = {  0, +1, +2, +2, +2, +2, +2, +1, 0, -1, -2, -2, -2, -2, -2, -1 };
+	return _x_fact[dir];
+}
+
+inline int Direction_YFactor(Direction dir) {
+	static const int _y_fact[] = { -1, -1,  0, +1, +1, +1,  0, -1 };
+	//static const int _y_fact16[] = { -2, -2, -2, -1,  0, +1, +2, +2, +2, +2, +2, +1, 0, -1, -2, -2 };
+	return _y_fact[dir];
+}
 
 /**
  *  Return the direction for a given slope (0-7).
@@ -121,16 +129,23 @@ inline Direction Direction_GetWorldDirInRange(int deltay, int deltax, uint16 ndi
 
 inline Direction Direction_Invert(Direction dir) {
 	assert(dir != dir_current);
-	// TODO: Will need to add more cases for 16 dir support.
 	switch (dir) {
 		case dir_north:		return dir_south;
+		case dir_nne:		return dir_ssw;
 		case dir_northeast:	return dir_southwest;
+		case dir_ene:		return dir_wsw;
 		case dir_east:		return dir_west;
+		case dir_ese:		return dir_wnw;
 		case dir_southeast:	return dir_northwest;
+		case dir_sse:		return dir_nnw;
 		case dir_south:		return dir_north;
+		case dir_ssw:		return dir_nne;
 		case dir_southwest:	return dir_northeast;
+		case dir_wsw:		return dir_ene;
 		case dir_west:		return dir_east;
+		case dir_wnw:		return dir_ese;
 		case dir_northwest:	return dir_southeast;
+		case dir_nnw:		return dir_sse;
 		default:			return dir_north;
 	}
 }
diff --git a/engines/ultima/ultima8/world/actors/actor.cpp b/engines/ultima/ultima8/world/actors/actor.cpp
index 10c7a43fb0..829b4a0f2d 100644
--- a/engines/ultima/ultima8/world/actors/actor.cpp
+++ b/engines/ultima/ultima8/world/actors/actor.cpp
@@ -1382,7 +1382,7 @@ void Actor::saveData(Common::WriteStream *ws) {
 	ws->writeUint16LE(_enemyAlignment);
 	ws->writeUint16LE(_lastAnim);
 	ws->writeUint16LE(_animFrame);
-	ws->writeUint16LE(_direction);
+	ws->writeUint16LE(Direction_ToUsecodeDir(_direction));
 	ws->writeUint32LE(_fallStart);
 	ws->writeUint32LE(_actorFlags);
 	ws->writeByte(_unkByte);
@@ -1412,7 +1412,7 @@ bool Actor::loadData(Common::ReadStream *rs, uint32 version) {
 	_enemyAlignment = rs->readUint16LE();
 	_lastAnim = static_cast<Animation::Sequence>(rs->readUint16LE());
 	_animFrame = rs->readUint16LE();
-	_direction = static_cast<Direction>(rs->readUint16LE());
+	_direction = Direction_FromUsecodeDir(rs->readUint16LE());
 	_fallStart = rs->readUint32LE();
 	_actorFlags = rs->readUint32LE();
 	_unkByte = rs->readByte();
diff --git a/engines/ultima/ultima8/world/actors/actor_anim_process.cpp b/engines/ultima/ultima8/world/actors/actor_anim_process.cpp
index 89b6de61cf..4cc1ef470d 100644
--- a/engines/ultima/ultima8/world/actors/actor_anim_process.cpp
+++ b/engines/ultima/ultima8/world/actors/actor_anim_process.cpp
@@ -385,8 +385,8 @@ void ActorAnimProcess::doSpecial() {
 			skull->setFlag(Item::FLG_FAST_ONLY);
 			int32 x, y, z;
 			a->getLocation(x, y, z);
-			int dirNum = a->getDir();
-			skull->move(x + 32 * x_fact[dirNum], y + 32 * y_fact[dirNum], z);
+			Direction dirNum = a->getDir();
+			skull->move(x + 32 * Direction_XFactor(dirNum), y + 32 * Direction_XFactor(dirNum), z);
 			hostile = skull;
 		} else if (a->getMapNum() != 54) { // Khumash-Gor doesn't summon ghouls
 			// otherwise, summon ghoul
@@ -553,8 +553,8 @@ void ActorAnimProcess::doHitSpecial(Item *hit) {
 			Kernel *kernel = Kernel::get_instance();
 
 			int32 fx, fy, fz;
-			fx = x + 96 * x_fact[_dir];
-			fy = y + 96 * y_fact[_dir];
+			fx = x + 96 * Direction_XFactor(_dir);
+			fy = y + 96 * Direction_YFactor(_dir);
 			fz = z;
 
 			// CONSTANTS!! (lots of them)
@@ -646,7 +646,7 @@ void ActorAnimProcess::saveData(Common::WriteStream *ws) {
 	ws->writeByte(ab);
 	uint8 attacked = _attackedSomething ? 1 : 0;
 	ws->writeByte(attacked);
-	ws->writeByte(static_cast<uint8>(_dir));
+	ws->writeByte(static_cast<uint8>(Direction_ToUsecodeDir(_dir)));
 	ws->writeUint16LE(static_cast<uint16>(_action));
 	ws->writeUint16LE(static_cast<uint16>(_steps));
 	ws->writeUint16LE(static_cast<uint16>(_repeatCounter));
@@ -665,7 +665,7 @@ bool ActorAnimProcess::loadData(Common::ReadStream *rs, uint32 version) {
 	_firstFrame = (rs->readByte() != 0);
 	_animAborted = (rs->readByte() != 0);
 	_attackedSomething = (rs->readByte() != 0);
-	_dir = static_cast<Direction>(rs->readByte());
+	_dir = Direction_FromUsecodeDir(rs->readByte());
 	_action = static_cast<Animation::Sequence>(rs->readUint16LE());
 	_steps = rs->readUint16LE();
 	_repeatCounter = rs->readUint16LE();
diff --git a/engines/ultima/ultima8/world/actors/animation_tracker.cpp b/engines/ultima/ultima8/world/actors/animation_tracker.cpp
index c54384631c..bc5b5e3bad 100644
--- a/engines/ultima/ultima8/world/actors/animation_tracker.cpp
+++ b/engines/ultima/ultima8/world/actors/animation_tracker.cpp
@@ -156,8 +156,8 @@ void AnimationTracker::evaluateMaxAnimTravel(int32 &max_endx, int32 &max_endy, D
 	for (;;) {
 		AnimFrame &f = _animAction->frames[dir][testframe];
 		// determine movement for this frame
-		int32 dx = 4 * x_fact[dir] * f._deltaDir;
-		int32 dy = 4 * y_fact[dir] * f._deltaDir;
+		int32 dx = 4 * Direction_XFactor(dir) * f._deltaDir;
+		int32 dy = 4 * Direction_YFactor(dir) * f._deltaDir;
 		max_endx += dx;
 		max_endy += dy;
 		testframe = getNextFrame(testframe);
@@ -206,8 +206,8 @@ bool AnimationTracker::step() {
 	_flipped = f.is_flipped();
 
 	// determine movement for this frame
-	int32 dx = 4 * x_fact[_dir] * f._deltaDir;
-	int32 dy = 4 * y_fact[_dir] * f._deltaDir;
+	int32 dx = 4 * Direction_XFactor(_dir) * f._deltaDir;
+	int32 dy = 4 * Direction_YFactor(_dir) * f._deltaDir;
 	int32 dz = f._deltaZ;
 
 	if (_mode == TargetMode && !(f._flags & AnimFrame::AFF_ONGROUND)) {
@@ -445,8 +445,8 @@ void AnimationTracker::setTargetedMode(int32 x_, int32 y_, int32 z_) {
 			++offGround;
 	}
 
-	end_dx = 4 * x_fact[_dir] * totaldir;
-	end_dy = 4 * y_fact[_dir] * totaldir;
+	end_dx = 4 * Direction_XFactor(_dir) * totaldir;
+	end_dy = 4 * Direction_YFactor(_dir) * totaldir;
 	end_dz = totalz;
 
 	if (offGround) {
@@ -475,7 +475,7 @@ void AnimationTracker::checkWeaponHit() {
 
 	Box abox = a->getWorldBox();
 	abox.MoveAbs(_x, _y, _z);
-	abox.MoveRel(x_fact[_dir] * 32 * range, y_fact[_dir] * 32 * range, 0);
+	abox.MoveRel(Direction_XFactor(_dir) * 32 * range, Direction_YFactor(_dir) * 32 * range, 0);
 
 #ifdef WATCHACTOR
 	if (a->getObjId() == watchactor) {
@@ -584,7 +584,7 @@ void AnimationTracker::save(Common::WriteStream *ws) {
 	ws->writeUint32LE(_currentFrame);
 
 	ws->writeUint16LE(_actor);
-	ws->writeByte(static_cast<uint8>(_dir));
+	ws->writeByte(static_cast<uint8>(Direction_ToUsecodeDir(_dir)));
 
 	if (_animAction) {
 		ws->writeUint32LE(_animAction->_shapeNum);
@@ -630,7 +630,7 @@ bool AnimationTracker::load(Common::ReadStream *rs, uint32 version) {
 	_currentFrame = rs->readUint32LE();
 
 	_actor = rs->readUint16LE();
-	_dir = static_cast<Direction>(rs->readByte());
+	_dir = Direction_FromUsecodeDir(rs->readByte());
 
 	uint32 shapenum = rs->readUint32LE();
 	uint32 action = rs->readUint32LE();
diff --git a/engines/ultima/ultima8/world/actors/pathfinder_process.cpp b/engines/ultima/ultima8/world/actors/pathfinder_process.cpp
index 1646a62fa6..fb59e9d5c5 100644
--- a/engines/ultima/ultima8/world/actors/pathfinder_process.cpp
+++ b/engines/ultima/ultima8/world/actors/pathfinder_process.cpp
@@ -26,6 +26,7 @@
 #include "ultima/ultima8/world/actors/actor.h"
 #include "ultima/ultima8/world/actors/pathfinder.h"
 #include "ultima/ultima8/world/get_object.h"
+#include "ultima/ultima8/misc/direction_util.h"
 
 namespace Ultima {
 namespace Ultima8 {
@@ -250,7 +251,7 @@ void PathfinderProcess::saveData(Common::WriteStream *ws) {
 	ws->writeUint16LE(static_cast<uint16>(_path.size()));
 	for (unsigned int i = 0; i < _path.size(); ++i) {
 		ws->writeUint16LE(static_cast<uint16>(_path[i]._action));
-		ws->writeUint16LE(static_cast<uint16>(_path[i]._direction));
+		ws->writeUint16LE(static_cast<uint16>(Direction_ToUsecodeDir(_path[i]._direction)));
 	}
 }
 
@@ -268,7 +269,7 @@ bool PathfinderProcess::loadData(Common::ReadStream *rs, uint32 version) {
 	_path.resize(pathsize);
 	for (unsigned int i = 0; i < pathsize; ++i) {
 		_path[i]._action = static_cast<Animation::Sequence>(rs->readUint16LE());
-		_path[i]._direction = static_cast<Direction>(rs->readUint16LE());
+		_path[i]._direction = Direction_FromUsecodeDir(rs->readUint16LE());
 	}
 
 	return true;
diff --git a/engines/ultima/ultima8/world/current_map.cpp b/engines/ultima/ultima8/world/current_map.cpp
index 0cbe688be3..489f83347d 100644
--- a/engines/ultima/ultima8/world/current_map.cpp
+++ b/engines/ultima/ultima8/world/current_map.cpp
@@ -810,16 +810,16 @@ bool CurrentMap::isValidPosition(int32 x, int32 y, int32 z,
 }
 
 bool CurrentMap::scanForValidPosition(int32 x, int32 y, int32 z, const Item *item,
-                                      int movedir, bool wantsupport,
+                                      Direction movedir, bool wantsupport,
                                       int32 &tx, int32 &ty, int32 &tz) {
 	// TODO: clean this up. Currently the mask arrays are filled with more
 	// data than is actually used.
 	const uint32 blockflagmask = (ShapeInfo::SI_SOLID | ShapeInfo::SI_DAMAGING) & item->getShapeInfo()->_flags;
 
-	int searchdir = (movedir + 2) % 4;
+	Direction searchdir = static_cast<Direction>(((int)movedir + 2) % 4);
 
-	bool xdir = (x_fact[searchdir] != 0);
-	bool ydir = (y_fact[searchdir] != 0);
+	bool xdir = (Direction_XFactor(searchdir) != 0);
+	bool ydir = (Direction_YFactor(searchdir) != 0);
 
 	// mark everything as valid, but without support
 	uint32 validmask[17];
@@ -838,7 +838,6 @@ bool CurrentMap::scanForValidPosition(int32 x, int32 y, int32 z, const Item *ite
 	// in which case positive horiz points in the (positive x, negative y)
 	// direction.
 
-
 	// next, we'll loop over all objects in the area, and mark the areas
 	// overlapped and supported by each object
 
diff --git a/engines/ultima/ultima8/world/current_map.h b/engines/ultima/ultima8/world/current_map.h
index d4ec9a82d4..75c01ffb89 100644
--- a/engines/ultima/ultima8/world/current_map.h
+++ b/engines/ultima/ultima8/world/current_map.h
@@ -138,7 +138,7 @@ public:
 
 	//! Scan for a valid position for item in directions orthogonal to movedir
 	bool scanForValidPosition(int32 x, int32 y, int32 z, const Item *item,
-	                          int movedir, bool wantsupport,
+	                          Direction movedir, bool wantsupport,
 	                          int32 &tx, int32 &ty, int32 &tz);
 
 	struct SweepItem {
diff --git a/engines/ultima/ultima8/world/fireball_process.cpp b/engines/ultima/ultima8/world/fireball_process.cpp
index ce4cdf56b3..81bdafde2a 100644
--- a/engines/ultima/ultima8/world/fireball_process.cpp
+++ b/engines/ultima/ultima8/world/fireball_process.cpp
@@ -103,8 +103,8 @@ void FireballProcess::run() {
 	Direction targetdir = item->getDirToItemCentre(*t);
 
 	if (_xSpeed == 0 && _ySpeed == 0 && dx / 64 == 0 && dy / 64 == 0) {
-		_xSpeed += 2 * x_fact[targetdir];
-		_ySpeed += 2 * y_fact[targetdir];
+		_xSpeed += 2 * Direction_XFactor(targetdir);
+		_ySpeed += 2 * Direction_YFactor(targetdir);
 	} else {
 		_xSpeed += (dx / 64);
 		_ySpeed += (dy / 64);
@@ -131,7 +131,8 @@ void FireballProcess::run() {
 	}
 
 	Item *tailitem = getItem(_tail[2]);
-	tailitem->setFrame(Direction_GetWorldDir(_ySpeed, _xSpeed));
+	Direction movedir = Direction_GetWorldDir(_ySpeed, _xSpeed);
+	tailitem->setFrame(Direction_ToUsecodeDir(movedir));
 	tailitem->move(x, y, z);
 
 	_tail[2] = _tail[1];
diff --git a/engines/ultima/ultima8/world/item.cpp b/engines/ultima/ultima8/world/item.cpp
index 6329999d0a..0f792ef5e8 100644
--- a/engines/ultima/ultima8/world/item.cpp
+++ b/engines/ultima/ultima8/world/item.cpp
@@ -1279,8 +1279,8 @@ uint16 Item::fireWeapon(int32 x, int32 y, int32 z, Direction dir, int firetype,
 				// Just send the projectile off into the distance
 				// CHECKME: This is not how the game does it - it has different
 				// tables (at 1478:129b and 1478:12ac). Check the logic here.
-				ssx = ix + x_fact[dir] * 0x500;
-				ssy = iy + x_fact[dir] * 0x500;
+				ssx = ix + Direction_XFactor(dir) * 0x500;
+				ssy = iy + Direction_YFactor(dir) * 0x500;
 				ssz = iz;
 			}
 
@@ -1966,7 +1966,7 @@ void Item::receiveHitU8(uint16 other, Direction dir, int damage, uint16 type) {
 
 	// nothing special, so just hurl the item
 	// TODO: hurl item in direction, with speed depending on damage
-	hurl(-16 * x_fact[dir], -16 * y_fact[dir], 16, 4); //!! constants
+	hurl(-16 * Direction_XFactor(dir), -16 * Direction_YFactor(dir), 16, 4); //!! constants
 }
 
 
@@ -1999,7 +1999,7 @@ void Item::receiveHitCru(uint16 other, Direction dir, int damage, uint16 type) {
 	int yhurl = 10 + getRandom() % 15;
 
 	// nothing special, so just hurl the item
-	hurl(-xhurl * x_fact[dir], -yhurl * y_fact[dir], 16, 4); //!! constants
+	hurl(-xhurl * Direction_XFactor(dir), -yhurl * Direction_YFactor(dir), 16, 4); //!! constants
 }
 
 
diff --git a/engines/ultima/ultima8/world/super_sprite_process.cpp b/engines/ultima/ultima8/world/super_sprite_process.cpp
index 564da41698..5c5d4b0034 100644
--- a/engines/ultima/ultima8/world/super_sprite_process.cpp
+++ b/engines/ultima/ultima8/world/super_sprite_process.cpp
@@ -208,7 +208,7 @@ void SuperSpriteProcess::run() {
 					item = getItem(_itemNum);
 				}
 				if (item) {
-					item->setFrame(dir + 0x11);
+					item->setFrame(Direction_ToUsecodeDir(dir) + 0x11);
 				}
 			}
 		}


Commit: 08c987843ad868ccad7281657441d747f88d97f8
    https://github.com/scummvm/scummvm/commit/08c987843ad868ccad7281657441d747f88d97f8
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-07-29T14:10:15+09:00

Commit Message:
ULTIMA8: Better encapsulate AnimAction and make ShapeInfo const.

Changed paths:
    engines/ultima/ultima8/graphics/anim_dat.cpp
    engines/ultima/ultima8/graphics/anim_dat.h
    engines/ultima/ultima8/graphics/main_shape_archive.cpp
    engines/ultima/ultima8/graphics/main_shape_archive.h
    engines/ultima/ultima8/graphics/wpn_ovlay_dat.cpp
    engines/ultima/ultima8/gumps/container_gump.cpp
    engines/ultima/ultima8/gumps/shape_viewer_gump.cpp
    engines/ultima/ultima8/world/actors/actor.cpp
    engines/ultima/ultima8/world/actors/actor_anim_process.cpp
    engines/ultima/ultima8/world/actors/anim_action.cpp
    engines/ultima/ultima8/world/actors/anim_action.h
    engines/ultima/ultima8/world/actors/animation_tracker.cpp
    engines/ultima/ultima8/world/actors/animation_tracker.h
    engines/ultima/ultima8/world/actors/combat_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
    engines/ultima/ultima8/world/item_factory.cpp
    engines/ultima/ultima8/world/map.cpp


diff --git a/engines/ultima/ultima8/graphics/anim_dat.cpp b/engines/ultima/ultima8/graphics/anim_dat.cpp
index 3f47ad402b..a0f63af529 100644
--- a/engines/ultima/ultima8/graphics/anim_dat.cpp
+++ b/engines/ultima/ultima8/graphics/anim_dat.cpp
@@ -42,14 +42,14 @@ AnimDat::~AnimDat() {
 		delete _anims[i];
 }
 
-ActorAnim *AnimDat::getAnim(uint32 shape) const {
+const ActorAnim *AnimDat::getAnim(uint32 shape) const {
 	if (shape >= _anims.size())
 		return nullptr;
 
 	return _anims[shape];
 }
 
-AnimAction *AnimDat::getAnim(uint32 shape, uint32 action) const {
+const AnimAction *AnimDat::getAnim(uint32 shape, uint32 action) const {
 	if (shape >= _anims.size())
 		return nullptr;
 	if (_anims[shape] == 0)
@@ -169,7 +169,7 @@ void AnimDat::load(Common::SeekableReadStream *rs) {
 			a->_actions[action]->_dirCount = dirCount;
 
 			for (unsigned int dir = 0; dir < dirCount; dir++) {
-				a->_actions[action]->frames[dir].clear();
+				a->_actions[action]->_frames[dir].clear();
 
 				for (unsigned int j = 0; j < actionsize; j++) {
 					if (GAME_IS_U8) {
@@ -201,7 +201,7 @@ void AnimDat::load(Common::SeekableReadStream *rs) {
 						f._deltaZ = 0;
 						f._sfx = 0;
 					}
-					a->_actions[action]->frames[dir].push_back(f);
+					a->_actions[action]->_frames[dir].push_back(f);
 				}
 			}
 		}
diff --git a/engines/ultima/ultima8/graphics/anim_dat.h b/engines/ultima/ultima8/graphics/anim_dat.h
index 36d0ac86dc..3de05f95bd 100644
--- a/engines/ultima/ultima8/graphics/anim_dat.h
+++ b/engines/ultima/ultima8/graphics/anim_dat.h
@@ -39,8 +39,8 @@ public:
 
 	void load(Common::SeekableReadStream *rs);
 
-	ActorAnim *getAnim(uint32 shape) const;
-	AnimAction *getAnim(uint32 shape, uint32 action) const;
+	const ActorAnim *getAnim(uint32 shape) const;
+	const AnimAction *getAnim(uint32 shape, uint32 action) const;
 
 	//! Return the action number for a given animation sequence
 	static uint32 getActionNumberForSequence(Animation::Sequence action);
diff --git a/engines/ultima/ultima8/graphics/main_shape_archive.cpp b/engines/ultima/ultima8/graphics/main_shape_archive.cpp
index e20ea63dfe..e064ef34b0 100644
--- a/engines/ultima/ultima8/graphics/main_shape_archive.cpp
+++ b/engines/ultima/ultima8/graphics/main_shape_archive.cpp
@@ -54,7 +54,7 @@ void MainShapeArchive::loadDamageDat(Common::SeekableReadStream *rs) {
 	_typeFlags->loadDamageDat(rs);
 }
 
-ShapeInfo *MainShapeArchive::getShapeInfo(uint32 shapenum) {
+const ShapeInfo *MainShapeArchive::getShapeInfo(uint32 shapenum) {
 	assert(_typeFlags);
 
 	return _typeFlags->getShapeInfo(shapenum);
@@ -70,13 +70,13 @@ void MainShapeArchive::loadAnimDat(Common::SeekableReadStream *rs) {
 	_animDat->load(rs);
 }
 
-ActorAnim *MainShapeArchive::getAnim(uint32 shape) const {
+const ActorAnim *MainShapeArchive::getAnim(uint32 shape) const {
 	assert(_animDat);
 
 	return _animDat->getAnim(shape);
 }
 
-AnimAction *MainShapeArchive::getAnim(uint32 shape, uint32 action) const {
+const AnimAction *MainShapeArchive::getAnim(uint32 shape, uint32 action) const {
 	assert(_animDat);
 
 	return _animDat->getAnim(shape, action);
diff --git a/engines/ultima/ultima8/graphics/main_shape_archive.h b/engines/ultima/ultima8/graphics/main_shape_archive.h
index 73041670c9..5563d5ba8d 100644
--- a/engines/ultima/ultima8/graphics/main_shape_archive.h
+++ b/engines/ultima/ultima8/graphics/main_shape_archive.h
@@ -51,11 +51,11 @@ public:
 
 	void loadTypeFlags(Common::SeekableReadStream *rs);
 	void loadDamageDat(Common::SeekableReadStream *rs);
-	ShapeInfo *getShapeInfo(uint32 shapenum);
+	const ShapeInfo *getShapeInfo(uint32 shapenum);
 
 	void loadAnimDat(Common::SeekableReadStream *rs);
-	ActorAnim *getAnim(uint32 shape) const;
-	AnimAction *getAnim(uint32 shape, uint32 action) const;
+	const ActorAnim *getAnim(uint32 shape) const;
+	const AnimAction *getAnim(uint32 shape, uint32 action) const;
 
 protected:
 	TypeFlags *_typeFlags;
diff --git a/engines/ultima/ultima8/graphics/wpn_ovlay_dat.cpp b/engines/ultima/ultima8/graphics/wpn_ovlay_dat.cpp
index b85253868c..807118a5e3 100644
--- a/engines/ultima/ultima8/graphics/wpn_ovlay_dat.cpp
+++ b/engines/ultima/ultima8/graphics/wpn_ovlay_dat.cpp
@@ -73,7 +73,7 @@ void WpnOvlayDat::load(RawArchive *overlaydat) {
 
 		if (rs && rs->size()) {
 			// get Avatar's animation
-			AnimAction *anim = msf->getAnim(1, action);
+			const AnimAction *anim = msf->getAnim(1, action);
 			if (!anim) {
 				perr << "Skipping wpnovlay action " << action << " because animation doesn't exist." << Std::endl;
 				continue;
@@ -82,8 +82,8 @@ void WpnOvlayDat::load(RawArchive *overlaydat) {
 			AnimWeaponOverlay *awo = new AnimWeaponOverlay;
 			_overlay[action] = awo;
 
-			unsigned int animlength = anim->_size;
-			unsigned int dircount = anim->_dirCount;
+			unsigned int animlength = anim->getSize();
+			unsigned int dircount = anim->getDirCount();
 
 			unsigned int typecount = rs->size() / (4 * dircount * animlength);
 			awo->_overlay.resize(typecount);
diff --git a/engines/ultima/ultima8/gumps/container_gump.cpp b/engines/ultima/ultima8/gumps/container_gump.cpp
index 61f4f76e13..d0b37e6d00 100644
--- a/engines/ultima/ultima8/gumps/container_gump.cpp
+++ b/engines/ultima/ultima8/gumps/container_gump.cpp
@@ -285,7 +285,7 @@ Container *ContainerGump::getTargetContainer(Item *item, int mx, int my) {
 		targetcontainer = nullptr;
 
 	if (targetcontainer) {
-		ShapeInfo *targetinfo = targetcontainer->getShapeInfo();
+		const ShapeInfo *targetinfo = targetcontainer->getShapeInfo();
 		if ((targetcontainer->getObjId() == item->getObjId()) ||
 		        targetinfo->is_land() ||
 		        targetcontainer->hasFlags(Item::FLG_IN_NPC_LIST)) {
diff --git a/engines/ultima/ultima8/gumps/shape_viewer_gump.cpp b/engines/ultima/ultima8/gumps/shape_viewer_gump.cpp
index 96e6eb2d49..60a9533954 100644
--- a/engines/ultima/ultima8/gumps/shape_viewer_gump.cpp
+++ b/engines/ultima/ultima8/gumps/shape_viewer_gump.cpp
@@ -163,7 +163,7 @@ void ShapeViewerGump::PaintThis(RenderSurface *surf, int32 lerp_factor, bool /*s
 		char buf4[128];
 		char buf5[128];
 		char buf6[512];
-		ShapeInfo *info = mainshapes->getShapeInfo(_curShape);
+		const ShapeInfo *info = mainshapes->getShapeInfo(_curShape);
 		if (info) {
 			sprintf(buf3, "x: %d, y: %d, z: %d\n flags: 0x%04X, family: %d",
 					info->_x, info->_y, info->_z, info->_flags, info->_family);
diff --git a/engines/ultima/ultima8/world/actors/actor.cpp b/engines/ultima/ultima8/world/actors/actor.cpp
index 829b4a0f2d..b78f510a3d 100644
--- a/engines/ultima/ultima8/world/actors/actor.cpp
+++ b/engines/ultima/ultima8/world/actors/actor.cpp
@@ -129,7 +129,7 @@ bool Actor::loadMonsterStatsCru() {
 
 bool Actor::loadMonsterStatsU8() {
 
-	ShapeInfo *shapeinfo = getShapeInfo();
+	const ShapeInfo *shapeinfo = getShapeInfo();
 	MonsterInfo *mi = nullptr;
 	if (shapeinfo) mi = shapeinfo->_monsterInfo;
 	if (!mi)
@@ -358,7 +358,7 @@ bool Actor::giveTreasure() {
 			n = getRandom() % ti._frames.size();
 			uint32 frameNum = ti._frames[n];
 
-			ShapeInfo *si = GameData::get_instance()->getMainShapes()->
+			const ShapeInfo *si = GameData::get_instance()->getMainShapes()->
 			                getShapeInfo(shapeNum);
 			if (!si) {
 				perr << "Trying to create treasure with an invalid shapeNum ("
@@ -510,7 +510,7 @@ Animation::Result Actor::tryAnim(Animation::Sequence anim, Direction dir,
 	}
 
 	if (tracker.isBlocked() &&
-	        !(animaction->_flags & AnimAction::AAF_UNSTOPPABLE)) {
+	        !animaction->hasFlags(AnimAction::AAF_UNSTOPPABLE)) {
 		return Animation::FAILURE;
 	}
 
@@ -681,7 +681,7 @@ int16 Actor::getAttackingDex() const {
 }
 
 uint16 Actor::getDamageType() const {
-	ShapeInfo *si = getShapeInfo();
+	const ShapeInfo *si = getShapeInfo();
 	if (si->_monsterInfo)
 		return si->_monsterInfo->_damageType;
 	else
@@ -1010,7 +1010,7 @@ ProcId Actor::die(uint16 damageType) {
 	destroyContents();
 	giveTreasure();
 
-	ShapeInfo *shapeinfo = getShapeInfo();
+	const ShapeInfo *shapeinfo = getShapeInfo();
 	MonsterInfo *mi = nullptr;
 	if (shapeinfo) mi = shapeinfo->_monsterInfo;
 
diff --git a/engines/ultima/ultima8/world/actors/actor_anim_process.cpp b/engines/ultima/ultima8/world/actors/actor_anim_process.cpp
index 4cc1ef470d..c0fa2c4dc2 100644
--- a/engines/ultima/ultima8/world/actors/actor_anim_process.cpp
+++ b/engines/ultima/ultima8/world/actors/actor_anim_process.cpp
@@ -155,7 +155,7 @@ void ActorAnimProcess::run() {
 
 	if (!_firstFrame)
 		_repeatCounter++;
-	if (_repeatCounter > _tracker->getAnimAction()->_frameRepeat)
+	if (_repeatCounter > _tracker->getAnimAction()->getFrameRepeat())
 		_repeatCounter = 0;
 
 	Actor *a = getActor(_itemNum);
@@ -228,7 +228,7 @@ void ActorAnimProcess::run() {
 
 
 			if (_tracker->isBlocked() &&
-			        !(_tracker->getAnimAction()->_flags & AnimAction::AAF_UNSTOPPABLE)) {
+			        !(_tracker->getAnimAction()->hasFlags(AnimAction::AAF_UNSTOPPABLE))) {
 				// FIXME: For blocked large _steps we may still want to do
 				//        a partial move. (But how would that work with
 				//        repeated frames?)
@@ -332,7 +332,7 @@ void ActorAnimProcess::run() {
 #endif
 
 
-	if (_repeatCounter == _tracker->getAnimAction()->_frameRepeat) {
+	if (_repeatCounter == _tracker->getAnimAction()->getFrameRepeat()) {
 		if (_tracker->isUnsupported()) {
 			_animAborted = true;
 
@@ -610,7 +610,7 @@ void ActorAnimProcess::terminate() {
 	if (a) {
 		if (_tracker) { // if we were really animating...
 			a->clearActorFlag(Actor::ACT_ANIMLOCK);
-			if (_tracker->getAnimAction()->_flags & AnimAction::AAF_DESTROYACTOR) {
+			if (_tracker->getAnimAction()->hasFlags(AnimAction::AAF_DESTROYACTOR)) {
 				// destroy the actor
 #ifdef WATCHACTOR
 				if (_itemNum == watchactor)
diff --git a/engines/ultima/ultima8/world/actors/anim_action.cpp b/engines/ultima/ultima8/world/actors/anim_action.cpp
index ed12bb652e..bd99b7874e 100644
--- a/engines/ultima/ultima8/world/actors/anim_action.cpp
+++ b/engines/ultima/ultima8/world/actors/anim_action.cpp
@@ -27,8 +27,8 @@
 namespace Ultima {
 namespace Ultima8 {
 
-void AnimAction::getAnimRange(unsigned int lastanim, int lastdir,
-                              bool firststep, int dir,
+void AnimAction::getAnimRange(unsigned int lastanim, Direction lastdir,
+                              bool firststep, Direction dir,
                               unsigned int &startframe, unsigned int &endframe) const {
 	startframe = 0;
 	endframe = _size;
@@ -59,7 +59,7 @@ void AnimAction::getAnimRange(unsigned int lastanim, int lastdir,
 	}
 }
 
-void AnimAction::getAnimRange(const Actor *actor, int dir,
+void AnimAction::getAnimRange(const Actor *actor, Direction dir,
                               unsigned int &startframe,
                               unsigned int &endframe) const {
 	getAnimRange(actor->getLastAnim(), actor->getDir(),
@@ -67,5 +67,17 @@ void AnimAction::getAnimRange(const Actor *actor, int dir,
 	             dir, startframe, endframe);
 }
 
+const AnimFrame &AnimAction::getFrame(Direction dir, unsigned int frameno) const {
+	assert((unsigned int)dir < _dirCount);
+	assert(frameno < _frames[dir].size());
+
+	uint32 diroff = static_cast<uint32>(dir);
+	// HACK for 16 dir support
+	if (_dirCount == 16)
+		diroff *= 2;
+
+	return _frames[diroff][frameno];
+}
+
 } // End of namespace Ultima8
 } // End of namespace Ultima
diff --git a/engines/ultima/ultima8/world/actors/anim_action.h b/engines/ultima/ultima8/world/actors/anim_action.h
index 8acbd282c9..bb3ce36d10 100644
--- a/engines/ultima/ultima8/world/actors/anim_action.h
+++ b/engines/ultima/ultima8/world/actors/anim_action.h
@@ -24,6 +24,7 @@
 #define WORLD_ACTORS_ANIMACTION_H
 
 #include "ultima/shared/std/containers.h"
+#include "ultima/ultima8/misc/direction.h"
 
 namespace Ultima {
 namespace Ultima8 {
@@ -54,23 +55,16 @@ struct AnimFrame {
 	}
 };
 
-struct AnimAction {
-	uint32 _shapeNum;
-	uint32 _action;
-
-	Std::vector<AnimFrame> frames[16]; // 8 or 16 directions
-	unsigned int _size;
-	int _frameRepeat;
-	uint32 _flags;
-
-	unsigned int _dirCount;
+class AnimAction {
+	friend class AnimDat;
 
+public:
 	//! return the range of the animation to play
 	//! \param actor The actor to play the animation for
 	//! \param dir The direction
 	//! \param startframe The first frame to play
 	//! \param endframe The frame after the last frame to play
-	void getAnimRange(const Actor *actor, int dir,
+	void getAnimRange(const Actor *actor, Direction dir,
 	                  unsigned int &startframe, unsigned int &endframe) const;
 
 	//! return the range of the animation to play
@@ -80,11 +74,35 @@ struct AnimAction {
 	//! \param dir The direction
 	//! \param startframe The first frame to play
 	//! \param endframe The frame after the last frame to play
-	void getAnimRange(unsigned int lastanim, int lastdir,
-	                  bool firststep, int dir,
+	void getAnimRange(unsigned int lastanim, Direction lastdir,
+	                  bool firststep, Direction dir,
 	                  unsigned int &startframe, unsigned int &endframe) const;
 
-	unsigned int getDirCount() const;
+	unsigned int getDirCount() const {
+		return _dirCount;
+	}
+
+	unsigned int getSize() const {
+		return _size;
+	}
+	
+	int getFrameRepeat() const {
+		return _frameRepeat;
+	}
+	
+	uint32 getShapeNum() const {
+		return _shapeNum;
+	}
+	
+	uint32 getAction() const {
+		return _action;
+	}
+	
+	bool hasFlags(uint32 mask) const {
+		return (_flags & mask) != 0;
+	}
+	
+	const AnimFrame &getFrame(Direction dir, unsigned int frameno) const;
 
 	enum AnimActionFlags {
 		AAF_TWOSTEP      = 0x0001,
@@ -96,6 +114,17 @@ struct AnimAction {
 		AAF_CRUS_16DIRS  = 0x4000, // Crusader
 		AAF_DESTROYACTOR = 0x8000  // destroy actor after animation finishes
 	};
+
+private:
+	uint32 _shapeNum;
+	uint32 _action;
+
+	Std::vector<AnimFrame> _frames[16]; // 8 or 16 directions
+	unsigned int _size;
+	int _frameRepeat;
+	uint32 _flags;
+
+	unsigned int _dirCount;
 };
 
 } // End of namespace Ultima8
diff --git a/engines/ultima/ultima8/world/actors/animation_tracker.cpp b/engines/ultima/ultima8/world/actors/animation_tracker.cpp
index bc5b5e3bad..286459df72 100644
--- a/engines/ultima/ultima8/world/actors/animation_tracker.cpp
+++ b/engines/ultima/ultima8/world/actors/animation_tracker.cpp
@@ -117,8 +117,8 @@ unsigned int AnimationTracker::getNextFrame(unsigned int frame) const {
 		return _endFrame;
 
 	// loop if necessary
-	if (frame >= _animAction->_size) {
-		if (_animAction->_flags & (AnimAction::AAF_LOOPING |
+	if (frame >= _animAction->getSize()) {
+		if (_animAction->hasFlags(AnimAction::AAF_LOOPING |
 		                         AnimAction::AAF_LOOPING2)) {
 			// CHECKME: unknown flag
 			frame = 1;
@@ -154,7 +154,7 @@ void AnimationTracker::evaluateMaxAnimTravel(int32 &max_endx, int32 &max_endy, D
 		testframe = getNextFrame(_currentFrame);
 
 	for (;;) {
-		AnimFrame &f = _animAction->frames[dir][testframe];
+		const AnimFrame &f = _animAction->getFrame(dir, testframe);
 		// determine movement for this frame
 		int32 dx = 4 * Direction_XFactor(dir) * f._deltaDir;
 		int32 dy = 4 * Direction_YFactor(dir) * f._deltaDir;
@@ -181,7 +181,7 @@ bool AnimationTracker::step() {
 		_done = true;
 
 		// toggle ACT_FIRSTSTEP flag if necessary
-		if (_animAction->_flags & AnimAction::AAF_TWOSTEP)
+		if (_animAction->hasFlags(AnimAction::AAF_TWOSTEP))
 			_firstStep = !_firstStep;
 		else
 			_firstStep = true;
@@ -200,7 +200,7 @@ bool AnimationTracker::step() {
 
 	_firstFrame = false;
 
-	const AnimFrame &f = _animAction->frames[_dir][_currentFrame];
+	const AnimFrame &f = _animAction->getFrame(_dir, _currentFrame);
 
 	_shapeFrame = f._frame;
 	_flipped = f.is_flipped();
@@ -388,7 +388,7 @@ bool AnimationTracker::step() {
 
 
 	// if attack animation, see if we hit something
-	if ((_animAction->_flags & AnimAction::AAF_ATTACK) &&
+	if (_animAction->hasFlags(AnimAction::AAF_ATTACK) &&
 	        (_hitObject == 0) && f.attack_range() > 0) {
 		checkWeaponHit();
 	}
@@ -427,7 +427,7 @@ bool AnimationTracker::step() {
 }
 
 const AnimFrame *AnimationTracker::getAnimFrame() const {
-	return &_animAction->frames[_dir][_currentFrame];
+	return &_animAction->getFrame(_dir, _currentFrame);
 }
 
 void AnimationTracker::setTargetedMode(int32 x_, int32 y_, int32 z_) {
@@ -438,7 +438,7 @@ void AnimationTracker::setTargetedMode(int32 x_, int32 y_, int32 z_) {
 	int32 end_dx, end_dy, end_dz;
 
 	for (i = _startFrame; i != _endFrame; i = getNextFrame(i)) {
-		AnimFrame &f = _animAction->frames[_dir][i];
+		const AnimFrame &f = _animAction->getFrame(_dir, i);
 		totaldir += f._deltaDir;  // This line sometimes seg faults.. ????
 		totalz += f._deltaZ;
 		if (!(f._flags & AnimFrame::AFF_ONGROUND))
@@ -467,7 +467,7 @@ void AnimationTracker::setTargetedMode(int32 x_, int32 y_, int32 z_) {
 }
 
 void AnimationTracker::checkWeaponHit() {
-	int range = _animAction->frames[_dir][_currentFrame].attack_range();
+	int range = _animAction->getFrame(_dir, _currentFrame).attack_range();
 
 	const Actor *a = getActor(_actor);
 	assert(a);
@@ -547,7 +547,7 @@ void AnimationTracker::updateActorFlags() {
 		a->clearActorFlag(Actor::ACT_FIRSTSTEP);
 
 	if (_animAction) {
-		bool hanging = (_animAction->_flags & AnimAction::AAF_HANGING) != 0;
+		bool hanging = _animAction->hasFlags(AnimAction::AAF_HANGING);
 		if (hanging)
 			a->setFlag(Item::FLG_HANGING);
 		else
@@ -564,9 +564,11 @@ void AnimationTracker::getInterpolatedPosition(int32 &x_, int32 &y_,
 	int32 dy = _y - _prevY;
 	int32 dz = _z - _prevZ;
 
-	x_ = _prevX + (dx * fc) / (_animAction->_frameRepeat + 1);
-	y_ = _prevY + (dy * fc) / (_animAction->_frameRepeat + 1);
-	z_ = _prevZ + (dz * fc) / (_animAction->_frameRepeat + 1);
+	int repeat = _animAction->getFrameRepeat();
+
+	x_ = _prevX + (dx * fc) / (repeat + 1);
+	y_ = _prevY + (dy * fc) / (repeat + 1);
+	z_ = _prevZ + (dz * fc) / (repeat + 1);
 }
 
 void AnimationTracker::getSpeed(int32 &dx, int32 &dy, int32 &dz) const {
@@ -587,8 +589,8 @@ void AnimationTracker::save(Common::WriteStream *ws) {
 	ws->writeByte(static_cast<uint8>(Direction_ToUsecodeDir(_dir)));
 
 	if (_animAction) {
-		ws->writeUint32LE(_animAction->_shapeNum);
-		ws->writeUint32LE(_animAction->_action);
+		ws->writeUint32LE(_animAction->getShapeNum());
+		ws->writeUint32LE(_animAction->getAction());
 	} else {
 		ws->writeUint32LE(0);
 		ws->writeUint32LE(0);
@@ -665,7 +667,7 @@ bool AnimationTracker::load(Common::ReadStream *rs, uint32 version) {
 			if (!_firstFrame) i = getNextFrame(i);
 
 			for (; i != _endFrame; i = getNextFrame(i)) {
-				AnimFrame &f = _animAction->frames[_dir][i];
+				const AnimFrame &f = _animAction->getFrame(_dir, i);
 				if (!(f._flags & AnimFrame::AFF_ONGROUND))
 					++_targetOffGroundLeft;
 			}
diff --git a/engines/ultima/ultima8/world/actors/animation_tracker.h b/engines/ultima/ultima8/world/actors/animation_tracker.h
index 7cf8ebf919..2f1de49840 100644
--- a/engines/ultima/ultima8/world/actors/animation_tracker.h
+++ b/engines/ultima/ultima8/world/actors/animation_tracker.h
@@ -124,7 +124,7 @@ private:
 	ObjId _actor;
 	Direction _dir;
 
-	AnimAction *_animAction;
+	const AnimAction *_animAction;
 
 	// actor state
 	int32 _prevX, _prevY, _prevZ;
diff --git a/engines/ultima/ultima8/world/actors/combat_process.cpp b/engines/ultima/ultima8/world/actors/combat_process.cpp
index cfce2a20ea..9effb4f482 100644
--- a/engines/ultima/ultima8/world/actors/combat_process.cpp
+++ b/engines/ultima/ultima8/world/actors/combat_process.cpp
@@ -277,7 +277,7 @@ bool CombatProcess::inAttackRange() {
 	Actor *a = getActor(_itemNum);
 	if (!a)
 		return false; // shouldn't happen
-	ShapeInfo *shapeinfo = a->getShapeInfo();
+	const ShapeInfo *shapeinfo = a->getShapeInfo();
 	MonsterInfo *mi = nullptr;
 	if (shapeinfo) mi = shapeinfo->_monsterInfo;
 
@@ -302,7 +302,7 @@ void CombatProcess::waitForTarget() {
 	Actor *a = getActor(_itemNum);
 	if (!a)
 		return; // shouldn't happen
-	ShapeInfo *shapeinfo = a->getShapeInfo();
+	const ShapeInfo *shapeinfo = a->getShapeInfo();
 	MonsterInfo *mi = nullptr;
 	if (shapeinfo) mi = shapeinfo->_monsterInfo;
 
diff --git a/engines/ultima/ultima8/world/actors/main_actor.cpp b/engines/ultima/ultima8/world/actors/main_actor.cpp
index 19fa077753..609ccbd1e4 100644
--- a/engines/ultima/ultima8/world/actors/main_actor.cpp
+++ b/engines/ultima/ultima8/world/actors/main_actor.cpp
@@ -363,7 +363,7 @@ uint16 MainActor::getDefenseType() const {
 	Std::list<Item *>::const_iterator iter;
 	for (iter = _contents.begin(); iter != _contents.end(); ++iter) {
 		uint32 frameNum = (*iter)->getFrame();
-		ShapeInfo *si = (*iter)->getShapeInfo();
+		const ShapeInfo *si = (*iter)->getShapeInfo();
 		if (si->_armourInfo) {
 			type |= si->_armourInfo[frameNum]._defenseType;
 		}
@@ -378,7 +378,7 @@ uint32 MainActor::getArmourClass() const {
 	Std::list<Item *>::const_iterator iter;
 	for (iter = _contents.begin(); iter != _contents.end(); ++iter) {
 		uint32 frameNum = (*iter)->getFrame();
-		ShapeInfo *si = (*iter)->getShapeInfo();
+		const ShapeInfo *si = (*iter)->getShapeInfo();
 		if (si->_armourInfo) {
 			armour += si->_armourInfo[frameNum]._armourClass;
 		}
@@ -395,7 +395,7 @@ int16 MainActor::getDefendingDex() const {
 
 	Item *weapon = getItem(getEquip(ShapeInfo::SE_WEAPON));
 	if (weapon) {
-		ShapeInfo *si = weapon->getShapeInfo();
+		const ShapeInfo *si = weapon->getShapeInfo();
 		assert(si->_weaponInfo);
 		dex += si->_weaponInfo->_dexDefendBonus;
 	}
@@ -410,7 +410,7 @@ int16 MainActor::getAttackingDex() const {
 
 	Item *weapon = getItem(getEquip(ShapeInfo::SE_WEAPON));
 	if (weapon) {
-		ShapeInfo *si = weapon->getShapeInfo();
+		const ShapeInfo *si = weapon->getShapeInfo();
 		assert(si->_weaponInfo);
 		dex += si->_weaponInfo->_dexAttackBonus;
 	}
@@ -442,7 +442,7 @@ int MainActor::getDamageAmount() const {
 		int kick_bonus = 0;
 		Item *legs = getItem(getEquip(ShapeInfo::SE_LEGS));
 		if (legs) {
-			ShapeInfo *si = legs->getShapeInfo();
+			const ShapeInfo *si = legs->getShapeInfo();
 			assert(si->_armourInfo);
 			kick_bonus = si->_armourInfo[legs->getFrame()]._kickAttackBonus;
 		}
@@ -459,7 +459,7 @@ int MainActor::getDamageAmount() const {
 	if (weapon) {
 		// weapon equipped?
 
-		ShapeInfo *si = weapon->getShapeInfo();
+		const ShapeInfo *si = weapon->getShapeInfo();
 		assert(si->_weaponInfo);
 
 		int base = si->_weaponInfo->_baseDamage;
@@ -581,7 +581,7 @@ void MainActor::getWeaponOverlay(const WeaponOverlayFrame *&frame_, uint32 &shap
 	Item *weapon = getItem(weaponid);
 	if (!weapon) return;
 
-	ShapeInfo *shapeinfo = weapon->getShapeInfo();
+	const ShapeInfo *shapeinfo = weapon->getShapeInfo();
 	if (!shapeinfo) return;
 
 	WeaponInfo *weaponinfo = shapeinfo->_weaponInfo;
diff --git a/engines/ultima/ultima8/world/current_map.cpp b/engines/ultima/ultima8/world/current_map.cpp
index 489f83347d..fe58139e0a 100644
--- a/engines/ultima/ultima8/world/current_map.cpp
+++ b/engines/ultima/ultima8/world/current_map.cpp
@@ -742,7 +742,7 @@ bool CurrentMap::isValidPosition(int32 x, int32 y, int32 z,
 				if (item->hasExtFlags(Item::EXT_SPRITE))
 					continue;
 
-				ShapeInfo *si = item->getShapeInfo();
+				const ShapeInfo *si = item->getShapeInfo();
 				//!! need to check is_sea() and is_land() maybe?
 				if (!(si->_flags & flagmask))
 					continue; // not an interesting item
diff --git a/engines/ultima/ultima8/world/item.cpp b/engines/ultima/ultima8/world/item.cpp
index 0f792ef5e8..9045c93a24 100644
--- a/engines/ultima/ultima8/world/item.cpp
+++ b/engines/ultima/ultima8/world/item.cpp
@@ -114,7 +114,7 @@ void Item::dumpInfo() const {
 	     << ", f:0x" << Std::hex << getFlags() << ", ef:0x"
 		 << getExtFlags();
 
-	ShapeInfo *info = getShapeInfo();
+	const ShapeInfo *info = getShapeInfo();
 	if (info) {
 		pout << " shapeinfo f:" << info->_flags << ", fam:"
 			 << info->_family << ", et:" << info->_equipType;
@@ -457,7 +457,7 @@ void Item::randomGumpLocation() {
 
 void Item::getCentre(int32 &X, int32 &Y, int32 &Z) const {
 	// constants!
-	ShapeInfo *shapeinfo = getShapeInfo();
+	const ShapeInfo *shapeinfo = getShapeInfo();
 	if (_flags & FLG_FLIPPED) {
 		X = _x - shapeinfo->_y * 16;
 		Y = _y - shapeinfo->_x * 16;
@@ -713,7 +713,7 @@ int Item::getRangeIfVisible(const Item &item2) const {
 	return distance;
 }
 
-ShapeInfo *Item::getShapeInfoFromGameInstance() const {
+const ShapeInfo *Item::getShapeInfoFromGameInstance() const {
 	return GameData::get_instance()->getMainShapes()->getShapeInfo(_shape);
 }
 
@@ -1540,8 +1540,8 @@ void Item::setupLerp(int32 gametick) {
 
 // Animate the item
 void Item::animateItem() {
-	ShapeInfo *info = getShapeInfo();
-	Shape *shp = getShapeObject();
+	const ShapeInfo *info = getShapeInfo();
+	const Shape *shp = getShapeObject();
 
 	if (!info->_animType) return;
 
@@ -1630,7 +1630,7 @@ void Item::enterFastArea() {
 	}
 
 	if (!hasFlags(FLG_BROKEN) && GAME_IS_CRUSADER) {
-		ShapeInfo *si = getShapeInfo();
+		const ShapeInfo *si = getShapeInfo();
 		if ((si->_flags & ShapeInfo::SI_TARGETABLE) || (si->_flags & ShapeInfo::SI_OCCL)) {
 			World::get_instance()->getCurrentMap()->addTargetItem(this);
 		}
@@ -1926,7 +1926,7 @@ void Item::explode(int explosion_type, bool destroy_item, bool cause_damage) {
 }
 
 uint16 Item::getDamageType() const {
-	ShapeInfo *si = getShapeInfo();
+	const ShapeInfo *si = getShapeInfo();
 	if (si->_weaponInfo) {
 		return si->_weaponInfo->_damageType;
 	}
@@ -2004,7 +2004,7 @@ void Item::receiveHitCru(uint16 other, Direction dir, int damage, uint16 type) {
 
 
 bool Item::canDrag() {
-	ShapeInfo *si = getShapeInfo();
+	const ShapeInfo *si = getShapeInfo();
 	if (si->is_fixed()) return false;
 	if (si->_weight == 0) return false;
 
@@ -3571,7 +3571,7 @@ uint32 Item::I_isCrusTypeNPC(const uint8 *args, unsigned int /*argsize*/) {
 
 	if (sh == 0x7FE) return 1;
 
-	ShapeInfo *info;
+	const ShapeInfo *info;
 	info = GameData::get_instance()->getMainShapes()->getShapeInfo(sh);
 	if (!info) return 0;
 
diff --git a/engines/ultima/ultima8/world/item.h b/engines/ultima/ultima8/world/item.h
index c4467c6932..96942e3c71 100644
--- a/engines/ultima/ultima8/world/item.h
+++ b/engines/ultima/ultima8/world/item.h
@@ -241,10 +241,10 @@ public:
 	}
 
 	//! Get the ShapeInfo object for this Item. (The pointer will be cached.)
-	inline ShapeInfo *getShapeInfo() const;
+	inline const ShapeInfo *getShapeInfo() const;
 
 	//! Get the ShapeInfo object for this Item from the game instance.
-	ShapeInfo *getShapeInfoFromGameInstance() const;
+	const ShapeInfo *getShapeInfoFromGameInstance() const;
 
 	//! Get the Shape object for this Item. (The pointer will be cached.)
 	Shape *getShapeObject() const;
@@ -607,7 +607,7 @@ protected:
 	ObjId _parent; // objid container this item is in (or 0 for top-level items)
 
 	mutable Shape *_cachedShape;
-	mutable ShapeInfo *_cachedShapeInfo;
+	mutable const ShapeInfo *_cachedShapeInfo;
 
 	// This is stuff that is used for displaying and interpolation
 	struct Lerped {
@@ -682,7 +682,7 @@ public:
 	};
 };
 
-inline ShapeInfo *Item::getShapeInfo() const {
+inline const ShapeInfo *Item::getShapeInfo() const {
 	if (!_cachedShapeInfo)
 		_cachedShapeInfo = getShapeInfoFromGameInstance();
 	return _cachedShapeInfo;
diff --git a/engines/ultima/ultima8/world/item_factory.cpp b/engines/ultima/ultima8/world/item_factory.cpp
index 4eaaad1591..7a11f7897d 100644
--- a/engines/ultima/ultima8/world/item_factory.cpp
+++ b/engines/ultima/ultima8/world/item_factory.cpp
@@ -81,7 +81,7 @@ Item *ItemFactory::createItem(uint32 shape, uint32 frame, uint16 quality,
                               uint16 flags, uint16 npcnum, uint16 mapnum,
                               uint32 extendedflags, bool objId) {
 	// check what class to create
-	ShapeInfo *info = GameData::get_instance()->getMainShapes()->
+	const ShapeInfo *info = GameData::get_instance()->getMainShapes()->
 	                  getShapeInfo(shape);
 	if (info == nullptr)
 		return nullptr;
diff --git a/engines/ultima/ultima8/world/map.cpp b/engines/ultima/ultima8/world/map.cpp
index e20651287f..4c28aba4b0 100644
--- a/engines/ultima/ultima8/world/map.cpp
+++ b/engines/ultima/ultima8/world/map.cpp
@@ -250,7 +250,7 @@ void Map::loadFixedFormatObjects(Std::list<Item *> &itemlist,
 		if (!item) {
 			pout << shape << "," << frame << ":\t(" << x << "," << y << "," << z << "),\t" << Std::hex << flags << Std::dec << ", " << quality << ", " << npcNum << ", " << mapNum << ", " << next;
 
-			ShapeInfo *info = GameData::get_instance()->getMainShapes()->
+			const ShapeInfo *info = GameData::get_instance()->getMainShapes()->
 			                  getShapeInfo(shape);
 			if (info) pout << ", family = " << info->_family;
 			pout << Std::endl;
@@ -258,7 +258,7 @@ void Map::loadFixedFormatObjects(Std::list<Item *> &itemlist,
 			pout << "Couldn't create item" << Std::endl;
 			continue;
 		} else {
-			ShapeInfo *info = item->getShapeInfo();
+			const ShapeInfo *info = item->getShapeInfo();
 			assert(info);
 			if (info->_family > 10) {
 				//warning("Created fixed item unknown family %d, shape (%d, %d) at (%d, %d, %d)", info->_family, shape, frame, x, y, z);


Commit: 4ac5cdc5cfbc1a4ae44976a6cc35a845de032117
    https://github.com/scummvm/scummvm/commit/4ac5cdc5cfbc1a4ae44976a6cc35a845de032117
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-07-29T14:10:15+09:00

Commit Message:
ULTIMA8: More const improvements

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


diff --git a/engines/ultima/ultima8/world/actors/actor.cpp b/engines/ultima/ultima8/world/actors/actor.cpp
index b78f510a3d..6aa347319c 100644
--- a/engines/ultima/ultima8/world/actors/actor.cpp
+++ b/engines/ultima/ultima8/world/actors/actor.cpp
@@ -130,7 +130,7 @@ bool Actor::loadMonsterStatsCru() {
 bool Actor::loadMonsterStatsU8() {
 
 	const ShapeInfo *shapeinfo = getShapeInfo();
-	MonsterInfo *mi = nullptr;
+	const MonsterInfo *mi = nullptr;
 	if (shapeinfo) mi = shapeinfo->_monsterInfo;
 	if (!mi)
 		return false;
@@ -159,7 +159,7 @@ bool Actor::loadMonsterStatsU8() {
 bool Actor::giveTreasure() {
 	MainShapeArchive *mainshapes = GameData::get_instance()->getMainShapes();
 	const ShapeInfo *shapeinfo = getShapeInfo();
-	MonsterInfo *mi = nullptr;
+	const MonsterInfo *mi = nullptr;
 	if (shapeinfo) mi = shapeinfo->_monsterInfo;
 	if (!mi)
 		return false;
@@ -1011,7 +1011,7 @@ ProcId Actor::die(uint16 damageType) {
 	giveTreasure();
 
 	const ShapeInfo *shapeinfo = getShapeInfo();
-	MonsterInfo *mi = nullptr;
+	const MonsterInfo *mi = nullptr;
 	if (shapeinfo) mi = shapeinfo->_monsterInfo;
 
 	if (mi && mi->_resurrection && !(damageType & WeaponInfo::DMG_FIRE)) {
diff --git a/engines/ultima/ultima8/world/actors/combat_process.cpp b/engines/ultima/ultima8/world/actors/combat_process.cpp
index 9effb4f482..14c5fceea6 100644
--- a/engines/ultima/ultima8/world/actors/combat_process.cpp
+++ b/engines/ultima/ultima8/world/actors/combat_process.cpp
@@ -158,7 +158,7 @@ void CombatProcess::run() {
 }
 
 ObjId CombatProcess::getTarget() {
-	Actor *t = getActor(_target);
+	const Actor *t = getActor(_target);
 
 	if (!t || !isValidTarget(t))
 		_target = 0;
@@ -174,9 +174,9 @@ void CombatProcess::setTarget(ObjId newtarget) {
 	_target = newtarget;
 }
 
-bool CombatProcess::isValidTarget(Actor *target_) {
+bool CombatProcess::isValidTarget(const Actor *target_) const {
 	assert(target_);
-	Actor *a = getActor(_itemNum);
+	const Actor *a = getActor(_itemNum);
 	if (!a) return false; // uh oh
 
 	// don't target_ self
@@ -199,10 +199,10 @@ bool CombatProcess::isValidTarget(Actor *target_) {
 	return true;
 }
 
-bool CombatProcess::isEnemy(Actor *target_) {
+bool CombatProcess::isEnemy(const Actor *target_) const {
 	assert(target_);
 
-	Actor *a = getActor(_itemNum);
+	const Actor *a = getActor(_itemNum);
 	if (!a) return false; // uh oh
 
 	return ((a->getEnemyAlignment() & target_->getAlignment()) != 0);
@@ -236,9 +236,9 @@ ObjId CombatProcess::seekTarget() {
 	return 0;
 }
 
-Direction CombatProcess::getTargetDirection() {
-	Actor *a = getActor(_itemNum);
-	Actor *t = getActor(_target);
+Direction CombatProcess::getTargetDirection() const {
+	const Actor *a = getActor(_itemNum);
+	const Actor *t = getActor(_target);
 	if (!a || !t)
 		return dir_north; // shouldn't happen
 
@@ -273,12 +273,12 @@ void CombatProcess::turnToDirection(Direction direction) {
 	if (prevpid) waitFor(prevpid);
 }
 
-bool CombatProcess::inAttackRange() {
-	Actor *a = getActor(_itemNum);
+bool CombatProcess::inAttackRange() const {
+	const Actor *a = getActor(_itemNum);
 	if (!a)
 		return false; // shouldn't happen
 	const ShapeInfo *shapeinfo = a->getShapeInfo();
-	MonsterInfo *mi = nullptr;
+	const MonsterInfo *mi = nullptr;
 	if (shapeinfo) mi = shapeinfo->_monsterInfo;
 
 	if (mi && mi->_ranged)
@@ -303,7 +303,7 @@ void CombatProcess::waitForTarget() {
 	if (!a)
 		return; // shouldn't happen
 	const ShapeInfo *shapeinfo = a->getShapeInfo();
-	MonsterInfo *mi = nullptr;
+	const MonsterInfo *mi = nullptr;
 	if (shapeinfo) mi = shapeinfo->_monsterInfo;
 
 	if (mi && mi->_shifter && a->getMapNum() != 43 && (getRandom() % 2) == 0) {
diff --git a/engines/ultima/ultima8/world/actors/combat_process.h b/engines/ultima/ultima8/world/actors/combat_process.h
index a3cca3dc23..24de0d41f3 100644
--- a/engines/ultima/ultima8/world/actors/combat_process.h
+++ b/engines/ultima/ultima8/world/actors/combat_process.h
@@ -53,10 +53,10 @@ public:
 	void saveData(Common::WriteStream *ws) override;
 
 protected:
-	bool isValidTarget(Actor *target_);
-	bool isEnemy(Actor *target_);
-	bool inAttackRange();
-	Direction getTargetDirection();
+	bool isValidTarget(const Actor *target_) const;
+	bool isEnemy(const Actor *target_) const;
+	bool inAttackRange() const;
+	Direction getTargetDirection() const;
 
 	void turnToDirection(Direction direction);
 	void waitForTarget();


Commit: 3cae01c410d832f3d085469a8788f7f5cfa437b4
    https://github.com/scummvm/scummvm/commit/3cae01c410d832f3d085469a8788f7f5cfa437b4
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-07-29T14:10:15+09:00

Commit Message:
ULTIMA8: Plumbing for 16 dir support (still only uses 8 dirs)

Changed paths:
    engines/ultima/ultima8/kernel/mouse.cpp
    engines/ultima/ultima8/misc/direction.h
    engines/ultima/ultima8/misc/direction_util.h
    engines/ultima/ultima8/world/actors/actor.cpp
    engines/ultima/ultima8/world/actors/actor.h
    engines/ultima/ultima8/world/actors/avatar_mover_process.cpp
    engines/ultima/ultima8/world/actors/combat_process.cpp
    engines/ultima/ultima8/world/actors/pathfinder.cpp
    engines/ultima/ultima8/world/actors/surrender_process.cpp
    engines/ultima/ultima8/world/current_map.cpp
    engines/ultima/ultima8/world/current_map.h
    engines/ultima/ultima8/world/fireball_process.cpp
    engines/ultima/ultima8/world/item.cpp
    engines/ultima/ultima8/world/super_sprite_process.cpp
    engines/ultima/ultima8/world/target_reticle_process.cpp


diff --git a/engines/ultima/ultima8/kernel/mouse.cpp b/engines/ultima/ultima8/kernel/mouse.cpp
index c349f0e12b..99a5aea95f 100644
--- a/engines/ultima/ultima8/kernel/mouse.cpp
+++ b/engines/ultima/ultima8/kernel/mouse.cpp
@@ -180,7 +180,7 @@ Direction Mouse::getMouseDirectionWorld(int mx, int my) {
 	int dx = mx - dims.w / 2;
 	int dy = (dims.h / 2 + (dims.h * 14 / 200)) - my; //! constant
 
-	return Direction_Get(dy * 2, dx);
+	return Direction_Get(dy * 2, dx, dirmode_8dirs);
 }
 
 int Mouse::getMouseDirectionScreen(int mx, int my) {
diff --git a/engines/ultima/ultima8/misc/direction.h b/engines/ultima/ultima8/misc/direction.h
index 6286cecde6..4c60e121fa 100644
--- a/engines/ultima/ultima8/misc/direction.h
+++ b/engines/ultima/ultima8/misc/direction.h
@@ -49,6 +49,11 @@ enum Direction {
 	dir_nnw
 };
 
+enum DirectionMode {
+	dirmode_8dirs,
+	dirmode_16dirs
+};
+
 } // End of namespace Ultima8
 } // End of namespace Ultima
 
diff --git a/engines/ultima/ultima8/misc/direction_util.h b/engines/ultima/ultima8/misc/direction_util.h
index 7da658f898..972fb4e8b4 100644
--- a/engines/ultima/ultima8/misc/direction_util.h
+++ b/engines/ultima/ultima8/misc/direction_util.h
@@ -54,7 +54,7 @@ inline int Direction_YFactor(Direction dir) {
  *  NOTE: The returned direction is rotated 45 degrees clockwise! This is
  *  how U8 things should be.
  */
-inline Direction Direction_Get(int deltay, int deltax) {
+inline Direction Direction_Get(int deltay, int deltax, DirectionMode dirmode) {
 	if (deltax == 0)
 		return deltay > 0 ? dir_northwest : dir_southeast;
 	int dydx = (1024 * deltay) / deltax; // Figure 1024*tan.
@@ -73,7 +73,7 @@ inline Direction Direction_Get(int deltay, int deltax) {
 			   : dir_northwest;
 }
 
-inline Direction Direction_GetWorldDir(int deltay, int deltax) {
+inline Direction Direction_GetWorldDir(int deltay, int deltax, DirectionMode dirmode) {
 	if (deltax == 0) {
 		if (deltay == 0) return dir_northeast; // for better compatibility with U8
 		return deltay > 0 ? dir_south : dir_north;
@@ -91,10 +91,11 @@ inline Direction Direction_GetWorldDir(int deltay, int deltax) {
 		return dydx >= -424 ? dir_west : dydx >= -2472 ? dir_southwest : dir_south;
 }
 
-inline Direction Direction_GetWorldDirInRange(int deltay, int deltax, uint16 ndirs, Direction mindir, Direction maxdir) {
+inline Direction Direction_GetWorldDirInRange(int deltay, int deltax, DirectionMode dirmode, Direction mindir, Direction maxdir) {
 	// TODO: Implement 16 directions here.
-	ndirs = 8;
-	Direction dir = Direction_GetWorldDir(deltay, deltax);
+	int ndirs = 8;
+	dirmode = dirmode_8dirs;
+	Direction dir = Direction_GetWorldDir(deltay, deltax, dirmode);
 
 	if ((dir < mindir) || (dir > maxdir)) {
 		int32 dmin1 = dir - mindir;
@@ -151,19 +152,20 @@ inline Direction Direction_Invert(Direction dir) {
 }
 
 //! Return the direction one left (aka counter-clockwise) of the input
-inline Direction Direction_OneLeft(Direction dir) {
+inline Direction Direction_OneLeft(Direction dir, DirectionMode mode) {
 	// TODO: support 16 dirs here.
 	return static_cast<Direction>((static_cast<int>(dir) + 7) % 8);
 }
 
 //! Return the direction one right (aka clockwise) of the input
-inline Direction Direction_OneRight(Direction dir) {
+inline Direction Direction_OneRight(Direction dir, DirectionMode mode) {
 	// TODO: support 16 dirs here.
 	return static_cast<Direction>((static_cast<int>(dir) + 1) % 8);
 }
 
-inline Direction Direction_TurnByDelta(Direction dir, int delta) {
-	return delta == 1 ? Direction_OneRight(dir) : Direction_OneLeft(dir);
+inline Direction Direction_TurnByDelta(Direction dir, int delta, DirectionMode mode) {
+	assert(delta == 1 || delta == -1);
+	return delta == 1 ? Direction_OneRight(dir, mode) : Direction_OneLeft(dir, mode);
 }
 
 //! Get a turn delta (-1 for left, +1 for right) to turn the fastest
diff --git a/engines/ultima/ultima8/world/actors/actor.cpp b/engines/ultima/ultima8/world/actors/actor.cpp
index 6aa347319c..acfa18ab6c 100644
--- a/engines/ultima/ultima8/world/actors/actor.cpp
+++ b/engines/ultima/ultima8/world/actors/actor.cpp
@@ -546,6 +546,14 @@ Animation::Result Actor::tryAnim(Animation::Sequence anim, Direction dir,
 	return Animation::END_OFF_LAND;
 }
 
+DirectionMode Actor::animDirMode(Animation::Sequence anim) const {
+	const AnimAction *action = GameData::get_instance()->getMainShapes()->
+	getAnim(getShape(), anim);
+	if (!action)
+		return dirmode_8dirs;
+	return action->getDirCount() == 8 ? dirmode_8dirs : dirmode_16dirs;
+}
+
 uint16 Actor::turnTowardDir(Direction targetdir) {
 	Direction curdir = _direction;
 	if (targetdir == curdir)
@@ -561,9 +569,11 @@ uint16 Actor::turnTowardDir(Direction targetdir) {
 
 	ProcId prevpid = 0;
 
+	DirectionMode dirmode = animDirMode(turnanim);
+
 	// Create a sequence of turn animations from
 	// our current direction to the new one
-	for (Direction dir = curdir; dir != targetdir; dir = Direction_TurnByDelta(dir, stepDelta)) {
+	for (Direction dir = curdir; dir != targetdir; dir = Direction_TurnByDelta(dir, stepDelta, dirmode)) {
 		ProcId animpid = doAnim(turnanim, dir);
 		if (prevpid) {
 			Process *proc = Kernel::get_instance()->getProcess(animpid);
diff --git a/engines/ultima/ultima8/world/actors/actor.h b/engines/ultima/ultima8/world/actors/actor.h
index d59f7e3850..3abaa4e9cc 100644
--- a/engines/ultima/ultima8/world/actors/actor.h
+++ b/engines/ultima/ultima8/world/actors/actor.h
@@ -238,6 +238,9 @@ public:
 	//! \param state the state to start from, or 0 to use the current state
 	Animation::Result tryAnim(Animation::Sequence anim, Direction dir, unsigned int steps = 0, PathfindingState *state = 0);
 
+	//! Get the number of directions supported by a given animation
+	DirectionMode animDirMode(Animation::Sequence anim) const;
+
 	//! overrides the standard item collideMove so we  can notify nearby objects.
 	int32 collideMove(int32 x, int32 y, int32 z, bool teleport, bool force,
 	                  ObjId *hititem = 0, uint8 *dirs = 0) override;
diff --git a/engines/ultima/ultima8/world/actors/avatar_mover_process.cpp b/engines/ultima/ultima8/world/actors/avatar_mover_process.cpp
index e0f7d8817d..9f23c18df1 100644
--- a/engines/ultima/ultima8/world/actors/avatar_mover_process.cpp
+++ b/engines/ultima/ultima8/world/actors/avatar_mover_process.cpp
@@ -290,14 +290,16 @@ void AvatarMoverProcess::handleCombatMode() {
 
 	bool moving = (lastanim == Animation::advance || lastanim == Animation::retreat);
 
+	DirectionMode dirmode = avatar->animDirMode(Animation::combatStand);
+
 	//  if we are trying to move, allow change direction only after move occurs to avoid spinning
 	if (moving || !hasMovementFlags(MOVE_FORWARD | MOVE_BACK)) {
 		if (hasMovementFlags(MOVE_TURN_LEFT)) {
-			direction = Direction_OneLeft(direction);
+			direction = Direction_OneLeft(direction, dirmode);
 		}
 
 		if (hasMovementFlags(MOVE_TURN_RIGHT)) {
-			direction = Direction_OneRight(direction);
+			direction = Direction_OneRight(direction, dirmode);
 		}
 	}
 
@@ -344,7 +346,7 @@ void AvatarMoverProcess::handleCombatMode() {
 	}
 
 	if (x != 0 || y != 0) {
-		Direction nextdir = Direction_Get(y, x);
+		Direction nextdir = Direction_Get(y, x, dirmode_8dirs);
 
 		if (checkTurn(nextdir, true))
 			return;
@@ -621,14 +623,16 @@ void AvatarMoverProcess::handleNormalMode() {
 
 	bool moving = (lastanim == Animation::step || lastanim == Animation::run || lastanim == Animation::walk);
 
+	DirectionMode dirmode = avatar->animDirMode(Animation::step);
+
 	//  if we are trying to move, allow change direction only after move occurs to avoid spinning
 	if (moving || !hasMovementFlags(MOVE_FORWARD | MOVE_BACK)) {
 		if (hasMovementFlags(MOVE_TURN_LEFT)) {
-			direction = Direction_OneLeft(direction);
+			direction = Direction_OneLeft(direction, dirmode);
 		}
 
 		if (hasMovementFlags(MOVE_TURN_RIGHT)) {
-			direction = Direction_OneRight(direction);
+			direction = Direction_OneRight(direction, dirmode);
 		}
 	}
 
@@ -674,7 +678,7 @@ void AvatarMoverProcess::handleNormalMode() {
 	}
 
 	if (x != 0 || y != 0) {
-		direction = Direction_Get(y, x);
+		direction = Direction_Get(y, x, dirmode_8dirs);
 		step(nextanim, direction);
 		return;
 	}
@@ -737,8 +741,8 @@ void AvatarMoverProcess::step(Animation::Sequence action, Direction direction,
 	if (res == Animation::FAILURE ||
 	        (action == Animation::step && res == Animation::END_OFF_LAND)) {
 		debug(6, "Step: end off land dir %d, try other dir", stepdir);
-		Direction altdir1 = Direction_OneRight(stepdir);
-		Direction altdir2 = Direction_OneLeft(stepdir);
+		Direction altdir1 = Direction_OneRight(stepdir, dirmode_8dirs);
+		Direction altdir2 = Direction_OneLeft(stepdir, dirmode_8dirs);
 
 		res = avatar->tryAnim(action, altdir1);
 		if (res == Animation::FAILURE ||
@@ -870,7 +874,9 @@ void AvatarMoverProcess::turnToDirection(Direction direction) {
 
 	// Create a sequence of turn animations from
 	// our current direction to the new one
-	for (Direction dir = curdir; dir != direction; dir = Direction_TurnByDelta(dir, stepDelta)) {
+	DirectionMode dirmode = avatar->animDirMode(turnanim);
+
+	for (Direction dir = curdir; dir != direction; dir = Direction_TurnByDelta(dir, stepDelta, dirmode)) {
 		ProcId animpid = avatar->doAnim(turnanim, dir);
 
 		if (prevpid) {
diff --git a/engines/ultima/ultima8/world/actors/combat_process.cpp b/engines/ultima/ultima8/world/actors/combat_process.cpp
index 14c5fceea6..accebf3a84 100644
--- a/engines/ultima/ultima8/world/actors/combat_process.cpp
+++ b/engines/ultima/ultima8/world/actors/combat_process.cpp
@@ -256,7 +256,9 @@ void CombatProcess::turnToDirection(Direction direction) {
 	ProcId prevpid = 0;
 	bool done = false;
 
-	for (Direction dir = curdir; !done;	dir = Direction_TurnByDelta(dir, stepDelta)) {
+	DirectionMode mode = a->animDirMode(turnanim);
+
+	for (Direction dir = curdir; !done;	dir = Direction_TurnByDelta(dir, stepDelta, mode)) {
 		ProcId animpid = a->doAnim(turnanim, dir);
 
 		if (dir == direction) done = true;
diff --git a/engines/ultima/ultima8/world/actors/pathfinder.cpp b/engines/ultima/ultima8/world/actors/pathfinder.cpp
index 4adf390a45..bc3a273d03 100644
--- a/engines/ultima/ultima8/world/actors/pathfinder.cpp
+++ b/engines/ultima/ultima8/world/actors/pathfinder.cpp
@@ -436,7 +436,7 @@ void Pathfinder::expandNode(PathNode *node) {
 	// try walking in all 8 directions - TODO: should this support 16 dirs?
 	Direction dir = dir_north;
 	for (int i = 0; i < 8; i++) {
-		dir = Direction_OneRight(dir);
+		dir = Direction_OneRight(dir, dirmode_8dirs);
 		state = node->state;
 		state._lastAnim = walkanim;
 		state._direction = dir;
diff --git a/engines/ultima/ultima8/world/actors/surrender_process.cpp b/engines/ultima/ultima8/world/actors/surrender_process.cpp
index cfd2497440..0a69bce050 100644
--- a/engines/ultima/ultima8/world/actors/surrender_process.cpp
+++ b/engines/ultima/ultima8/world/actors/surrender_process.cpp
@@ -85,10 +85,10 @@ void SurrenderProcess::run() {
 		Animation::Sequence turnanim;
 		Direction nextdir;
 		if (Direction_GetShorterTurnDelta(curdir, direction) == -1) {
-			nextdir = Direction_OneLeft(curdir);
+			nextdir = Direction_OneLeft(curdir, dirmode_8dirs);
 			turnanim = Animation::lookLeft;
 		} else {
-			nextdir = Direction_OneRight(curdir);
+			nextdir = Direction_OneRight(curdir, dirmode_8dirs);
 			turnanim = Animation::lookRight;
 		}
 		ProcId animpid = a->doAnim(turnanim, nextdir);
diff --git a/engines/ultima/ultima8/world/current_map.cpp b/engines/ultima/ultima8/world/current_map.cpp
index fe58139e0a..2d03cfec79 100644
--- a/engines/ultima/ultima8/world/current_map.cpp
+++ b/engines/ultima/ultima8/world/current_map.cpp
@@ -311,7 +311,7 @@ void CurrentMap::removeTargetItem(const Item *item) {
 }
 
 
-Item *CurrentMap::findBestTargetItem(int32 x, int32 y, Direction dir) {
+Item *CurrentMap::findBestTargetItem(int32 x, int32 y, Direction dir, DirectionMode dirmode) {
 	// "best" means:
 	// Shape info SI_OCCL
 	// isNPC
@@ -338,7 +338,7 @@ Item *CurrentMap::findBestTargetItem(int32 x, int32 y, Direction dir) {
 
 		int32 ix, iy, iz;
 		item->getLocation(ix, iy, iz);
-		Direction itemdir = Direction_GetWorldDir(iy - y, ix - x);
+		Direction itemdir = Direction_GetWorldDir(iy - y, ix - x, dirmode);
 		if (itemdir != dir)
 			continue;
 
diff --git a/engines/ultima/ultima8/world/current_map.h b/engines/ultima/ultima8/world/current_map.h
index 75c01ffb89..3542865ac5 100644
--- a/engines/ultima/ultima8/world/current_map.h
+++ b/engines/ultima/ultima8/world/current_map.h
@@ -76,7 +76,7 @@ public:
 	//! Remove an item from the list of possible targets (in Crusader)
 	void removeTargetItem(const Item *item);
 	//! Find the best target item in the given direction
-	Item *findBestTargetItem(int32 x, int32 y, Direction dir);
+	Item *findBestTargetItem(int32 x, int32 y, Direction dir, DirectionMode dirmode);
 
 	//! Update the fast area for the cameras position
 	void updateFastArea(int32 from_x, int32 from_y, int32 from_z, int32 to_x, int32 to_y, int32 to_z);
diff --git a/engines/ultima/ultima8/world/fireball_process.cpp b/engines/ultima/ultima8/world/fireball_process.cpp
index 81bdafde2a..7bc9c03bca 100644
--- a/engines/ultima/ultima8/world/fireball_process.cpp
+++ b/engines/ultima/ultima8/world/fireball_process.cpp
@@ -131,7 +131,7 @@ void FireballProcess::run() {
 	}
 
 	Item *tailitem = getItem(_tail[2]);
-	Direction movedir = Direction_GetWorldDir(_ySpeed, _xSpeed);
+	Direction movedir = Direction_GetWorldDir(_ySpeed, _xSpeed, dirmode_8dirs);
 	tailitem->setFrame(Direction_ToUsecodeDir(movedir));
 	tailitem->move(x, y, z);
 
diff --git a/engines/ultima/ultima8/world/item.cpp b/engines/ultima/ultima8/world/item.cpp
index 9045c93a24..7201d47849 100644
--- a/engines/ultima/ultima8/world/item.cpp
+++ b/engines/ultima/ultima8/world/item.cpp
@@ -629,14 +629,14 @@ Direction Item::getDirToItemCentre(const Item &item2) const {
 	int32 i2x, i2y, i2z;
 	item2.getCentre(i2x, i2y, i2z);
 
-	return Direction_GetWorldDir(i2y - yv, i2x - xv);
+	return Direction_GetWorldDir(i2y - yv, i2x - xv, dirmode_8dirs);
 }
 
 Direction Item::getDirToItemCentre(const Point3 &pt) const {
 	int32 xv, yv, zv;
 	getCentre(xv, yv, zv);
 
-	return Direction_GetWorldDir(pt.y - yv, pt.x - xv);
+	return Direction_GetWorldDir(pt.y - yv, pt.x - xv, dirmode_8dirs);
 }
 
 
@@ -1180,7 +1180,7 @@ uint16 Item::fireWeapon(int32 x, int32 y, int32 z, Direction dir, int firetype,
 		Item *block = getItem(blocker->getObjId());
 		Point3 blockpt;
 		block->getLocation(blockpt);
-		Direction damagedir = Direction_GetWorldDir(blockpt.y - iy, blockpt.x - ix);
+		Direction damagedir = Direction_GetWorldDir(blockpt.y - iy, blockpt.x - ix, dirmode_8dirs);
 		block->receiveHit(getObjId(), damagedir, damage, firetype);
 		int splashdamage = firetypedat->getRandomDamage();
 		firetypedat->applySplashDamageAround(blockpt, splashdamage, block, this);
@@ -1222,7 +1222,7 @@ uint16 Item::fireWeapon(int32 x, int32 y, int32 z, Direction dir, int firetype,
 			if (this != getControlledActor()) {
 				target = getControlledActor();
 			} else {
-				target = currentmap->findBestTargetItem(ix, iy, dir);
+				target = currentmap->findBestTargetItem(ix, iy, dir, dirmode_8dirs);
 			}
 		}
 
@@ -1919,7 +1919,7 @@ void Item::explode(int explosion_type, bool destroy_item, bool cause_damage) {
 		if (getRange(*item, true) > 160) continue; // check vertical distance
 
 		item->getLocation(xv, yv, zv);
-		Direction dir = Direction_GetWorldDir(xv - xv, yv - yv); //!! CHECKME
+		Direction dir = Direction_GetWorldDir(xv - xv, yv - yv, dirmode_8dirs); //!! CHECKME
 		item->receiveHit(0, dir, 6 + (getRandom() % 6),
 		                 WeaponInfo::DMG_BLUNT | WeaponInfo::DMG_FIRE);
 	}
@@ -3276,7 +3276,7 @@ uint32 Item::I_getDirToCoords(const uint8 *args, unsigned int /*argsize*/) {
 	int32 ix, iy, iz;
 	item->getLocationAbsolute(ix, iy, iz);
 
-	return Direction_ToUsecodeDir(Direction_GetWorldDir(y - iy, x - ix));
+	return Direction_ToUsecodeDir(Direction_GetWorldDir(y - iy, x - ix, dirmode_8dirs));
 }
 
 uint32 Item::I_getDirFromCoords(const uint8 *args, unsigned int /*argsize*/) {
@@ -3293,7 +3293,7 @@ uint32 Item::I_getDirFromCoords(const uint8 *args, unsigned int /*argsize*/) {
 	int32 ix, iy, iz;
 	item->getLocationAbsolute(ix, iy, iz);
 
-	return Direction_ToUsecodeDir(Direction_GetWorldDir(iy - y, ix - x));
+	return Direction_ToUsecodeDir(Direction_GetWorldDir(iy - y, ix - x, dirmode_8dirs));
 }
 
 uint32 Item::I_getDirToItem(const uint8 *args, unsigned int /*argsize*/) {
@@ -3308,7 +3308,7 @@ uint32 Item::I_getDirToItem(const uint8 *args, unsigned int /*argsize*/) {
 	int32 i2x, i2y, i2z;
 	item2->getLocationAbsolute(i2x, i2y, i2z);
 
-	return Direction_ToUsecodeDir(Direction_GetWorldDir(i2y - iy, i2x - ix));
+	return Direction_ToUsecodeDir(Direction_GetWorldDir(i2y - iy, i2x - ix, dirmode_8dirs));
 }
 
 uint32 Item::I_getDirFromItem(const uint8 *args, unsigned int /*argsize*/) {
@@ -3323,7 +3323,7 @@ uint32 Item::I_getDirFromItem(const uint8 *args, unsigned int /*argsize*/) {
 	int32 i2x, i2y, i2z;
 	item2->getLocationAbsolute(i2x, i2y, i2z);
 
-	return Direction_ToUsecodeDir(Direction_Invert(Direction_GetWorldDir(i2y - iy, i2x - ix)));
+	return Direction_ToUsecodeDir(Direction_Invert(Direction_GetWorldDir(i2y - iy, i2x - ix, dirmode_8dirs)));
 }
 
 uint32 Item::I_getDirFromTo16(const uint8 *args, unsigned int /*argsize*/) {
@@ -3335,7 +3335,7 @@ uint32 Item::I_getDirFromTo16(const uint8 *args, unsigned int /*argsize*/) {
 	if (x1 == x2 && y1 == y2)
 		return 16;
 
-	return Direction_ToUsecodeDir(Direction_GetWorldDir(y2 - y1, x2 - x1));
+	return Direction_ToUsecodeDir(Direction_GetWorldDir(y2 - y1, x2 - x1, dirmode_16dirs));
 }
 
 uint32 Item::I_getClosestDirectionInRange(const uint8 *args, unsigned int /*argsize*/) {
@@ -3349,7 +3349,8 @@ uint32 Item::I_getClosestDirectionInRange(const uint8 *args, unsigned int /*args
 
 	Direction mindir = Direction_FromUsecodeDir(mind);
 	Direction maxdir = Direction_FromUsecodeDir(maxd);
-	Direction result = Direction_GetWorldDirInRange(y2 - y1, x2 - x1, ndirs, mindir, maxdir);
+	DirectionMode mode = (ndirs == 16 ? dirmode_16dirs : dirmode_8dirs);
+	Direction result = Direction_GetWorldDirInRange(y2 - y1, x2 - x1, mode, mindir, maxdir);
 	return Direction_ToUsecodeDir(result);
 }
 
diff --git a/engines/ultima/ultima8/world/super_sprite_process.cpp b/engines/ultima/ultima8/world/super_sprite_process.cpp
index 5c5d4b0034..3232ba342e 100644
--- a/engines/ultima/ultima8/world/super_sprite_process.cpp
+++ b/engines/ultima/ultima8/world/super_sprite_process.cpp
@@ -200,7 +200,7 @@ void SuperSpriteProcess::run() {
 
 		if (_fireType == 9 && !_expired) {
 			if (_nowpt.x != newpt.x || _nowpt.y != newpt.y) {
-				Direction dir = Direction_GetWorldDir(_nowpt.y - newpt.y, _nowpt.x - newpt.x);
+				Direction dir = Direction_GetWorldDir(_nowpt.y - newpt.y, _nowpt.x - newpt.x, dirmode_8dirs);
 				Item *item;
 				if (_itemNum == 0) {
 					item = getItem(_spriteNo);
@@ -318,7 +318,7 @@ void SuperSpriteProcess::hitAndFinish() {
 		// it should work? See disasm 1138:1384, lines 142 ~ 172
 		// There is some random factor added for non-actor items
 		// which needs checking
-		Direction dir = Direction_GetWorldDir(iy - _nowpt.y, ix - _nowpt.x);
+		Direction dir = Direction_GetWorldDir(iy - _nowpt.y, ix - _nowpt.x, dirmode_8dirs);
 		item->receiveHit(_itemNum, dir, _damage, _fireType);
 	}
 	makeBulletSplash(pt);
diff --git a/engines/ultima/ultima8/world/target_reticle_process.cpp b/engines/ultima/ultima8/world/target_reticle_process.cpp
index f60a8ee1bc..e516c06660 100644
--- a/engines/ultima/ultima8/world/target_reticle_process.cpp
+++ b/engines/ultima/ultima8/world/target_reticle_process.cpp
@@ -88,7 +88,7 @@ bool TargetReticleProcess::findTargetItem() {
 	int32 x, y, z;
 	mainactor->getCentre(x, y, z);
 
-	Item *item = currentmap->findBestTargetItem(x, y, dir);
+	Item *item = currentmap->findBestTargetItem(x, y, dir, dirmode_16dirs);
 
 	if (item && item->getObjId() != _lastTargetItem) {
 		Item *lastItem = getItem(_lastTargetItem);




More information about the Scummvm-git-logs mailing list