[Scummvm-git-logs] scummvm master -> 93f65daecf3c29e08cda7927f97909c91011da45

OMGPizzaGuy noreply at scummvm.org
Sat Jun 8 01:17:07 UTC 2024


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

Summary:
93f65daecf ULTIMA8: Expand use of Point3


Commit: 93f65daecf3c29e08cda7927f97909c91011da45
    https://github.com/scummvm/scummvm/commit/93f65daecf3c29e08cda7927f97909c91011da45
Author: Matthew Jimenez (matthew.jimenez at outlook.com)
Date: 2024-06-07T20:17:02-05:00

Commit Message:
ULTIMA8: Expand use of Point3

Changed paths:
    engines/ultima/ultima8/audio/audio_process.cpp
    engines/ultima/ultima8/games/start_u8_process.cpp
    engines/ultima/ultima8/games/u8_game.cpp
    engines/ultima/ultima8/gumps/fast_area_vis_gump.cpp
    engines/ultima/ultima8/gumps/game_map_gump.cpp
    engines/ultima/ultima8/gumps/game_map_gump.h
    engines/ultima/ultima8/misc/debugger.cpp
    engines/ultima/ultima8/misc/point3.h
    engines/ultima/ultima8/usecode/uc_machine.cpp
    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/animation_tracker.h
    engines/ultima/ultima8/world/actors/attack_process.cpp
    engines/ultima/ultima8/world/actors/cru_avatar_mover_process.cpp
    engines/ultima/ultima8/world/actors/cru_pathfinder_process.cpp
    engines/ultima/ultima8/world/actors/cru_pathfinder_process.h
    engines/ultima/ultima8/world/actors/grant_peace_process.cpp
    engines/ultima/ultima8/world/actors/loiter_process.cpp
    engines/ultima/ultima8/world/actors/main_actor.cpp
    engines/ultima/ultima8/world/actors/pathfinder.cpp
    engines/ultima/ultima8/world/actors/pathfinder.h
    engines/ultima/ultima8/world/actors/pathfinder_process.cpp
    engines/ultima/ultima8/world/actors/pathfinder_process.h
    engines/ultima/ultima8/world/actors/quick_avatar_mover_process.cpp
    engines/ultima/ultima8/world/actors/rolling_thunder_process.cpp
    engines/ultima/ultima8/world/actors/targeted_anim_process.cpp
    engines/ultima/ultima8/world/actors/targeted_anim_process.h
    engines/ultima/ultima8/world/actors/u8_avatar_mover_process.cpp
    engines/ultima/ultima8/world/bobo_boomer_process.cpp
    engines/ultima/ultima8/world/camera_process.cpp
    engines/ultima/ultima8/world/camera_process.h
    engines/ultima/ultima8/world/crosshair_process.cpp
    engines/ultima/ultima8/world/current_map.cpp
    engines/ultima/ultima8/world/damage_info.cpp
    engines/ultima/ultima8/world/egg_hatcher_process.cpp
    engines/ultima/ultima8/world/fire_type.cpp
    engines/ultima/ultima8/world/fireball_process.cpp
    engines/ultima/ultima8/world/gravity_process.cpp
    engines/ultima/ultima8/world/item.cpp
    engines/ultima/ultima8/world/item.h
    engines/ultima/ultima8/world/item_sorter.cpp
    engines/ultima/ultima8/world/item_sorter.h
    engines/ultima/ultima8/world/map.cpp
    engines/ultima/ultima8/world/minimap.cpp
    engines/ultima/ultima8/world/missile_tracker.cpp
    engines/ultima/ultima8/world/snap_process.cpp
    engines/ultima/ultima8/world/super_sprite_process.cpp
    engines/ultima/ultima8/world/target_reticle_process.cpp
    engines/ultima/ultima8/world/world.cpp


diff --git a/engines/ultima/ultima8/audio/audio_process.cpp b/engines/ultima/ultima8/audio/audio_process.cpp
index 557e4306a9e..c29deb5e112 100644
--- a/engines/ultima/ultima8/audio/audio_process.cpp
+++ b/engines/ultima/ultima8/audio/audio_process.cpp
@@ -55,13 +55,11 @@ bool AudioProcess::calculateSoundVolume(ObjId objId, int16 &volume, int8 &balanc
 	}
 
 	// Need to get items relative coords from avatar
-
-	int32 ax, ay, az, ix, iy, iz;
-	CameraProcess::GetCameraLocation(ax, ay, az);
-	item->getLocationAbsolute(ix, iy, iz);
-	ix -= ax;
-	iy -= ay;
-	iz -= az;
+	Point3 a = CameraProcess::GetCameraLocation();
+	Point3 i = item->getLocationAbsolute();
+	i.x -= a.x;
+	i.y -= a.y;
+	i.z -= a.z;
 
 	//
 	// Convert to screenspace
