[Scummvm-git-logs] scummvm master -> 403b55c5ba7535ded50fe0c304b775cedfa4e312

mduggan noreply at scummvm.org
Sun Jul 21 10:01:10 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:
403b55c5ba DGDS: Add support for both-button ops


Commit: 403b55c5ba7535ded50fe0c304b775cedfa4e312
    https://github.com/scummvm/scummvm/commit/403b55c5ba7535ded50fe0c304b775cedfa4e312
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2024-07-21T19:58:38+10:00

Commit Message:
DGDS: Add support for both-button ops

This allows you to shoot the snakes in HoC.

Changed paths:
    engines/dgds/dgds.cpp
    engines/dgds/inventory.cpp
    engines/dgds/scene.cpp
    engines/dgds/scene.h
    engines/dgds/ttm.cpp


diff --git a/engines/dgds/dgds.cpp b/engines/dgds/dgds.cpp
index cf75726e6af..7eab4bc9d90 100644
--- a/engines/dgds/dgds.cpp
+++ b/engines/dgds/dgds.cpp
@@ -494,7 +494,8 @@ Common::Error DgdsEngine::run() {
 					break;
 				}
 			} else if (ev.type == Common::EVENT_LBUTTONDOWN || ev.type == Common::EVENT_LBUTTONUP
-					|| ev.type == Common::EVENT_RBUTTONUP || ev.type == Common::EVENT_MOUSEMOVE) {
+					|| ev.type == Common::EVENT_RBUTTONDOWN || ev.type == Common::EVENT_RBUTTONUP
+					|| ev.type == Common::EVENT_MOUSEMOVE) {
 				mouseEvent = ev.type;
 				_lastMouse = ev.mouse;
 			}
@@ -584,6 +585,9 @@ Common::Error DgdsEngine::run() {
 				case Common::EVENT_LBUTTONUP:
 					_scene->mouseLUp(_lastMouse);
 					break;
+				case Common::EVENT_RBUTTONDOWN:
+					_scene->mouseRDown(_lastMouse);
+					break;
 				case Common::EVENT_RBUTTONUP:
 					_scene->mouseRUp(_lastMouse);
 					break;
diff --git a/engines/dgds/inventory.cpp b/engines/dgds/inventory.cpp
index c5dfc2a76cb..1f2c8d09489 100644
--- a/engines/dgds/inventory.cpp
+++ b/engines/dgds/inventory.cpp
@@ -378,7 +378,7 @@ void Inventory::mouseLUp(const Common::Point &pt) {
 				break;
 			}
 		}
