[Scummvm-git-logs] scummvm master -> 7a3862b44bf44939af7f3350451b7d08604d111d

scemino noreply at scummvm.org
Sun May 5 19:15:28 UTC 2024


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

Summary:
c49960fed5 TWP: Add Goto next/previous object
213af70cc6 TWP: Use correct gamepad mapping
9105713b42 TWP: Fix unchecked return value in getUserPref function.
7a3862b44b TWP: Add Select Verb/Inventory


Commit: c49960fed5eaa72d97733332b3da1d6189e6c23b
    https://github.com/scummvm/scummvm/commit/c49960fed5eaa72d97733332b3da1d6189e6c23b
Author: scemino (scemino74 at gmail.com)
Date: 2024-05-05T21:15:17+02:00

Commit Message:
TWP: Add Goto next/previous object

Changed paths:
    engines/twp/actions.h
    engines/twp/metaengine.cpp
    engines/twp/object.cpp
    engines/twp/twp.cpp


diff --git a/engines/twp/actions.h b/engines/twp/actions.h
index 472d692f5ff..9d5c40a402f 100644
--- a/engines/twp/actions.h
+++ b/engines/twp/actions.h
@@ -31,6 +31,8 @@ enum TwpAction {
 	kMoveRight,
 	kMoveUp,
 	kMoveDown,
+	kGotoNextObject,
+	kGotoPreviousObject,
 	kSkipCutscene,
 	kSelectActor1,
 	kSelectActor2,
diff --git a/engines/twp/metaengine.cpp b/engines/twp/metaengine.cpp
index 0494eb40c2c..145a6fd8dc3 100644
--- a/engines/twp/metaengine.cpp
+++ b/engines/twp/metaengine.cpp
@@ -153,6 +153,8 @@ Common::Array<Common::Keymap *> TwpMetaEngine::initKeymaps(const char *target) c
 		{Common::kStandardActionMoveRight, _s("Right"), Twp::kMoveRight, "RIGHT|JOY_RIGHT", Common::EVENT_INVALID, Common::KEYCODE_RIGHT},
 		{Common::kStandardActionMoveUp, _s("Up"), Twp::kMoveUp, "UP|JOY_UP", Common::EVENT_INVALID, Common::KEYCODE_UP},
 		{Common::kStandardActionMoveDown, _s("Down"), Twp::kMoveDown, "DOWN|JOY_DOWN", Common::EVENT_INVALID, Common::KEYCODE_DOWN},
+		{"GOTONPREVOBJECT", _s("Go to previous object"), Twp::kGotoPreviousObject, "JOY_LEFT_SHOULDER", Common::EVENT_INVALID, Common::KEYCODE_INVALID},
+		{"GOTONEXTOBJECT", _s("Go to next object"), Twp::kGotoNextObject, "JOY_RIGHT_SHOULDER", Common::EVENT_INVALID, Common::KEYCODE_INVALID},
 		{"SKIPCUTSCENE", _s("Skip cutscene"), Twp::kSkipCutscene, "ESCAPE", Common::EVENT_INVALID, Common::KEYCODE_INVALID},
 		{"SELECTACTOR1", _s("Select Actor 1"), Twp::kSelectActor1, "1", Common::EVENT_INVALID, Common::KEYCODE_INVALID},
 		{"SELECTACTOR2", _s("Select Actor 2"), Twp::kSelectActor2, "2", Common::EVENT_INVALID, Common::KEYCODE_INVALID},
diff --git a/engines/twp/object.cpp b/engines/twp/object.cpp
index 3ea740f8f14..292cdb9a2d9 100644
--- a/engines/twp/object.cpp
+++ b/engines/twp/object.cpp
@@ -505,7 +505,7 @@ bool Object::inInventory() {
 }
 
 bool Object::contains(const Math::Vector2d &pos) {
-	Math::Vector2d p = pos - _node->getPos() - _node->getOffset();
+	Math::Vector2d p = pos - _node->getAbsPos();
 	return _hotspot.contains(p.getX(), p.getY());
 }
 
diff --git a/engines/twp/twp.cpp b/engines/twp/twp.cpp
index 5bff288b697..dd5c678448c 100644
--- a/engines/twp/twp.cpp
+++ b/engines/twp/twp.cpp
@@ -60,6 +60,118 @@ namespace Twp {
 
 TwpEngine *g_twp;
 
+struct GetNoun {
+	GetNoun(int verbId, Common::SharedPtr<Object> &obj) : _verbId(verbId), _noun(obj) {
+		_noun = nullptr;
+	}
+
+	bool operator()(Common::SharedPtr<Object> obj) {
+		if (((_verbId == VERB_TALKTO) || (_verbId == VERB_WALKTO) || !g_twp->_resManager->isActor(obj->getId())) && (obj->_node->getZSort() <= _zOrder)) {
+			_noun = obj;
+			_zOrder = obj->_node->getZSort();
+		}
+		return false;
+	}
+
+public:
+	Common::SharedPtr<Object> &_noun;
+	int _zOrder = INT_MAX;
+	const int _verbId;
+};
+
+struct GetUseNoun2 {
+	explicit GetUseNoun2(Common::SharedPtr<Object> &obj) : _noun2(obj) {
+		_noun2 = nullptr;
+	}
+
+	bool operator()(Common::SharedPtr<Object> obj) {
+		if (obj->_node->getZSort() <= _zOrder) {
+			if ((obj != g_twp->_actor) && (g_twp->_noun2 != obj)) {
+				_noun2 = obj;
+				_zOrder = obj->_node->getZSort();
+			}
+		}
+		return false;
+	}
+
+public:
+	Common::SharedPtr<Object> &_noun2;
+	int _zOrder = INT_MAX;
+};
+
+struct GetGiveableNoun2 {
+	explicit GetGiveableNoun2(Common::SharedPtr<Object> &obj) : _noun2(obj) {
+		_noun2 = nullptr;
+	}
+
+	bool operator()(Common::SharedPtr<Object> obj) {
+		if ((obj != g_twp->_actor) && (obj->getFlags() & GIVEABLE) && (g_twp->_noun2 != obj)) {
+			_noun2 = obj;
+			return true;
+		}
+		return false;
+	}
+
+public:
+	Common::SharedPtr<Object> &_noun2;
+};
+
+struct InInventory {
+	explicit InInventory(Common::SharedPtr<Object> &obj) : _obj(obj) { _obj = nullptr; }
+	bool operator()(Common::SharedPtr<Object> obj) {
+		if (obj->inInventory()) {
+			_obj = obj;
+			return true;
+		}
+		return false;
+	}
+
+public:
+	Common::SharedPtr<Object> &_obj;
+};
+
+typedef struct ObjPos {
+	ObjPos(Common::SharedPtr<Object> obj, const Math::Vector2d &pos, float distance, int index) : _obj(obj), _pos(pos), _distance(distance), _index(index) {}
+	float _distance = 0.f;
+	Math::Vector2d _pos;
+	Common::SharedPtr<Object> _obj;
+	int _index;
+} ObjPos;
+
+struct ObjPosComparer {
+	bool operator()(const ObjPos &x, const ObjPos &y) const {
+		return x._distance < y._distance;
+	}
+};
+
+struct GetByZOrder {
+	explicit GetByZOrder(Common::SharedPtr<Object> &result) : _result(result) {
+		result = nullptr;
+	}
+
+	bool operator()(Common::SharedPtr<Object> obj) {
+		if (obj->_node->getZSort() <= _zOrder) {
+			if (!g_twp->_resManager->isActor(obj->getId()) || !obj->_key.empty()) {
+				_result = obj;
+				_zOrder = obj->_node->getZSort();
+			}
+		}
+		return false;
+	}
+
+public:
+	Common::SharedPtr<Object> &_result;
+
+private:
+	int _zOrder = INT_MAX;
+};
+
+struct DefineObjectParams {
+	HSQUIRRELVM v;
+	bool pseudo;
+	Common::SharedPtr<Room> room;
+};
+
 TwpEngine::TwpEngine(OSystem *syst, const TwpGameDescription *gameDesc)
 	: Engine(syst),
 	  _gameDescription(gameDesc),
@@ -326,20 +438,6 @@ void objsAt(Math::Vector2d pos, TFunc func) {
 	}
 }
 
-struct InInventory {
-	explicit InInventory(Common::SharedPtr<Object> &obj) : _obj(obj) { _obj = nullptr; }
-	bool operator()(Common::SharedPtr<Object> obj) {
-		if (obj->inInventory()) {
-			_obj = obj;
-			return true;
-		}
-		return false;
-	}
-
-public:
-	Common::SharedPtr<Object> &_obj;
-};
-
 Common::SharedPtr<Object> inventoryAt(Math::Vector2d pos) {
 	Common::SharedPtr<Object> result;
 	objsAt(Common::move(pos), InInventory(result));
@@ -390,62 +488,6 @@ Common::Array<ActorSwitcherSlot> TwpEngine::actorSwitcherSlots() {
 	return result;
 }
 
-struct GetNoun {
-	GetNoun(int verbId, Common::SharedPtr<Object> &obj) : _verbId(verbId), _noun(obj) {
-		_noun = nullptr;
-	}
-
-	bool operator()(Common::SharedPtr<Object> obj) {
-		if (((_verbId == VERB_TALKTO) || (_verbId == VERB_WALKTO) || !g_twp->_resManager->isActor(obj->getId())) && (obj->_node->getZSort() <= _zOrder)) {
-			_noun = obj;
-			_zOrder = obj->_node->getZSort();
-		}
-		return false;
-	}
-
-public:
-	Common::SharedPtr<Object> &_noun;
-	int _zOrder = INT_MAX;
-	const int _verbId;
-};
-
-struct GetUseNoun2 {
-	explicit GetUseNoun2(Common::SharedPtr<Object> &obj) : _noun2(obj) {
-		_noun2 = nullptr;
-	}
-
-	bool operator()(Common::SharedPtr<Object> obj) {
-		if (obj->_node->getZSort() <= _zOrder) {
-			if ((obj != g_twp->_actor) && (g_twp->_noun2 != obj)) {
-				_noun2 = obj;
-				_zOrder = obj->_node->getZSort();
-			}
-		}
-		return false;
-	}
-
-public:
-	Common::SharedPtr<Object> &_noun2;
-	int _zOrder = INT_MAX;
-};
-
-struct GetGiveableNoun2 {
-	explicit GetGiveableNoun2(Common::SharedPtr<Object> &obj) : _noun2(obj) {
-		_noun2 = nullptr;
-	}
-
-	bool operator()(Common::SharedPtr<Object> obj) {
-		if ((obj != g_twp->_actor) && (obj->getFlags() & GIVEABLE) && (g_twp->_noun2 != obj)) {
-			_noun2 = obj;
-			return true;
-		}
-		return false;
-	}
-
-public:
-	Common::SharedPtr<Object> &_noun2;
-};
-
 void TwpEngine::update(float elapsed) {
 	const uint32 startUpdateTime = _system->getMillis();
 	_time += elapsed;
@@ -797,6 +839,75 @@ static void setVerbAction(int verbSlot) {
 	g_twp->_hud->selectVerb(slot->verbSlots[verbSlot]._verb);
 }
 
+static bool isOnScreen(Common::SharedPtr<Object> obj) {
+	Math::Vector2d pos = obj->_node->getPos() - g_twp->getGfx().cameraPos();
+	Math::Vector2d size = g_twp->getGfx().camera();
+	return Common::Rect(0.0f, 0.0f, size.getX(), size.getY()).contains(pos.getX(), pos.getY());
+}
+
+static void gotoObject(bool next) {
+	if (!g_twp->_room || !g_twp->_inputState._inputActive || !g_twp->_inputState._showCursor)
+		return;
+
+	// get all objects touchable and on screen and get their distance to the actor
+	Math::Vector2d actorPos(g_twp->_actor->_node->getAbsPos());
+	Common::Array<ObjPos> objPos;
+	for (size_t i = 0; i < g_twp->_room->_layers.size(); i++) {
+		Common::SharedPtr<Layer> layer = g_twp->_room->_layers[i];
+		for (size_t j = 0; j < layer->_objects.size(); j++) {
+			Common::SharedPtr<Object> obj(layer->_objects[j]);
+			if (g_twp->_resManager->isActor(obj->getId()) || !obj->isTouchable() || !isOnScreen(obj))
+				continue;
+
+			Math::Vector2d pos(obj->_node->getAbsPos());
+			if (pos == Math::Vector2d())
+				continue;
+
+			Common::Rect hotspot = obj->_hotspot;
+			Math::Vector2d center(hotspot.left + hotspot.width() / 2.f, hotspot.top + hotspot.height() / 2.f);
+			pos += center;
+			const float d = actorPos.getX() - pos.getX();
+			objPos.push_back(ObjPos(obj, pos, d, j));
+		}
+	}
+
+	if (objPos.empty())
+		return;
+
+	// sort these objects by distance
+	Common::sort(objPos.begin(), objPos.end(), ObjPosComparer());
+
+	// find between them if the cursor is currently on one object if so find the next object
+	int index = 0;
+	int zsort = INT_MAX;
+	int objIndex = INT_MAX;
+	Math::Vector2d mousePos(g_twp->screenToRoom(g_twp->winToScreen(g_twp->_cursor.pos)));
+	for (size_t i = 0; i < objPos.size(); i++) {
+		if (objPos[i]._obj->contains(mousePos)) {
+			const int objZ = objPos[i]._obj->_node->getZSort();
+			if (objZ > zsort)
+				continue;
+			if (objZ == zsort && objPos[i]._index >= objIndex)
+				continue;
+			objIndex = objPos[i]._index;
+			zsort = objZ;
+			if (next) {
+				index = (i + 1) % objPos.size();
+			} else {
+				index = i - 1;
+				if (index < 0) {
+					index = objPos.size() - 1;
+				}
+			}
+		}
+	}
+
+	// move the cursor to this object
+	Math::Vector2d pos(objPos[index]._pos);
+	pos = g_twp->roomToScreen(pos);
+	g_twp->_moveCursorTo.reset(new MoveCursorTo(g_twp->screenToWin(pos), 0.1f));
+}
+
 Common::Error TwpEngine::run() {
 	const Common::String &gameTarget = ConfMan.getActiveDomainName();
 	AchMan.setActiveDomain(getMetaEngine()->getAchievementsInfo(gameTarget));
@@ -891,6 +1002,10 @@ Common::Error TwpEngine::run() {
 				case TwpAction::kSkipCutscene:
 					skipCutscene();
 					break;
+				case TwpAction::kGotoNextObject:
+				case TwpAction::kGotoPreviousObject:
+					gotoObject((TwpAction)e.customType == TwpAction::kGotoNextObject);
+					break;
 				case TwpAction::kSelectActor1:
 				case TwpAction::kSelectActor2:
 				case TwpAction::kSelectActor3:
@@ -1164,12 +1279,6 @@ Common::Error TwpEngine::saveGameStream(Common::WriteStream *stream, bool isAuto
 	return Common::kNoError;
 }
 
-struct DefineObjectParams {
-	HSQUIRRELVM v;
-	bool pseudo;
-	Common::SharedPtr<Room> room;
-};
-
 static void onGetPairs(const Common::String &k, HSQOBJECT &oTable, void *data) {
 	DefineObjectParams *params = static_cast<DefineObjectParams *>(data);
 	if (oTable._type == OT_TABLE) {
@@ -1581,28 +1690,6 @@ void TwpEngine::fadeTo(FadeEffect effect, float duration, bool fadeToSep) {
 	_fadeShader->_elapsed = 0.f;
 }
 
-struct GetByZOrder {
-	explicit GetByZOrder(Common::SharedPtr<Object> &result) : _result(result) {
-		result = nullptr;
-	}
-
-	bool operator()(Common::SharedPtr<Object> obj) {
-		if (obj->_node->getZSort() <= _zOrder) {
-			if (!g_twp->_resManager->isActor(obj->getId()) || !obj->_key.empty()) {
-				_result = obj;
-				_zOrder = obj->_node->getZSort();
-			}
-		}
-		return false;
-	}
-
-public:
-	Common::SharedPtr<Object> &_result;
-
-private:
-	int _zOrder = INT_MAX;
-};
-
 Common::SharedPtr<Object> TwpEngine::objAt(const Math::Vector2d &pos) {
 	Common::SharedPtr<Object> result;
 	objsAt(pos, GetByZOrder(result));


Commit: 213af70cc6716cb3655611b7fa709251d5e9e47c
    https://github.com/scummvm/scummvm/commit/213af70cc6716cb3655611b7fa709251d5e9e47c
Author: scemino (scemino74 at gmail.com)
Date: 2024-05-05T21:15:17+02:00

Commit Message:
TWP: Use correct gamepad mapping

Changed paths:
    engines/twp/metaengine.cpp


diff --git a/engines/twp/metaengine.cpp b/engines/twp/metaengine.cpp
index 145a6fd8dc3..e725beb68f5 100644
--- a/engines/twp/metaengine.cpp
+++ b/engines/twp/metaengine.cpp
@@ -149,13 +149,13 @@ Common::Array<Common::Keymap *> TwpMetaEngine::initKeymaps(const char *target) c
 	} actions[] = {
 		{"ACTION", _s("Action"), Twp::kDefaultAction, "MOUSE_LEFT|JOY_A|RETURN", Common::EVENT_LBUTTONDOWN, Common::KEYCODE_INVALID},
 		{"SELECTHIGHLIGHTEDVERB", _s("Select highlighted verb"), Twp::kSelectHighlightedVerb, "MOUSE_RIGHT|JOY_X", Common::EVENT_RBUTTONDOWN, Common::KEYCODE_INVALID},
-		{Common::kStandardActionMoveLeft, _s("Left"), Twp::kMoveLeft, "LEFT|JOY_LEFT", Common::EVENT_INVALID, Common::KEYCODE_LEFT},
-		{Common::kStandardActionMoveRight, _s("Right"), Twp::kMoveRight, "RIGHT|JOY_RIGHT", Common::EVENT_INVALID, Common::KEYCODE_RIGHT},
-		{Common::kStandardActionMoveUp, _s("Up"), Twp::kMoveUp, "UP|JOY_UP", Common::EVENT_INVALID, Common::KEYCODE_UP},
-		{Common::kStandardActionMoveDown, _s("Down"), Twp::kMoveDown, "DOWN|JOY_DOWN", Common::EVENT_INVALID, Common::KEYCODE_DOWN},
+		{Common::kStandardActionMoveLeft, _s("Left"), Twp::kMoveLeft, "LEFT|JOY_LEFT_STICK_X-", Common::EVENT_INVALID, Common::KEYCODE_LEFT},
+		{Common::kStandardActionMoveRight, _s("Right"), Twp::kMoveRight, "RIGHT|JOY_LEFT_STICK_X+", Common::EVENT_INVALID, Common::KEYCODE_RIGHT},
+		{Common::kStandardActionMoveUp, _s("Up"), Twp::kMoveUp, "UP|JOY_LEFT_STICK_Y-", Common::EVENT_INVALID, Common::KEYCODE_UP},
+		{Common::kStandardActionMoveDown, _s("Down"), Twp::kMoveDown, "DOWN|JOY_LEFT_STICK_Y+", Common::EVENT_INVALID, Common::KEYCODE_DOWN},
 		{"GOTONPREVOBJECT", _s("Go to previous object"), Twp::kGotoPreviousObject, "JOY_LEFT_SHOULDER", Common::EVENT_INVALID, Common::KEYCODE_INVALID},
 		{"GOTONEXTOBJECT", _s("Go to next object"), Twp::kGotoNextObject, "JOY_RIGHT_SHOULDER", Common::EVENT_INVALID, Common::KEYCODE_INVALID},
-		{"SKIPCUTSCENE", _s("Skip cutscene"), Twp::kSkipCutscene, "ESCAPE", Common::EVENT_INVALID, Common::KEYCODE_INVALID},
+		{"SKIPCUTSCENE", _s("Skip cutscene"), Twp::kSkipCutscene, "ESCAPE|JOY_Y", Common::EVENT_INVALID, Common::KEYCODE_INVALID},
 		{"SELECTACTOR1", _s("Select Actor 1"), Twp::kSelectActor1, "1", Common::EVENT_INVALID, Common::KEYCODE_INVALID},
 		{"SELECTACTOR2", _s("Select Actor 2"), Twp::kSelectActor2, "2", Common::EVENT_INVALID, Common::KEYCODE_INVALID},
 		{"SELECTACTOR3", _s("Select Actor 3"), Twp::kSelectActor3, "3", Common::EVENT_INVALID, Common::KEYCODE_INVALID},
@@ -167,9 +167,9 @@ Common::Array<Common::Keymap *> TwpMetaEngine::initKeymaps(const char *target) c
 		{"SELECTCHOICE4", _s("Select Choice 4"), Twp::kSelectChoice4, "4", Common::EVENT_INVALID, Common::KEYCODE_INVALID},
 		{"SELECTCHOICE5", _s("Select Choice 5"), Twp::kSelectChoice5, "5", Common::EVENT_INVALID, Common::KEYCODE_INVALID},
 		{"SELECTCHOICE6", _s("Select Choice 6"), Twp::kSelectChoice6, "6", Common::EVENT_INVALID, Common::KEYCODE_INVALID},
-		{"SELECTNEXTACTOR", _s("Select Next Actor"), Twp::kSelectNextActor, "0", Common::EVENT_INVALID, Common::KEYCODE_INVALID},
-		{"SELECTPREVACTOR", _s("Select Previous Actor"), Twp::kSelectPreviousActor, "9", Common::EVENT_INVALID, Common::KEYCODE_INVALID},
-		{"SKIPTEXT", _s("Skip Text"), Twp::kSkipText, "MOUSE_MIDDLE|PERIOD|JOY_Y", Common::EVENT_INVALID, Common::KEYCODE_INVALID},
+		{"SELECTNEXTACTOR", _s("Select Next Actor"), Twp::kSelectNextActor, "0|JOY_RIGHT_TRIGGER", Common::EVENT_INVALID, Common::KEYCODE_INVALID},
+		{"SELECTPREVACTOR", _s("Select Previous Actor"), Twp::kSelectPreviousActor, "9|JOY_LEFT_TRIGGER", Common::EVENT_INVALID, Common::KEYCODE_INVALID},
+		{"SKIPTEXT", _s("Skip Text"), Twp::kSkipText, "MOUSE_MIDDLE|PERIOD|JOY_B", Common::EVENT_INVALID, Common::KEYCODE_INVALID},
 		{"SHOWHOTSPOTS", _s("Show hotspots"), Twp::kShowHotspots, "TAB", Common::EVENT_INVALID, Common::KEYCODE_INVALID},
 		{"OPEN", _s("Open"), Twp::kOpen, "q", Common::EVENT_INVALID, Common::KEYCODE_INVALID},
 		{"CLOSE", _s("Close"), Twp::kClose, "a", Common::EVENT_INVALID, Common::KEYCODE_INVALID},


Commit: 9105713b42cfa2a2fb91c85c7671a9f0fc345c46
    https://github.com/scummvm/scummvm/commit/9105713b42cfa2a2fb91c85c7671a9f0fc345c46
Author: scemino (scemino74 at gmail.com)
Date: 2024-05-05T21:15:17+02:00

Commit Message:
TWP: Fix unchecked return value in getUserPref function.

Coverity CID 1544403

Changed paths:
    engines/twp/genlib.cpp


diff --git a/engines/twp/genlib.cpp b/engines/twp/genlib.cpp
index 29e03955f2d..416926a4dfc 100644
--- a/engines/twp/genlib.cpp
+++ b/engines/twp/genlib.cpp
@@ -371,13 +371,17 @@ static SQInteger getUserPref(HSQUIRRELVM v) {
 		SQObjectType type = sq_gettype(v, 3);
 		if (type == SQObjectType::OT_STRING) {
 			Common::String str;
-			sqget(v, 3, str);
+			if (SQ_FAILED(sqget(v, 3, str))) {
+				return sq_throwerror(v, _SC("failed to get string"));
+			}
 			sqpush(v, ConfMan.hasKey(key) ? ConfMan.get(key) : str);
 			return 1;
 		}
 		if (type == SQObjectType::OT_INTEGER) {
 			SQInteger integer;
-			sqget(v, 3, integer);
+			if (SQ_FAILED(sqget(v, 3, integer))) {
+				return sq_throwerror(v, _SC("failed to get integer"));
+			}
 			if (ConfMan.hasKey(key)) {
 				Common::String value = ConfMan.get(key);
 				bool bValue = false;
@@ -394,7 +398,9 @@ static SQInteger getUserPref(HSQUIRRELVM v) {
 		}
 		if (type == SQObjectType::OT_FLOAT) {
 			SQFloat fl;
-			sqget(v, 3, fl);
+			if (SQ_FAILED(sqget(v, 3, fl))) {
+				return sq_throwerror(v, _SC("failed to get float"));
+			}
 			sqpush(v, ConfMan.hasKey(key) ? atof(ConfMan.get(key).c_str()) : fl);
 			return 1;
 		}


Commit: 7a3862b44bf44939af7f3350451b7d08604d111d
    https://github.com/scummvm/scummvm/commit/7a3862b44bf44939af7f3350451b7d08604d111d
Author: scemino (scemino74 at gmail.com)
Date: 2024-05-05T21:15:17+02:00

Commit Message:
TWP: Add Select Verb/Inventory

Changed paths:
    engines/twp/actions.h
    engines/twp/hud.cpp
    engines/twp/hud.h
    engines/twp/metaengine.cpp
    engines/twp/scenegraph.cpp
    engines/twp/scenegraph.h
    engines/twp/twp.cpp


diff --git a/engines/twp/actions.h b/engines/twp/actions.h
index 9d5c40a402f..5ceda046c75 100644
--- a/engines/twp/actions.h
+++ b/engines/twp/actions.h
@@ -33,6 +33,10 @@ enum TwpAction {
 	kMoveDown,
 	kGotoNextObject,
 	kGotoPreviousObject,
+	kSelectVerbInventoryLeft,
+	kSelectVerbInventoryRight,
+	kSelectVerbInventoryUp,
+	kSelectVerbInventoryDown,
 	kSkipCutscene,
 	kSelectActor1,
 	kSelectActor2,
diff --git a/engines/twp/hud.cpp b/engines/twp/hud.cpp
index d4057d6c965..4e022a40c0c 100644
--- a/engines/twp/hud.cpp
+++ b/engines/twp/hud.cpp
@@ -279,4 +279,14 @@ void Hud::setVisible(bool visible) {
 	}
 }
 
+Math::Vector2d Hud::getVerbPos(const VerbSlot &verbSlot) const {
+	SpriteSheet *verbSheet = g_twp->_resManager->spriteSheet("VerbSheet");
+	bool retroVerbs = ConfMan.getBool("retroVerbs");
+	Common::String verbSuffix = retroVerbs ? "_retro" : "";
+	Common::String lang = ConfMan.get("language");
+	const SpriteSheetFrame &verbFrame = verbSheet->getFrame(Common::String::format("%s%s_%s", verbSlot._verb.image.c_str(), verbSuffix.c_str(), lang.c_str()));
+	Common::Rect r = verbFrame.spriteSourceSize;
+	return Math::Vector2d(r.left + r.width() / 2.f, r.top + r.height() / 2.f);
+}
+
 } // namespace Twp
diff --git a/engines/twp/hud.h b/engines/twp/hud.h
index d7617c44f87..c74674dbd58 100644
--- a/engines/twp/hud.h
+++ b/engines/twp/hud.h
@@ -126,6 +126,8 @@ public:
 	void setVisible(bool visible) override;
 	void selectVerb(const Verb &verb);
 
+	Math::Vector2d getVerbPos(const VerbSlot &verbSlot) const;
+
 private:
 	void drawCore(const Math::Matrix4 &trsf) final;
 	void drawSprite(const SpriteSheetFrame &sf, Texture *texture, const Color &color, const Math::Matrix4 &trsf);
diff --git a/engines/twp/metaengine.cpp b/engines/twp/metaengine.cpp
index e725beb68f5..d0359ac707d 100644
--- a/engines/twp/metaengine.cpp
+++ b/engines/twp/metaengine.cpp
@@ -155,6 +155,10 @@ Common::Array<Common::Keymap *> TwpMetaEngine::initKeymaps(const char *target) c
 		{Common::kStandardActionMoveDown, _s("Down"), Twp::kMoveDown, "DOWN|JOY_LEFT_STICK_Y+", Common::EVENT_INVALID, Common::KEYCODE_DOWN},
 		{"GOTONPREVOBJECT", _s("Go to previous object"), Twp::kGotoPreviousObject, "JOY_LEFT_SHOULDER", Common::EVENT_INVALID, Common::KEYCODE_INVALID},
 		{"GOTONEXTOBJECT", _s("Go to next object"), Twp::kGotoNextObject, "JOY_RIGHT_SHOULDER", Common::EVENT_INVALID, Common::KEYCODE_INVALID},
+		{"SELVERBINVENOTRYLEFT", _s("Select verb/item Left"), Twp::kSelectVerbInventoryLeft, "JOY_LEFT", Common::EVENT_INVALID, Common::KEYCODE_INVALID},
+		{"SELVERBINVENOTRYRIGHT", _s("Select verb/item Right"), Twp::kSelectVerbInventoryRight, "JOY_RIGHT", Common::EVENT_INVALID, Common::KEYCODE_INVALID},
+		{"SELVERBINVENOTRYUP", _s("Select verb/item Up"), Twp::kSelectVerbInventoryUp, "JOY_UP", Common::EVENT_INVALID, Common::KEYCODE_INVALID},
+		{"SELVERBINVENOTRYDOWN", _s("Select verb/item Down"), Twp::kSelectVerbInventoryDown, "JOY_DOWN", Common::EVENT_INVALID, Common::KEYCODE_INVALID},
 		{"SKIPCUTSCENE", _s("Skip cutscene"), Twp::kSkipCutscene, "ESCAPE|JOY_Y", Common::EVENT_INVALID, Common::KEYCODE_INVALID},
 		{"SELECTACTOR1", _s("Select Actor 1"), Twp::kSelectActor1, "1", Common::EVENT_INVALID, Common::KEYCODE_INVALID},
 		{"SELECTACTOR2", _s("Select Actor 2"), Twp::kSelectActor2, "2", Common::EVENT_INVALID, Common::KEYCODE_INVALID},
diff --git a/engines/twp/scenegraph.cpp b/engines/twp/scenegraph.cpp
index 1717c9f8f70..df9054f9847 100644
--- a/engines/twp/scenegraph.cpp
+++ b/engines/twp/scenegraph.cpp
@@ -611,6 +611,19 @@ Math::Vector2d Inventory::getPos(Common::SharedPtr<Object> inv) const {
 	return {};
 }
 
+Math::Vector2d Inventory::getPos(int i) const {
+	assert((i >= 0) && (i < 8));
+	return Math::Vector2d(_itemRects[i].left + _itemRects[i].width() / 2.f, _itemRects[i].top + _itemRects[i].height() / 2.f);
+}
+
+int Inventory::getOverIndex() const {
+	for (int i = 0; i < NUMOBJECTS; i++) {
+		if (_inventoryOver[i])
+			return i;
+	}
+	return -1;
+}
+
 void Inventory::drawSprite(const SpriteSheetFrame &sf, Texture *texture, const Color &color, const Math::Matrix4 &t) {
 	Math::Matrix4 trsf(t);
 	Math::Vector3d pos(sf.spriteSourceSize.left - sf.sourceSize.getX() / 2.f, -sf.spriteSourceSize.height() - sf.spriteSourceSize.top + sf.sourceSize.getY() / 2.f, 0.f);
@@ -746,6 +759,8 @@ void Inventory::update(float elapsed, Common::SharedPtr<Object> actor, const Col
 						_shake[i] = Common::ScopedPtr<Motor>(new ShakeInventory(_shakeOffset[i], 0.4f));
 						_inventoryOver[i] = true;
 					}
+				} else {
+					_inventoryOver[i] = true;
 				}
 			} else {
 				_inventoryOver[i] = false;
diff --git a/engines/twp/scenegraph.h b/engines/twp/scenegraph.h
index 7202762176f..4fbc4cb70f9 100644
--- a/engines/twp/scenegraph.h
+++ b/engines/twp/scenegraph.h
@@ -1,4 +1,3 @@
-
 /* ScummVM - Graphic Adventure Engine
  *
  * ScummVM is the legal property of its developers, whose names
@@ -301,6 +300,8 @@ public:
 	bool isOver() const { return _over; }
 	Common::SharedPtr<Object> getObject() const { return _obj; }
 	Math::Vector2d getPos(Common::SharedPtr<Object> inv) const;
+	Math::Vector2d getPos(int index) const;
+	int getOverIndex() const;
 
 	void setVisible(bool visible) override;
 
diff --git a/engines/twp/twp.cpp b/engines/twp/twp.cpp
index dd5c678448c..013009caf03 100644
--- a/engines/twp/twp.cpp
+++ b/engines/twp/twp.cpp
@@ -845,6 +845,10 @@ static bool isOnScreen(Common::SharedPtr<Object> obj) {
 	return Common::Rect(0.0f, 0.0f, size.getX(), size.getY()).contains(pos.getX(), pos.getY());
 }
 
+static void moveCursorTo(const Math::Vector2d &pos) {
+	g_twp->_moveCursorTo.reset(new MoveCursorTo(pos, 0.1f));
+}
+
 static void gotoObject(bool next) {
 	if (!g_twp->_room || !g_twp->_inputState._inputActive || !g_twp->_inputState._showCursor)
 		return;
@@ -905,7 +909,108 @@ static void gotoObject(bool next) {
 	// move the cursor to this object
 	Math::Vector2d pos(objPos[index]._pos);
 	pos = g_twp->roomToScreen(pos);
-	g_twp->_moveCursorTo.reset(new MoveCursorTo(g_twp->screenToWin(pos), 0.1f));
+	moveCursorTo(g_twp->screenToWin(pos));
+}
+
+static void selectVerbInventory(int direction) {
+	if (!g_twp->_room || !g_twp->_inputState._inputActive || !g_twp->_hud->isVisible())
+		return;
+
+	ActorSlot *slot = g_twp->_hud->actorSlot(g_twp->_actor);
+	if (!slot)
+		return;
+
+	if (g_twp->_uiInv.isOver()) {
+		int invIndex = g_twp->_uiInv.getOverIndex();
+		if (invIndex != -1) {
+			switch (direction) {
+			case 0: // Left
+			{
+				if (invIndex == 0) {
+					moveCursorTo(g_twp->_hud->getVerbPos(slot->verbSlots[7]));
+					return;
+				}
+				if (invIndex == 4) {
+					moveCursorTo(g_twp->_hud->getVerbPos(slot->verbSlots[8]));
+					return;
+				}
+				invIndex--;
+			} break;
+			case 1: // Right
+			{
+				if (invIndex == 3 || invIndex == 7)
+					return;
+				invIndex++;
+			} break;
+			case 2: // Up
+			{
+				if (invIndex < 4) {
+					g_twp->_actor->inventoryScrollUp();
+					return;
+				}
+				invIndex -= 4;
+			} break;
+			case 3: // Down
+				if (invIndex > 3) {
+					g_twp->_actor->inventoryScrollDown();
+					return;
+				}
+				invIndex += 4;
+				break;
+			}
+			moveCursorTo(g_twp->screenToWin(g_twp->_uiInv.getPos(invIndex)));
+			return;
+		}
+	}
+
+	// get the verb where the cursor is
+	int id = 0;
+	for (int i = 1; i < MAX_VERBS; i++) {
+		const VerbSlot &verbSlot = slot->verbSlots[i];
+		if (verbSlot._over) {
+			id = i;
+			break;
+		}
+	}
+
+	if (!id) {
+		const VerbSlot &verbSlot = slot->verbSlots[5];
+		Math::Vector2d pos(g_twp->_hud->getVerbPos(verbSlot));
+		moveCursorTo(pos);
+		return;
+	}
+
+	switch (direction) {
+	case 0: // Left
+	{
+		if (id < 4)
+			break;
+		id -= 3;
+	} break;
+	case 1: // Right
+	{
+		if (id > 6) {
+			moveCursorTo(g_twp->screenToWin(g_twp->_uiInv.getPos(id == 7 ? 0 : 4)));
+			return;
+		}
+		id += 3;
+	} break;
+	case 2: // Up
+	{
+		if ((id % 3) == 1)
+			break;
+		id--;
+	} break;
+	case 3: // Down
+		if ((id % 3) == 0)
+			break;
+		id++;
+		break;
+	}
+
+	const VerbSlot &verbSlot = slot->verbSlots[id];
+	Math::Vector2d pos(g_twp->_hud->getVerbPos(verbSlot));
+	moveCursorTo(pos);
 }
 
 Common::Error TwpEngine::run() {
@@ -1006,6 +1111,12 @@ Common::Error TwpEngine::run() {
 				case TwpAction::kGotoPreviousObject:
 					gotoObject((TwpAction)e.customType == TwpAction::kGotoNextObject);
 					break;
+				case TwpAction::kSelectVerbInventoryLeft:
+				case TwpAction::kSelectVerbInventoryRight:
+				case TwpAction::kSelectVerbInventoryUp:
+				case TwpAction::kSelectVerbInventoryDown:
+					selectVerbInventory(e.customType - (int)TwpAction::kSelectVerbInventoryLeft);
+					break;
 				case TwpAction::kSelectActor1:
 				case TwpAction::kSelectActor2:
 				case TwpAction::kSelectActor3:
@@ -1095,14 +1206,14 @@ Common::Error TwpEngine::run() {
 					break;
 				case Common::KEYCODE_UP:
 					if (_dialog->getState() == WaitingForChoice) {
-						_moveCursorTo.reset(new MoveCursorTo(screenToWin(_dialog->getPreviousChoicePos(winToScreen(_cursor.pos))), 0.1f));
+						moveCursorTo(screenToWin(_dialog->getPreviousChoicePos(winToScreen(_cursor.pos))));
 					} else {
 						_cursor.holdUp = true;
 					}
 					break;
 				case Common::KEYCODE_DOWN:
 					if (_dialog->getState() == WaitingForChoice) {
-						_moveCursorTo.reset(new MoveCursorTo(screenToWin(_dialog->getNextChoicePos(winToScreen(_cursor.pos))), 0.1f));
+						moveCursorTo(screenToWin(_dialog->getNextChoicePos(winToScreen(_cursor.pos))));
 					} else {
 						_cursor.holdDown = true;
 					}




More information about the Scummvm-git-logs mailing list