@@ -69,8 +67,8 @@ bool AudioProcess::calculateSoundVolume(ObjId objId, int16 &volume, int8 &balanc
 	// Note that this should also correct for Crusader too.
 	//
 
-	int x = (ix - iy) / 4;
-	int y = (ix + iy) / 8 - iz;
+	int x = (i.x - i.y) / 4;
+	int y = (i.x + i.y) / 8 - i.z;
 
 	// Fall off over 350 pixels
 	int limit = 350 * 350;
diff --git a/engines/ultima/ultima8/games/start_u8_process.cpp b/engines/ultima/ultima8/games/start_u8_process.cpp
index 565fb9810c0..c07e035a142 100644
--- a/engines/ultima/ultima8/games/start_u8_process.cpp
+++ b/engines/ultima/ultima8/games/start_u8_process.cpp
@@ -84,10 +84,9 @@ void StartU8Process::run() {
 
 		uint16 objid = uclist.getuint16(0);
 		Egg *egg = dynamic_cast<Egg *>(getObject(objid));
-		int32 ix, iy, iz;
-		egg->getLocation(ix, iy, iz);
+		Point3 pt = egg->getLocation();
 		// Center on egg
-		CameraProcess::SetCameraProcess(new CameraProcess(ix, iy, iz));
+		CameraProcess::SetCameraProcess(new CameraProcess(pt.x, pt.y, pt.z));
 		egg->hatch();
 	}
 
diff --git a/engines/ultima/ultima8/games/u8_game.cpp b/engines/ultima/ultima8/games/u8_game.cpp
index cefdb4a8a19..a3b250edeff 100644
--- a/engines/ultima/ultima8/games/u8_game.cpp
+++ b/engines/ultima/ultima8/games/u8_game.cpp
@@ -240,7 +240,6 @@ void U8Game::playQuotes() {
 
 void U8Game::writeSaveInfo(Common::WriteStream *ws) {
 	MainActor *av = getMainActor();
-	int32 x, y, z;
 
 	const Std::string &avname = av->getName();
 	const uint8 namelength = static_cast<uint8>(avname.size());
@@ -248,11 +247,11 @@ void U8Game::writeSaveInfo(Common::WriteStream *ws) {
 	for (unsigned int i = 0; i < namelength; ++i)
 		ws->writeByte(static_cast<uint8>(avname[i]));
 
-	av->getLocation(x, y, z);
+	Point3 pt = av->getLocation();
 	ws->writeUint16LE(av->getMapNum());
-	ws->writeUint32LE(static_cast<uint32>(x));
-	ws->writeUint32LE(static_cast<uint32>(y));
-	ws->writeUint32LE(static_cast<uint32>(z));
+	ws->writeUint32LE(static_cast<uint32>(pt.x));
+	ws->writeUint32LE(static_cast<uint32>(pt.y));
+	ws->writeUint32LE(static_cast<uint32>(pt.z));
 
 	ws->writeUint16LE(av->getStr());
 	ws->writeUint16LE(av->getInt());
diff --git a/engines/ultima/ultima8/gumps/fast_area_vis_gump.cpp b/engines/ultima/ultima8/gumps/fast_area_vis_gump.cpp
index 692ccdd9443..d437707bd3c 100644
--- a/engines/ultima/ultima8/gumps/fast_area_vis_gump.cpp
+++ b/engines/ultima/ultima8/gumps/fast_area_vis_gump.cpp
@@ -58,14 +58,13 @@ void FastAreaVisGump::PaintThis(RenderSurface *surf, int32 lerp_factor, bool sca
 	// Put a red dot where the avatar is
 	Item *avatar = getItem(1);
 	if (avatar) {
-		int32 x, y, z;
-		avatar->getLocation(x, y, z);
+		Point3 pt = avatar->getLocation();
 		int chunksize = currentmap->getChunkSize();
-		x /= chunksize;
-		y /= chunksize;
-		if (x >= 0 && x < MAP_NUM_CHUNKS && y >= 0 && y < MAP_NUM_CHUNKS) {
+		pt.x /= chunksize;
+		pt.y /= chunksize;
+		if (pt.x >= 0 && pt.x < MAP_NUM_CHUNKS && pt.y >= 0 && pt.y < MAP_NUM_CHUNKS) {
 			color = TEX32_PACK_RGB(0xFF, 0x10, 0x10);
-			surf->fill32(color, x + 1, y + 1, 1, 1);
+			surf->fill32(color, pt.x + 1, pt.y + 1, 1, 1);
 		}
 	}
 }
diff --git a/engines/ultima/ultima8/gumps/game_map_gump.cpp b/engines/ultima/ultima8/gumps/game_map_gump.cpp
index 59b74249a19..43c7fd64b65 100644
--- a/engines/ultima/ultima8/gumps/game_map_gump.cpp
+++ b/engines/ultima/ultima8/gumps/game_map_gump.cpp
@@ -66,14 +66,12 @@ GameMapGump::~GameMapGump() {
 	delete _displayList;
 }
 
-void GameMapGump::GetCameraLocation(int32 &lx, int32 &ly, int32 &lz,
-									int lerp_factor) {
+Point3 GameMapGump::GetCameraLocation(int lerp_factor) {
 	CameraProcess *camera = CameraProcess::GetCameraProcess();
-	if (!camera) {
-		CameraProcess::GetCameraLocation(lx, ly, lz);
-	} else {
-		camera->GetLerped(lx, ly, lz, lerp_factor);
+	if (camera) {
+		return camera->GetLerped(lerp_factor);
 	}
+	return CameraProcess::GetCameraLocation();
 }
 
 void GameMapGump::PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled) {
@@ -85,8 +83,7 @@ void GameMapGump::PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled)
 
 
 	// Get the camera location
-	int32 lx, ly, lz;
-	GetCameraLocation(lx, ly, lz, lerp_factor);
+	Point3 loc = GetCameraLocation(lerp_factor);
 
 	CameraProcess *camera = CameraProcess::GetCameraProcess();
 
@@ -109,7 +106,7 @@ void GameMapGump::PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled)
 
 	Rect clipWindow;
 	surf->GetClippingRect(clipWindow);
-	_displayList->BeginDisplayList(clipWindow, lx, ly, lz);
+	_displayList->BeginDisplayList(clipWindow, loc);
 
 	uint32 gametick = Kernel::get_instance()->getFrameNum();
 
@@ -147,9 +144,8 @@ void GameMapGump::PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled)
 						if (item->hasExtFlags(Item::EXT_TRANSPARENT))
 							continue;
 
-						int32 x_, y_, z_;
-						item->getLerped(x_, y_, z_);
-						_displayList->AddItem(x_, y_, z_, item->getShape(), item->getFrame(), item->getFlags() & ~Item::FLG_INVISIBLE, item->getExtFlags() | Item::EXT_TRANSPARENT, 1);
+						_displayList->AddItem(item->getLerped(), item->getShape(), item->getFrame(),
+							item->getFlags() & ~Item::FLG_INVISIBLE, item->getExtFlags() | Item::EXT_TRANSPARENT, 1);
 					}
 
 					continue;
@@ -162,8 +158,7 @@ void GameMapGump::PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled)
 	// Dragging:
 
 	if (_displayDragging) {
-		_displayList->AddItem(_draggingPos[0], _draggingPos[1], _draggingPos[2],
-		                      _draggingShape, _draggingFrame,
+		_displayList->AddItem(_draggingPos, _draggingShape, _draggingFrame,
 		                      _draggingFlags, Item::EXT_TRANSPARENT);
 	}
 
@@ -180,14 +175,13 @@ uint16 GameMapGump::TraceObjId(int32 mx, int32 my) {
 	return _displayList->Trace(mx, my, 0, _highlightItems);
 }
 
-uint16 GameMapGump::TraceCoordinates(int mx, int my, int32 coords[3],
+uint16 GameMapGump::TraceCoordinates(int mx, int my, Point3 &coords,
 									 int offsetx, int offsety, Item *item) {
 	int32 dxd = 0, dyd = 0, dzd = 0;
 	if (item)
 		item->getFootpadWorld(dxd, dyd, dzd);
 
-	int32 cx, cy, cz;
-	GetCameraLocation(cx, cy, cz);
+	Point3 c = GetCameraLocation();
 
 	ItemSorter::HitFace face;
 	ObjId trace = _displayList->Trace(mx, my, &face);
@@ -196,36 +190,35 @@ uint16 GameMapGump::TraceCoordinates(int mx, int my, int32 coords[3],
 	if (!hit) // strange...
 		return 0;
 
-	int32 hx, hy, hz;
 	int32 hxd, hyd, hzd;
-	hit->getLocation(hx, hy, hz);
+	Point3 h = hit->getLocation();
 	hit->getFootpadWorld(hxd, hyd, hzd);
 
 	// adjust mx (if dragged item wasn't 'picked up' at its origin)
 	mx -= offsetx;
 	my -= offsety;
 
-	// mx = (coords[0]-cx-coords[1]+cy)/4
-	// my = (coords[0]-cx+coords[1]-cy)/8 - coords[2] + cz
+	// mx = (coords.x - c.x - coords.y + c.y) / 4
+	// my = (coords.x - c.x + coords.y - c.y) / 8 - coords.z + c.z
 
 	// the below expressions solve these two equations to two of the coords,
 	// while fixing the other coord
 
 	switch (face) {
 	case ItemSorter::Z_FACE:
-		coords[0] = 2 * mx + 4 * (my + hz + hzd) + cx - 4 * cz;
-		coords[1] = -2 * mx + 4 * (my + hz + hzd) + cy - 4 * cz;
-		coords[2] = hz + hzd;
+		coords.x = 2 * mx + 4 * (my + h.z + hzd) + c.x - 4 * c.z;
+		coords.y = -2 * mx + 4 * (my + h.z + hzd) + c.y - 4 * c.z;
+		coords.z = h.z + hzd;
 		break;
 	case ItemSorter::X_FACE:
-		coords[0] = hx + dxd;
-		coords[1] = -4 * mx + hx + dxd - cx + cy;
-		coords[2] = -my + (hx + dxd) / 4 - mx / 2 - cx / 4 + cz;
+		coords.x = h.x + dxd;
+		coords.y = -4 * mx + h.x + dxd - c.x + c.y;
+		coords.z = -my + (h.x + dxd) / 4 - mx / 2 - c.x / 4 + c.z;
 		break;
 	case ItemSorter::Y_FACE:
-		coords[0] = 4 * mx + hy + dyd + cx - cy;
-		coords[1] = hy + dyd;
-		coords[2] = -my + mx / 2 + (hy + dyd) / 4 - cy / 4 + cz;
+		coords.x = 4 * mx + h.y + dyd + c.x - c.y;
+		coords.y = h.y + dyd;
+		coords.z = -my + mx / 2 + (h.y + dyd) / 4 - c.y / 4 + c.z;
 		break;
 	}
 
@@ -243,28 +236,28 @@ bool GameMapGump::GetLocationOfItem(uint16 itemid, int32 &gx, int32 &gy,
 	if (root)
 		item = root;
 
-	int32 ix, iy, iz;
-
 	// Hacks be us. Force the item into the fast area
 	item->setupLerp(Kernel::get_instance()->getFrameNum());
 	item->doLerp(lerp_factor);
-	item->getLerped(ix, iy, iz);
+	Point3 i = item->getLerped();
 
 	// Get the camera's location
-	int32 cx, cy, cz;
+	Point3 c;
 	CameraProcess *cam = CameraProcess::GetCameraProcess();
-	if (!cam) CameraProcess::GetCameraLocation(cx, cy, cz);
-	else cam->GetLerped(cx, cy, cz, lerp_factor, true);
+	if (cam)
+		c = cam->GetLerped(lerp_factor, true);
+	else
+		c = CameraProcess::GetCameraLocation();
 
 	// Screenspace bounding box bottom x coord (RNB x coord)
-	gx = (ix - iy) / 4;
+	gx = (i.x - i.y) / 4;
 	// Screenspace bounding box bottom extent  (RNB y coord)
-	gy = (ix + iy) / 8 - iz;
+	gy = (i.x + i.y) / 8 - i.z;
 
 	// Screenspace bounding box bottom x coord (RNB x coord)
-	gx -= (cx - cy) / 4;
+	gx -= (c.x - c.y) / 4;
 	// Screenspace bounding box bottom extent  (RNB y coord)
-	gy -= (cx + cy) / 8 - cz;
+	gy -= (c.x + c.y) / 8 - c.z;
 
 	return true;
 }
@@ -306,8 +299,6 @@ void GameMapGump::onMouseClick(int button, int32 mx, int32 my) {
 		uint16 objID = TraceObjId(mx, my);
 		Item *item = getItem(objID);
 		if (item) {
-			int32 xv, yv, zv;
-			item->getLocation(xv, yv, zv);
 			debugC(kDebugObject, "%s", item->dumpInfo().c_str());
 
 			if (Ultima8Engine::get_instance()->isAvatarInStasis()) {
@@ -321,7 +312,7 @@ void GameMapGump::onMouseClick(int button, int32 mx, int32 my) {
 	case Mouse::BUTTON_MIDDLE: {
 		ParentToGump(mx, my);
 
-		int32 coords[3];
+		Point3 coords;
 		uint16 objID = TraceCoordinates(mx, my, coords);
 		Item *item = getItem(objID);
 		if (item) {
@@ -331,7 +322,7 @@ void GameMapGump::onMouseClick(int button, int32 mx, int32 my) {
 				debugC(kDebugObject, "Can't move: avatarInStasis");
 			} else {
 				Actor *avatarControlled = getControlledActor();
-				PathfinderProcess *pfp = new PathfinderProcess(avatarControlled, coords[0], coords[1], coords[2]);
+				PathfinderProcess *pfp = new PathfinderProcess(avatarControlled, coords.x, coords.y, coords.z);
 				Kernel::get_instance()->killProcesses(avatarControlled->getObjId(), PathfinderProcess::PATHFINDER_PROC_TYPE, true);
 				Kernel::get_instance()->addProcess(pfp);
 			}
@@ -353,8 +344,6 @@ void GameMapGump::onMouseDouble(int button, int32 mx, int32 my) {
 		uint16 objID = TraceObjId(mx, my);
 		Item *item = getItem(objID);
 		if (item) {
-			int32 xv, yv, zv;
-			item->getLocation(xv, yv, zv);
 			debugC(kDebugObject, "%s", item->dumpInfo().c_str());
 
 			int range = 128; // CONSTANT!
@@ -428,17 +417,16 @@ bool GameMapGump::DraggingItem(Item *item, int mx, int my) {
 
 	bool throwing = false;
 	if (!avatar->canReach(item, 128, // CONSTANT!
-	                      _draggingPos[0], _draggingPos[1], _draggingPos[2])) {
+	                      _draggingPos.x, _draggingPos.y, _draggingPos.z)) {
 		// can't reach, so see if we can throw
 		int throwrange = item->getThrowRange();
-		if (throwrange && avatar->canReach(item, throwrange, _draggingPos[0],
-		                                   _draggingPos[1], _draggingPos[2])) {
+		if (throwrange && avatar->canReach(item, throwrange, _draggingPos.x,
+		                                   _draggingPos.y, _draggingPos.z)) {
 			int speed = 64 - item->getTotalWeight() + avatar->getStr();
 			if (speed < 1) speed = 1;
-			int32 ax, ay, az;
-			avatar->getLocation(ax, ay, az);
-			MissileTracker t(item, 1, ax, ay, az,
-			                 _draggingPos[0], _draggingPos[1], _draggingPos[2],
+			Point3 pt = avatar->getLocation();
+			MissileTracker t(item, 1, pt.x, pt.y, pt.z,
+			                 _draggingPos.x, _draggingPos.y, _draggingPos.z,
 			                 speed, 4);
 			if (t.isPathClear())
 				throwing = true;
@@ -449,7 +437,7 @@ bool GameMapGump::DraggingItem(Item *item, int mx, int my) {
 		}
 	}
 
-	if (!item->canExistAt(_draggingPos[0], _draggingPos[1], _draggingPos[2]))
+	if (!item->canExistAt(_draggingPos.x, _draggingPos.y, _draggingPos.z))
 		return false;
 
 	if (throwing)
@@ -482,7 +470,7 @@ void GameMapGump::DropItem(Item *item, int mx, int my) {
 	ObjId trace = TraceCoordinates(mx, my, _draggingPos, dox, doy, item);
 	Item *targetitem = getItem(trace);
 	bool canReach = avatar->canReach(item, 128, // CONSTANT!
-									_draggingPos[0], _draggingPos[1], _draggingPos[2]);
+									_draggingPos.x, _draggingPos.y, _draggingPos.z);
 
 	if (item->getShapeInfo()->hasQuantity()) {
 		if (item->getQuality() > 1) {
@@ -550,17 +538,17 @@ void GameMapGump::DropItem(Item *item, int mx, int my) {
 	if (!canReach) {
 		// can't reach, so throw
 		debugC(kDebugObject, "Throwing item to (%d, %d, %d)",
-			   _draggingPos[0], _draggingPos[1], _draggingPos[2]);
+			   _draggingPos.x, _draggingPos.y, _draggingPos.z);
 		int speed = 64 - item->getTotalWeight() + avatar->getStr();
-		if (speed < 1) speed = 1;
-		int32 ax, ay, az;
-		avatar->getLocation(ax, ay, az);
+		if (speed < 1)
+			speed = 1;
+		Point3 pt = avatar->getLocation();
 		// CHECKME: correct position to throw from?
 		// CHECKME: correct events triggered when doing this move?
-		item->move(ax, ay, az + 24);
+		item->move(pt.x, pt.y, pt.z + 24);
 		int32 tx, ty;
-		tx = _draggingPos[0];
-		ty = _draggingPos[1];
+		tx = _draggingPos.x;
+		ty = _draggingPos.y;
 		int inaccuracy = 4 * (30 - avatar->getDex());
 		if (inaccuracy < 20)
 			inaccuracy = 20; // just in case dex > 25
@@ -568,22 +556,22 @@ void GameMapGump::DropItem(Item *item, int mx, int my) {
 		Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
 		tx += rs.getRandomNumberRngSigned(-inaccuracy, inaccuracy);
 		ty += rs.getRandomNumberRngSigned(-inaccuracy, inaccuracy);
-		MissileTracker t(item, 1, tx, ty, _draggingPos[2],
+		MissileTracker t(item, 1, tx, ty, _draggingPos.z,
 		                 speed, 4);
 		t.launchItem();
 
-		Direction dir = Direction_GetWorldDir(_draggingPos[1] - ay,
-											  _draggingPos[0] - ax,
+		Direction dir = Direction_GetWorldDir(_draggingPos.y - pt.y,
+											  _draggingPos.x - pt.x,
 											   dirmode_8dirs);
 		avatar->doAnim(Animation::stand, dir);
 	} else {
 		debugC(kDebugObject, "Dropping item at (%d, %d, %d)",
-			   _draggingPos[0], _draggingPos[1], _draggingPos[2]);
+			   _draggingPos.x, _draggingPos.y, _draggingPos.z);
 
 		// CHECKME: collideMove and grab (in StopDraggingItem)
 		// both call release on supporting items.
 
-		item->collideMove(_draggingPos[0], _draggingPos[1], _draggingPos[2],
+		item->collideMove(_draggingPos.x, _draggingPos.y, _draggingPos.z,
 		                  true, true); // teleport item
 		item->fall();
 	}
diff --git a/engines/ultima/ultima8/gumps/game_map_gump.h b/engines/ultima/ultima8/gumps/game_map_gump.h
index 4c53d9896a1..0a3bcf74ee6 100644
--- a/engines/ultima/ultima8/gumps/game_map_gump.h
+++ b/engines/ultima/ultima8/gumps/game_map_gump.h
@@ -24,6 +24,7 @@
 
 #include "ultima/ultima8/gumps/gump.h"
 #include "ultima/ultima8/misc/classtype.h"
+#include "ultima/ultima8/misc/point3.h"
 
 namespace Ultima {
 namespace Ultima8 {
@@ -47,14 +48,13 @@ public:
 
 	void        PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled) override;
 
-	void                GetCameraLocation(int32 &x, int32 &y, int32 &z,
-	                                      int lerp_factor = 256);
+	Point3 GetCameraLocation(int lerp_factor = 256);
 
 	// Trace a click, and return ObjId (_parent coord space)
 	uint16      TraceObjId(int32 mx, int32 my) override;
 
 	// Trace a click, return ObjId, and the coordinates of the mouse click (gump coord space)
-	virtual uint16      TraceCoordinates(int mx, int my, int32 coords[3],
+	virtual uint16      TraceCoordinates(int mx, int my, Point3 &coords,
 	                                     int offsetx = 0, int offsety = 0,
 	                                     Item *item = 0);
 
@@ -96,7 +96,7 @@ protected:
 	uint32 _draggingShape;
 	uint32 _draggingFrame;
 	uint32 _draggingFlags;
-	int32 _draggingPos[3];
+	Point3 _draggingPos;
 
 	static bool _highlightItems;
 	static bool _showFootpads;
diff --git a/engines/ultima/ultima8/misc/debugger.cpp b/engines/ultima/ultima8/misc/debugger.cpp
index 7c052a7914c..ac278eecf09 100644
--- a/engines/ultima/ultima8/misc/debugger.cpp
+++ b/engines/ultima/ultima8/misc/debugger.cpp
@@ -978,11 +978,10 @@ bool Debugger::cmdMark(int argc, const char **argv) {
 
 	MainActor *mainActor = getMainActor();
 	int curmap = mainActor->getMapNum();
-	int32 x, y, z;
-	mainActor->getLocation(x, y, z);
+	Point3 pt = mainActor->getLocation();
 
 	Common::String key = Common::String::format("mark_%s", argv[1]);
-	Common::String value = Common::String::format("%d %d %d %d", curmap, x, y, z);
+	Common::String value = Common::String::format("%d %d %d %d", curmap, pt.x, pt.y, pt.z);
 	ConfMan.set(key, value);
 
 	debugPrintf("Set mark \"%s\" to %s\n", argv[1], value.c_str());
diff --git a/engines/ultima/ultima8/misc/point3.h b/engines/ultima/ultima8/misc/point3.h
index 8f2c1558396..a2d513e08ac 100644
--- a/engines/ultima/ultima8/misc/point3.h
+++ b/engines/ultima/ultima8/misc/point3.h
@@ -31,6 +31,13 @@ struct Point3 {
 	Point3() : x(0), y(0), z(0) {}
 	Point3(int32 nx, int32 ny, int32 nz) : x(nx), y(ny), z(nz) {}
 
+	bool operator==(const Point3 &rhs) const { return equals(rhs); }
+	bool operator!=(const Point3 &rhs) const { return !equals(rhs); }
+
+	bool equals(const Point3 &p) const {
+		return (x == p.x && y == p.y && z == p.z);
+	}
+
 	int maxDistXYZ(const Point3 &other) const {
 		int xdiff = abs(x - other.x);
 		int ydiff = abs(y - other.y);
diff --git a/engines/ultima/ultima8/usecode/uc_machine.cpp b/engines/ultima/ultima8/usecode/uc_machine.cpp
index f6a5514d8d7..7a626ec311a 100644
--- a/engines/ultima/ultima8/usecode/uc_machine.cpp
+++ b/engines/ultima/ultima8/usecode/uc_machine.cpp
@@ -1731,11 +1731,10 @@ void UCMachine::execProcess(UCProcess *p) {
 				const uint16 range = GAME_IS_CRUSADER ? ui16b * 2 : ui16b;
 
 				if (item) {
-					int32 ix, iy, iz;
-					item->getLocationAbsolute(ix, iy, iz);
+					Point3 pt = item->getLocationAbsolute();
 					world->getCurrentMap()->areaSearch(itemlist, script,
 					                                   scriptsize, nullptr,
-					                                   range, recurse, ix, iy);
+					                                   range, recurse, pt.x, pt.y);
 				} else {
 					// return error or return empty list?
 					warning("Invalid item %u passed to area search", ui16a);
diff --git a/engines/ultima/ultima8/world/actors/actor.cpp b/engines/ultima/ultima8/world/actors/actor.cpp
index 2a8d4170c74..1ec95ab803c 100644
--- a/engines/ultima/ultima8/world/actors/actor.cpp
+++ b/engines/ultima/ultima8/world/actors/actor.cpp
@@ -986,11 +986,9 @@ void Actor::receiveHitCru(uint16 other, Direction dir, int damage, uint16 damage
 		// If the attacker is the controlled npc and this actor is not pathfinding
 		if (attacker && attacker == getControlledActor() &&
 			kernel->findProcess(_objId, PathfinderProcess::PATHFINDER_PROC_TYPE) != nullptr) {
-			int32 x, y, z;
-			int32 ox, oy, oz;
-			getLocation(x, y, z);
-			attacker->getLocation(ox, oy, oz);
-			int32 maxdiff = MAX(MAX(abs(x - ox), abs(y - oy)), abs(z - oz));
+			Point3 pt1 = getLocation();
+			Point3 pt2 = attacker->getLocation();
+			int32 maxdiff = MAX(MAX(abs(pt1.x - pt2.x), abs(pt1.y - pt2.y)), abs(pt1.z - pt2.z));
 			if (maxdiff < 641 && isOnScreen()) {
 				// TODO: implement the equivalent of this function.  For now, we always
 				// cancel pathfinding for the NPC.
@@ -1203,10 +1201,9 @@ void Actor::receiveHitU8(uint16 other, Direction dir, int damage, uint16 damage_
 			end = 25;
 		}
 
-		int32 xv, yv, zv;
-		getLocation(xv, yv, zv);
-		zv += rs.getRandomNumber(23);
-		Process *sp = new SpriteProcess(620, start, end, 1, 1, xv, yv, zv);
+		Point3 pt = getLocation();
+		pt.z += rs.getRandomNumber(23);
+		Process *sp = new SpriteProcess(620, start, end, 1, 1, pt.x, pt.y, pt.z);
 		Kernel::get_instance()->addProcess(sp);
 	}
 
@@ -2648,9 +2645,8 @@ uint32 Actor::I_createActorCru(const uint8 *args, unsigned int /*argsize*/) {
 
 	newactor->setDir(static_cast<Direction>(dir * 2));
 
-	int32 x, y, z;
-	item->getLocation(x, y, z);
-	newactor->move(x, y, z);
+	Point3 pt = item->getLocation();
+	newactor->move(pt.x, pt.y, pt.z);
 
 	newactor->setDefaultActivity(0, other->getQuality() >> 8);
 	newactor->setDefaultActivity(1, item->getQuality() >> 8);
@@ -2686,7 +2682,7 @@ uint32 Actor::I_createActorCru(const uint8 *args, unsigned int /*argsize*/) {
 	}
 
 	newactor->setCombatTactic(0);
-	newactor->setHomePosition(x, y, z);
+	newactor->setHomePosition(pt.x, pt.y, pt.z);
 
 	/*
 	 TODO: once I know what this field is.. seems to never be used in game?
diff --git a/engines/ultima/ultima8/world/actors/actor_anim_process.cpp b/engines/ultima/ultima8/world/actors/actor_anim_process.cpp
index f7169701f6b..86a2edca25f 100644
--- a/engines/ultima/ultima8/world/actors/actor_anim_process.cpp
+++ b/engines/ultima/ultima8/world/actors/actor_anim_process.cpp
@@ -193,9 +193,8 @@ void ActorAnimProcess::run() {
 	bool resultVal = true;
 	if (_repeatCounter == 0) {
 		// next step:
-		int32 x, y, z;
-		a->getLocation(x, y, z);
-		resultVal = _tracker->stepFrom(x, y, z);
+		Point3 pt = a->getLocation();
+		resultVal = _tracker->stepFrom(pt.x, pt.y, pt.z);
 		_tracker->updateActorFlags();
 		_currentStep++;
 
@@ -211,7 +210,7 @@ void ActorAnimProcess::run() {
 #endif
 
 				// TODO: there are _three_ places where we can fall; clean up
-				if (_tracker->isUnsupported() && z > 0) {
+				if (_tracker->isUnsupported() && pt.z > 0) {
 #ifdef WATCHACTOR
 					if (_itemNum == watchactor) {
 						debugC(kDebugActor, "Animation [%u] ActorAnimProcess falling at end",
@@ -239,7 +238,7 @@ void ActorAnimProcess::run() {
 						  Kernel::get_instance()->getFrameNum());
 #endif
 
-				if (_tracker->isUnsupported() && z > 0) {
+				if (_tracker->isUnsupported() && pt.z > 0) {
 #ifdef WATCHACTOR
 					if (_itemNum == watchactor) {
 						debugC(kDebugActor, "Animation [%u] ActorAnimProcess falling from blocked",
@@ -289,15 +288,15 @@ void ActorAnimProcess::run() {
 		}
 	}
 
-	int32 x, y, z, x2, y2, z2;
-	a->getLocation(x, y, z);
+	int32 x2, y2, z2;
+	Point3 pt = a->getLocation();
 
 	if (_interpolate) {
 		// Apply interpolated position on repeated frames
 		_tracker->getInterpolatedPosition(x2, y2, z2, _repeatCounter);
-		if (x == x2 && y == y2 && z == z2) {
-			_tracker->getInterpolatedPosition(x, y, z, _repeatCounter + 1);
-			a->collideMove(x, y, z, false, true); // forced move
+		if (pt.x == x2 && pt.y == y2 && pt.z == z2) {
+			_tracker->getInterpolatedPosition(pt.x, pt.y, pt.z, _repeatCounter + 1);
+			a->collideMove(pt.x, pt.y, pt.z, false, true); // forced move
 			a->setFrame(_tracker->getFrame());
 #ifdef WATCHACTOR
 		} else {
@@ -314,9 +313,9 @@ void ActorAnimProcess::run() {
 			a->collideMove(x2, y2, z2, false, true); // forced move
 			a->setFrame(_tracker->getFrame());
 		} else {
-			x2 = x;
-			y2 = y;
-			z2 = z;
+			x2 = pt.x;
+			y2 = pt.y;
+			z2 = pt.z;
 		}
 	}
 
@@ -344,7 +343,7 @@ void ActorAnimProcess::run() {
 			info += "H";
 
 		debugC(kDebugActor, "Animation [%u] ActorAnimProcess showing frame (%d, %d, %d)-(%d, %d, %d) shp (%u, %u) sfx %d rep %d flg %04X %s",
-			  Kernel::get_instance()->getFrameNum(), x, y, z, x2, y2, z2,
+			  Kernel::get_instance()->getFrameNum(), pt.x, pt.y, pt.z, x2, y2, z2,
 			  a->getShape(), _tracker->getFrame(), _tracker->getAnimFrame()->_sfx,
 			  _repeatCounter, _tracker->getAnimFrame()->_flags, info.c_str());
 	}
@@ -352,7 +351,7 @@ void ActorAnimProcess::run() {
 
 
 	if (_repeatCounter == _tracker->getAnimAction()->getFrameRepeat()) {
-		if (_tracker->isUnsupported() && z > 0) {
+		if (_tracker->isUnsupported() && pt.z > 0) {
 			_animAborted = !_tracker->getAnimAction()->hasFlags(AnimAction::AAF_UNSTOPPABLE);
 
 #ifdef WATCHACTOR
@@ -410,29 +409,27 @@ void ActorAnimProcess::doSpecial() {
 			Actor *skull = Actor::createActor(0x19d, 0);
 			if (!skull) return;
 			skull->setFlag(Item::FLG_FAST_ONLY);
-			int32 x, y, z;
-			a->getLocation(x, y, z);
+			Point3 pt = a->getLocation();
 			Direction dirNum = a->getDir();
-			skull->move(x + 32 * Direction_XFactor(dirNum), y + 32 * Direction_XFactor(dirNum), z);
+			skull->move(pt.x + 32 * Direction_XFactor(dirNum), pt.y + 32 * Direction_XFactor(dirNum), pt.z);
 			hostile = skull;
 		} else if (a->getMapNum() != 54) { // Khumash-Gor doesn't summon ghouls
 			// otherwise, summon ghoul
 			unsigned int ghoulcount = a->countNearby(0x8e, 8 * 256);
 			if (ghoulcount > 2) return;
 
-			int32 x, y, z;
-			a->getLocation(x, y, z);
-			x += rs.getRandomNumberRngSigned(-3 * 256, 3 * 256);
-			y += rs.getRandomNumberRngSigned(-3 * 256, 3 * 256);
+			Point3 pt = a->getLocation();
+			pt.x += rs.getRandomNumberRngSigned(-3 * 256, 3 * 256);
+			pt.y += rs.getRandomNumberRngSigned(-3 * 256, 3 * 256);
 
 			Actor *ghoul = Actor::createActor(0x8e, 0);
 			if (!ghoul) return;
 			ghoul->setFlag(Item::FLG_FAST_ONLY);
-			if (!ghoul->canExistAt(x, y, z, true)) {
+			if (!ghoul->canExistAt(pt.x, pt.y, pt.z, true)) {
 				ghoul->destroy();
 				return;
 			}
-			ghoul->move(x, y, z);
+			ghoul->move(pt.x, pt.y, pt.z);
 			ghoul->doAnim(Animation::standUp, dir_north);
 			hostile = ghoul;
 		}
@@ -462,14 +459,13 @@ void ActorAnimProcess::doSpecial() {
 	// play PC/NPC footsteps
 	bool playavfootsteps = ConfMan.getBool("footsteps");
 	if (_itemNum != kMainActorId || playavfootsteps) {
-		int32 x, y, z;
 		int32 xd, yd, zd;
-		a->getLocation(x, y, z);
+		Point3 pt = a->getLocation();
 		a->getFootpadWorld(xd, yd, zd);
-		Box start(x, y, z, xd, yd, zd);
+		Box start(pt.x, pt.y, pt.z, xd, yd, zd);
 
-		_tracker->getPosition(x, y, z);
-		Box target(x, y, z, xd, yd, zd);
+		_tracker->getPosition(pt.x, pt.y, pt.z);
+		Box target(pt.x, pt.y, pt.z, xd, yd, zd);
 
 		CurrentMap *cm = World::get_instance()->getCurrentMap();
 		PositionInfo info = cm->getPositionInfo(target, start, a->getShapeInfo()->_flags, _itemNum);
@@ -510,8 +506,8 @@ void ActorAnimProcess::doSpecial() {
 			}
 
 			if (splash) {
-				a->getLocation(x, y, z);
-				Process *sp = new SpriteProcess(475, 0, 7, 1, 1, x, y, z);
+				pt = a->getLocation();
+				Process *sp = new SpriteProcess(475, 0, 7, 1, 1, pt.x, pt.y, pt.z);
 				Kernel::get_instance()->addProcess(sp);
 			}
 		}
@@ -600,8 +596,7 @@ void ActorAnimProcess::doHitSpecial(Item *hit) {
 			if (audioproc) audioproc->playSFX(sfx, 0x60, 1, 0, false,
 				                                  0x10000 + rs.getRandomNumber(0x1FFF) - 0x1000);
 
-			int32 x, y, z;
-			a->getLocation(x, y, z);
+			Point3 pt = a->getLocation();
 			// 1: create flame sprite
 			// 2: create flame object
 			// 3: wait
@@ -610,9 +605,9 @@ void ActorAnimProcess::doHitSpecial(Item *hit) {
 			Kernel *kernel = Kernel::get_instance();
 
 			int32 fx, fy, fz;
-			fx = x + 96 * Direction_XFactor(_dir);
-			fy = y + 96 * Direction_YFactor(_dir);
-			fz = z;
+			fx = pt.x + 96 * Direction_XFactor(_dir);
+			fy = pt.y + 96 * Direction_YFactor(_dir);
+			fz = pt.z;
 
 			// CONSTANTS!! (lots of them)
 
diff --git a/engines/ultima/ultima8/world/actors/animation_tracker.cpp b/engines/ultima/ultima8/world/actors/animation_tracker.cpp
index eff0749c686..7086d022df2 100644
--- a/engines/ultima/ultima8/world/actors/animation_tracker.cpp
+++ b/engines/ultima/ultima8/world/actors/animation_tracker.cpp
@@ -44,8 +44,8 @@ static const int watchactor = WATCHACTOR;
 
 AnimationTracker::AnimationTracker() : _firstFrame(true), _done(false),
 	_blocked(false), _unsupported(false), _hitObject(0), _mode(NormalMode),
-	_actor(0), _dir(dir_north), _animAction(nullptr), _x(0), _y(0), _z(0),
-	_prevX(0), _prevY(0), _prevZ(0), _startX(0), _startY(0), _startZ(0),
+	_actor(0), _dir(dir_north), _animAction(nullptr),
+	_prev(), _curr(), _start(),
 	_targetDx(0), _targetDy(0), _targetDz(0), _targetOffGroundLeft(0),
 	_firstStep(false), _shapeFrame(0), _currentFrame(0), _startFrame(0),
 	_endFrame(0), _flipped(false) {
@@ -77,7 +77,7 @@ bool AnimationTracker::init(const Actor *actor, Animation::Sequence action,
 
 	if (state == 0) {
 		_animAction->getAnimRange(actor, _dir, _startFrame, _endFrame);
-		actor->getLocation(_x, _y, _z);
+		_curr = actor->getLocation();
 		_flipped = actor->hasFlags(Item::FLG_FLIPPED);
 		_firstStep = actor->hasActorFlags(Actor::ACT_FIRSTSTEP);
 	} else {
@@ -85,13 +85,9 @@ bool AnimationTracker::init(const Actor *actor, Animation::Sequence action,
 		                         state->_firstStep, _dir, _startFrame, _endFrame);
 		_flipped = state->_flipped;
 		_firstStep = state->_firstStep;
-		_x = state->_x;
-		_y = state->_y;
-		_z = state->_z;
+		_curr = state->_point;
 	}
-	_startX = _x;
-	_startY = _y;
-	_startZ = _z;
+	_start = _curr;
 
 #ifdef WATCHACTOR
 	if (actor && actor->getObjId() == watchactor) {
@@ -131,16 +127,16 @@ unsigned int AnimationTracker::getNextFrame(unsigned int frame) const {
 }
 
 bool AnimationTracker::stepFrom(int32 x, int32 y, int32 z) {
-	_x = x;
-	_y = y;
-	_z = z;
+	_curr.x = x;
+	_curr.y = y;
+	_curr.z = z;
 
 	return step();
 }
 
 void AnimationTracker::evaluateMaxAnimTravel(int32 &max_endx, int32 &max_endy, Direction dir) {
-	max_endx = _x;
-	max_endy = _y;
+	max_endx = _curr.x;
+	max_endy = _curr.y;
 
 	if (_done) return;
 
@@ -188,9 +184,7 @@ bool AnimationTracker::step() {
 	const bool is_u8 = GAME_IS_U8;
 	const bool is_crusader = !is_u8;
 
-	_prevX = _x;
-	_prevY = _y;
-	_prevZ = _z;
+	_prev = _curr;
 
 	// reset status flags
 	_unsupported = false;
@@ -269,14 +263,14 @@ bool AnimationTracker::step() {
 	// scanForValidPosition after a teleport would work around that problem.
 
 	int32 tx, ty, tz;
-	tx = _x + dx;
-	ty = _y + dy;
-	tz = _z + dz;
+	tx = _curr.x + dx;
+	ty = _curr.y + dy;
+	tz = _curr.z + dz;
 
 	// Only for particularly large steps we do a full sweepTest
 	if (ABS(dx) >= xd - 8 || ABS(dy) >= yd - 8 || ABS(dz) >= zd - 8) {
 
-		int32 start[3] = { _x, _y, _z };
+		int32 start[3] = { _curr.x, _curr.y, _curr.z };
 		int32 end[3] = { tx, ty, tz };
 		int32 dims[3] = { xd, yd, zd };
 
@@ -297,9 +291,9 @@ bool AnimationTracker::step() {
 #endif
 				_blocked = true;
 				it->GetInterpolatedCoords(end, start, end);
-				_x = end[0];
-				_y = end[1];
-				_z = end[2];
+				_curr.x = end[0];
+				_curr.y = end[1];
+				_curr.z = end[2];
 				return false;
 			}
 		}
@@ -308,7 +302,7 @@ bool AnimationTracker::step() {
 	}
 
 	Box target(tx, ty, tz, xd, yd, zd);
-	Box start(_startX, _startY, _startZ, xd, yd, zd);
+	Box start(_start.x, _start.y, _start.z, xd, yd, zd);
 	PositionInfo info = cm->getPositionInfo(target, start, a->getShapeInfo()->_flags, _actor);
 
 	if (is_u8 && info.valid && info.supported && info.land) {
@@ -378,9 +372,9 @@ bool AnimationTracker::step() {
 	}
 #endif
 
-	_x = tx;
-	_y = ty;
-	_z = tz;
+	_curr.x = tx;
+	_curr.y = ty;
+	_curr.z = tz;
 
 
 	// if attack animation, see if we hit something
@@ -433,9 +427,9 @@ void AnimationTracker::setTargetedMode(int32 x, int32 y, int32 z) {
 	if (offGround) {
 		_mode = TargetMode;
 		_targetOffGroundLeft = offGround;
-		_targetDx = x - _x - end_dx;
-		_targetDy = y - _y - end_dy;
-		_targetDz = z - _z - end_dz;
+		_targetDx = x - _curr.x - end_dx;
+		_targetDy = y - _curr.y - end_dy;
+		_targetDz = z - _curr.z - end_dz;
 
 		// Don't allow large changes in Z
 		if (_targetDz > 16)
@@ -455,7 +449,7 @@ void AnimationTracker::checkWeaponHit() {
 
 
 	Box abox = a->getWorldBox();
-	abox.moveTo(_x, _y, _z);
+	abox.moveTo(_curr.x, _curr.y, _curr.z);
 	abox.translate(Direction_XFactor(_dir) * 32 * range, Direction_YFactor(_dir) * 32 * range, 0);
 
 #ifdef WATCHACTOR
@@ -470,7 +464,7 @@ void AnimationTracker::checkWeaponHit() {
 	UCList itemlist(2);
 	LOOPSCRIPT(script, LS_TOKEN_END);
 
-	cm->areaSearch(&itemlist, script, sizeof(script), 0, 320, false, _x, _y);
+	cm->areaSearch(&itemlist, script, sizeof(script), 0, 320, false, _curr.x, _curr.y);
 
 	ObjId hit = 0;
 	for (unsigned int i = 0; i < itemlist.getSize(); ++i) {
@@ -503,9 +497,7 @@ void AnimationTracker::checkWeaponHit() {
 }
 
 void AnimationTracker::updateState(PathfindingState &state) {
-	state._x = _x;
-	state._y = _y;
-	state._z = _z;
+	state._point = _curr;
 	state._flipped = _flipped;
 	state._firstStep = _firstStep;
 }
@@ -539,21 +531,21 @@ void AnimationTracker::updateActorFlags() {
 
 void AnimationTracker::getInterpolatedPosition(int32 &x, int32 &y,
 											   int32 &z, int fc) const {
-	int32 dx = _x - _prevX;
-	int32 dy = _y - _prevY;
-	int32 dz = _z - _prevZ;
+	int32 dx = _curr.x - _prev.x;
+	int32 dy = _curr.y - _prev.y;
+	int32 dz = _curr.z - _prev.z;
 
 	int repeat = _animAction->getFrameRepeat();
 
-	x = _prevX + (dx * fc) / (repeat + 1);
-	y = _prevY + (dy * fc) / (repeat + 1);
-	z = _prevZ + (dz * fc) / (repeat + 1);
+	x = _prev.x + (dx * fc) / (repeat + 1);
+	y = _prev.y + (dy * fc) / (repeat + 1);
+	z = _prev.z + (dz * fc) / (repeat + 1);
 }
 
 void AnimationTracker::getSpeed(int32 &dx, int32 &dy, int32 &dz) const {
-	dx = _x - _prevX;
-	dy = _y - _prevY;
-	dz = _z - _prevZ;
+	dx = _curr.x - _prev.x;
+	dy = _curr.y - _prev.y;
+	dz = _curr.z - _prev.z;
 }
 
 
@@ -575,12 +567,12 @@ void AnimationTracker::save(Common::WriteStream *ws) {
 		ws->writeUint32LE(0);
 	}
 
-	ws->writeUint32LE(static_cast<uint32>(_prevX));
-	ws->writeUint32LE(static_cast<uint32>(_prevY));
-	ws->writeUint32LE(static_cast<uint32>(_prevZ));
-	ws->writeUint32LE(static_cast<uint32>(_x));
-	ws->writeUint32LE(static_cast<uint32>(_y));
-	ws->writeUint32LE(static_cast<uint32>(_z));
+	ws->writeUint32LE(static_cast<uint32>(_prev.x));
+	ws->writeUint32LE(static_cast<uint32>(_prev.y));
+	ws->writeUint32LE(static_cast<uint32>(_prev.z));
+	ws->writeUint32LE(static_cast<uint32>(_curr.x));
+	ws->writeUint32LE(static_cast<uint32>(_curr.y));
+	ws->writeUint32LE(static_cast<uint32>(_curr.z));
 
 	ws->writeUint16LE(static_cast<uint16>(_mode));
 	if (_mode == TargetMode) {
@@ -623,12 +615,12 @@ bool AnimationTracker::load(Common::ReadStream *rs, uint32 version) {
 		assert(_animAction);
 	}
 
-	_prevX = rs->readUint32LE();
-	_prevY = rs->readUint32LE();
-	_prevZ = rs->readUint32LE();
-	_x = rs->readUint32LE();
-	_y = rs->readUint32LE();
-	_z = rs->readUint32LE();
+	_prev.x = rs->readUint32LE();
+	_prev.y = rs->readUint32LE();
+	_prev.z = rs->readUint32LE();
+	_curr.x = rs->readUint32LE();
+	_curr.y = rs->readUint32LE();
+	_curr.z = rs->readUint32LE();
 
 	_mode = static_cast<Mode>(rs->readUint16LE());
 	if (_mode == TargetMode) {
diff --git a/engines/ultima/ultima8/world/actors/animation_tracker.h b/engines/ultima/ultima8/world/actors/animation_tracker.h
index 688d3985486..d2f508cf02e 100644
--- a/engines/ultima/ultima8/world/actors/animation_tracker.h
+++ b/engines/ultima/ultima8/world/actors/animation_tracker.h
@@ -24,6 +24,7 @@
 
 #include "ultima/ultima8/world/actors/animation.h"
 #include "ultima/ultima8/world/actors/pathfinder.h"
+#include "ultima/ultima8/misc/point3.h"
 
 namespace Ultima {
 namespace Ultima8 {
@@ -65,9 +66,9 @@ public:
 
 	//! get the current position
 	void getPosition(int32 &x, int32 &y, int32 &z) const {
-		x = _x;
-		y = _y;
-		z = _z;
+		x = _curr.x;
+		y = _curr.y;
+		z = _curr.z;
 	}
 
 	void getInterpolatedPosition(int32 &x, int32 &y, int32 &z, int fc)
@@ -126,9 +127,9 @@ private:
 	const AnimAction *_animAction;
 
 	// actor state
-	int32 _prevX, _prevY, _prevZ;
-	int32 _x, _y, _z;
-	int32 _startX, _startY, _startZ;
+	Point3 _prev;
+	Point3 _curr;
+	Point3 _start;
 	int32 _targetDx, _targetDy, _targetDz;
 	int32 _targetOffGroundLeft;
 	bool _firstStep, _flipped;
diff --git a/engines/ultima/ultima8/world/actors/attack_process.cpp b/engines/ultima/ultima8/world/actors/attack_process.cpp
index db8476deea1..718812b770a 100644
--- a/engines/ultima/ultima8/world/actors/attack_process.cpp
+++ b/engines/ultima/ultima8/world/actors/attack_process.cpp
@@ -281,23 +281,20 @@ void AttackProcess::run() {
 		case 0x8e:
 		{
 			// Pathfind to target
-			int32 x, y, z;
-			target->getLocation(x, y, z);
+			Point3 pt = target->getLocation();
 			ProcId pid = Kernel::get_instance()->addProcess(
-					   new CruPathfinderProcess(a, x, y, z, 12, 0x80, true));
+					   new CruPathfinderProcess(a, pt.x, pt.y, pt.z, 12, 0x80, true));
 			waitFor(pid);
 			return;
 		}
 		case 0x8f:
 		{
 			// Pathfind to a point between npc and the target
-			int32 tx, ty, tz;
-			target->getLocation(tx, ty, tz);
-			int32 ax, ay, az;
-			target->getLocation(ax, ay, az);
-			int32 x = (tx + ax) / 2;
-			int32 y = (ty + ay) / 2;
-			int32 z = (tz + az) / 2;
+			Point3 apt = a->getLocation();
+			Point3 tpt = target->getLocation();
+			int32 x = (tpt.x + apt.x) / 2;
+			int32 y = (tpt.y + apt.y) / 2;
+			int32 z = (tpt.z + apt.z) / 2;
 			ProcId pid = Kernel::get_instance()->addProcess(
 					   new CruPathfinderProcess(a, x, y, z, 12, 0x80, true));
 			waitFor(pid);
@@ -354,9 +351,8 @@ void AttackProcess::run() {
 		case 0x9a:
 		{
 			// get next word and jump to that offset if distance < 481
-			Point3 apt, tpt;
-			a->getLocation(apt);
-			target->getLocation(tpt);
+			Point3 apt = a->getLocation();
+			Point3 tpt = target->getLocation();
 			int maxdiff = apt.maxDistXYZ(tpt);
 			int16 data = readNextWordWithData();
 			if (maxdiff < 481) {
@@ -367,9 +363,8 @@ void AttackProcess::run() {
 		case 0x9b:
 		{
 			// get next word and jump to that offset if distance > 160
-			Point3 apt, tpt;
-			a->getLocation(apt);
-			target->getLocation(tpt);
+			Point3 apt = a->getLocation();
+			Point3 tpt = target->getLocation();
 			int maxdiff = apt.maxDistXYZ(tpt);
 			int16 data = readNextWordWithData();
 			if (maxdiff > 160) {
@@ -599,13 +594,12 @@ void AttackProcess::genericAttack() {
 			if (_itemNum == WATCHACTOR)
 				debug("Attack: genericAttack walking around looking for target %d", _target);
 #endif
-			int32 x, y, z;
-			a->getLocation(x, y, z);
-			x += rs.getRandomNumberRngSigned(-0x1ff, 0x1ff);
-			y += rs.getRandomNumberRngSigned(-0x1ff, 0x1ff);
+			Point3 pt = a->getLocation();
+			pt.x += rs.getRandomNumberRngSigned(-0x1ff, 0x1ff);
+			pt.y += rs.getRandomNumberRngSigned(-0x1ff, 0x1ff);
 			_field96 = true;
 			const ProcId pid = Kernel::get_instance()->addProcess(
-								new CruPathfinderProcess(a, x, y, z, 12, 0x80, true));
+								new CruPathfinderProcess(a, pt.x, pt.y, pt.z, 12, 0x80, true));
 			// add a tiny delay to avoid tight loops
 			Process *delayproc = new DelayProcess(2);
 			Kernel::get_instance()->addProcess(delayproc);
@@ -696,9 +690,8 @@ void AttackProcess::genericAttack() {
 			targetdir = a->getDirToItemCentre(*target);
 		}
 
-		Point3 apt, tpt;
-		a->getLocation(apt);
-		target->getLocation(tpt);
+		Point3 apt = a->getLocation();
+		Point3 tpt = target->getLocation();
 		const int32 dist = apt.maxDistXYZ(tpt);
 		const int32 zdiff = abs(a->getZ() - target->getZ());
 		const bool onscreen = a->isPartlyOnScreen(); // note: original uses "isMajorityOnScreen", this is close enough.
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 0ff34f034a2..bec549f9c91 100644
--- a/engines/ultima/ultima8/world/actors/cru_avatar_mover_process.cpp
+++ b/engines/ultima/ultima8/world/actors/cru_avatar_mover_process.cpp
@@ -489,8 +489,7 @@ void CruAvatarMoverProcess::step(Animation::Sequence action, Direction direction
 
 		Direction dir_right = Direction_TurnByDelta(direction, 4, dirmode_16dirs);
 		Direction dir_left = Direction_TurnByDelta(direction, -4, dirmode_16dirs);
-		Point3 origpt;
-		avatar->getLocation(origpt);
+		Point3 origpt = avatar->getLocation();
 
 		int32 dims[3];
 		avatar->getFootpadWorld(dims[0], dims[1], dims[2]);
diff --git a/engines/ultima/ultima8/world/actors/cru_pathfinder_process.cpp b/engines/ultima/ultima8/world/actors/cru_pathfinder_process.cpp
index 257d8f4710f..f08e555ee07 100644
--- a/engines/ultima/ultima8/world/actors/cru_pathfinder_process.cpp
+++ b/engines/ultima/ultima8/world/actors/cru_pathfinder_process.cpp
@@ -42,7 +42,7 @@ DEFINE_RUNTIME_CLASSTYPE_CODE(CruPathfinderProcess)
 
 CruPathfinderProcess::CruPathfinderProcess() : Process(),
 		_currentStep(0), _targetItem(0), _currentDistance(0),
-		_targetX(0), _targetY(0), _targetZ(0), _randomFlag(false),
+		_target(), _randomFlag(false),
 		_nextTurn(false), _turnAtEnd(false), _lastDir(dir_current),
 		_nextDir(dir_current), _nextDir2(dir_current),
 		_solidObject(true), _directPathBlocked(false), _noShotAvailable(true),
@@ -51,7 +51,7 @@ CruPathfinderProcess::CruPathfinderProcess() : Process(),
 }
 
 CruPathfinderProcess::CruPathfinderProcess(Actor *actor, Item *target, int maxsteps, int stopdistance, bool turnatend) :
-		_currentStep(0), _currentDistance(0), _targetX(0), _targetY(0), _targetZ(0),
+		_currentStep(0), _currentDistance(0), _target(),
 		_maxSteps(maxsteps), _stopDistance(stopdistance), _nextTurn(false), _turnAtEnd(turnatend),
 		_lastDir(dir_current), _nextDir(dir_current), _nextDir2(dir_current),
 		_directPathBlocked(false), _noShotAvailable(true), _dir16Flag(false) {
@@ -61,11 +61,10 @@ CruPathfinderProcess::CruPathfinderProcess(Actor *actor, Item *target, int maxst
 	Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
 	_randomFlag = rs.getRandomBit() != 0;
 	_targetItem = target->getObjId();
-	target->getLocation(_targetX, _targetY, _targetZ);
+	_target = target->getLocation();
 
-	int32 ax, ay, az;
-	actor->getLocation(ax, ay, az);
-	_currentDistance = MAX(abs(ax - _targetX), abs(ay - _targetY));
+	Point3 pt = actor->getLocation();
+	_currentDistance = MAX(abs(pt.x - _target.x), abs(pt.y - _target.y));
 
 	const ShapeInfo *si = actor->getShapeInfo();
 	_solidObject = (si->_flags & ShapeInfo::SI_SOLID) && si->_z > 0;
@@ -79,7 +78,7 @@ CruPathfinderProcess::CruPathfinderProcess(Actor *actor, Item *target, int maxst
 }
 
 CruPathfinderProcess::CruPathfinderProcess(Actor *actor, int32 x, int32 y, int32 z, int maxsteps, int stopdistance, bool turnatend) :
-		_targetX(x), _targetY(y), _targetZ(z), _targetItem(0), _currentStep(0),
+		_target(x, y, z), _targetItem(0), _currentStep(0),
 		_maxSteps(maxsteps), _stopDistance(stopdistance), _nextTurn(false), _turnAtEnd(turnatend),
 		_lastDir(dir_current), _nextDir(dir_current), _nextDir2(dir_current),
 		_directPathBlocked(false), _noShotAvailable(true), _dir16Flag(false) {
@@ -89,9 +88,8 @@ CruPathfinderProcess::CruPathfinderProcess(Actor *actor, int32 x, int32 y, int32
 	Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
 	_randomFlag = rs.getRandomBit() != 0;
 
-	int32 ax, ay, az;
-	actor->getLocation(ax, ay, az);
-	_currentDistance = MAX(abs(ax - _targetX), abs(ay - _targetY));
+	Point3 pt = actor->getLocation();
+	_currentDistance = MAX(abs(pt.x - _target.x), abs(pt.y - _target.y));
 
 	const ShapeInfo *si = actor->getShapeInfo();
 	_solidObject = (si->_flags & ShapeInfo::SI_SOLID) && si->_z > 0;
@@ -118,16 +116,14 @@ void CruPathfinderProcess::terminate() {
 		if (_turnAtEnd) {
 			Direction destdir = dir_current;
 			// TODO: this logic can be cleaned up a bit by just updating targetx/y?
-			int32 ix, iy, iz;
-			actor->getLocationAbsolute(ix, iy, iz);
+			Point3 i = actor->getLocationAbsolute();
 			if (_targetItem == 0) {
-				destdir = Direction_GetWorldDir(_targetY - iy, _targetX - ix, dirmode_8dirs);
+				destdir = Direction_GetWorldDir(_target.y - i.y, _target.x - i.x, dirmode_8dirs);
 			} else {
 				const Item *target = getItem(_targetItem);
 				if (target) {
-					int32 tx, ty, tz;
-					target->getLocationAbsolute(tx, ty, tz);
-					destdir = Direction_GetWorldDir(ty - iy, tx - ix, dirmode_8dirs);
+					Point3 t = target->getLocationAbsolute();
+					destdir = Direction_GetWorldDir(t.y - i.y, t.x - i.x, dirmode_8dirs);
 				}
 			}
 			if (destdir != dir_current)
@@ -143,19 +139,17 @@ void CruPathfinderProcess::terminate() {
 }
 
 Direction CruPathfinderProcess::nextDirFromPoint(struct Point3 &npcpt) {
-	const Direction dirtotarget = Direction_GetWorldDir(_targetY - npcpt.y, _targetX - npcpt.x, dirmode_8dirs);
+	const Direction dirtotarget = Direction_GetWorldDir(_target.y - npcpt.y, _target.x - npcpt.x, dirmode_8dirs);
 	Actor *npc = getActor(_itemNum);
 
 	//assert(npc);
 
-	const int maxdiffxy = MAX(abs(npcpt.x - _targetX), abs(npcpt.y - _targetY));
+	const int maxdiffxy = MAX(abs(npcpt.x - _target.x), abs(npcpt.y - _target.y));
 	if (maxdiffxy < _currentDistance) {
 		// each time we get closer, check again if we can walk toward the target.
 		_currentDistance = maxdiffxy;
 		PathfindingState state;
-		state._x = npcpt.x;
-		state._y = npcpt.y;
-		state._z = npcpt.z;
+		state._point = npcpt;
 		state._direction = dirtotarget;
 		state._combat = npc->isInCombat();
 		Animation::Sequence anim = npc->isInCombat() ? Animation::walk : Animation::advanceSmallWeapon;
@@ -216,9 +210,7 @@ Direction CruPathfinderProcess::nextDirFromPoint(struct Point3 &npcpt) {
 
 		// LAB_1110_0c26:
 		Animation::Sequence anim = npc->isInCombat() ? Animation::walk : Animation::advanceSmallWeapon;
-		state._x = npcpt.x;
-		state._y = npcpt.y;
-		state._z = npcpt.z;
+		state._point = npcpt;
 		state._direction = _nextDir2;
 		state._combat = npc->isInCombat();
 		animresult = npc->tryAnim(anim, _nextDir2, 0, &state);
@@ -228,7 +220,7 @@ Direction CruPathfinderProcess::nextDirFromPoint(struct Point3 &npcpt) {
 			return dir_invalid;
 		}
 
-		if (_stopDistance && (MAX(abs(_targetX - state._x), abs(_targetY - state._y)) <= _stopDistance)) {
+		if (_stopDistance && (MAX(abs(_target.x - state._point.x), abs(_target.y - state._point.y)) <= _stopDistance)) {
 			_turnAtEnd = true;
 			return dir_invalid;
 		}
@@ -246,9 +238,7 @@ Direction CruPathfinderProcess::nextDirFromPoint(struct Point3 &npcpt) {
 		_nextTurn = (i % 2);
 	}
 
-	npcpt.x = state._x;
-	npcpt.y = state._y;
-	npcpt.z = state._z;
+	npcpt = state._point;
 	bool is_controlled = World::get_instance()->getControlledNPCNum() == _itemNum;
 	if (npc->isInCombat() && !is_controlled) {
 		AttackProcess *attackproc = dynamic_cast<AttackProcess *>
@@ -287,13 +277,11 @@ void CruPathfinderProcess::run() {
 	if (_targetItem != 0 && _solidObject) {
 		Item *target = getItem(_targetItem);
 		if (target)
-			target->getLocation(_targetX, _targetY, _targetZ);
+			_target = target->getLocation();
 	}
 
-	Point3 npcpt;
-	npc->getLocation(npcpt);
-
-	if (_targetX == npcpt.x && _targetY == npcpt.y) {
+	Point3 npcpt = npc->getLocation();
+	if (_target.x == npcpt.x && _target.y == npcpt.y) {
 		terminate(); // _destpt.z != npcpt.z
 		return;
 	}
@@ -334,9 +322,9 @@ void CruPathfinderProcess::saveData(Common::WriteStream *ws) {
 	Process::saveData(ws);
 
 	ws->writeUint16LE(_targetItem);
-	ws->writeUint16LE(static_cast<uint16>(_targetX));
-	ws->writeUint16LE(static_cast<uint16>(_targetY));
-	ws->writeUint16LE(static_cast<uint16>(_targetZ));
+	ws->writeUint16LE(static_cast<uint16>(_target.x));
+	ws->writeUint16LE(static_cast<uint16>(_target.y));
+	ws->writeUint16LE(static_cast<uint16>(_target.z));
 	ws->writeUint16LE(static_cast<uint16>(_currentDistance));
 	ws->writeByte(_randomFlag ? 1 : 0);
 	ws->writeByte(_nextTurn ? 1 : 0);
@@ -357,9 +345,9 @@ bool CruPathfinderProcess::loadData(Common::ReadStream *rs, uint32 version) {
 	if (!Process::loadData(rs, version)) return false;
 
 	_targetItem = rs->readUint16LE();
-	_targetX = rs->readUint16LE();
-	_targetY = rs->readUint16LE();
-	_targetZ = rs->readUint16LE();
+	_target.x = rs->readUint16LE();
+	_target.y = rs->readUint16LE();
+	_target.z = rs->readUint16LE();
 	_currentDistance = rs->readUint16LE();
 	_randomFlag = rs->readByte();
 	_nextTurn = rs->readByte();
diff --git a/engines/ultima/ultima8/world/actors/cru_pathfinder_process.h b/engines/ultima/ultima8/world/actors/cru_pathfinder_process.h
index 883645f9570..068727489a3 100644
--- a/engines/ultima/ultima8/world/actors/cru_pathfinder_process.h
+++ b/engines/ultima/ultima8/world/actors/cru_pathfinder_process.h
@@ -24,6 +24,7 @@
 
 #include "ultima/ultima8/kernel/process.h"
 #include "ultima/ultima8/misc/direction.h"
+#include "ultima/ultima8/misc/point3.h"
 
 namespace Ultima {
 namespace Ultima8 {
@@ -56,7 +57,7 @@ private:
 
 	Direction nextDirFromPoint(struct Point3 &npcpt);
 
-	int32 _targetX, _targetY, _targetZ;
+	Point3 _target;
 	ObjId _targetItem;
 	int _currentDistance;
 	bool _randomFlag;
diff --git a/engines/ultima/ultima8/world/actors/grant_peace_process.cpp b/engines/ultima/ultima8/world/actors/grant_peace_process.cpp
index b5a3e9e81ba..9d31a740995 100644
--- a/engines/ultima/ultima8/world/actors/grant_peace_process.cpp
+++ b/engines/ultima/ultima8/world/actors/grant_peace_process.cpp
@@ -115,11 +115,10 @@ void GrantPeaceProcess::run() {
 				hit = true;
 
 				if (t->getShape() == 411 && khumash) { // CONSTANT!
-					int32 tx, ty, tz;
-					t->getLocation(tx, ty, tz);
+					Point3 pt = t->getLocation();
 
 					// CONSTANT! (shape 480, frame 0-9, repeat 1, delay 1)
-					Process *sp = new SpriteProcess(480, 0, 9, 1, 1, tx, ty, tz);
+					Process *sp = new SpriteProcess(480, 0, 9, 1, 1, pt.x, pt.y, pt.z);
 					Kernel::get_instance()->addProcess(sp);
 
 					Item *throne = getItem(KGlist.getuint16(0));
diff --git a/engines/ultima/ultima8/world/actors/loiter_process.cpp b/engines/ultima/ultima8/world/actors/loiter_process.cpp
index d79d2fb0364..23a51ea25a6 100644
--- a/engines/ultima/ultima8/world/actors/loiter_process.cpp
+++ b/engines/ultima/ultima8/world/actors/loiter_process.cpp
@@ -70,19 +70,18 @@ void LoiterProcess::run() {
 		return;
 	}
 
-	int32 x, y, z;
-	a->getLocation(x, y, z);
+	Point3 pt = a->getLocation();
 
 	Common::RandomSource &rs = Ultima8Engine::get_instance()->getRandomSource();
 
-	x += 32 * rs.getRandomNumberRngSigned(-10, 10);
-	y += 32 * rs.getRandomNumberRngSigned(-10, 10);
+	pt.x += 32 * rs.getRandomNumberRngSigned(-10, 10);
+	pt.y += 32 * rs.getRandomNumberRngSigned(-10, 10);
 
 	Process *pfp;
 	if (GAME_IS_U8)
-		pfp = new PathfinderProcess(a, x, y, z);
+		pfp = new PathfinderProcess(a, pt.x, pt.y, pt.z);
 	else
-		pfp = new CruPathfinderProcess(a, x, y, z, 0xc, 0x80, false);
+		pfp = new CruPathfinderProcess(a, pt.x, pt.y, pt.z, 0xc, 0x80, false);
 
 	Kernel::get_instance()->addProcess(pfp);
 
diff --git a/engines/ultima/ultima8/world/actors/main_actor.cpp b/engines/ultima/ultima8/world/actors/main_actor.cpp
index 28fcce91720..debb5c52955 100644
--- a/engines/ultima/ultima8/world/actors/main_actor.cpp
+++ b/engines/ultima/ultima8/world/actors/main_actor.cpp
@@ -135,8 +135,7 @@ int16 MainActor::addItemCru(Item *item, bool showtoast) {
 		return 0;
 
 	int shapeno = item->getShape();
-	int32 x, y, z;
-	getLocation(x, y, z);
+	Point3 pt = getLocation();
 
 	CruPickupAreaGump *pickupArea = CruPickupAreaGump::get_instance();
 	assert(pickupArea);
@@ -177,7 +176,7 @@ int16 MainActor::addItemCru(Item *item, bool showtoast) {
 			} else {
 				item->setQuality(winfo->_clipSize);
 			}
-			item->setLocation(x, y, z);
+			item->setLocation(pt.x, pt.y, pt.z);
 			item->moveToContainer(this);
 			if (!_activeWeapon)
 				_activeWeapon = item->getObjId();
@@ -391,8 +390,7 @@ void MainActor::teleport(int mapNum, int32 x, int32 y, int32 z) {
 // all running processes
 void MainActor::teleport(int mapNum, int teleport_id) {
 	int oldmap = getMapNum();
-	int32 oldx, oldy, oldz;
-	getLocation(oldx, oldy, oldz);
+	Point3 old = getLocation();
 
 	World *world = World::get_instance();
 	CurrentMap *currentmap = world->getCurrentMap();
@@ -412,23 +410,22 @@ void MainActor::teleport(int mapNum, int teleport_id) {
 	TeleportEgg *egg = currentmap->findDestination(teleport_id);
 	if (!egg) {
 		warning("MainActor::teleport(): destination egg not found");
-		teleport(oldmap, oldx, oldy, oldz);
+		teleport(oldmap, old.x, old.y, old.z);
 		return;
 	}
-	int32 xv, yv, zv;
-	egg->getLocation(xv, yv, zv);
+	Point3 pt = egg->getLocation();
 
-	debugC(kDebugActor, "Found destination: %d, %d, %d", xv, yv, zv);
+	debugC(kDebugActor, "Found destination: %d, %d, %d", pt.x, pt.y, pt.z);
 	debugC(kDebugActor, "%s", egg->dumpInfo().c_str());
 
 	if (GAME_IS_CRUSADER) {
 		// Keep the camera on the avatar (the snap process will update on next move)
 		// We don't add a new camera process here, as that would update the fast area
 		// before the cachein calls above have run.
-		CameraProcess::GetCameraProcess()->moveToLocation(xv, yv, zv);
+		CameraProcess::GetCameraProcess()->moveToLocation(pt.x, pt.y, pt.z);
 	}
 
-	Actor::teleport(mapNum, xv, yv, zv);
+	Actor::teleport(mapNum, pt.x, pt.y, pt.z);
 
 	_justTeleported = true;
 }
@@ -1025,7 +1022,7 @@ int MainActor::receiveShieldHit(int damage, uint16 damage_type) {
 			uint16 shieldstartframe;
 			uint16 shieldendframe;
 			bool remembersprite;
-			int32 x, y, z;
+			Point3 pt;
 
 			switch (shieldtype) {
 			case 1:
@@ -1035,27 +1032,27 @@ int MainActor::receiveShieldHit(int damage, uint16 damage_type) {
 				remembersprite = false;
 				// NOTE: In the game, this is put in the location of the
 				// hit.  For now just put in centre.
-				getCentre(x, y, z);
+				getCentre(pt.x, pt.y, pt.z);
 				break;
 			case 2:
 				shieldsprite = 0x5a9;
 				shieldstartframe = 0;
 				shieldendframe = 6;
 				remembersprite = false;
-				getCentre(x, y, z);
+				getCentre(pt.x, pt.y, pt.z);
 				break;
 			default:
 				shieldsprite = 0x52b;
 				shieldstartframe = 0;
 				shieldendframe = 8;
-				getLocation(x, y, z);
-				x += 0x10;
-				y += 0x18;
+				pt = getLocation();
+				pt.x += 0x10;
+				pt.y += 0x18;
 				remembersprite = true;
 				break;
 			}
 			Process *p = new SpriteProcess(shieldsprite, shieldstartframe,
-										   shieldendframe, 1, 4, x, y, z);
+										   shieldendframe, 1, 4, pt.x, pt.y, pt.z);
 			kernel->addProcess(p);
 			if (remembersprite) {
 				_shieldSpriteProc = p->getPid();
diff --git a/engines/ultima/ultima8/world/actors/pathfinder.cpp b/engines/ultima/ultima8/world/actors/pathfinder.cpp
index 15006e49f7d..2874db37aa2 100644
--- a/engines/ultima/ultima8/world/actors/pathfinder.cpp
+++ b/engines/ultima/ultima8/world/actors/pathfinder.cpp
@@ -51,7 +51,7 @@ struct PathNode {
 static unsigned int expandednodes = 0;
 
 void PathfindingState::load(const Actor *_actor) {
-	_actor->getLocation(_x, _y, _z);
+	_point = _actor->getLocation();
 	_lastAnim = _actor->getLastAnim();
 	_direction = _actor->getDir();
 	_firstStep = _actor->hasActorFlags(Actor::ACT_FIRSTSTEP);
@@ -61,32 +61,31 @@ void PathfindingState::load(const Actor *_actor) {
 
 bool PathfindingState::checkPoint(int32 x, int32 y, int32 z,
 								  int sqr_range) const {
-	int distance = (_x - x) * (_x - x) + (_y - y) * (_y - y) + (_z - z) * (_z - z);
+	int distance = (_point.x - x) * (_point.x - x) + (_point.y - y) * (_point.y - y) + (_point.z - z) * (_point.z - z);
 	return distance < sqr_range;
 }
 
 bool PathfindingState::checkItem(const Item *item, int xyRange, int zRange) const {
-	int32 itemX, itemY, itemZ;
 	int32 itemXd, itemYd, itemZd;
 	int32 itemXmin, itemYmin;
 
-	item->getLocationAbsolute(itemX, itemY, itemZ);
+	Point3 pt = item->getLocationAbsolute();
 	item->getFootpadWorld(itemXd, itemYd, itemZd);
 
-	itemXmin = itemX - itemXd;
-	itemYmin = itemY - itemYd;
+	itemXmin = pt.x - itemXd;
+	itemYmin = pt.y - itemYd;
 
 	int range = 0;
-	if (_x - itemX > range)
-		range = _x - itemX;
-	if (itemXmin - _x > range)
-		range = itemXmin - _x;
-	if (_y - itemY > range)
-		range = _y - itemY;
-	if (itemYmin - _y > range)
-		range = itemYmin - _y;
+	if (_point.x - pt.x > range)
+		range = _point.x - pt.x;
+	if (itemXmin - _point.x > range)
+		range = itemXmin - _point.x;
+	if (_point.y - pt.y > range)
+		range = _point.y - pt.y;
+	if (itemYmin - _point.y > range)
+		range = itemYmin - _point.y;
 
-	// FIXME: check _z properly
+	// FIXME: check _point.z properly
 
 	return (range <= xyRange);
 }
@@ -115,8 +114,8 @@ bool PathNodeCmp::operator()(const PathNode *n1, const PathNode *n2) const {
 }
 
 Pathfinder::Pathfinder() : _actor(nullptr), _targetItem(nullptr),
-		_hitMode(false), _expandTime(0), _targetX(0), _targetY(0),
-		_targetZ(0), _actorXd(0), _actorYd(0), _actorZd(0) {
+		_hitMode(false), _expandTime(0), _target(),
+		_actorXd(0), _actorYd(0), _actorZd(0) {
 	expandednodes = 0;
 	_visited.reserve(1500);
 }
@@ -144,9 +143,9 @@ void Pathfinder::init(Actor *actor, PathfindingState *state) {
 }
 
 void Pathfinder::setTarget(int32 x, int32 y, int32 z) {
-	_targetX = x;
-	_targetY = y;
-	_targetZ = z;
+	_target.x = x;
+	_target.y = y;
+	_target.z = z;
 	_targetItem = 0;
 	_hitMode = false;
 }
@@ -156,8 +155,8 @@ void Pathfinder::setTarget(Item *item, bool hit) {
 	_targetItem = root ? root : item;
 
 	// set target to centre of item for the cost heuristic
-	item->getCentre(_targetX, _targetY, _targetZ);
-	_targetZ = item->getZ();
+	item->getCentre(_target.x, _target.y, _target.z);
+	_target.z = item->getZ();
 
 	if (hit) {
 		assert(_start._combat);
@@ -201,7 +200,7 @@ bool Pathfinder::checkTarget(const PathNode *node) const {
 			return node->state.checkItem(_targetItem, 32, 8);
 		}
 	} else {
-		return node->state.checkPoint(_targetX, _targetY, _targetZ, 48*48);
+		return node->state.checkPoint(_target.x, _target.y, _target.z, 48*48);
 	}
 }
 
@@ -211,17 +210,17 @@ unsigned int Pathfinder::costHeuristic(PathNode *node) const {
 #if 0
 	double sqrddist;
 
-	sqrddist = (_targetX - node->state._x + _actorXd / 2) *
-	           (_targetX - node->state._x + _actorXd / 2);
-	sqrddist += (_targetY - node->state._y + _actorYd / 2) *
-	            (_targetY - node->state._y + _actorYd / 2);
+	sqrddist = (_target.x - node->state._point.x + _actorXd / 2) *
+	           (_target.x - node->state._point.x + _actorXd / 2);
+	sqrddist += (_target.y - node->state._point.y + _actorYd / 2) *
+	            (_target.y - node->state._point.y + _actorYd / 2);
 
 	unsigned int dist = static_cast<unsigned int>(sqrt(sqrddist));
 #else
 	// This calculates the distance to the target using only lines in
 	// the 8 available directions (instead of the straight line above)
-	int xd = ABS(_targetX - node->state._x + _actorXd / 2);
-	int yd = ABS(_targetY - node->state._y + _actorYd / 2);
+	int xd = ABS(_target.x - node->state._point.x + _actorXd / 2);
+	int yd = ABS(_target.y - node->state._point.y + _actorYd / 2);
 	double m = (xd < yd) ? xd : yd;
 	unsigned int dist = ABS(xd - yd) + static_cast<unsigned int>(m * 1.41421356);
 
@@ -308,18 +307,18 @@ static void drawedge(Graphics::ManagedSurface *screen, const PathNode *from, con
 
 	int32 x0, y0, x1, y1;
 
-	cx = from->state._x - cx;
-	cy = from->state._y - cy;
-	cz = from->state._z - cz;
+	cx = from->state._point.x - cx;
+	cy = from->state._point.y - cy;
+	cz = from->state._point.z - cz;
 
 	x0 = (d.width() / 2) + (cx - cy) / 4;
 	y0 = (d.height() / 2) + (cx + cy) / 8 - cz;
 
 	Ultima8Engine::get_instance()->getGameMapGump()->GetCameraLocation(cx, cy, cz);
 
-	cx = to->state._x - cx;
-	cy = to->state._y - cy;
-	cz = to->state._z - cz;
+	cx = to->state._point.x - cx;
+	cy = to->state._point.y - cy;
+	cz = to->state._point.z - cz;
 
 	x1 = (d.width() / 2) + (cx - cy) / 4;
 	y1 = (d.height() / 2) + (cx + cy) / 8 - cz;
@@ -337,12 +336,12 @@ static void drawpath(Graphics::ManagedSurface *screen, PathNode *to, uint32 rgb,
 		drawedge(screen, n1, n2, rgb);
 
 		if (done && n1 == to)
-			drawdot(screen, n1->state._x, n1->state._y, n1->state._z, 2, color1);
+			drawdot(screen, n1->state._point.x, n1->state._point.y, n1->state._point.z, 2, color1);
 		else
-			drawdot(screen, n1->state._x, n1->state._y, n1->state._z, 1, color2);
+			drawdot(screen, n1->state._point.x, n1->state._point.y, n1->state._point.z, 1, color2);
 
 
-		drawdot(screen, n2->state._x, n2->state._y, n2->state._z, 2, color2);
+		drawdot(screen, n2->state._point.x, n2->state._point.y, n2->state._point.z, 2, color2);
 
 		n1 = n2;
 		n2 = n1->parent;
@@ -361,12 +360,12 @@ void Pathfinder::newNode(PathNode *oldnode, PathfindingState &state,
 
 	double sqrddist;
 
-	sqrddist = ((newnode->state._x - oldnode->state._x) *
-	            (newnode->state._x - oldnode->state._x));
-	sqrddist += ((newnode->state._y - oldnode->state._y) *
-	             (newnode->state._y - oldnode->state._y));
-	sqrddist += ((newnode->state._z - oldnode->state._z) *
-	             (newnode->state._z - oldnode->state._z));
+	sqrddist = ((newnode->state._point.x - oldnode->state._point.x) *
+	            (newnode->state._point.x - oldnode->state._point.x));
+	sqrddist += ((newnode->state._point.y - oldnode->state._point.y) *
+	             (newnode->state._point.y - oldnode->state._point.y));
+	sqrddist += ((newnode->state._point.z - oldnode->state._point.z) *
+	             (newnode->state._point.z - oldnode->state._point.z));
 
 	unsigned int dist;
 	dist = static_cast<unsigned int>(sqrt(sqrddist));
@@ -389,7 +388,7 @@ void Pathfinder::newNode(PathNode *oldnode, PathfindingState &state,
 
 	debugC(kDebugPath, "Trying dir %d, steps %d from (%d, %d) to (%d, %d), cost %d, heurtotcost %d",
 		   state._direction, steps,
-		   oldnode->state._x, oldnode->state._y, newnode->state._x, newnode->state._y,
+		   oldnode->state._point.x, oldnode->state._point.y, newnode->state._point.x, newnode->state._point.y,
 		   newnode->cost, newnode->heuristicTotalCost);
 
 #ifdef DEBUG_PATHFINDER
@@ -433,37 +432,37 @@ void Pathfinder::expandNode(PathNode *node) {
 		// determine how far the _actor will travel if the animation runs to completion
 		int32 max_endx, max_endy;
 		tracker.evaluateMaxAnimTravel(max_endx, max_endy, dir);
-		if (alreadyVisited(max_endx, max_endy, state._z)) continue;
+		if (alreadyVisited(max_endx, max_endy, state._point.z)) continue;
 
-		const int x_travel = ABS(max_endx - state._x);
-		const int y_travel = ABS(max_endy - state._y);
+		const int x_travel = ABS(max_endx - state._point.x);
+		const int y_travel = ABS(max_endy - state._point.y);
 		const int xy_maxtravel = MAX(x_travel, y_travel);
 
 		int sqrddist = x_travel * x_travel + y_travel * y_travel;
 		if (sqrddist > 400) {
 			// range is greater than 20; see if a node has been visited at range 10
-			if (alreadyVisited(state._x + x_travel * 10 / xy_maxtravel,
-			                   state._y + y_travel * 10 / xy_maxtravel,
-			                   state._z)) {
+			if (alreadyVisited(state._point.x + x_travel * 10 / xy_maxtravel,
+			                   state._point.y + y_travel * 10 / xy_maxtravel,
+			                   state._point.z)) {
 				continue;
 			}
 		}
 
 		uint32 steps = 0, beststeps = 0;
 		int bestsqdist;
-		bestsqdist = (_targetX - node->state._x + _actorXd / 2) *
-					 (_targetX - node->state._x + _actorXd / 2);
-		bestsqdist += (_targetY - node->state._y + _actorYd / 2) *
-					  (_targetY - node->state._y + _actorYd / 2);
+		bestsqdist = (_target.x - node->state._point.x + _actorXd / 2) *
+					 (_target.x - node->state._point.x + _actorXd / 2);
+		bestsqdist += (_target.y - node->state._point.y + _actorYd / 2) *
+					  (_target.y - node->state._point.y + _actorYd / 2);
 
 		while (tracker.step()) {
 			steps++;
 			tracker.updateState(state);
 
-			sqrddist = (_targetX - state._x + _actorXd / 2) *
-			           (_targetX - state._x + _actorXd / 2);
-			sqrddist += (_targetY - state._y + _actorYd / 2) *
-			            (_targetY - state._y + _actorYd / 2);
+			sqrddist = (_target.x - state._point.x + _actorXd / 2) *
+			           (_target.x - state._point.x + _actorXd / 2);
+			sqrddist += (_target.y - state._point.y + _actorYd / 2) *
+			            (_target.y - state._point.y + _actorYd / 2);
 
 			if (sqrddist < bestsqdist) {
 				bestsqdist = sqrddist;
@@ -474,7 +473,7 @@ void Pathfinder::expandNode(PathNode *node) {
 
 		if (tracker.isDone()) {
 			tracker.updateState(state);
-			if (!alreadyVisited(state._x, state._y, state._z)) {
+			if (!alreadyVisited(state._point.x, state._point.y, state._point.z)) {
 				newNode(node, state, 0);
 				_visited.push_back(state);
 			}
@@ -498,7 +497,7 @@ bool Pathfinder::pathfind(Std::vector<PathfindingAction> &path) {
 		debugC(kDebugPath, "Actor %u pathfinding to item %u", _actor->getObjId(), _targetItem->getObjId());
 		debugC(kDebugPath, "Target Item: %s", _targetItem->dumpInfo().c_str());
 	} else {
-		debugC(kDebugPath, "Actor %u pathfinding to (%d, %d, %d)", _actor->getObjId(), _targetX, _targetY, _targetZ);
+		debugC(kDebugPath, "Actor %u pathfinding to (%d, %d, %d)", _actor->getObjId(), _target.x, _target.y, _target.z);
 	}
 
 #ifdef DEBUG_PATHFINDER
@@ -538,8 +537,8 @@ bool Pathfinder::pathfind(Std::vector<PathfindingAction> &path) {
 		_nodes.pop();
 
 		debugC(kDebugPath, "Trying node: (%d, %d, %d) target=(%d, %d, %d)",
-			node->state._x, node->state._y, node->state._z,
-			_targetX, _targetY, _targetZ);
+			node->state._point.x, node->state._point.y, node->state._point.z,
+			_target.x, _target.y, _target.z);
 
 		if (checkTarget(node)) {
 			// done!
diff --git a/engines/ultima/ultima8/world/actors/pathfinder.h b/engines/ultima/ultima8/world/actors/pathfinder.h
index 2021b6f51c2..25f6c0593d0 100644
--- a/engines/ultima/ultima8/world/actors/pathfinder.h
+++ b/engines/ultima/ultima8/world/actors/pathfinder.h
@@ -24,6 +24,7 @@
 
 #include "ultima/shared/std/containers.h"
 #include "ultima/ultima8/misc/direction.h"
+#include "ultima/ultima8/misc/point3.h"
 #include "ultima/ultima8/world/actors/animation.h"
 
 //#define DEBUG_PATHFINDER
@@ -35,10 +36,10 @@ class Actor;
 class Item;
 
 struct PathfindingState {
-	PathfindingState() : _x(0), _y(0), _z(0),  _direction(dir_north),
+	PathfindingState() : _point(), _direction(dir_north),
 		_lastAnim(Animation::walk), _flipped(false),
 		_firstStep(true), _combat(false) {};
-	int32 _x, _y, _z;
+	Point3 _point;
 	Animation::Sequence _lastAnim;
 	Direction _direction;
 	bool _flipped;
@@ -87,7 +88,7 @@ public:
 protected:
 	PathfindingState _start;
 	Actor *_actor;
-	int32 _targetX, _targetY, _targetZ;
+	Point3 _target;
 	Item *_targetItem;
 	bool _hitMode;
 	int32 _expandTime;
diff --git a/engines/ultima/ultima8/world/actors/pathfinder_process.cpp b/engines/ultima/ultima8/world/actors/pathfinder_process.cpp
index 7dbe2e0a831..cf48b1cb816 100644
--- a/engines/ultima/ultima8/world/actors/pathfinder_process.cpp
+++ b/engines/ultima/ultima8/world/actors/pathfinder_process.cpp
@@ -37,12 +37,12 @@ DEFINE_RUNTIME_CLASSTYPE_CODE(PathfinderProcess)
 
 PathfinderProcess::PathfinderProcess() : Process(),
 		_currentStep(0), _targetItem(0), _hitMode(false),
-		_targetX(0), _targetY(0), _targetZ(0) {
+		_target() {
 }
 
 PathfinderProcess::PathfinderProcess(Actor *actor, ObjId itemid, bool hit) :
 		_currentStep(0), _targetItem(itemid), _hitMode(hit),
-		_targetX(0), _targetY(0), _targetZ(0) {
+		_target() {
 	assert(actor);
 	_itemNum = actor->getObjId();
 	_type = PATHFINDER_PROC_TYPE;
@@ -58,7 +58,7 @@ PathfinderProcess::PathfinderProcess(Actor *actor, ObjId itemid, bool hit) :
 
 	assert(_targetItem);
 
-	item->getLocation(_targetX, _targetY, _targetZ);
+	_target = item->getLocation();
 
 	Pathfinder pf;
 	pf.init(actor);
@@ -79,7 +79,7 @@ PathfinderProcess::PathfinderProcess(Actor *actor, ObjId itemid, bool hit) :
 }
 
 PathfinderProcess::PathfinderProcess(Actor *actor, int32 x, int32 y, int32 z) :
-		_targetX(x), _targetY(y), _targetZ(z), _targetItem(0), _currentStep(0),
+		_target(x, y, z), _targetItem(0), _currentStep(0),
 		_hitMode(false) {
 	assert(actor);
 	_itemNum = actor->getObjId();
@@ -87,7 +87,7 @@ PathfinderProcess::PathfinderProcess(Actor *actor, int32 x, int32 y, int32 z) :
 
 	Pathfinder pf;
 	pf.init(actor);
-	pf.setTarget(_targetX, _targetY, _targetZ);
+	pf.setTarget(_target.x, _target.y, _target.z);
 
 	bool ok = pf.pathfind(_path);
 
@@ -127,7 +127,6 @@ void PathfinderProcess::run() {
 	bool ok = true;
 
 	if (_targetItem) {
-		int32 curx, cury, curz;
 		Item *item = getItem(_targetItem);
 		if (!item) {
 			warning("PathfinderProcess: target missing");
@@ -136,9 +135,9 @@ void PathfinderProcess::run() {
 			return;
 		}
 
-		item->getLocation(curx, cury, curz);
-		if (ABS(curx - _targetX) >= 32 || ABS(cury - _targetY) >= 32 ||
-		        ABS(curz - _targetZ) >= 8) {
+		Point3 cur = item->getLocation();
+		if (ABS(cur.x - _target.x) >= 32 || ABS(cur.y - _target.y) >= 32 ||
+		        ABS(cur.z - _target.z) >= 8) {
 			// target moved
 			ok = false;
 		}
@@ -187,10 +186,10 @@ void PathfinderProcess::run() {
 					_hitMode = false;
 				}
 				pf.setTarget(item, _hitMode);
-				item->getLocation(_targetX, _targetY, _targetZ);
+				_target = item->getLocation();
 			}
 		} else {
-			pf.setTarget(_targetX, _targetY, _targetZ);
+			pf.setTarget(_target.x, _target.y, _target.z);
 		}
 		if (ok)
 			ok = pf.pathfind(_path);
@@ -229,9 +228,9 @@ void PathfinderProcess::saveData(Common::WriteStream *ws) {
 	Process::saveData(ws);
 
 	ws->writeUint16LE(_targetItem);
-	ws->writeUint16LE(static_cast<uint16>(_targetX));
-	ws->writeUint16LE(static_cast<uint16>(_targetY));
-	ws->writeUint16LE(static_cast<uint16>(_targetZ));
+	ws->writeUint16LE(static_cast<uint16>(_target.x));
+	ws->writeUint16LE(static_cast<uint16>(_target.y));
+	ws->writeUint16LE(static_cast<uint16>(_target.z));
 	ws->writeByte(_hitMode ? 1 : 0);
 	ws->writeUint16LE(static_cast<uint16>(_currentStep));
 
@@ -251,9 +250,9 @@ bool PathfinderProcess::loadData(Common::ReadStream *rs, uint32 version) {
 	}
 
 	_targetItem = rs->readUint16LE();
-	_targetX = rs->readUint16LE();
-	_targetY = rs->readUint16LE();
-	_targetZ = rs->readUint16LE();
+	_target.x = rs->readUint16LE();
+	_target.y = rs->readUint16LE();
+	_target.z = rs->readUint16LE();
 	_hitMode = (rs->readByte() != 0);
 	_currentStep = rs->readUint16LE();
 
diff --git a/engines/ultima/ultima8/world/actors/pathfinder_process.h b/engines/ultima/ultima8/world/actors/pathfinder_process.h
index e7878e01550..46377c3299e 100644
--- a/engines/ultima/ultima8/world/actors/pathfinder_process.h
+++ b/engines/ultima/ultima8/world/actors/pathfinder_process.h
@@ -25,6 +25,7 @@
 #include "ultima/ultima8/kernel/process.h"
 
 #include "ultima/ultima8/world/actors/pathfinder.h"
+#include "ultima/ultima8/misc/point3.h"
 
 namespace Ultima {
 namespace Ultima8 {
@@ -47,7 +48,7 @@ public:
 	void saveData(Common::WriteStream *ws) override;
 
 protected:
-	int32 _targetX, _targetY, _targetZ;
+	Point3 _target;
 	ObjId _targetItem;
 	bool _hitMode;
 
diff --git a/engines/ultima/ultima8/world/actors/quick_avatar_mover_process.cpp b/engines/ultima/ultima8/world/actors/quick_avatar_mover_process.cpp
index 25408aac61a..9ddec105314 100644
--- a/engines/ultima/ultima8/world/actors/quick_avatar_mover_process.cpp
+++ b/engines/ultima/ultima8/world/actors/quick_avatar_mover_process.cpp
@@ -88,8 +88,7 @@ void QuickAvatarMoverProcess::run() {
 	}
 
 	MainActor *avatar = getMainActor();
-	int32 x, y, z;
-	avatar->getLocation(x, y, z);
+	Point3 pt = avatar->getLocation();
 	int32 ixd, iyd, izd;
 	avatar->getFootpadWorld(ixd, iyd, izd);
 
@@ -121,28 +120,28 @@ void QuickAvatarMoverProcess::run() {
 			while (dxv || dyv || dzv) {
 				uint32 shapeFlags = avatar->getShapeInfo()->_flags;
 
-				Box start(x, y, z, ixd, iyd, izd);
-				PositionInfo info = cm->getPositionInfo(Box(x + dxv, y + dyv, z + dzv, ixd, iyd, izd), start, shapeFlags, 1);
+				Box start(pt.x, pt.y, pt.z, ixd, iyd, izd);
+				PositionInfo info = cm->getPositionInfo(Box(pt.x + dxv, pt.y + dyv, pt.z + dzv, ixd, iyd, izd), start, shapeFlags, 1);
 				if (info.valid) {
 					if (!dzv && !info.supported) {
 						// Adjust to stay on ground
-						if (cm->getPositionInfo(Box(x + dxv, y + dyv, z - 8, ixd, iyd, izd), start, shapeFlags, 1).valid &&
-							!cm->getPositionInfo(Box(x, y, z - 8, ixd, iyd, izd), start, shapeFlags, 1).valid) {
+						if (cm->getPositionInfo(Box(pt.x + dxv, pt.y + dyv, pt.z - 8, ixd, iyd, izd), start, shapeFlags, 1).valid &&
+							!cm->getPositionInfo(Box(pt.x, pt.y, pt.z - 8, ixd, iyd, izd), start, shapeFlags, 1).valid) {
 							dzv = -8;
-						} else if (cm->getPositionInfo(Box(x + dxv, y + dyv, z - 16, ixd, iyd, izd), start, shapeFlags, 1).valid &&
-								   !cm->getPositionInfo(Box(x, y, z - 16, ixd, iyd, izd), start, shapeFlags, 1).valid) {
+						} else if (cm->getPositionInfo(Box(pt.x + dxv, pt.y + dyv, pt.z - 16, ixd, iyd, izd), start, shapeFlags, 1).valid &&
+								   !cm->getPositionInfo(Box(pt.x, pt.y, pt.z - 16, ixd, iyd, izd), start, shapeFlags, 1).valid) {
 							dzv = -16;
-						} else if (cm->getPositionInfo(Box(x + dxv, y + dyv, z - 24, ixd, iyd, izd), start, shapeFlags, 1).valid &&
-								   !cm->getPositionInfo(Box(x, y, z - 24, ixd, iyd, izd), start, shapeFlags, 1).valid) {
+						} else if (cm->getPositionInfo(Box(pt.x + dxv, pt.y + dyv, pt.z - 24, ixd, iyd, izd), start, shapeFlags, 1).valid &&
+								   !cm->getPositionInfo(Box(pt.x, pt.y, pt.z - 24, ixd, iyd, izd), start, shapeFlags, 1).valid) {
 							dzv = -24;
-						} else if (cm->getPositionInfo(Box(x + dxv, y + dyv, z - 32, ixd, iyd, izd), start, shapeFlags, 1).valid &&
-								   !cm->getPositionInfo(Box(x, y, z - 32, ixd, iyd, izd), start, shapeFlags, 1).valid) {
+						} else if (cm->getPositionInfo(Box(pt.x + dxv, pt.y + dyv, pt.z - 32, ixd, iyd, izd), start, shapeFlags, 1).valid &&
+								   !cm->getPositionInfo(Box(pt.x, pt.y, pt.z - 32, ixd, iyd, izd), start, shapeFlags, 1).valid) {
 							dzv = -32;
 						}
 					}
 					ok = true;
 					break;
-				} else if (cm->getPositionInfo(Box(x + dxv, y + dyv, z + dzv + 8, ixd, iyd, izd), start, shapeFlags, 1).valid) {
+				} else if (cm->getPositionInfo(Box(pt.x + dxv, pt.y + dyv, pt.z + dzv + 8, ixd, iyd, izd), start, shapeFlags, 1).valid) {
 					dzv += 8;
 					ok = true;
 					break;
@@ -158,11 +157,11 @@ void QuickAvatarMoverProcess::run() {
 	}
 
 	// Yes, i know, not entirely correct
-	avatar->collideMove(x + dxv, y + dyv, z + dzv, false, true);
+	avatar->collideMove(pt.x + dxv, pt.y + dyv, pt.z + dzv, false, true);
 
 	if (GAME_IS_CRUSADER) {
 		// Keep the camera on the avatar while we're quick-moving.
-		CameraProcess::SetCameraProcess(new CameraProcess(x + dxv, y + dyv, z + dzv));
+		CameraProcess::SetCameraProcess(new CameraProcess(pt.x + dxv, pt.y + dyv, pt.z + dzv));
 	}
 
 	// Prevent avatar from running an idle animation while moving around
diff --git a/engines/ultima/ultima8/world/actors/rolling_thunder_process.cpp b/engines/ultima/ultima8/world/actors/rolling_thunder_process.cpp
index db65f2b65a5..64b12f53485 100644
--- a/engines/ultima/ultima8/world/actors/rolling_thunder_process.cpp
+++ b/engines/ultima/ultima8/world/actors/rolling_thunder_process.cpp
@@ -110,10 +110,9 @@ void RollingThunderProcess::run() {
 	}
 
 	if (!canroll) {
-		int32 x, y, z, tx, ty, tz;
-		actor->getLocation(x, y, z);
-		target->getLocation(tx, ty, tz);
-		Direction dirtotarget = Direction_GetWorldDir(ty - y, tx - x, dirmode_16dirs);
+		Point3 pta = actor->getLocation();
+		Point3 ptt = target->getLocation();
+		Direction dirtotarget = Direction_GetWorldDir(ptt.y - pta.y, ptt.x - pta.x, dirmode_16dirs);
 
 		if (dirtotarget == actordir) {
 			uint32 now = Kernel::get_instance()->getTickNum();
@@ -169,9 +168,8 @@ bool RollingThunderProcess::checkDir(Animation::Sequence anim, Direction &outdir
 		return false;
 
 	// check if the dir to the target is within 2 direction steps of the current dir
-	int32 tx, ty, tz;
-	target->getLocation(tx, ty, tz);
-	Direction dirtotarget = Direction_GetWorldDir(ty - state._y, tx - state._x, dirmode_16dirs);
+	Point3 pt = target->getLocation();
+	Direction dirtotarget = Direction_GetWorldDir(pt.y - state._point.y, pt.x - state._point.x, dirmode_16dirs);
 
 	static const int DIROFFSETS[] = {0, -1, 1, -2, 2};
 
@@ -192,7 +190,7 @@ bool RollingThunderProcess::checkDir(Animation::Sequence anim, Direction &outdir
 	// Check whether we can fire in that direction and hit the target
 	for (int i = 0; i < ARRAYSIZE(DIROFFSETS); i++) {
 		Direction dir = Direction_TurnByDelta(dirtotarget, DIROFFSETS[i], dirmode_16dirs);
-		if (fireDistance(dir, state._x, state._y, state._z))
+		if (fireDistance(dir, state._point.x, state._point.y, state._point.z))
 			return true;
 	}
 
@@ -221,8 +219,7 @@ bool RollingThunderProcess::fireDistance(Direction dir, int32 x, int32 y, int32
 	if (!actor || !target)
 		return 0;
 
-	int32 tx, ty, tz;
-	target->getLocation(tx, ty, tz);
+	Point3 pt = target->getLocation();
 
 	uint16 shapeno = actor->getShape();
 	uint32 actionno = AnimDat::getActionNumberForSequence(Animation::attack, actor);
@@ -263,7 +260,7 @@ bool RollingThunderProcess::fireDistance(Direction dir, int32 x, int32 y, int32
 		PositionInfo info = cm->getPositionInfo(cx, cy, cz, BULLET_SPLASH_SHAPE, _itemNum);
 		if (!info.valid && info.blocker) {
 			if (info.blocker->getObjId() == target->getObjId())
-				dist = MAX(abs(x - tx), abs(y - ty));
+				dist = MAX(abs(x - pt.x), abs(y - pt.y));
 		} else {
 			int32 ocx, ocy, ocz;
 			target->getCentre(ocx, ocy, ocz);
@@ -306,13 +303,12 @@ bool RollingThunderProcess::checkForSpiderBomb() {
 	currentmap->areaSearch(&spiderlist, script, sizeof(script), actor, 800, false);
 
 	for (unsigned int i = 0; i < spiderlist.getSize(); ++i) {
-		int32 x, y, z, sx, sy, sz;
 		const Item *spider = getItem(spiderlist.getuint16(i));
 		if (!spider)
 			continue;
-		actor->getLocation(x, y, z);
-		spider->getLocation(sx, sy, sz);
-		Direction dirtospider = Direction_GetWorldDir(sy - y, sx - x, dirmode_16dirs);
+		Point3 pta = actor->getLocation();
+		Point3 pts = spider->getLocation();
+		Direction dirtospider = Direction_GetWorldDir(pts.y - pta.y, pts.x - pta.x, dirmode_16dirs);
 		uint16 dist = actor->fireDistance(spider, dirtospider, 0, 0, 0);
 		if (dist > 0) {
 			_target = spider->getObjId();
diff --git a/engines/ultima/ultima8/world/actors/targeted_anim_process.cpp b/engines/ultima/ultima8/world/actors/targeted_anim_process.cpp
index 87c82010efe..531e9fb6244 100644
--- a/engines/ultima/ultima8/world/actors/targeted_anim_process.cpp
+++ b/engines/ultima/ultima8/world/actors/targeted_anim_process.cpp
@@ -32,9 +32,9 @@ TargetedAnimProcess::TargetedAnimProcess() : ActorAnimProcess(),
 		_x(0), _y(0), _z(0) {
 }
 
-TargetedAnimProcess::TargetedAnimProcess(Actor *actor, Animation::Sequence action, Direction dir, int32 coords[3]) :
+TargetedAnimProcess::TargetedAnimProcess(Actor *actor, Animation::Sequence action, Direction dir, const Point3 &coords) :
 	ActorAnimProcess(actor, action, dir),
-	_x(coords[0]), _y(coords[1]), _z(coords[2]) {
+	_x(coords.x), _y(coords.y), _z(coords.z) {
 }
 
 bool TargetedAnimProcess::init() {
diff --git a/engines/ultima/ultima8/world/actors/targeted_anim_process.h b/engines/ultima/ultima8/world/actors/targeted_anim_process.h
index c8388ab3644..863326a5523 100644
--- a/engines/ultima/ultima8/world/actors/targeted_anim_process.h
+++ b/engines/ultima/ultima8/world/actors/targeted_anim_process.h
@@ -25,6 +25,7 @@
 #include "ultima/ultima8/world/actors/actor_anim_process.h"
 #include "ultima/ultima8/world/actors/animation.h"
 #include "ultima/ultima8/misc/classtype.h"
+#include "ultima/ultima8/misc/point3.h"
 
 namespace Ultima {
 namespace Ultima8 {
@@ -34,7 +35,7 @@ public:
 	TargetedAnimProcess();
 	//! note: this probably needs some more parameters
 	TargetedAnimProcess(Actor *actor, Animation::Sequence action, Direction dir,
-	                    int32 coords[3]);
+	                    const Point3 &coords);
 
 	ENABLE_RUNTIME_CLASSTYPE()
 
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 707b0a4adf4..8756f4b5ba0 100644
--- a/engines/ultima/ultima8/world/actors/u8_avatar_mover_process.cpp
+++ b/engines/ultima/ultima8/world/actors/u8_avatar_mover_process.cpp
@@ -697,9 +697,8 @@ void U8AvatarMoverProcess::step(Animation::Sequence action, Direction direction,
 
 	if (action == Animation::step && res == Animation::END_OFF_LAND &&
 	        lastanim != Animation::keepBalance && !adjusted) {
-		int32 ax, ay, az;
-		avatar->getLocation(ax, ay, az);
-		if (az > 0) {
+		Point3 pt = avatar->getLocation();
+		if (pt.z > 0) {
 			if (checkTurn(stepdir, false))
 				return;
 			debug(6, "Step: end off land both altdirs failed, keep balance.");
@@ -749,7 +748,7 @@ void U8AvatarMoverProcess::jump(Animation::Sequence action, Direction direction)
 	bool targeting = ConfMan.getBool("targetedjump");
 	if (targeting) {
 		Mouse *mouse = Mouse::get_instance();
-		int32 coords[3];
+		Point3 coords;
 		int32 mx, my;
 		mouse->getMouseCoords(mx, my);
 		GameMapGump *gameMap = Ultima8Engine::get_instance()->getGameMapGump();
@@ -761,8 +760,8 @@ void U8AvatarMoverProcess::jump(Animation::Sequence action, Direction direction)
 		int32 ax, ay, az;
 		avatar->getCentre(ax, ay, az);
 
-		int32 xrange = abs(ax - coords[0]);
-		int32 yrange = abs(ay - coords[1]);
+		int32 xrange = abs(ax - coords.x);
+		int32 yrange = abs(ay - coords.y);
 		int maxrange = avatar->getStr() * 32;
 
 		if (target && target->getShapeInfo()->is_land() &&
diff --git a/engines/ultima/ultima8/world/bobo_boomer_process.cpp b/engines/ultima/ultima8/world/bobo_boomer_process.cpp
index 1e819ed645a..6ae7906ae5b 100644
--- a/engines/ultima/ultima8/world/bobo_boomer_process.cpp
+++ b/engines/ultima/ultima8/world/bobo_boomer_process.cpp
@@ -39,7 +39,10 @@ _counter(0), _x(0), _y(0), _z(0)
 BoboBoomerProcess::BoboBoomerProcess(const Item *item) : Process(), _counter(0)
 {
 	assert(item);
-	item->getLocation(_x, _y, _z);
+	Point3 pt = item->getLocation();
+	_x = pt.x;
+	_y = pt.y;
+	_z = pt.z;
 	_type = 0x264;
 }
 
diff --git a/engines/ultima/ultima8/world/camera_process.cpp b/engines/ultima/ultima8/world/camera_process.cpp
index f2402f1d829..4b716427d94 100644
--- a/engines/ultima/ultima8/world/camera_process.cpp
+++ b/engines/ultima/ultima8/world/camera_process.cpp
@@ -41,8 +41,8 @@ int32 CameraProcess::_earthquake = 0;
 int32 CameraProcess::_eqX = 0;
 int32 CameraProcess::_eqY = 0;
 
-CameraProcess::CameraProcess() : Process(), _sx(0), _sy(0), _sz(0),
-	_ex(0), _ey(0), _ez(0), _time(0), _elapsed(0),
+CameraProcess::CameraProcess() : Process(), _s(),
+	_e(), _time(0), _elapsed(0),
 	_itemNum(0), _lastFrameNum(0) {
 }
 
@@ -71,36 +71,38 @@ void CameraProcess::moveToLocation(int32 x, int32 y, int32 z) {
 		_itemNum = 0;
 	}
 
-	_sx = _sy = _sz = _time = _elapsed = _lastFrameNum = 0;
+	_s.x = _s.y = _s.z = _time = _elapsed = _lastFrameNum = 0;
 	_eqX = _eqY = _earthquake = 0;
-	_ex = x;
-	_ey = y;
-	_ez = z;
-	GetCameraLocation(_sx, _sy, _sz);
+	_e.x = x;
+	_e.y = y;
+	_e.z = z;
+	_s = GetCameraLocation();
 }
 
-void CameraProcess::GetCameraLocation(int32 &x, int32 &y, int32 &z) {
-	if (!_camera) {
-		World *world = World::get_instance();
-		CurrentMap *map = world->getCurrentMap();
-		int map_num = map->getNum();
-		Actor *av = getControlledActor();
-
-		if (!av || av->getMapNum() != map_num) {
-			x = 8192;
-			y = 8192;
-			z = 64;
-		} else {
-			av->getLocation(x, y, z);
-		}
+Point3 CameraProcess::GetCameraLocation() {
+	if (_camera) {
+		return _camera->GetLerped(256, true);
+	}
 
-		if (_earthquake) {
-			x += 2 * _eqX + 4 * _eqY;
-			y += -2 * _eqX + 4 * _eqY;
-		}
+	World *world = World::get_instance();
+	CurrentMap *map = world->getCurrentMap();
+	int map_num = map->getNum();
+	Actor *av = getControlledActor();
+	Point3 pt;
+
+	if (!av || av->getMapNum() != map_num) {
+		pt.x = 8192;
+		pt.y = 8192;
+		pt.z = 64;
 	} else {
-		_camera->GetLerped(x, y, z, 256, true);
+		pt = av->getLocation();
 	}
+
+	if (_earthquake) {
+		pt.x += 2 * _eqX + 4 * _eqY;
+		pt.y += -2 * _eqX + 4 * _eqY;
+	}
+	return pt;
 }
 
 //
@@ -109,42 +111,35 @@ void CameraProcess::GetCameraLocation(int32 &x, int32 &y, int32 &z) {
 
 // Track item, do nothing
 CameraProcess::CameraProcess(uint16 _itemnum) :
-	_time(0), _elapsed(0), _itemNum(_itemnum), _lastFrameNum(0) {
-	GetCameraLocation(_sx, _sy, _sz);
+	_e(), _time(0), _elapsed(0), _itemNum(_itemnum), _lastFrameNum(0) {
+	_s = GetCameraLocation();
 
 	if (_itemNum) {
 		Item *item = getItem(_itemNum);
 		if (item) {
 			item->setExtFlag(Item::EXT_CAMERA);
-			item->getLocation(_ex, _ey, _ez);
-			_ez += 20; //!!constant
-		} else {
-			_ex = 0;
-			_ey = 0;
-			_ez = 0;
+			_e = item->getLocation();
+			_e.z += 20; //!!constant
 		}
-		return;
+	} else {
+		// No item
+		_itemNum = 0;
+		_e = _s;
 	}
-
-	// No item
-	_itemNum = 0;
-	_ex = _sx;
-	_ey = _sy;
-	_ez = _sz;
 }
 
 // Stay over point
 CameraProcess::CameraProcess(int32 x, int32 y, int32 z) :
-	_ex(x), _ey(y), _ez(z), _time(0), _elapsed(0), _itemNum(0), _lastFrameNum(0) {
-	GetCameraLocation(_sx, _sy, _sz);
+	_e(x, y, z), _time(0), _elapsed(0), _itemNum(0), _lastFrameNum(0) {
+	_s = GetCameraLocation();
 }
 
 // Scroll
 CameraProcess::CameraProcess(int32 x, int32 y, int32 z, int32 time) :
-	_ex(x), _ey(y), _ez(z), _time(time), _elapsed(0), _itemNum(0), _lastFrameNum(0) {
-	GetCameraLocation(_sx, _sy, _sz);
+	_e(x, y, z), _time(time), _elapsed(0), _itemNum(0), _lastFrameNum(0) {
+	_s = GetCameraLocation();
 	debug(10, "Scrolling from (%d, %d,%d) to (%d, %d, %d) in %d frames",
-		_sx, _sy, _sz, _ex, _ey, _ez,  _time);
+		_s.x, _s.y, _s.z, _e.x, _e.y, _e.z,  _time);
 }
 
 void CameraProcess::terminate() {
@@ -171,7 +166,7 @@ void CameraProcess::run() {
 
 	if (_time && _elapsed > _time) {
 		_result = 0; // do we need this
-		CameraProcess::SetCameraProcess(0); // This will terminate us
+		CameraProcess::SetCameraProcess(nullptr); // This will terminate us
 		return;
 	}
 
@@ -188,21 +183,21 @@ void CameraProcess::itemMoved() {
 	if (!item || !item->hasExtFlags(Item::EXT_LERP_NOPREV))
 		return;
 
-	int32 ix, iy, iz;
-	item->getLocation(ix, iy, iz);
+	Point3 pt = item->getLocation();
 
-	int32 maxdist = MAX(MAX(abs(_ex - iz), abs(_ey - iy)), abs(_ez - iz));
+	int32 maxdist = MAX(MAX(abs(_e.x - pt.z), abs(_e.y - pt.y)), abs(_e.z - pt.z));
 
 	if (GAME_IS_U8 || (GAME_IS_CRUSADER && maxdist > 0x40)) {
-		_sx = _ex = ix;
-		_sy = _ey = iy;
-		_ez = iz;
-		_sz = _ez += 20;
-		World::get_instance()->getCurrentMap()->updateFastArea(_sx, _sy, _sz, _ex, _ey, _ez);
+		_s.x = _e.x = pt.x;
+		_s.y = _e.y = pt.y;
+		_e.z = pt.z;
+		_s.z = _e.z += 20;
+		World::get_instance()->getCurrentMap()->updateFastArea(_s.x, _s.y, _s.z, _e.x, _e.y, _e.z);
 	}
 }
 
-void CameraProcess::GetLerped(int32 &x, int32 &y, int32 &z, int32 factor, bool noupdate) {
+Point3 CameraProcess::GetLerped(int32 factor, bool noupdate) {
+	Point3 pt;
 	if (_time == 0) {
 		if (!noupdate) {
 
@@ -216,40 +211,32 @@ void CameraProcess::GetLerped(int32 &x, int32 &y, int32 &z, int32 factor, bool n
 			}
 
 			if (!inBetween) {
-				_sx = _ex;
-				_sy = _ey;
-				_sz = _ez;
+				_s = _e;
 
 				if (_itemNum) {
 					Item *item = getItem(_itemNum);
 					// Got it
 					if (item) {
 						item->setExtFlag(Item::EXT_CAMERA);
-						_sx = _ex;
-						_sy = _ey;
-						_sz = _ez;
-						item->getLocation(_ex, _ey, _ez);
-						_ez += 20; //!!constant
+						_s = _e;
+						_e = item->getLocation();
+						_e.z += 20; //!!constant
 					}
 				}
 				// Update the fast area
-				World::get_instance()->getCurrentMap()->updateFastArea(_sx, _sy, _sz, _ex, _ey, _ez);
+				World::get_instance()->getCurrentMap()->updateFastArea(_s.x, _s.y, _s.z, _e.x, _e.y, _e.z);
 			}
 		}
 
 		if (factor == 256) {
-			x = _ex;
-			y = _ey;
-			z = _ez;
+			pt = _e;
 		} else if (factor == 0) {
-			x = _sx;
-			y = _sy;
-			z = _sz;
+			pt = _s;
 		} else {
 			// This way while possibly slower is more accurate
-			x = ((_sx * (256 - factor) + _ex * factor) >> 8);
-			y = ((_sy * (256 - factor) + _ey * factor) >> 8);
-			z = ((_sz * (256 - factor) + _ez * factor) >> 8);
+			pt.x = ((_s.x * (256 - factor) + _e.x * factor) >> 8);
+			pt.y = ((_s.y * (256 - factor) + _e.y * factor) >> 8);
+			pt.z = ((_s.z * (256 - factor) + _e.z * factor) >> 8);
 		}
 	} else {
 		// Do a quadratic interpolation here of velocity (maybe), but not yet
@@ -259,39 +246,39 @@ void CameraProcess::GetLerped(int32 &x, int32 &y, int32 &z, int32 factor, bool n
 		if (sfactor > _time) sfactor = _time;
 		if (efactor > _time) efactor = _time;
 
-		int32 lsx = ((_sx * (_time - sfactor) + _ex * sfactor) / _time);
-		int32 lsy = ((_sy * (_time - sfactor) + _ey * sfactor) / _time);
-		int32 lsz = ((_sz * (_time - sfactor) + _ez * sfactor) / _time);
+		int32 lsx = ((_s.x * (_time - sfactor) + _e.x * sfactor) / _time);
+		int32 lsy = ((_s.y * (_time - sfactor) + _e.y * sfactor) / _time);
+		int32 lsz = ((_s.z * (_time - sfactor) + _e.z * sfactor) / _time);
 
-		int32 lex = ((_sx * (_time - efactor) + _ex * efactor) / _time);
-		int32 ley = ((_sy * (_time - efactor) + _ey * efactor) / _time);
-		int32 lez = ((_sz * (_time - efactor) + _ez * efactor) / _time);
+		int32 lex = ((_s.x * (_time - efactor) + _e.x * efactor) / _time);
+		int32 ley = ((_s.y * (_time - efactor) + _e.y * efactor) / _time);
+		int32 lez = ((_s.z * (_time - efactor) + _e.z * efactor) / _time);
 
 		// Update the fast area
 		if (!noupdate) World::get_instance()->getCurrentMap()->updateFastArea(lsx, lsy, lsz, lex, ley, lez);
 
 		// This way while possibly slower is more accurate
-		x = ((lsx * (256 - factor) + lex * factor) >> 8);
-		y = ((lsy * (256 - factor) + ley * factor) >> 8);
-		z = ((lsz * (256 - factor) + lez * factor) >> 8);
+		pt.x = ((lsx * (256 - factor) + lex * factor) >> 8);
+		pt.y = ((lsy * (256 - factor) + ley * factor) >> 8);
+		pt.z = ((lsz * (256 - factor) + lez * factor) >> 8);
 	}
 
 	if (_earthquake) {
-		x += 2 * _eqX + 4 * _eqY;
-		y += -2 * _eqX + 4 * _eqY;
+		pt.x += 2 * _eqX + 4 * _eqY;
+		pt.y += -2 * _eqX + 4 * _eqY;
 	}
+	return pt;
 }
 
 uint16 CameraProcess::findRoof(int32 factor) {
-	int32 x, y, z;
 	int32 earthquake_old = _earthquake;
 	_earthquake = 0;
-	GetLerped(x, y, z, factor);
+	Point3 pt = GetLerped(factor);
 	_earthquake = earthquake_old;
 
 	// Default camera box based on 1x1x1 footpad,
 	// which is the minimal size to avoid floor detected as roof
-	Box target(x, y, z, 32, 32, 8);
+	Box target(pt.x, pt.y, pt.z, 32, 32, 8);
 
 	// Should _itemNum be used when not focused on main actor?
 	Item *item = getItem(1);
@@ -309,12 +296,12 @@ uint16 CameraProcess::findRoof(int32 factor) {
 void CameraProcess::saveData(Common::WriteStream *ws) {
 	Process::saveData(ws);
 
-	ws->writeUint32LE(static_cast<uint32>(_sx));
-	ws->writeUint32LE(static_cast<uint32>(_sy));
-	ws->writeUint32LE(static_cast<uint32>(_sz));
-	ws->writeUint32LE(static_cast<uint32>(_ex));
-	ws->writeUint32LE(static_cast<uint32>(_ey));
-	ws->writeUint32LE(static_cast<uint32>(_ez));
+	ws->writeUint32LE(static_cast<uint32>(_s.x));
+	ws->writeUint32LE(static_cast<uint32>(_s.y));
+	ws->writeUint32LE(static_cast<uint32>(_s.z));
+	ws->writeUint32LE(static_cast<uint32>(_e.x));
+	ws->writeUint32LE(static_cast<uint32>(_e.y));
+	ws->writeUint32LE(static_cast<uint32>(_e.z));
 	ws->writeUint32LE(static_cast<uint32>(_time));
 	ws->writeUint32LE(static_cast<uint32>(_elapsed));
 	ws->writeUint16LE(_itemNum);
@@ -327,12 +314,12 @@ void CameraProcess::saveData(Common::WriteStream *ws) {
 bool CameraProcess::loadData(Common::ReadStream *rs, uint32 version) {
 	if (!Process::loadData(rs, version)) return false;
 
-	_sx = static_cast<int32>(rs->readUint32LE());
-	_sy = static_cast<int32>(rs->readUint32LE());
-	_sz = static_cast<int32>(rs->readUint32LE());
-	_ex = static_cast<int32>(rs->readUint32LE());
-	_ey = static_cast<int32>(rs->readUint32LE());
-	_ez = static_cast<int32>(rs->readUint32LE());
+	_s.x = static_cast<int32>(rs->readUint32LE());
+	_s.y = static_cast<int32>(rs->readUint32LE());
+	_s.z = static_cast<int32>(rs->readUint32LE());
+	_e.x = static_cast<int32>(rs->readUint32LE());
+	_e.y = static_cast<int32>(rs->readUint32LE());
+	_e.z = static_cast<int32>(rs->readUint32LE());
 	_time = static_cast<int32>(rs->readUint32LE());
 	_elapsed = static_cast<int32>(rs->readUint32LE());
 	_itemNum = rs->readUint16LE();
@@ -392,23 +379,20 @@ uint32 CameraProcess::I_stopQuake(const uint8 * /*args*/, unsigned int /*argsize
 }
 
 uint32 CameraProcess::I_getCameraX(const uint8 *args, unsigned int argsize) {
-	int32 x, y, z;
 	assert(GAME_IS_CRUSADER);
-	GetCameraLocation(x, y, z);
-	return World_ToUsecodeCoord(x);
+	Point3 pt = GetCameraLocation();
+	return World_ToUsecodeCoord(pt.x);
 }
 
 uint32 CameraProcess::I_getCameraY(const uint8 *args, unsigned int argsize) {
-	int32 x, y, z;
 	assert(GAME_IS_CRUSADER);
-	GetCameraLocation(x, y, z);
-	return World_ToUsecodeCoord(y);
+	Point3 pt = GetCameraLocation();
+	return World_ToUsecodeCoord(pt.y);
 }
 
 uint32 CameraProcess::I_getCameraZ(const uint8 *args, unsigned int argsize) {
-	int32 x, y, z;
-	GetCameraLocation(x, y, z);
-	return z;
+	Point3 pt = GetCameraLocation();
+	return pt.z;
 }
 
 } // End of namespace Ultima8
diff --git a/engines/ultima/ultima8/world/camera_process.h b/engines/ultima/ultima8/world/camera_process.h
index fbea9a504de..7056142e1a5 100644
--- a/engines/ultima/ultima8/world/camera_process.h
+++ b/engines/ultima/ultima8/world/camera_process.h
@@ -25,6 +25,7 @@
 #include "ultima/ultima8/kernel/process.h"
 #include "ultima/ultima8/usecode/intrinsics.h"
 #include "ultima/ultima8/misc/classtype.h"
+#include "ultima/ultima8/misc/point3.h"
 
 namespace Ultima {
 namespace Ultima8 {
@@ -51,7 +52,7 @@ public:
 	void run() override;
 
 	// You will notice that this isn't the same as how Item::GetLerped works
-	void GetLerped(int32 &x, int32 &y, int32 &z, int32 factor, bool noupdate = false);
+	Point3 GetLerped(int32 factor, bool noupdate = false);
 
 	//! Find the roof above the camera.
 	//! \param factor Interpolation factor for this frame
@@ -76,7 +77,7 @@ public:
 	INTRINSIC(I_getCameraY);
 	INTRINSIC(I_getCameraZ);
 
-	static void             GetCameraLocation(int32 &x, int32 &y, int32 &z);
+	static Point3           GetCameraLocation();
 	static CameraProcess   *GetCameraProcess() {
 		return _camera;
 	}
@@ -107,8 +108,8 @@ public:
 	}
 
 private:
-	int32 _sx, _sy, _sz;
-	int32 _ex, _ey, _ez;
+	Point3 _s;
+	Point3 _e;
 	int32 _time;
 	int32 _elapsed;
 	uint16 _itemNum;
diff --git a/engines/ultima/ultima8/world/crosshair_process.cpp b/engines/ultima/ultima8/world/crosshair_process.cpp
index a725e225d42..a2f292188cf 100644
--- a/engines/ultima/ultima8/world/crosshair_process.cpp
+++ b/engines/ultima/ultima8/world/crosshair_process.cpp
@@ -59,9 +59,8 @@ void CrosshairProcess::run() {
 	if (actor->isInCombat()) {
 		Kernel *kernel = Kernel::get_instance();
 		assert(kernel);
-		int32 ax, ay, az;
-		actor->getLocation(ax, ay, az);
-		actor->addFireAnimOffsets(ax, ay, az);
+		Point3 pt = actor->getLocation();
+		actor->addFireAnimOffsets(pt.x, pt.y, pt.z);
 
 		const CruAvatarMoverProcess *mover = dynamic_cast<CruAvatarMoverProcess *>(Ultima8Engine::get_instance()->getAvatarMoverProcess());
 		if (!mover) {
@@ -77,8 +76,8 @@ void CrosshairProcess::run() {
 		double rads = Common::deg2rad(angle);
 		float xoff = CROSSHAIR_DIST * cos(rads);
 		float yoff = CROSSHAIR_DIST * sin(rads);
-		ax -= static_cast<int32>(xoff);
-		ay -= static_cast<int32>(yoff);
+		pt.x -= static_cast<int32>(xoff);
+		pt.y -= static_cast<int32>(yoff);
 
 		Item *item;
 		if (_itemNum) {
@@ -90,7 +89,7 @@ void CrosshairProcess::run() {
 			setItemNum(item->getObjId());
 		}
 		if (item)
-			item->move(ax, ay, az);
+			item->move(pt.x, pt.y, pt.z);
 		else
 			_itemNum = 0; // sprite gone? can happen during teleport.
 	} else {
diff --git a/engines/ultima/ultima8/world/current_map.cpp b/engines/ultima/ultima8/world/current_map.cpp
index 5a25d83bf56..7a5c35a097a 100644
--- a/engines/ultima/ultima8/world/current_map.cpp
+++ b/engines/ultima/ultima8/world/current_map.cpp
@@ -231,18 +231,16 @@ void CurrentMap::loadMap(Map *map) {
 }
 
 void CurrentMap::addItem(Item *item) {
-	int32 ix, iy, iz;
+	Point3 pt = item->getLocation();
 
-	item->getLocation(ix, iy, iz);
-
-	if (ix < 0 || ix >= _mapChunkSize * MAP_NUM_CHUNKS ||
-	        iy < 0 || iy >= _mapChunkSize * MAP_NUM_CHUNKS) {
-		//warning("Skipping item %u: out of range (%d, %d)", item->getObjId(), ix, iy);
+	if (pt.x < 0 || pt.x >= _mapChunkSize * MAP_NUM_CHUNKS ||
+	        pt.y < 0 || pt.y >= _mapChunkSize * MAP_NUM_CHUNKS) {
+		//warning("Skipping item %u: out of range (%d, %d)", item->getObjId(), pt.x, pt.y);
 		return;
 	}
 
-	int32 cx = ix / _mapChunkSize;
-	int32 cy = iy / _mapChunkSize;
+	int32 cx = pt.x / _mapChunkSize;
+	int32 cy = pt.y / _mapChunkSize;
 
 #ifdef VALIDATE_CHUNKS
 	for (int32 ccy = 0; ccy < MAP_NUM_CHUNKS; ccy++) {
@@ -270,18 +268,16 @@ void CurrentMap::addItem(Item *item) {
 }
 
 void CurrentMap::addItemToEnd(Item *item) {
-	int32 ix, iy, iz;
-
-	item->getLocation(ix, iy, iz);
+	Point3 pt = item->getLocation();
 
-	if (ix < 0 || ix >= _mapChunkSize * MAP_NUM_CHUNKS ||
-	        iy < 0 || iy >= _mapChunkSize * MAP_NUM_CHUNKS) {
-		//warning("Skipping item %u: out of range (%d, %d)", item->getObjId(), ix, iy);
+	if (pt.x < 0 || pt.x >= _mapChunkSize * MAP_NUM_CHUNKS ||
+	        pt.y < 0 || pt.y >= _mapChunkSize * MAP_NUM_CHUNKS) {
+		//warning("Skipping item %u: out of range (%d, %d)", item->getObjId(), pt.x, pt.y);
 		return;
 	}
 
-	int32 cx = ix / _mapChunkSize;
-	int32 cy = iy / _mapChunkSize;
+	int32 cx = pt.x / _mapChunkSize;
+	int32 cy = pt.y / _mapChunkSize;
 
 #ifdef VALIDATE_CHUNKS
 	for (int32 ccy = 0; ccy < MAP_NUM_CHUNKS; ccy++) {
@@ -309,11 +305,9 @@ void CurrentMap::addItemToEnd(Item *item) {
 }
 
 void CurrentMap::removeItem(Item *item) {
-	int32 ix, iy, iz;
+	Point3 pt = item->getLocation();
 
-	item->getLocation(ix, iy, iz);
-
-	removeItemFromList(item, ix, iy);
+	removeItemFromList(item, pt.x, pt.y);
 }
 
 void CurrentMap::addTargetItem(const Item *item) {
@@ -371,9 +365,8 @@ Item *CurrentMap::findBestTargetItem(int32 x, int32 y, int32 z, Direction dir, D
 		const ShapeInfo *si = item->getShapeInfo();
 		bool isoccl = si->_flags & ShapeInfo::SI_OCCL;
 
-		int32 ix, iy, iz;
-		item->getLocation(ix, iy, iz);
-		Direction itemdir = Direction_GetWorldDir(iy - y, ix - x, dirmode);
+		Point3 pt = item->getLocation();
+		Direction itemdir = Direction_GetWorldDir(pt.y - y, pt.x - x, dirmode);
 		if (itemdir != dir)
 			continue;
 
@@ -381,9 +374,9 @@ Item *CurrentMap::findBestTargetItem(int32 x, int32 y, int32 z, Direction dir, D
 		if ((bestisoccl && !isoccl) || (bestisnpc && !actor) || !item->isPartlyOnScreen())
 			continue;
 
-		int xdiff = abs(x - ix);
-		int ydiff = abs(y - iy);
-		int zdiff = abs(z - iz);
+		int xdiff = abs(x - pt.x);
+		int ydiff = abs(y - pt.y);
+		int zdiff = abs(z - pt.z);
 		int dist = MAX(MAX(xdiff, ydiff), zdiff);
 
 		if (dist < bestdist) {
@@ -565,8 +558,10 @@ void CurrentMap::areaSearch(UCList *itemlist, const uint8 *loopscript,
 	// if item != 0, search an area around item. Otherwise, search an area
 	// around (x,y)
 	if (check) {
-		int32 z, zd;
-		check->getLocationAbsolute(x, y, z);
+		int32 zd;
+		Point3 pt = check->getLocationAbsolute();
+		x = pt.x;
+		y = pt.y;
 		check->getFootpadWorld(xd, yd, zd);
 	}
 
@@ -607,9 +602,8 @@ void CurrentMap::areaSearch(UCList *itemlist, const uint8 *loopscript,
 					continue;
 
 				// check if item is in range
-				int32 ix, iy, iz;
-				item->getLocation(ix, iy, iz);
-				if (searchrange.containsXY(ix, iy)) {
+				Point3 pt = item->getLocation();
+				if (searchrange.containsXY(pt.x, pt.y)) {
 					// check item against loopscript
 					if (item->checkLoopScript(loopscript, scriptsize)) {
 						assert(itemlist->getElementSize() == 2);
@@ -632,16 +626,15 @@ void CurrentMap::areaSearch(UCList *itemlist, const uint8 *loopscript,
 void CurrentMap::surfaceSearch(UCList *itemlist, const uint8 *loopscript,
 							   uint32 scriptsize, const Item *check,
 							   bool above, bool below, bool recurse) const {
-	int32 x, y, z;
 	int32 xd, yd, zd;
-	check->getLocationAbsolute(x, y, z);
+	Point3 pt = check->getLocationAbsolute();
 	check->getFootpadWorld(xd, yd, zd);
-	const Box searchrange(x, y, z, xd, yd, zd);
+	const Box searchrange(pt.x, pt.y, pt.z, xd, yd, zd);
 
-	int minx = ((x - xd) / _mapChunkSize) - 1;
-	int maxx = (x / _mapChunkSize) + 1;
-	int miny = ((y - yd) / _mapChunkSize) - 1;
-	int maxy = (y / _mapChunkSize) + 1;
+	int minx = ((pt.x - xd) / _mapChunkSize) - 1;
+	int maxx = (pt.x / _mapChunkSize) + 1;
+	int miny = ((pt.y - yd) / _mapChunkSize) - 1;
+	int maxy = (pt.y / _mapChunkSize) + 1;
 	clipMapChunks(minx, maxx, miny, maxy);
 
 	for (int cy = miny; cy <= maxy; cy++) {
@@ -872,19 +865,19 @@ bool CurrentMap::scanForValidPosition(int32 x, int32 y, int32 z, const Item *ite
 				if (!(si->_flags & blockflagmask))
 					continue; // not an interesting item
 
-				int32 ix, iy, iz, ixd, iyd, izd;
-				citem->getLocation(ix, iy, iz);
+				int32 ixd, iyd, izd;
+				Point3 pt = citem->getLocation();
 				citem->getFootpadWorld(ixd, iyd, izd);
 
-				int minv = iz - z - zd + 1;
-				int maxv = iz + izd - z - 1;
+				int minv = pt.z - z - zd + 1;
+				int maxv = pt.z + izd - z - 1;
 				if (minv < -scansize) minv = -scansize;
 				if (maxv > scansize) maxv = scansize;
 
-				int sminx = ix - ixd + 1 - x;
-				int smaxx = ix + xd - 1  - x;
-				int sminy = iy - iyd + 1 - y;
-				int smaxy = iy + yd - 1  - y;
+				int sminx = pt.x - ixd + 1 - x;
+				int smaxx = pt.x + xd - 1  - x;
+				int sminy = pt.y - iyd + 1 - y;
+				int smaxy = pt.y + yd - 1  - y;
 
 				int minh = -100;
 				int maxh = 100;
@@ -914,9 +907,9 @@ bool CurrentMap::scanForValidPosition(int32 x, int32 y, int32 z, const Item *ite
 						validmask[j + scansize] &= ~(1 << (i + scansize));
 
 				if (wantsupport && si->is_solid() &&
-				        iz + izd >= z - scansize && iz + izd <= z + scansize) {
+				        pt.z + izd >= z - scansize && pt.z + izd <= z + scansize) {
 					for (int i = minh; i <= maxh; ++i)
-						supportmask[iz + izd - z + scansize] |= (1 << (i + scansize));
+						supportmask[pt.z + izd - z + scansize] |= (1 << (i + scansize));
 
 				}
 			}
@@ -1057,7 +1050,10 @@ bool CurrentMap::sweepTest(const int32 start[3], const int32 end[3],
 					continue;
 
 				int32 other[3], oext[3];
-				other_item->getLocation(other[0], other[1], other[2]);
+				Point3 opt = other_item->getLocation();
+				other[0] = opt.x;
+				other[1] = opt.y;
+				other[2] = opt.z;
 				other_item->getFootpadWorld(oext[0], oext[1], oext[2]);
 
 				// If the objects overlapped at the start, ignore collision.
diff --git a/engines/ultima/ultima8/world/damage_info.cpp b/engines/ultima/ultima8/world/damage_info.cpp
index 40bf5a9925f..9b095f744ae 100644
--- a/engines/ultima/ultima8/world/damage_info.cpp
+++ b/engines/ultima/ultima8/world/damage_info.cpp
@@ -57,8 +57,7 @@ bool DamageInfo::applyToItem(Item *item, uint16 points) const {
 	// Get some data out of the item before we potentially delete
 	// it by explosion
 	uint16 q = item->getQuality();
-	int32 x, y, z;
-	item->getLocation(x, y, z);
+	Point3 pt = item->getLocation();
 	int32 mapnum = item->getMapNum();
 
 	if (explode()) {
@@ -77,7 +76,7 @@ bool DamageInfo::applyToItem(Item *item, uint16 points) const {
 		uint16 replacementShape = getReplacementShape();
 		uint8 replacementFrame = getReplacementFrame();
 		Item *newitem = ItemFactory::createItem(replacementShape, replacementFrame, q, 0, 0, mapnum, 0, true);
-		newitem->move(x, y, z);
+		newitem->move(pt.x, pt.y, pt.z);
 		if (item)
 			item->destroy();
 	} else if (!explodeDestroysItem()) {
diff --git a/engines/ultima/ultima8/world/egg_hatcher_process.cpp b/engines/ultima/ultima8/world/egg_hatcher_process.cpp
index 9d09b8c60af..004f171e4b8 100644
--- a/engines/ultima/ultima8/world/egg_hatcher_process.cpp
+++ b/engines/ultima/ultima8/world/egg_hatcher_process.cpp
@@ -62,19 +62,17 @@ void EggHatcherProcess::run() {
 		Egg *egg = dynamic_cast<Egg *>(getObject(eggid));
 		if (!egg) continue; // egg gone
 
-		int32 x, y, z;
-		egg->getLocation(x, y, z);
+		Point3 pte = egg->getLocation();
 
 		//! constants
-		int32 x1 = x - range_mul * egg->getXRange();
-		int32 x2 = x + range_mul * egg->getXRange();
-		int32 y1 = y - range_mul * egg->getYRange();
-		int32 y2 = y + range_mul * egg->getYRange();
+		int32 x1 = pte.x - range_mul * egg->getXRange();
+		int32 x2 = pte.x + range_mul * egg->getXRange();
+		int32 y1 = pte.y - range_mul * egg->getYRange();
+		int32 y2 = pte.y + range_mul * egg->getYRange();
 
 		// get avatar location
-		int32 ax, ay, az;
 		int32 axs, ays, azs;
-		av->getLocation(ax, ay, az);
+		Point3 pta = av->getLocation();
 		av->getFootpadWorld(axs, ays, azs);
 
 		// 'justTeleported':
@@ -83,8 +81,8 @@ void EggHatcherProcess::run() {
 		// unset it when you're out of range of any teleport eggs
 		TeleportEgg *tegg = dynamic_cast<TeleportEgg *>(egg);
 
-		if (x1 <= ax && ax - axs < x2 && y1 <= ay && ay - ays < y2 &&
-		        z - z_range < az && az <= z + z_range) {
+		if (x1 <= pta.x && pta.x - axs < x2 && y1 <= pta.y && pta.y - ays < y2 &&
+		        pte.z - z_range < pta.z && pta.z <= pte.z + z_range) {
 			if (tegg && tegg->isTeleporter())
 				nearteleporter = true;
 
diff --git a/engines/ultima/ultima8/world/fire_type.cpp b/engines/ultima/ultima8/world/fire_type.cpp
index d5de56f0d8f..67c190730f0 100644
--- a/engines/ultima/ultima8/world/fire_type.cpp
+++ b/engines/ultima/ultima8/world/fire_type.cpp
@@ -260,8 +260,7 @@ void FireType::applySplashDamageAround(const Point3 &pt, int damage, int rangedi
 			continue;
 		int splashitemdamage = damage;
 		if (_typeNo == 3 || _typeNo == 4 || _typeNo == 10) {
-			Point3 pt2;
-			splashitem->getLocation(pt2);
+			Point3 pt2 = splashitem->getLocation();
 			int splashrange = pt.maxDistXYZ(pt2);
 			splashrange = (splashrange / 32) / 3;
 			if (splashrange)
diff --git a/engines/ultima/ultima8/world/fireball_process.cpp b/engines/ultima/ultima8/world/fireball_process.cpp
index 708f661a913..be418aed561 100644
--- a/engines/ultima/ultima8/world/fireball_process.cpp
+++ b/engines/ultima/ultima8/world/fireball_process.cpp
@@ -84,14 +84,12 @@ void FireballProcess::run() {
 	//   * deal damage if hit Actor
 	//   * turn around if hit non-Actor
 
-	int32 x, y, z;
-	int32 tx, ty, tz;
 	int32 dx, dy;
-	item->getLocation(x, y, z);
-	t->getLocationAbsolute(tx, ty, tz);
+	Point3 pt1 = item->getLocation();
+	Point3 pt2 = t->getLocationAbsolute();
 
-	dx = tx - x;
-	dy = ty - y;
+	dx = pt2.x - pt1.x;
+	dy = pt2.y - pt1.y;
 
 	Direction targetdir = item->getDirToItemCentre(*t);
 
@@ -111,7 +109,7 @@ void FireballProcess::run() {
 	}
 
 	ObjId hititem = 0;
-	item->collideMove(x + _xSpeed, y + _ySpeed, z, false, false, &hititem);
+	item->collideMove(pt1.x + _xSpeed, pt1.y + _ySpeed, pt1.z, false, false, &hititem);
 
 	// handle _tail
 	// _tail is shape 261, frame 0-7 (0 = to top-right, 7 = to top)
@@ -126,7 +124,7 @@ void FireballProcess::run() {
 	Item *tailitem = getItem(_tail[2]);
 	Direction movedir = Direction_GetWorldDir(_ySpeed, _xSpeed, dirmode_8dirs);
 	tailitem->setFrame(Direction_ToUsecodeDir(movedir));
-	tailitem->move(x, y, z);
+	tailitem->move(pt1.x, pt1.y, pt1.z);
 
 	_tail[2] = _tail[1];
 	_tail[1] = _tail[0];
diff --git a/engines/ultima/ultima8/world/gravity_process.cpp b/engines/ultima/ultima8/world/gravity_process.cpp
index 94b9139b8d7..4420b7c1b4e 100644
--- a/engines/ultima/ultima8/world/gravity_process.cpp
+++ b/engines/ultima/ultima8/world/gravity_process.cpp
@@ -98,20 +98,19 @@ void GravityProcess::run() {
 	//     - bounce off the item (need to consider FLG_LOW_FRICTION?)
 	//     - call the relevant events: hit/gothit ?
 
-	int32 ix, iy, iz;
-	item->getLocation(ix, iy, iz);
+	Point3 pt = item->getLocation();
 
 	// Shouldn't go negative as original did not allow it
-	if (iz <= 0 && _zSpeed < 0) {
+	if (pt.z <= 0 && _zSpeed < 0) {
 		terminateDeferred();
 		fallStopped();
 		return;
 	}
 
 	int32 tx, ty, tz;
-	tx = ix + _xSpeed;
-	ty = iy + _ySpeed;
-	tz = iz + _zSpeed;
+	tx = pt.x + _xSpeed;
+	ty = pt.y + _ySpeed;
+	tz = pt.z + _zSpeed;
 
 	if (tz < 0)
 		tz = 0;
@@ -161,19 +160,19 @@ void GravityProcess::run() {
 			termFlag = false;
 			_zSpeed = 0;
 
-			item->getCentre(ix, iy, iz);
+			item->getCentre(pt.x, pt.y, pt.z);
 			target = hititem->getWorldBox();
 			if (ABS(_xSpeed) < 16) {
-				if (ix + 16 > target._x)
+				if (pt.x + 16 > target._x)
 					_xSpeed = 16;
-				else if (ix - 16 < target._x - target._xd)
+				else if (pt.x - 16 < target._x - target._xd)
 					_xSpeed = -16;
 			}
 
 			if (ABS(_ySpeed) < 16) {
-				if (iy + 16 > target._y)
+				if (pt.y + 16 > target._y)
 					_ySpeed = 16;
-				else if (iy - 16 < target._y - target._yd)
+				else if (pt.y - 16 < target._y - target._yd)
 					_ySpeed = -16;
 			}
 		} else if (_zSpeed < -2 && !actor) {
diff --git a/engines/ultima/ultima8/world/item.cpp b/engines/ultima/ultima8/world/item.cpp
index 7e2596bc30d..493e541644f 100644
--- a/engines/ultima/ultima8/world/item.cpp
+++ b/engines/ultima/ultima8/world/item.cpp
@@ -418,19 +418,16 @@ int32 Item::getZ() const {
 	return _z;
 }
 
-void Item::getLocationAbsolute(int32 &X, int32 &Y, int32 &Z) const {
+Point3 Item::getLocationAbsolute() const {
 	if (_parent) {
 		Item *p = getParentAsContainer();
 
 		if (p) {
-			p->getLocationAbsolute(X, Y, Z);
-			return;
+			return p->getLocationAbsolute();
 		}
 	}
 
-	X = _x;
-	Y = _y;
-	Z = _z;
+	return Point3(_x, _y, _z);
 }
 
 void Item::getGumpLocation(int32 &X, int32 &Y) const {
@@ -500,67 +497,75 @@ void Item::setShape(uint32 shape) {
 }
 
 bool Item::overlaps(const Item &item2) const {
-	int32 x1a, y1a, z1a, x1b, y1b, z1b;
-	int32 x2a, y2a, z2a, x2b, y2b, z2b;
-	getLocation(x1b, y1b, z1a);
-	item2.getLocation(x2b, y2b, z2a);
+	int32 x1a, y1a, z1b;
+	int32 x2a, y2a, z2b;
+	Point3 pt1 = getLocation();
+	Point3 pt2 = item2.getLocation();
 
 	int32 xd, yd, zd;
 	getFootpadWorld(xd, yd, zd);
-	x1a = x1b - xd;
-	y1a = y1b - yd;
-	z1b = z1a + zd;
+	x1a = pt1.x - xd;
+	y1a = pt1.y - yd;
+	z1b = pt1.z + zd;
 
 	item2.getFootpadWorld(xd, yd, zd);
-	x2a = x2b - xd;
-	y2a = y2b - yd;
-	z2b = z2a + zd;
+	x2a = pt2.x - xd;
+	y2a = pt2.y - yd;
+	z2b = pt2.z + zd;
 
-	if (x1b <= x2a || x2b <= x1a) return false;
-	if (y1b <= y2a || y2b <= y1a) return false;
-	if (z1b <= z2a || z2b <= z1a) return false;
+	if (pt1.x <= x2a || pt2.x <= x1a)
+		return false;
+	if (pt1.y <= y2a || pt2.y <= y1a)
+		return false;
+	if (z1b <= pt2.z || z2b <= pt1.z)
+		return false;
 	return true;
 }
 
 bool Item::overlapsxy(const Item &item2) const {
-	int32 x1a, y1a, z1a, x1b, y1b;
-	int32 x2a, y2a, z2a, x2b, y2b;
-	getLocation(x1b, y1b, z1a);
-	item2.getLocation(x2b, y2b, z2a);
+	int32 x1a, y1a;
+	int32 x2a, y2a;
+	Point3 pt1 = getLocation();
+	Point3 pt2 = item2.getLocation();
 
 	int32 xd, yd, zd;
 	getFootpadWorld(xd, yd, zd);
-	x1a = x1b - xd;
-	y1a = y1b - yd;
+	x1a = pt1.x - xd;
+	y1a = pt1.y - yd;
 
 	item2.getFootpadWorld(xd, yd, zd);
-	x2a = x2b - xd;
-	y2a = y2b - yd;
+	x2a = pt2.x - xd;
+	y2a = pt2.y - yd;
 
-	if (x1b <= x2a || x2b <= x1a) return false;
-	if (y1b <= y2a || y2b <= y1a) return false;
+	if (pt1.x <= x2a || pt2.x <= x1a)
+		return false;
+	if (pt1.y <= y2a || pt2.y <= y1a)
+		return false;
 	return true;
 }
 
 bool Item::isOn(const Item &item2) const {
-	int32 x1a, y1a, z1a, x1b, y1b;
-	int32 x2a, y2a, z2a, x2b, y2b, z2b;
-	getLocation(x1b, y1b, z1a);
-	item2.getLocation(x2b, y2b, z2a);
+	int32 x1a, y1a;
+	int32 x2a, y2a, z2b;
+	Point3 pt1 = getLocation();
+	Point3 pt2 = item2.getLocation();
 
 	int32 xd, yd, zd;
 	getFootpadWorld(xd, yd, zd);
-	x1a = x1b - xd;
-	y1a = y1b - yd;
+	x1a = pt1.x - xd;
+	y1a = pt1.y - yd;
 
 	item2.getFootpadWorld(xd, yd, zd);
-	x2a = x2b - xd;
-	y2a = y2b - yd;
-	z2b = z2a + zd;
+	x2a = pt2.x - xd;
+	y2a = pt2.y - yd;
+	z2b = pt2.z + zd;
 
-	if (x1b <= x2a || x2b <= x1a) return false;
-	if (y1b <= y2a || y2b <= y1a) return false;
-	if (z2b == z1a) return true;
+	if (pt1.x <= x2a || pt2.x <= x1a)
+		return false;
+	if (pt1.y <= y2a || pt2.y <= y1a)
+		return false;
+	if (z2b == pt1.z)
+		return true;
 	return false;
 }
 
@@ -568,42 +573,45 @@ bool Item::isCompletelyOn(const Item &item2) const {
 	if (hasFlags(FLG_CONTAINED) || item2.hasFlags(FLG_CONTAINED))
 		return false;
 
-	int32 x1a, y1a, z1a, x1b, y1b;
-	int32 x2a, y2a, z2a, x2b, y2b, z2b;
-	getLocation(x1b, y1b, z1a);
-	item2.getLocation(x2b, y2b, z2a);
+	int32 x1a, y1a;
+	int32 x2a, y2a, z2b;
+	Point3 pt1 = getLocation();
+	Point3 pt2 = item2.getLocation();
 
 	int32 xd, yd, zd;
 	getFootpadWorld(xd, yd, zd);
-	x1a = x1b - xd;
-	y1a = y1b - yd;
+	x1a = pt1.x - xd;
+	y1a = pt1.y - yd;
 
 	item2.getFootpadWorld(xd, yd, zd);
-	x2a = x2b - xd;
-	y2a = y2b - yd;
-	z2b = z2a + zd;
+	x2a = pt2.x - xd;
+	y2a = pt2.y - yd;
+	z2b = pt2.z + zd;
 
-	return ((x1b <= x2b && x2a <= x1a) &&
-			(y1b <= y2b && y2a <= y1a) &&
-			(z2b == z1a));
+	return ((pt1.x <= pt2.x && x2a <= x1a) &&
+			(pt1.y <= pt2.y && y2a <= y1a) &&
+			(z2b == pt1.z));
 }
 
 bool Item::isCentreOn(const Item &item2) const {
 	int32 x1c, y1c, z1c;
-	int32 x2a, y2a, z2a, x2b, y2b, z2b;
-	item2.getLocation(x2b, y2b, z2a);
+	int32 x2a, y2a, z2b;
+	Point3 pt2 = item2.getLocation();
 
 	getCentre(x1c, y1c, z1c);
 
 	int32 xd, yd, zd;
 	item2.getFootpadWorld(xd, yd, zd);
-	x2a = x2b - xd;
-	y2a = y2b - yd;
-	z2b = z2a + zd;
+	x2a = pt2.x - xd;
+	y2a = pt2.y - yd;
+	z2b = pt2.z + zd;
 
-	if (x1c <= x2a || x2b <= x1c) return false;
-	if (y1c <= y2a || y2b <= y1c) return false;
-	if (z2b == getZ()) return true;
+	if (x1c <= x2a || pt2.x <= x1c)
+		return false;
+	if (y1c <= y2a || pt2.y <= y1c)
+		return false;
+	if (z2b == getZ())
+		return true;
 	return false;
 }
 
@@ -689,40 +697,38 @@ Direction Item::getDirToItemCentre(const Point3 &pt) const {
 
 
 int Item::getRange(const Item &item2, bool checkz) const {
-	int32 thisX, thisY, thisZ;
-	int32 otherX, otherY, otherZ;
 	int32 thisXd, thisYd, thisZd;
 	int32 otherXd, otherYd, otherZd;
 	int32 thisXmin, thisYmin, thisZmax;
 	int32 otherXmin, otherYmin, otherZmax;
 
-	getLocationAbsolute(thisX, thisY, thisZ);
-	item2.getLocationAbsolute(otherX, otherY, otherZ);
+	Point3 pt1 = getLocationAbsolute();
+	Point3 pt2 = item2.getLocationAbsolute();
 	getFootpadWorld(thisXd, thisYd, thisZd);
 	item2.getFootpadWorld(otherXd, otherYd, otherZd);
 
-	thisXmin = thisX - thisXd;
-	thisYmin = thisY - thisYd;
-	thisZmax = thisZ + thisZd;
+	thisXmin = pt1.x - thisXd;
+	thisYmin = pt1.y - thisYd;
+	thisZmax = pt1.z + thisZd;
 
-	otherXmin = otherX - otherXd;
-	otherYmin = otherY - otherYd;
-	otherZmax = otherZ + otherZd;
+	otherXmin = pt2.x - otherXd;
+	otherYmin = pt2.y - otherYd;
+	otherZmax = pt2.z + otherZd;
 
 	int32 range = 0;
 
-	if (thisXmin - otherX > range)
-		range = thisYmin - otherY;
-	if (otherXmin - thisX > range)
-		range = thisXmin - otherX;
-	if (thisYmin - otherY > range)
-		range = otherXmin - thisX;
-	if (otherYmin - thisY > range)
-		range = otherYmin - thisY;
-	if (checkz && thisZ - otherZmax > range)
-		range = thisZ - otherZmax;
-	if (checkz && otherZ - thisZmax > range)
-		range = otherZ - thisZmax;
+	if (thisXmin - pt2.x > range)
+		range = thisYmin - pt2.y;
+	if (otherXmin - pt1.x > range)
+		range = thisXmin - pt2.x;
+	if (thisYmin - pt2.y > range)
+		range = otherXmin - pt1.x;
+	if (otherYmin - pt1.y > range)
+		range = otherYmin - pt1.y;
+	if (checkz && pt1.z - otherZmax > range)
+		range = pt1.z - otherZmax;
+	if (checkz && pt2.z - thisZmax > range)
+		range = pt2.z - thisZmax;
 
 	return range;
 }
@@ -1051,7 +1057,10 @@ int32 Item::collideMove(int32 dx, int32 dy, int32 dz, bool teleport, bool force,
 		start[2] = end[2];
 	} else {
 		// Otherwise check from where we are to where we want to go
-		getLocation(start[0], start[1], start[2]);
+		Point3 pt = getLocation();
+		start[0] = pt.x;
+		start[1] = pt.y;
+		start[2] = pt.z;
 	}
 
 	int32 dims[3];
@@ -1204,15 +1213,14 @@ int32 Item::collideMove(int32 dx, int32 dy, int32 dz, bool teleport, bool force,
 }
 
 uint16 Item::fireWeapon(int32 x, int32 y, int32 z, Direction dir, int firetype, bool findtarget) {
-	int32 ix, iy, iz;
-	getLocation(ix, iy, iz);
+	Point3 pt = getLocation();
 
 	if (!GAME_IS_CRUSADER)
 		return 0;
 
-	ix += x;
-	iy += y;
-	iz += z;
+	pt.x += x;
+	pt.y += y;
+	pt.z += z;
 
 	CurrentMap *currentmap = World::get_instance()->getCurrentMap();
 	const FireType *firetypedat = GameData::get_instance()->getFireType(firetype);
@@ -1225,20 +1233,19 @@ uint16 Item::fireWeapon(int32 x, int32 y, int32 z, Direction dir, int firetype,
 
 	// CHECKME: the original doesn't exclude the source like this,
 	// but it seems obvious we have to or NPCs shoot themselves?
-	PositionInfo info = currentmap->getPositionInfo(ix, iy, iz, BULLET_SPLASH_SHAPE, _objId);
+	PositionInfo info = currentmap->getPositionInfo(pt.x, pt.y, pt.z, BULLET_SPLASH_SHAPE, _objId);
 
 	if (!info.valid && info.blocker) {
 		Item *block = getItem(info.blocker->getObjId());
-		Point3 blockpt;
-		block->getLocation(blockpt);
-		Direction damagedir = Direction_GetWorldDir(blockpt.y - iy, blockpt.x - ix, dirmode_8dirs);
+		Point3 blockpt = block->getLocation();
+		Direction damagedir = Direction_GetWorldDir(blockpt.y - pt.y, blockpt.x - pt.x, dirmode_8dirs);
 		block->receiveHit(getObjId(), damagedir, damage, firetype);
 		if (firetypedat->getRange() != 0) {
 			int splashdamage = firetypedat->getRandomDamage();
 			firetypedat->applySplashDamageAround(blockpt, splashdamage, 1, block, this);
 		}
 		if (firetypedat->getNearSprite())
-			firetypedat->makeBulletSplashShapeAndPlaySound(ix, iy, iz);
+			firetypedat->makeBulletSplashShapeAndPlaySound(pt.x, pt.y, pt.z);
 		return 0;
 	}
 
@@ -1315,7 +1322,7 @@ uint16 Item::fireWeapon(int32 x, int32 y, int32 z, Direction dir, int firetype,
 				target = getControlledActor();
 			// else already set above to attackproc target
 		} else {
-			target = currentmap->findBestTargetItem(ix, iy, iz - z, dir, dirmode);
+			target = currentmap->findBestTargetItem(pt.x, pt.y, pt.z - z, dir, dirmode);
 		}
 	}
 
@@ -1338,27 +1345,27 @@ uint16 Item::fireWeapon(int32 x, int32 y, int32 z, Direction dir, int firetype,
 		CrosshairProcess *chp = CrosshairProcess::get_instance();
 		assert(chp);
 		const Item *crosshair = getItem(chp->getItemNum());
-		int32 ssx, ssy, ssz;
+		Point3 ss;
 		if (tx != -1) {
 			// Shoot toward the target
-			ssx = tx;
-			ssy = ty;
-			ssz = tz;
+			ss.x = tx;
+			ss.y = ty;
+			ss.z = tz;
 			findtarget = true;
 		} else if (this == getControlledActor() && crosshair) {
 			// Shoot toward the crosshair
-			crosshair->getLocation(ssx, ssy, ssz);
-			ssz = iz;
+			ss = crosshair->getLocation();
+			ss.z = pt.z;
 		} else {
 			// Just send the projectile off into the distance
-			ssx = ix + Direction_XFactor(dir) * 0x500;
-			ssy = iy + Direction_YFactor(dir) * 0x500;
-			ssz = iz;
+			ss.x = pt.x + Direction_XFactor(dir) * 0x500;
+			ss.y = pt.y + Direction_YFactor(dir) * 0x500;
+			ss.z = pt.z;
 		}
 
 		uint16 targetid = (target ? target->getObjId() : 0);
 		ssp = new SuperSpriteProcess(BULLET_SPLASH_SHAPE, spriteframe,
-									 ix, iy, iz, ssx, ssy, ssz, firetype,
+									 pt.x, pt.y, pt.z, ss.x, ss.y, ss.z, firetype,
 									 damage, _objId, targetid, findtarget);
 		Kernel::get_instance()->addProcess(ssp);
 		spriteprocpid = ssp->getPid();
@@ -1429,11 +1436,8 @@ uint16 Item::fireDistance(const Item *other, Direction dir, int16 xoff, int16 yo
 		}
 	}
 
-	int32 x, y, z;
-	getLocation(x, y, z);
-
-	int32 ox, oy, oz;
-	other->getLocation(ox, oy, oz);
+	Point3 pt = getLocation();
+	Point3 pto = other->getLocation();
 
 	int32 dist = 0;
 
@@ -1442,13 +1446,13 @@ uint16 Item::fireDistance(const Item *other, Direction dir, int16 xoff, int16 yo
 		return 0;
 
 	for (int i = 0; i < (other_offsets ? 2 : 1) && dist == 0; i++) {
-		int32 cx = x + (i == 0 ? xoff : xoff2);
-		int32 cy = y + (i == 0 ? yoff : yoff2);
-		int32 cz = z + (i == 0 ? zoff : zoff2);
+		int32 cx = pt.x + (i == 0 ? xoff : xoff2);
+		int32 cy = pt.y + (i == 0 ? yoff : yoff2);
+		int32 cz = pt.z + (i == 0 ? zoff : zoff2);
 		PositionInfo info = cm->getPositionInfo(cx, cy, cz, BULLET_SPLASH_SHAPE, getObjId());
 		if (!info.valid && info.blocker) {
 			if (info.blocker->getObjId() == other->getObjId())
-				dist = MAX(abs(_x - ox), abs(_y - oy));
+				dist = MAX(abs(_x - pto.x), abs(_y - pto.y));
 		} else {
 			int32 ocx, ocy, ocz;
 			other->getCentre(ocx, ocy, ocz);
@@ -2096,9 +2100,8 @@ int32 Item::ascend(int delta) {
 	}
 
 	// move self
-	int32 xv, yv, zv;
-	getLocation(xv, yv, zv);
-	int dist = collideMove(xv, yv, zv + delta, false, false);
+	Point3 ptv = getLocation();
+	int dist = collideMove(ptv.x, ptv.y, ptv.z + delta, false, false);
 	delta = (delta * dist) / 0x4000;
 
 	debugC(kDebugObject, "Ascend: dist=%d", dist);
@@ -2109,7 +2112,10 @@ int32 Item::ascend(int delta) {
 		if (!item) continue;
 		if (item->getShapeInfo()->is_fixed()) continue;
 
-		item->getLocation(_ix, _iy, _iz);
+		Point3 pti = item->getLocation();
+		_ix = pti.x;
+		_iy = pti.y;
+		_iz = pti.z;
 
 		if (item->canExistAt(_ix, _iy, _iz + delta)) {
 			item->move(_ix, _iy, _iz + delta); // automatically un-etherealizes item
@@ -2255,8 +2261,7 @@ void Item::explode(int explosion_type, bool destroy_item, bool cause_damage) {
 		audioproc->playSFX(sfx, 0x60, 0, 0);
 	}
 
-	int32 xv, yv, zv;
-	getLocation(xv, yv, zv);
+	Point3 ptv = getLocation();
 
 	if (destroy_item) {
 		destroy(); // delete self
@@ -2271,21 +2276,20 @@ void Item::explode(int explosion_type, bool destroy_item, bool cause_damage) {
 		LOOPSCRIPT(script, LS_TOKEN_TRUE); // we want all items
 		CurrentMap *currentmap = World::get_instance()->getCurrentMap();
 		currentmap->areaSearch(&itemlist, script, sizeof(script), 0,
-							   160, false, xv, yv); //! CHECKME: 128?
+							   160, false, ptv.x, ptv.y); //! CHECKME: 128?
 
 		for (unsigned int i = 0; i < itemlist.getSize(); ++i) {
 			Item *item = getItem(itemlist.getuint16(i));
 			if (!item) continue;
 			if (getRange(*item, true) > 160) continue; // check vertical distance
 
-			item->getLocation(xv, yv, zv);
-			Direction dir = Direction_GetWorldDir(xv - xv, yv - yv, dirmode_8dirs); //!! CHECKME
+			Point3 pti = item->getLocation();
+			Direction dir = Direction_GetWorldDir(pti.x - ptv.x, pti.y - ptv.y, dirmode_8dirs); //!! CHECKME
 			item->receiveHit(0, dir, rs.getRandomNumberRng(6, 11),
 							 WeaponInfo::DMG_BLUNT | WeaponInfo::DMG_FIRE);
 		}
 	} else {
-		Point3 pt;
-		getLocation(pt);
+		Point3 pt = getLocation();
 		// Note: same FireType number used in both Remorse and Regret
 		const FireType *firetypedat = GameData::get_instance()->getFireType(4);
 		if (firetypedat) {
@@ -2445,7 +2449,6 @@ static bool checkLineOfSightCollisions(
 bool Item::canReach(const Item *other, int range,
 					int32 otherX, int32 otherY, int32 otherZ) const {
 	// get location and dimensions of self and other (or their root containers)
-	int32 thisX, thisY, thisZ;
 	int32 thisXd, thisYd, thisZd;
 	int32 otherXd, otherYd, otherZd;
 	int32 thisXmin, thisYmin;
@@ -2453,25 +2456,31 @@ bool Item::canReach(const Item *other, int range,
 
 	bool usingAlternatePos = (otherX != 0);
 
-	getLocationAbsolute(thisX, thisY, thisZ);
+	Point3 pt1 = getLocationAbsolute();
 	other = other->getTopItem();
-	if (otherX == 0)
-		other->getLocationAbsolute(otherX, otherY, otherZ);
+	if (otherX == 0) {
+		Point3 pt2 = other->getLocationAbsolute();
+		otherX = pt2.x;
+		otherY = pt2.y;
+		otherZ = pt2.z;
+	}
 
 	getFootpadWorld(thisXd, thisYd, thisZd);
 	other->getFootpadWorld(otherXd, otherYd, otherZd);
 
-	thisXmin = thisX - thisXd;
-	thisYmin = thisY - thisYd;
+	thisXmin = pt1.x - thisXd;
+	thisYmin = pt1.y - thisYd;
 
 	otherXmin = otherX - otherXd;
 	otherYmin = otherY - otherYd;
 
 	// if items are further away than range in any direction, return false
 	if (thisXmin - otherX > range) return false;
-	if (otherXmin - thisX > range) return false;
+	if (otherXmin - pt1.x > range)
+		return false;
 	if (thisYmin - otherY > range) return false;
-	if (otherYmin - thisY > range) return false;
+	if (otherYmin - pt1.y > range)
+		return false;
 
 
 	// if not, do line of sight between origins of items
@@ -2479,13 +2488,13 @@ bool Item::canReach(const Item *other, int range,
 	int32 end[3];
 	int32 dims[3] = { 2, 2, 2 };
 
-	start[0] = thisX;
-	start[1] = thisY;
-	start[2] = thisZ;
+	start[0] = pt1.x;
+	start[1] = pt1.y;
+	start[2] = pt1.z;
 	end[0] = otherX;
 	end[1] = otherY;
 	end[2] = otherZ;
-	if (otherZ > thisZ && otherZ < thisZ + thisZd)
+	if (otherZ > pt1.z && otherZ < pt1.z + thisZd)
 		start[2] = end[2]; // bottom of other between bottom and top of this
 
 	Std::list<CurrentMap::SweepItem> collisions;
@@ -2499,9 +2508,9 @@ bool Item::canReach(const Item *other, int range,
 		return true;
 
 	// if that fails, try line of sight between centers
-	start[0] = thisX - thisXd / 2; // xy center of this
-	start[1] = thisY - thisYd / 2;
-	start[2] = thisZ;
+	start[0] = pt1.x - thisXd / 2; // xy center of this
+	start[1] = pt1.y - thisYd / 2;
+	start[2] = pt1.z;
 	if (thisZd > 16)
 		start[2] += thisZd - 8; // eye height
 
@@ -2712,63 +2721,56 @@ uint32 Item::I_getX(const uint8 *args, unsigned int /*argsize*/) {
 	ARG_ITEM_FROM_PTR(item);
 	if (!item) return 0;
 
-	int32 x, y, z;
-	item->getLocationAbsolute(x, y, z);
-	return World_ToUsecodeCoord(x);
+	Point3 pt = item->getLocationAbsolute();
+	return World_ToUsecodeCoord(pt.x);
 }
 
 uint32 Item::I_getY(const uint8 *args, unsigned int /*argsize*/) {
 	ARG_ITEM_FROM_PTR(item);
 	if (!item) return 0;
 
-	int32 x, y, z;
-	item->getLocationAbsolute(x, y, z);
-	return World_ToUsecodeCoord(y);
+	Point3 pt = item->getLocationAbsolute();
+	return World_ToUsecodeCoord(pt.y);
 }
 
 uint32 Item::I_getZ(const uint8 *args, unsigned int /*argsize*/) {
 	ARG_ITEM_FROM_PTR(item);
 	if (!item) return 0;
 
-	int32 x, y, z;
-	item->getLocationAbsolute(x, y, z);
-	return z;
+	Point3 pt = item->getLocationAbsolute();
+	return pt.z;
 }
 
 uint32 Item::I_getCX(const uint8 *args, unsigned int /*argsize*/) {
 	ARG_ITEM_FROM_PTR(item);
 	if (!item) return 0;
 
-	int32 x, y, z;
-	item->getLocationAbsolute(x, y, z);
+	Point3 pt = item->getLocationAbsolute();
 
 	if (item->_flags & FLG_FLIPPED)
-		return World_ToUsecodeCoord(x - item->getShapeInfo()->_y * 16);
+		return World_ToUsecodeCoord(pt.x - item->getShapeInfo()->_y * 16);
 	else
-		return World_ToUsecodeCoord(x - item->getShapeInfo()->_x * 16);
+		return World_ToUsecodeCoord(pt.x - item->getShapeInfo()->_x * 16);
 }
 
 uint32 Item::I_getCY(const uint8 *args, unsigned int /*argsize*/) {
 	ARG_ITEM_FROM_PTR(item);
 	if (!item) return 0;
 
-	int32 x, y, z;
-	item->getLocationAbsolute(x, y, z);
+	Point3 pt = item->getLocationAbsolute();
 
 	if (item->_flags & FLG_FLIPPED)
-		return World_ToUsecodeCoord(y - item->getShapeInfo()->_x * 16);
+		return World_ToUsecodeCoord(pt.y - item->getShapeInfo()->_x * 16);
 	else
-		return World_ToUsecodeCoord(y - item->getShapeInfo()->_y * 16);
+		return World_ToUsecodeCoord(pt.y - item->getShapeInfo()->_y * 16);
 }
 
 uint32 Item::I_getCZ(const uint8 *args, unsigned int /*argsize*/) {
 	ARG_ITEM_FROM_PTR(item);
 	if (!item) return 0;
 
-	int32 x, y, z;
-	item->getLocationAbsolute(x, y, z);
-
-	return z + item->getShapeInfo()->_z * 4;
+	Point3 pt = item->getLocationAbsolute();
+	return pt.z + item->getShapeInfo()->_z * 4;
 }
 
 uint32 Item::I_getPoint(const uint8 *args, unsigned int /*argsize*/) {
@@ -2776,15 +2778,13 @@ uint32 Item::I_getPoint(const uint8 *args, unsigned int /*argsize*/) {
 	ARG_UC_PTR(ptr);
 	if (!item) return 0;
 
-	int32 x, y, z;
-	item->getLocationAbsolute(x, y, z);
-
-	World_ToUsecodeXY(x, y);
+	Point3 pt = item->getLocationAbsolute();
+	World_ToUsecodeXY(pt.x, pt.y);
 
 	WorldPoint point;
-	point.setX(x);
-	point.setY(y);
-	point.setZ(z);
+	point.setX(pt.x);
+	point.setY(pt.y);
+	point.setZ(pt.z);
 
 	UCMachine::get_instance()->assignPointer(ptr, point._buf, 5);
 
@@ -3523,8 +3523,7 @@ uint32 Item::I_popToContainer(const uint8 *args, unsigned int /*argsize*/) {
 	if (container) {
 		item->moveToContainer(container);
 	} else if (citem) {
-		Point3 pt;
-		citem->getLocation(pt);
+		Point3 pt = citem->getLocation();
 		item->move(pt);
 	} else {
 		warning("Trying to popToContainer to invalid container (%u)", id_citem);
@@ -3566,8 +3565,7 @@ uint32 Item::I_popToEnd(const uint8 *args, unsigned int /*argsize*/) {
 	if (container) {
 		item->moveToContainer(container);
 	} else if (citem) {
-		Point3 pt;
-		citem->getLocation(pt);
+		Point3 pt = citem->getLocation();
 		item->move(pt);
 	} else {
 		warning("Trying to popToEnd to invalid container (%u)", id_citem);
@@ -3636,7 +3634,10 @@ uint32 Item::I_legalMoveToPoint(const uint8 *args, unsigned int argsize) {
 	end[0] = x;
 	end[1] = y;
 	end[2] = z;
-	item->getLocation(start[0], start[1], start[2]);
+	Point3 pt = item->getLocation();
+	start[0] = pt.x;
+	start[1] = pt.y;
+	start[2] = pt.z;
 	item->getFootpadWorld(dims[0], dims[1], dims[2]);
 	CurrentMap *map = World::get_instance()->getCurrentMap();
 	map->sweepTest(start, end, dims, item->getShapeInfo()->_flags,
@@ -3714,10 +3715,9 @@ uint32 Item::I_getDirToCoords(const uint8 *args, unsigned int /*argsize*/) {
 
 	World_FromUsecodeXY(x, y);
 
-	int32 ix, iy, iz;
-	item->getLocationAbsolute(ix, iy, iz);
+	Point3 pt = item->getLocationAbsolute();
 
-	return Direction_ToUsecodeDir(Direction_GetWorldDir(y - iy, x - ix, dirmode_8dirs));
+	return Direction_ToUsecodeDir(Direction_GetWorldDir(y - pt.y, x - pt.x, dirmode_8dirs));
 }
 
 uint32 Item::I_getDirFromCoords(const uint8 *args, unsigned int /*argsize*/) {
@@ -3728,10 +3728,9 @@ uint32 Item::I_getDirFromCoords(const uint8 *args, unsigned int /*argsize*/) {
 
 	World_FromUsecodeXY(x, y);
 
-	int32 ix, iy, iz;
-	item->getLocationAbsolute(ix, iy, iz);
+	Point3 pt = item->getLocationAbsolute();
 
-	return Direction_ToUsecodeDir(Direction_GetWorldDir(iy - y, ix - x, dirmode_8dirs));
+	return Direction_ToUsecodeDir(Direction_GetWorldDir(pt.y - y, pt.x - x, dirmode_8dirs));
 }
 
 uint32 Item::I_getDirToItem(const uint8 *args, unsigned int /*argsize*/) {
@@ -3740,13 +3739,10 @@ uint32 Item::I_getDirToItem(const uint8 *args, unsigned int /*argsize*/) {
 	if (!item) return 0;
 	if (!item2) return 0;
 
-	int32 ix, iy, iz;
-	item->getLocationAbsolute(ix, iy, iz);
+	Point3 pt1 = item->getLocationAbsolute();
+	Point3 pt2 = item2->getLocationAbsolute();
 
-	int32 i2x, i2y, i2z;
-	item2->getLocationAbsolute(i2x, i2y, i2z);
-
-	return Direction_ToUsecodeDir(Direction_GetWorldDir(i2y - iy, i2x - ix, dirmode_8dirs));
+	return Direction_ToUsecodeDir(Direction_GetWorldDir(pt2.y - pt1.y, pt2.x - pt1.x, dirmode_8dirs));
 }
 
 uint32 Item::I_getDirFromItem(const uint8 *args, unsigned int /*argsize*/) {
@@ -3755,13 +3751,10 @@ uint32 Item::I_getDirFromItem(const uint8 *args, unsigned int /*argsize*/) {
 	if (!item) return 0;
 	if (!item2) return 0;
 
-	int32 ix, iy, iz;
-	item->getLocationAbsolute(ix, iy, iz);
-
-	int32 i2x, i2y, i2z;
-	item2->getLocationAbsolute(i2x, i2y, i2z);
+	Point3 pt1 = item->getLocationAbsolute();
+	Point3 pt2 = item2->getLocationAbsolute();
 
-	return Direction_ToUsecodeDir(Direction_Invert(Direction_GetWorldDir(i2y - iy, i2x - ix, dirmode_8dirs)));
+	return Direction_ToUsecodeDir(Direction_Invert(Direction_GetWorldDir(pt2.y - pt1.y, pt2.x - pt1.x, dirmode_8dirs)));
 }
 
 uint32 Item::I_getDirFromTo16(const uint8 *args, unsigned int /*argsize*/) {
diff --git a/engines/ultima/ultima8/world/item.h b/engines/ultima/ultima8/world/item.h
index 6940f89ccd0..a1e23928b52 100644
--- a/engines/ultima/ultima8/world/item.h
+++ b/engines/ultima/ultima8/world/item.h
@@ -96,14 +96,13 @@ public:
 
 	//! Get the location of the top-most container this Item is in, or
 	//! this Item's location if not in a container.
-	void getLocationAbsolute(int32 &x, int32 &y, int32 &z) const;
+	Point3 getLocationAbsolute() const;
 
 	//! Get this Item's location. Note that this does not return
 	//! 'usable' coordinates if the Item is contained or equipped.
-	inline void getLocation(int32 &x, int32 &y, int32 &z) const;
-
-	//! Get the Item's location using a Point3 struct.
-	inline void getLocation(Point3 &pt) const;
+	inline Point3 getLocation() const {
+		return Point3(_x, _y, _z);
+	}
 
 	//! Get this Item's Z coordinate.
 	int32 getZ() const;
@@ -461,10 +460,8 @@ public:
 	uint32 use();
 
 	//! Get lerped location.
-	inline void getLerped(int32 &xp, int32 &yp, int32 &zp) const {
-		xp = _ix;
-		yp = _iy;
-		zp = _iz;
+	inline Point3 getLerped() const {
+		return Point3(_ix, _iy, _iz);
 	}
 
 	//! Do lerping for an in between frame (0-256)
@@ -735,18 +732,6 @@ inline void Item::getFootpadWorld(int32 &X, int32 &Y, int32 &Z) const {
 	si->getFootpadWorld(X, Y, Z, _flags & Item::FLG_FLIPPED);
 }
 
-inline void Item::getLocation(int32 &X, int32 &Y, int32 &Z) const {
-	X = _x;
-	Y = _y;
-	Z = _z;
-}
-
-inline void Item::getLocation(Point3 &pt) const {
-	pt.x = _x;
-	pt.y = _y;
-	pt.z = _z;
-}
-
 } // End of namespace Ultima8
 } // End of namespace Ultima
 
diff --git a/engines/ultima/ultima8/world/item_sorter.cpp b/engines/ultima/ultima8/world/item_sorter.cpp
index 0d9681345cd..45fbbd9e30e 100644
--- a/engines/ultima/ultima8/world/item_sorter.cpp
+++ b/engines/ultima/ultima8/world/item_sorter.cpp
@@ -72,7 +72,7 @@ ItemSorter::~ItemSorter() {
 	}
 }
 
-void ItemSorter::BeginDisplayList(const Rect &clipWindow, int32 camx, int32 camy, int32 camz) {
+void ItemSorter::BeginDisplayList(const Rect &clipWindow, const Point3 &cam) {
 	// Get the _shapes, if required
 	if (!_shapes) _shapes = GameData::get_instance()->getMainShapes();
 
@@ -89,9 +89,9 @@ void ItemSorter::BeginDisplayList(const Rect &clipWindow, int32 camx, int32 camy
 	_painted = nullptr;
 
 	// Screenspace bounding box bottom x coord (RNB x coord)
-	int32 camSx = (camx - camy) / 4;
+	int32 camSx = (cam.x - cam.y) / 4;
 	// Screenspace bounding box bottom extent  (RNB y coord)
-	int32 camSy = (camx + camy) / 8 - camz;
+	int32 camSy = (cam.x + cam.y) / 8 - cam.z;
 
 	if (camSx != _camSx || camSy != _camSy) {
 		_camSx = camSx;
@@ -102,7 +102,7 @@ void ItemSorter::BeginDisplayList(const Rect &clipWindow, int32 camx, int32 camy
 	}
 }
 
-void ItemSorter::AddItem(int32 x, int32 y, int32 z, uint32 shapeNum, uint32 frame_num, uint32 flags, uint32 ext_flags, uint16 itemNum) {
+void ItemSorter::AddItem(const Point3 &pt, uint32 shapeNum, uint32 frame_num, uint32 flags, uint32 ext_flags, uint16 itemNum) {
 
 	// First thing, get a SortItem to use (first of unused)
 	if (!_itemsUnused)
@@ -135,7 +135,7 @@ void ItemSorter::AddItem(int32 x, int32 y, int32 z, uint32 shapeNum, uint32 fram
 	info->getFootpadWorld(xd, yd, zd, flags & Item::FLG_FLIPPED);
 
 	// Worldspace bounding box
-	Box box(x, y, z, xd, yd, zd);
+	Box box(pt.x, pt.y, pt.z, xd, yd, zd);
 	si->setBoxBounds(box, _camSx, _camSy);
 
 	// Real Screenspace from shape frame
@@ -270,9 +270,7 @@ void ItemSorter::AddItem(int32 x, int32 y, int32 z, uint32 shapeNum, uint32 fram
 }
 
 void ItemSorter::AddItem(const Item *add) {
-	int32 x, y, z;
-	add->getLerped(x, y, z);
-	AddItem(x, y, z, add->getShape(), add->getFrame(),
+	AddItem(add->getLerped(), add->getShape(), add->getFrame(),
 			add->getFlags(), add->getExtFlags(), add->getObjId());
 }
 
diff --git a/engines/ultima/ultima8/world/item_sorter.h b/engines/ultima/ultima8/world/item_sorter.h
index 974892f9ee7..0bdc2d80911 100644
--- a/engines/ultima/ultima8/world/item_sorter.h
+++ b/engines/ultima/ultima8/world/item_sorter.h
@@ -31,6 +31,7 @@ class MainShapeArchive;
 class Item;
 class RenderSurface;
 struct SortItem;
+struct Point3;
 
 class ItemSorter {
 	MainShapeArchive    *_shapes;
@@ -54,9 +55,9 @@ public:
 	};
 
 	// Begin creating the display list
-	void BeginDisplayList(const Rect &clipWindow, int32 camx, int32 camy, int32 camz);
+	void BeginDisplayList(const Rect &clipWindow, const Point3 &cam);
 
-	void AddItem(int32 x, int32 y, int32 z, uint32 shape_num, uint32 frame_num, uint32 item_flags, uint32 ext_flags, uint16 item_num = 0);
+	void AddItem(const Point3 &pt, uint32 shape_num, uint32 frame_num, uint32 item_flags, uint32 ext_flags, uint16 item_num = 0);
 	void AddItem(const Item *);                   // Add an Item. SetupLerp() MUST have been called
 
 	// Finishes the display list and Paints
diff --git a/engines/ultima/ultima8/world/map.cpp b/engines/ultima/ultima8/world/map.cpp
index d5b5b7e9c57..1ca363d8b13 100644
--- a/engines/ultima/ultima8/world/map.cpp
+++ b/engines/ultima/ultima8/world/map.cpp
@@ -144,12 +144,11 @@ void Map::loadFixed(Common::SeekableReadStream *rs) {
 
 		for (iter = _fixedItems.begin(); iter != _fixedItems.end(); ++iter) {
 			if ((*iter)->getShape() == 347 && (*iter)->getZ() == 96) {
-				int32 x, y, z;
-				(*iter)->getLocation(x, y, z);
-				if ((x == 23007 && y == 21343) || (x == 23135 && y == 21471) ||
-				        (x == 23135 && y == 21343)) {
-					shiftCoordsToZ(x, y, z, 40);
-					(*iter)->setLocation(x, y, z);
+				Point3 pt = (*iter)->getLocation();
+				if ((pt.x == 23007 && pt.y == 21343) || (pt.x == 23135 && pt.y == 21471) ||
+				        (pt.x == 23135 && pt.y == 21343)) {
+					shiftCoordsToZ(pt.x, pt.y, pt.z, 40);
+					(*iter)->setLocation(pt.x, pt.y, pt.z);
 				}
 			}
 		}
@@ -163,11 +162,10 @@ void Map::loadFixed(Common::SeekableReadStream *rs) {
 			int32 z = (*iter)->getZ();
 			uint32 sh = (*iter)->getShape();
 			if (z == 8 && (sh == 301 || sh == 31 || sh == 32)) {
-				int32 x, y;
-				(*iter)->getLocation(x, y, z);
-				if ((x == 6783 || x == 6655) && (y == 15743 || y == 15615)) {
-					shiftCoordsToZ(x, y, z, 16);
-					(*iter)->setLocation(x, y, z);
+				Point3 pt = (*iter)->getLocation();
+				if ((pt.x == 6783 || pt.x == 6655) && (pt.y == 15743 || pt.y == 15615)) {
+					shiftCoordsToZ(pt.x, pt.y, pt.z, 16);
+					(*iter)->setLocation(pt.x, pt.y, pt.z);
 				}
 			}
 		}
@@ -179,14 +177,13 @@ void Map::loadFixed(Common::SeekableReadStream *rs) {
 
 		for (iter = _fixedItems.begin(); iter != _fixedItems.end(); ++iter) {
 			if ((*iter)->getShape() == 71 && (*iter)->getFrame() == 8 && (*iter)->getZ() == 0) {
-				int32 x, y, z;
-				(*iter)->getLocation(x, y, z);
-				if ((x == 9151 && y == 24127) || (x == 9279 && y == 23999) ||
-				        (x == 9535 && y == 23615) || (x == 9151 && y == 23487) ||
-				        (x == 10303 && y == 23487) || (x == 9919 && y == 23487) ||
-				        (x == 10559 && y == 23487)) {
-					shiftCoordsToZ(x, y, z, 48);
-					(*iter)->setLocation(x, y, z);
+				Point3 pt = (*iter)->getLocation();
+				if ((pt.x == 9151 && pt.y == 24127) || (pt.x == 9279 && pt.y == 23999) ||
+				        (pt.x == 9535 && pt.y == 23615) || (pt.x == 9151 && pt.y == 23487) ||
+				        (pt.x == 10303 && pt.y == 23487) || (pt.x == 9919 && pt.y == 23487) ||
+				        (pt.x == 10559 && pt.y == 23487)) {
+					shiftCoordsToZ(pt.x, pt.y, pt.z, 48);
+					(*iter)->setLocation(pt.x, pt.y, pt.z);
 				}
 			}
 		}
diff --git a/engines/ultima/ultima8/world/minimap.cpp b/engines/ultima/ultima8/world/minimap.cpp
index 5a5c3fd57d3..bcb4bef9f98 100644
--- a/engines/ultima/ultima8/world/minimap.cpp
+++ b/engines/ultima/ultima8/world/minimap.cpp
@@ -75,12 +75,11 @@ void MiniMap::update(const CurrentMap &map) {
 }
 
 Common::Point MiniMap::getItemLocation(const Item &item, unsigned int chunkSize) {
-	int32 x, y, z;
-	item.getLocation(x, y, z);
+	Point3 pt = item.getLocation();
 
-	x = x / (chunkSize / MINMAPGUMP_SCALE);
-	y = y / (chunkSize / MINMAPGUMP_SCALE);
-	return Common::Point(x, y);
+	pt.x = pt.x / (chunkSize / MINMAPGUMP_SCALE);
+	pt.y = pt.y / (chunkSize / MINMAPGUMP_SCALE);
+	return Common::Point(pt.x, pt.y);
 }
 
 uint32 MiniMap::sampleAtPoint(const CurrentMap &map, int x, int y) {
@@ -110,12 +109,12 @@ uint32 MiniMap::sampleAtPoint(const CurrentMap &map, int x, int y) {
 }
 
 uint32 MiniMap::sampleAtPoint(const Item &item, int x, int y) {
-	int32 ix, iy, iz, idx, idy, idz;
-	item.getLocation(ix, iy, iz);
+	int32 idx, idy, idz;
+	Point3 pt = item.getLocation();
 	item.getFootpadWorld(idx, idy, idz);
 
-	ix -= x;
-	iy -= y;
+	pt.x -= x;
+	pt.y -= y;
 
 	const Shape *sh = item.getShapeObject();
 	if (!sh)
@@ -133,9 +132,9 @@ uint32 MiniMap::sampleAtPoint(const Item &item, int x, int y) {
 		return KEY_COLOR;
 
 	// Screenspace bounding box bottom x_ coord (RNB x_ coord)
-	int sx = (ix - iy) / 4;
+	int sx = (pt.x - pt.y) / 4;
 	// Screenspace bounding box bottom extent  (RNB y_ coord)
-	int sy = (ix + iy) / 8 + idz;
+	int sy = (pt.x + pt.y) / 8 + idz;
 
 	int w = 3;
 	int h = 3;
diff --git a/engines/ultima/ultima8/world/missile_tracker.cpp b/engines/ultima/ultima8/world/missile_tracker.cpp
index 3c9739406aa..aa7222602d4 100644
--- a/engines/ultima/ultima8/world/missile_tracker.cpp
+++ b/engines/ultima/ultima8/world/missile_tracker.cpp
@@ -50,10 +50,8 @@ MissileTracker::MissileTracker(const Item *item, ObjId owner,
 
 	_objId = item->getObjId();
 
-	int32 x, y, z;
-	item->getLocation(x, y, z);
-
-	init(x, y, z, speed);
+	Point3 pt = item->getLocation();
+	init(pt.x, pt.y, pt.z, speed);
 }
 
 void MissileTracker::init(int32 x, int32 y, int32 z, int32 speed) {
@@ -140,7 +138,10 @@ bool MissileTracker::isPathClear() const {
 	}
 
 	item->getFootpadWorld(dims[0], dims[1], dims[2]);
-	item->getLocation(start[0], start[1], start[2]);
+	Point3 pt = item->getLocation();
+	start[0] = pt.x;
+	start[1] = pt.y;
+	start[2] = pt.z;
 
 	for (int f = 0; f < _frames; ++f) {
 		end[0] = start[0] + sx;
diff --git a/engines/ultima/ultima8/world/snap_process.cpp b/engines/ultima/ultima8/world/snap_process.cpp
index 697ae6fbab8..04443193a99 100644
--- a/engines/ultima/ultima8/world/snap_process.cpp
+++ b/engines/ultima/ultima8/world/snap_process.cpp
@@ -92,10 +92,10 @@ void SnapProcess::updateCurrentEgg() {
 	if (!a)
 		return;
 
-	int32 ax, ay, az, axd, ayd, azd, x, y, z;
-	a->getLocation(ax, ay, az);
+	int32 axd, ayd, azd;
+	Point3 pta = a->getLocation();
 	a->getFootpadWorld(axd, ayd, azd);
-	Rect arect(ax, ay, ax + axd, ay + ayd);
+	Rect arect(pta.x, pta.y, pta.x + axd, pta.y + ayd);
 
 	for (Std::list<ObjId>::const_iterator iter = _snapEggs.begin();
 		 iter != _snapEggs.end(); iter++) {
@@ -103,9 +103,9 @@ void SnapProcess::updateCurrentEgg() {
 		if (!egg)
 			continue;
 		Rect r;
-		egg->getLocation(x, y, z);
+		Point3 pte = egg->getLocation();
 		getSnapEggRange(egg, r);
-		if (r.intersects(arect) && (az <= z + 0x30 && az >= z - 0x30)) {
+		if (r.intersects(arect) && (pta.z <= pte.z + 0x30 && pta.z >= pte.z - 0x30)) {
 			_currentSnapEgg = *iter;
 			_currentSnapEggRange = r;
 			CameraProcess::SetCameraProcess(new CameraProcess(_currentSnapEgg));
@@ -145,16 +145,16 @@ bool SnapProcess::isNpcInRangeOfCurrentEgg() const {
 	if (!a || !currentegg)
 		return false;
 
-	int32 ax, ay, az, axd, ayd, azd, x, y, z;
-	a->getLocation(ax, ay, az);
+	int32 axd, ayd, azd;
+	Point3 pta = a->getLocation();
 	a->getFootpadWorld(axd, ayd, azd);
-	currentegg->getLocation(x, y, z);
+	Point3 pte = currentegg->getLocation();
 
-	Rect arect(ax, ay, ax + axd, ay + ayd);
+	Rect arect(pta.x, pta.y, pta.x + axd, pta.y + ayd);
 
 	if (!_currentSnapEggRange.intersects(arect))
 		return false;
-	if (az > z + 0x30 || az < z - 0x30)
+	if (pta.z > pte.z + 0x30 || pta.z < pte.z - 0x30)
 		return false;
 
 	return true;
@@ -169,11 +169,10 @@ void SnapProcess::getSnapEggRange(const Item *item, Rect &rect) const {
 	int32 xrange = (qhi >> 4) * 0x20;
 	int32 yrange = (qhi & 0xf) * 0x20;
 
-	int32 x, y, z;
-	item->getLocation(x, y, z);
+	Point3 pt = item->getLocation();
 
-	rect.left = x - xrange + xoff;
-	rect.top = y - yrange + yoff;
+	rect.left = pt.x - xrange + xoff;
+	rect.top = pt.y - yrange + yoff;
 	rect.setWidth(xrange * 2);
 	rect.setHeight(yrange * 2);
 }
diff --git a/engines/ultima/ultima8/world/super_sprite_process.cpp b/engines/ultima/ultima8/world/super_sprite_process.cpp
index 43c50195085..cb72b8aed18 100644
--- a/engines/ultima/ultima8/world/super_sprite_process.cpp
+++ b/engines/ultima/ultima8/world/super_sprite_process.cpp
@@ -184,12 +184,11 @@ void SuperSpriteProcess::run() {
 				} else {
 					const Item *target = getItem(_target);
 					if (target) {
-						int32 tx, ty, tz;
 						int32 cx, cy, cz;
-						target->getLocation(tx, ty, tz);
+						Point3 ptt = target->getLocation();
 						target->getCentre(cx, cy, cz);
 						targetz = cz + 8;
-						dir8 = Direction_GetWorldDir(ty - _nowpt.y, tx - _nowpt.x, dirmode_8dirs);
+						dir8 = Direction_GetWorldDir(ptt.y - _nowpt.y, ptt.x - _nowpt.x, dirmode_8dirs);
 					}
 				}
 
@@ -357,16 +356,15 @@ void SuperSpriteProcess::hitAndFinish() {
 	if (item) {
 		int32 ifx, ify, ifz;
 		item->getFootpadData(ifx, ify, ifz);
-		int32 ix, iy, iz;
-		item->getLocation(ix, iy, iz);
+		Point3 pti = item->getLocation();
 
 		if (ifx > 2 && ify > 2 && ifz > 2) {
 			int32 ixsize = (ifx - 2) * 16;
 			int32 iysize = (ify - 2) * 16;
-			if (pt.x < ix - ixsize)
-				pt.x = ix - ixsize;
-			if (pt.y < iy - iysize)
-				pt.y = iy - iysize;
+			if (pt.x < pti.x - ixsize)
+				pt.x = pti.x - ixsize;
+			if (pt.y < pti.y - iysize)
+				pt.y = pti.y - iysize;
 		}
 
 		//Actor *actor = dynamic_cast<Actor *>(item);
@@ -374,7 +372,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, dirmode_8dirs);
+		Direction dir = Direction_GetWorldDir(pti.y - _nowpt.y, pti.x - _nowpt.x, dirmode_8dirs);
 		item->receiveHit(_itemNum, dir, _damage, _fireType);
 	}
 	makeBulletSplash(pt);
@@ -449,8 +447,12 @@ bool SuperSpriteProcess::areaSearch() {
 	int32 dims[3] = {1, 1, 1};
 
 	Item *item = getItem(_itemNum);
-	if (item)
-		item->getLocation(start[0], start[1], start[2]);
+	if (item) {
+		Point3 pt = item->getLocation();
+		start[0] = pt.x;
+		start[1] = pt.y;
+		start[2] = pt.z;
+	}
 
 	Std::list<CurrentMap::SweepItem> hits;
 	map->sweepTest(start, end, dims, ShapeInfo::SI_SOLID,
diff --git a/engines/ultima/ultima8/world/target_reticle_process.cpp b/engines/ultima/ultima8/world/target_reticle_process.cpp
index 9b5adbe2717..0426fff42c2 100644
--- a/engines/ultima/ultima8/world/target_reticle_process.cpp
+++ b/engines/ultima/ultima8/world/target_reticle_process.cpp
@@ -101,10 +101,9 @@ bool TargetReticleProcess::findTargetItem() {
 
 	Direction dir = mainactor->getDir();
 
-	int32 x, y, z;
-	mainactor->getLocation(x, y, z);
+	Point3 pt = mainactor->getLocation();
 
-	Item *item = currentmap->findBestTargetItem(x, y, z, dir, dirmode_16dirs);
+	Item *item = currentmap->findBestTargetItem(pt.x, pt.y, pt.z, dir, dirmode_16dirs);
 
 	if (item && item->getObjId() != _lastTargetItem) {
 		Item *lastItem = getItem(_lastTargetItem);
diff --git a/engines/ultima/ultima8/world/world.cpp b/engines/ultima/ultima8/world/world.cpp
index 1827c8e5385..27d855144e4 100644
--- a/engines/ultima/ultima8/world/world.cpp
+++ b/engines/ultima/ultima8/world/world.cpp
@@ -348,9 +348,8 @@ void World::worldStats() const {
 	g_debugger->debugPrintf("Avatar pos.: ");
 	if (av) {
 		g_debugger->debugPrintf("map %d, (", av->getMapNum());
-		int32 x, y, z;
-		av->getLocation(x, y, z);
-		g_debugger->debugPrintf("%d,%d,%d)\n", x, y, z);
+		Point3 pt = av->getLocation();
+		g_debugger->debugPrintf("%d,%d,%d)\n", pt.x, pt.y, pt.z);
 	} else {
 		g_debugger->debugPrintf("missing (null)\n");
 	}




More information about the Scummvm-git-logs mailing list