-	} else if (_changeCharBtn && _changeCharBtn->isVisible() && _changeCharBtn->containsPoint(pt)) {
+	} else if (_changeCharBtn && _changeCharBtn->containsPoint(pt)) {
 		int16 prevChar = gds->getGlobal(0x33);
 		gds->setGlobal(0x33, gds->getGlobal(0x34));
 		gds->setGlobal(0x34, prevChar);
diff --git a/engines/dgds/scene.cpp b/engines/dgds/scene.cpp
index fb5f6e124be..300c590a0e0 100644
--- a/engines/dgds/scene.cpp
+++ b/engines/dgds/scene.cpp
@@ -181,7 +181,7 @@ Common::String GameItem::dump(const Common::String &indent) const {
 			indent.c_str(), super.c_str(), indent.c_str(), _altCursor,
 			_iconNum, _inSceneNum, _flags, _quality);
 	str += _dumpStructList(indent, "onDragFinishedOps", onDragFinishedOps);
-	str += _dumpStructList(indent, "opList5", opList5);
+	str += _dumpStructList(indent, "onBothButtonsOps", onBothButtonsOps);
 	str += "\n";
 	str += indent + ">";
 	return str;
@@ -313,7 +313,7 @@ bool Scene::readGameItemList(Common::SeekableReadStream *s, Common::Array<GameIt
 		if (!isVersionUnder(" 1.204")) {
 			dst._altCursor = s->readUint16LE();
 			readOpList(s, dst.onDragFinishedOps);
-			readOpList(s, dst.opList5);
+			readOpList(s, dst.onBothButtonsOps);
 		}
 	}
 	return !s->err();
@@ -903,7 +903,7 @@ bool Scene::checkConditions(const Common::Array<SceneConditions> &conds) const {
 bool SDSScene::_dlgWithFlagLo8IsClosing = false;;
 DialogFlags SDSScene::_sceneDialogFlags = kDlgFlagNone;
 
-SDSScene::SDSScene() : _num(-1), _dragItem(nullptr), _shouldClearDlg(false), _ignoreMouseUp(false), _field6_0x14(0) {
+SDSScene::SDSScene() : _num(-1), _dragItem(nullptr), _shouldClearDlg(false), _ignoreMouseUp(false), _field6_0x14(0), _rbuttonDown(false) {
 }
 
 bool SDSScene::load(const Common::String &filename, ResourceManager *resourceManager, Decompressor *decompressor) {
@@ -1630,12 +1630,18 @@ void SDSScene::globalOps(const Common::Array<uint16> &args) {
 void SDSScene::mouseMoved(const Common::Point &pt) {
 	Dialog *dlg = getVisibleDialog();
 	const HotArea *area = findAreaUnderMouse(pt);
+	DgdsEngine *engine = static_cast<DgdsEngine *>(g_engine);
 
 	int16 cursorNum = (!dlg && area) ? area->_cursorNum : 0;
-	if (_dragItem)
+	if (_dragItem) {
 		cursorNum = _dragItem->_iconNum;
+	} else if (_rbuttonDown) {
+		GameItem *activeItem = engine->getGDSScene()->getActiveItem();
+		if (activeItem)
+			cursorNum = activeItem->_altCursor;
+	}
 
-	static_cast<DgdsEngine *>(g_engine)->setMouseCursor(cursorNum);
+	engine->setMouseCursor(cursorNum);
 }
 
 void SDSScene::mouseLDown(const Common::Point &pt) {
@@ -1664,6 +1670,20 @@ void SDSScene::mouseLDown(const Common::Point &pt) {
 	}
 }
 
+static bool _isInRect(const Common::Point &pt, const DgdsRect rect) {
+	return rect.x <= pt.x && (rect.x + rect.width) > pt.x
+			&& rect.y <= pt.y && (rect.y + rect.height) > pt.y;
+}
+
+static const ObjectInteraction * _findInteraction(const Common::Array<ObjectInteraction> &interList, int16 droppedNum, int16 targetNum) {
+	for (const auto &i : interList) {
+		if (i.matches(droppedNum, targetNum)) {
+			return &i;
+		}
+	}
+	return nullptr;
+}
+
 void SDSScene::mouseLUp(const Common::Point &pt) {
 	if (_ignoreMouseUp) {
 		debug(9, "Ignoring mouseup at %d,%d as it was used to clear a dialog", pt.x, pt.y);
@@ -1684,14 +1704,16 @@ void SDSScene::mouseLUp(const Common::Point &pt) {
 			area->_rect.width, area->_rect.height, area->_cursorNum);
 
 	DgdsEngine *engine = static_cast<DgdsEngine *>(g_engine);
-	engine->setMouseCursor(area->_cursorNum);
+	if (!_rbuttonDown)
+		engine->setMouseCursor(area->_cursorNum);
+
+	GDSScene *gds = engine->getGDSScene();
 
 	if (area && area->_num == 0) {
 		debug("Mouseup on inventory.");
 		engine->getInventory()->open();
 	} else if (area && area->_num == 0xffff) {
 		debug("Mouseup on swap characters.");
-		GDSScene *gds = engine->getGDSScene();
 		bool haveInvBtn = _hotAreaList.size() && _hotAreaList.front()._num == 0;
 		if (haveInvBtn)
 			removeInvButtonFromHotAreaList();
@@ -1701,33 +1723,34 @@ void SDSScene::mouseLUp(const Common::Point &pt) {
 		if (haveInvBtn)
 			addInvButtonToHotAreaList();
 	} else {
-		debug(" --> exec %d click ops for area %d", area->onLClickOps.size(), area->_num);
-		if ((area->_num == 58 || area->_num == 62) && engine->getScene()->getNum() == 53 && engine->getGameId() == GID_HOC) {
-			// FIXME: Handle gun (crosshair icon, action on snakes)
-			warning("HACK for the snake scene");
-			GDSScene *gds = engine->getGDSScene();
-			gds->setGlobal(126, 1);		// kill left snake
-			gds->setGlobal(132, 1);		// kill right snake
-			gds->setGlobal(110, 86);	// save Kate and open balcony door
-			return;
-		}
-		int16 addmins = engine->getGameGlobals()->getGameMinsToAddOnLClick();
-		runOps(area->onLClickOps, addmins);
-	}
-}
-
-static bool _isInRect(const Common::Point &pt, const DgdsRect rect) {
-	return rect.x <= pt.x && (rect.x + rect.width) > pt.x
-			&& rect.y <= pt.y && (rect.y + rect.height) > pt.y;
-}
-
-static const ObjectInteraction * _findInteraction(const Common::Array<ObjectInteraction> &interList, int16 droppedNum, int16 targetNum) {
-	for (const auto &i : interList) {
-		if (i.matches(droppedNum, targetNum)) {
-			return &i;
+		if (_rbuttonDown) {
+			debug(" --> exec %d both-button click ops for area %d", area->onLClickOps.size(), area->_num);
+			// A both-button-click event, find the interaction list.
+			const GameItem *activeItem = engine->getGDSScene()->getActiveItem();
+			if (activeItem) {
+				if (!runOps(activeItem->onBothButtonsOps))
+					return;
+				if (area) {
+					const GameItem *destItem = dynamic_cast<const GameItem *>(area);
+					const ObjectInteraction *i;
+					if (destItem) {
+						i =_findInteraction(gds->getObjInteractions2(), activeItem->_num, area->_num);
+					} else {
+						i = _findInteraction(_objInteractions2, activeItem->_num, area->_num);
+					}
+					if (i) {
+						debug(" --> exec %d both-click ops for item combo %d", i->opList.size(), activeItem->_num);
+						if (!runOps(i->opList, engine->getGameGlobals()->getGameMinsToAddOnObjInteraction()))
+							return;
+					}
+				}
+			}
+		} else {
+			debug(" --> exec %d click ops for area %d", area->onLClickOps.size(), area->_num);
+			int16 addmins = engine->getGameGlobals()->getGameMinsToAddOnLClick();
+			runOps(area->onLClickOps, addmins);
 		}
 	}
-	return nullptr;
 }
 
 void SDSScene::onDragFinish(const Common::Point &pt) {
@@ -1750,7 +1773,7 @@ void SDSScene::onDragFinish(const Common::Point &pt) {
 	for (const auto &item : gdsScene->getGameItems()) {
 		if (item._inSceneNum == _num && _isInRect(pt, item._rect)) {
 			debug("Dragged item %d onto item %d @ (%d, %d)", dragItem->_num, item._num, pt.x, pt.y);
-			const ObjectInteraction *i = _findInteraction(gdsScene->getObjInteractions2(), dragItem->_num, item._num);
+			const ObjectInteraction *i = _findInteraction(gdsScene->getObjInteractions1(), dragItem->_num, item._num);
 			if (i) {
 				debug(" --> exec %d drag ops for item %d", i->opList.size(), item._num);
 				if (!runOps(i->opList, globals->getGameMinsToAddOnObjInteraction()))
@@ -1770,7 +1793,7 @@ void SDSScene::onDragFinish(const Common::Point &pt) {
 			if (engine->getGameId() == GID_HOC)
 				dragItem->_quality = Inventory::HOC_CHARACTER_QUALS[gdsScene->getGlobal(0x33)];
 
-			const ObjectInteraction *i = _findInteraction(scene->getObjInteractions1(), dragItem->_num, 0xffff);
+			const ObjectInteraction *i = _findInteraction(gdsScene->getObjInteractions1(), dragItem->_num, 0xffff);
 			if (i) {
 				debug(" --> exec %d drag ops for area %d", i->opList.size(), 0xffff);
 				if (!runOps(i->opList, globals->getGameMinsToAddOnObjInteraction()))
@@ -1782,7 +1805,7 @@ void SDSScene::onDragFinish(const Common::Point &pt) {
 			if (engine->getGameId() == GID_HOC)
 				dragItem->_quality = Inventory::HOC_CHARACTER_QUALS[gdsScene->getGlobal(0x34)];
 
-			const ObjectInteraction *i = _findInteraction(scene->getObjInteractions1(), dragItem->_num, 0xffff);
+			const ObjectInteraction *i = _findInteraction(gdsScene->getObjInteractions1(), dragItem->_num, 0xffff);
 			if (i) {
 				debug(" --> exec %d drag ops for area %d", i->opList.size(), 0xffff);
 				if (!runOps(i->opList, globals->getGameMinsToAddOnObjInteraction()))
@@ -1808,8 +1831,12 @@ void SDSScene::onDragFinish(const Common::Point &pt) {
 	_dragItem = nullptr;
 }
 
+void SDSScene::mouseRDown(const Common::Point &pt) {
+	_rbuttonDown = true;
+}
 
 void SDSScene::mouseRUp(const Common::Point &pt) {
+	_rbuttonDown = false;
 	Dialog *dlg = getVisibleDialog();
 	if (dlg) {
 		// HACK: Check for dialog action selection! for now, just close
@@ -1818,6 +1845,9 @@ void SDSScene::mouseRUp(const Common::Point &pt) {
 		return;
 	}
 
+	// Update the cursor..
+	mouseMoved(pt);
+
 	const HotArea *area = findAreaUnderMouse(pt);
 	if (!area)
 		return;
@@ -1825,21 +1855,20 @@ void SDSScene::mouseRUp(const Common::Point &pt) {
 	DgdsEngine *engine = static_cast<DgdsEngine *>(g_engine);
 
 	if (area->_num == 0) {
-		debug("Right mouseup on inventory.");
+		debug("Mouse RUp on inventory.");
 		engine->getInventory()->setShowZoomBox(true);
 		engine->getInventory()->open();
-		return;
 	} else if (area->_num == 0xffff) {
-		debug("Right mouseup on character swap.");
+		debug("Mouse RUp on character swap.");
 		int16 swapDlgFile = engine->getGDSScene()->getGlobal(0x36);
 		int16 swapDlgNum = engine->getGDSScene()->getGlobal(0x35);
 		if (swapDlgFile && swapDlgNum)
 			showDialog(swapDlgFile, swapDlgNum);
-		return;
+	} else {
+		int16 addmins = engine->getGameGlobals()->getGameMinsToAddOnLClick();
+		debug("Mouse RUp on area %d, run %d ops (+%d mins)", area->_num, area->onRClickOps.size(), addmins);
+		runOps(area->onRClickOps, addmins);
 	}
-
-	int16 addmins = engine->getGameGlobals()->getGameMinsToAddOnLClick();
-	runOps(area->onRClickOps, addmins);
 }
 
 Dialog *SDSScene::getVisibleDialog() {
@@ -2163,9 +2192,9 @@ bool GDSScene::parse(Common::SeekableReadStream *stream) {
 	_iconFile = stream->readString();
 	readMouseHotspotList(stream, _cursorList);
 	readGameItemList(stream, _gameItems);
-	readObjInteractionList(stream, _objInteractions2);
+	readObjInteractionList(stream, _objInteractions1);
 	if (isVersionOver(" 1.205"))
-		readObjInteractionList(stream, _objInteractions1);
+		readObjInteractionList(stream, _objInteractions2);
 
 	if (isVersionOver(" 1.218")) {
 		_field38 = stream->readUint16LE();
@@ -2324,6 +2353,17 @@ int GDSScene::countItemsInScene2() const {
 	return result;
 }
 
+GameItem *GDSScene::getActiveItem() {
+	int16 itemNum = getGlobal(0x60);
+	if (!itemNum)
+		return nullptr;
+	for (auto &item : _gameItems) {
+		if (item._num == itemNum)
+			return &item;
+	}
+	return nullptr;
+}
+
 Common::Error GDSScene::syncState(Common::Serializer &s) {
 	// Only items and globals are stateful - everything else is stateless.
 	// Game should already be loaded at this point so the lsits are already
diff --git a/engines/dgds/scene.h b/engines/dgds/scene.h
index 842938d91a2..c63d1118a04 100644
--- a/engines/dgds/scene.h
+++ b/engines/dgds/scene.h
@@ -160,7 +160,7 @@ public:
 class GameItem : public HotArea {
 public:
 	Common::Array<SceneOp> onDragFinishedOps;
-	Common::Array<SceneOp> opList5;
+	Common::Array<SceneOp> onBothButtonsOps;
 	uint16 _altCursor;
 	uint16 _iconNum;
 
@@ -377,6 +377,7 @@ public:
 
 	Common::Error syncState(Common::Serializer &s) override;
 	void initIconSizes();
+	GameItem *getActiveItem();
 
 private:
 	Common::String _iconFile;
@@ -386,8 +387,8 @@ private:
 	Common::Array<SceneOp> _onChangeSceneOps;
 	Common::Array<MouseCursor> _cursorList;
 	Common::Array<PerSceneGlobal> _perSceneGlobals;
-	Common::Array<ObjectInteraction> _objInteractions1;
 	Common::Array<ObjectInteraction> _objInteractions2;
+	Common::Array<ObjectInteraction> _objInteractions1;
 
 	// Additional fields that appear in Willy Beamish (unused in others)
 	uint16 _field38;
@@ -423,6 +424,7 @@ public:
 	void mouseMoved(const Common::Point &pt);
 	void mouseLDown(const Common::Point &pt);
 	void mouseLUp(const Common::Point &pt);
+	void mouseRDown(const Common::Point &pt);
 	void mouseRUp(const Common::Point &pt);
 
 	void addInvButtonToHotAreaList();
@@ -497,6 +499,7 @@ private:
 	GameItem *_dragItem;
 	bool _shouldClearDlg;
 	bool _ignoreMouseUp;
+	bool _rbuttonDown;
 
 	static bool _dlgWithFlagLo8IsClosing;
 	static DialogFlags _sceneDialogFlags;
diff --git a/engines/dgds/ttm.cpp b/engines/dgds/ttm.cpp
index 9eb36798d34..fcdad7d0e64 100644
--- a/engines/dgds/ttm.cpp
+++ b/engines/dgds/ttm.cpp
@@ -158,11 +158,13 @@ static const char *ttmOpName(uint16 op) {
 	case 0x2000: return "SET DRAW COLORS";
 	case 0x2010: return "SET FRAME";
 	case 0x2020: return "SET RANDOM DELAY";
+	case 0x2030: return "SET SCROLL 2030??";
 	case 0x2300: return "PAL SET BLOCK SWAP 0";
 	case 0x2310: return "PAL SET BLOCK SWAP 1";
 	case 0x2320: return "PAL SET BLOCK SWAP 2";
 	case 0x2400: return "PAL DO BLOCK SWAP";
 	case 0x3000: return "GOSUB";
+	case 0x3100: return "SCROLL 3100??";
 	case 0x4000: return "SET CLIP WINDOW";
 	case 0x4110: return "FADE OUT";
 	case 0x4120: return "FADE IN";
@@ -199,6 +201,7 @@ static const char *ttmOpName(uint16 op) {
 	case 0xa520: return "DRAW SPRITE FLIPH";
 	case 0xa530: return "DRAW SPRITE FLIPHV";
 	case 0xa600: return "DRAW GETPUT";
+	case 0xa700: return "DRAW A700??";
 	case 0xaf00: return "DRAW FLOOD FILL";
 	case 0xaf10: return "DRAW EMPTY POLY";
 	case 0xaf20: return "DRAW FILLED POLY";
@@ -603,7 +606,7 @@ void TTMInterpreter::handleOperation(TTMEnviro &env, TTMSeq &seq, uint16 op, byt
 			break;
 		warning("TODO: 0x%04x Palette do block swaps 0x%x, 0x%x", op, ivals[0], ivals[1]);
 		break;
-	case 0x3000: {
+	case 0x3000: { // GOSUB ??,??,frame
 		_stackDepth++;
 		bool prevHitOp0110Val = _vm->adsInterpreter()->getHitTTMOp0110();
 		int32 target = findGOTOTarget(env, seq, ivals[2]);
@@ -613,7 +616,8 @@ void TTMInterpreter::handleOperation(TTMEnviro &env, TTMSeq &seq, uint16 op, byt
 		env.scr->seek(env._frameOffsets[target]);
 
 		// TODO: Set some other render-related globals here
-		warning("TODO: TTM 0x3000 GOSUB %d %d, use other args", ivals[0], ivals[1]);
+		if (ivals[0] || ivals[1])
+			warning("TODO: TTM 0x3000 GOSUB use offsets (%d, %d)", ivals[0], ivals[1]);
 
 		run(env, seq);
 		env.scr->seek(prevPos);
@@ -624,6 +628,11 @@ void TTMInterpreter::handleOperation(TTMEnviro &env, TTMSeq &seq, uint16 op, byt
 		_stackDepth--;
 		break;
 	}
+	case 0x3100: { // SCROLL ??,??,??
+		if (seq._executed) // this is a one-shot op.
+			break;
+		warning("TODO: TTM 0x3100 SCROLL %d %d %d", ivals[0], ivals[1], ivals[2]);
+	}
 	case 0x4000: // SET CLIP WINDOW x,y,x2,y2:int	[0..320,0..200]
 		// NOTE: params are xmax/ymax, NOT w/h
 		seq._drawWin = Common::Rect(ivals[0], ivals[1], ivals[2], ivals[3]);




More information about the Scummvm-git-logs mailing list