[Scummvm-git-logs] scummvm master -> 4bebb71d622218b3c5dd96b2f4b70aafa2e658cf

dreammaster noreply at scummvm.org
Fri Mar 10 06:51:45 UTC 2023


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

Summary:
6a9104f8b5 MM: MM1: Added unlock action
5591049454 MM: MM1: Implement trap display
4bebb71d62 MM: MM1: Add a generic WhoWillTry view


Commit: 6a9104f8b5b9f803dba72b8a6c2ee4bce957bb17
    https://github.com/scummvm/scummvm/commit/6a9104f8b5b9f803dba72b8a6c2ee4bce957bb17
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-03-09T22:51:38-08:00

Commit Message:
MM: MM1: Added unlock action

Changed paths:
  A engines/mm/mm1/views_enh/search.cpp
  A engines/mm/mm1/views_enh/search.h
  A engines/mm/mm1/views_enh/trap.cpp
  A engines/mm/mm1/views_enh/trap.h
  A engines/mm/mm1/views_enh/unlock.cpp
  A engines/mm/mm1/views_enh/unlock.h
    engines/mm/mm1/views/trap.cpp
    engines/mm/mm1/views/trap.h
    engines/mm/mm1/views_enh/character_select.cpp
    engines/mm/mm1/views_enh/dialogs.h
    engines/mm/mm1/views_enh/spells/cast_spell.cpp


diff --git a/engines/mm/mm1/views/trap.cpp b/engines/mm/mm1/views/trap.cpp
index c193d45e710..bd93e11e727 100644
--- a/engines/mm/mm1/views/trap.cpp
+++ b/engines/mm/mm1/views/trap.cpp
@@ -71,6 +71,16 @@ bool Trap::msgKeypress(const KeypressMessage &msg) {
 	return true;
 }
 
+bool Trap::msgAction(const ActionMessage &msg) {
+	if (_mode == MODE_TRIGGER) {
+		trap();
+	} else {
+		close();
+	}
+
+	return true;
+}
+
 void Trap::trap() {
 	TrapData::trap();
 
diff --git a/engines/mm/mm1/views/trap.h b/engines/mm/mm1/views/trap.h
index 48d6ce364f1..4589ff1b564 100644
--- a/engines/mm/mm1/views/trap.h
+++ b/engines/mm/mm1/views/trap.h
@@ -43,6 +43,7 @@ public:
 	bool msgGame(const GameMessage &msg) override;
 	void draw() override;
 	bool msgKeypress(const KeypressMessage &msg) override;
+	bool msgAction(const ActionMessage &msg) override;
 };
 
 } // namespace Views
diff --git a/engines/mm/mm1/views_enh/character_select.cpp b/engines/mm/mm1/views_enh/character_select.cpp
index ff804b37161..ac005c67b2b 100644
--- a/engines/mm/mm1/views_enh/character_select.cpp
+++ b/engines/mm/mm1/views_enh/character_select.cpp
@@ -28,7 +28,7 @@ namespace MM1 {
 namespace ViewsEnh {
 
 CharacterSelect::CharacterSelect() : PartyView("CharacterSelect") {
-	_bounds = Common::Rect(225, 18 * 8, 320, 200);
+	_bounds = Common:: Rect(225, 144, 320, 200);
 }
 
 bool CharacterSelect::msgFocus(const FocusMessage &msg) {
diff --git a/engines/mm/mm1/views_enh/dialogs.h b/engines/mm/mm1/views_enh/dialogs.h
index 5a2b3a2bec9..c25481cc6d2 100644
--- a/engines/mm/mm1/views_enh/dialogs.h
+++ b/engines/mm/mm1/views_enh/dialogs.h
@@ -35,7 +35,10 @@
 #include "mm/mm1/views_enh/main_menu.h"
 #include "mm/mm1/views_enh/map_popup.h"
 #include "mm/mm1/views_enh/quick_ref.h"
+#include "mm/mm1/views_enh/search.h"
 #include "mm/mm1/views_enh/title.h"
+#include "mm/mm1/views_enh/trap.h"
+#include "mm/mm1/views_enh/unlock.h"
 #include "mm/mm1/views_enh/interactions/statue.h"
 #include "mm/mm1/views_enh/locations/inn.h"
 #include "mm/mm1/views_enh/locations/market.h"
@@ -58,6 +61,9 @@ private:
 	ViewsEnh::Interactions::Statue _statue;
 	ViewsEnh::Locations::Inn _inn;
 	ViewsEnh::Locations::Market _market;
+	ViewsEnh::Search _search;
+	ViewsEnh::Trap _trap;
+	ViewsEnh::Unlock _unlock;
 	ViewsEnh::Locations::Tavern _tavern;
 	ViewsEnh::Locations::Temple _temple;
 	ViewsEnh::Locations::Training _training;
diff --git a/engines/mm/mm1/views_enh/search.cpp b/engines/mm/mm1/views_enh/search.cpp
new file mode 100644
index 00000000000..7cc66c66eed
--- /dev/null
+++ b/engines/mm/mm1/views_enh/search.cpp
@@ -0,0 +1,424 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views_enh/search.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace ViewsEnh {
+
+Search::Search() : ScrollView("Search") {
+	_bounds = Common::Rect(234, 144, 320, 200);
+}
+
+bool Search::msgGame(const GameMessage &msg) {
+	if (msg._name != "SHOW")
+		return false;
+
+	bool hasStuff = g_globals->_treasure.present();
+	if (hasStuff) {
+		// Focus view to show what was found
+		open();
+
+	} else {
+		// Otherwise send an info message to say nothing was found
+		Common::String line = STRING["dialogs.search.search"] +
+			STRING["dialogs.search.nothing"];
+		send(InfoMessage(0, 1, line));
+	}
+
+	return true;
+}
+
+bool Search::msgFocus(const FocusMessage &msg) {
+	_bounds = getLineBounds(20, 24);
+	_lineNum = 0;
+
+	if (_mode == FOCUS_GET_TREASURE) {
+		// Returning from trap display
+		if (g_globals->_party.checkPartyDead())
+			return true;
+
+		getTreasure();
+	} else {
+		_mode = INITIAL;
+	}
+
+	return true;
+}
+
+void Search::draw() {
+	Common::String line;
+	if (_mode != GET_ITEMS)
+		clearSurface();
+
+	switch (_mode) {
+	case INITIAL:
+		Sound::sound(SOUND_2);
+		line = STRING["dialogs.search.search"] +
+			STRING["dialogs.search.you_found"];
+		writeString(0, 1, line);
+		delaySeconds(2);
+		break;
+
+	case OPTIONS:
+		writeString(1, 1, STRING["dialogs.search.options1"]);
+		writeString(20, 2, STRING["dialogs.search.options2"]);
+		writeString(20, 3, STRING["dialogs.search.options3"]);
+		//escToGoBack(0, 3);
+		break;
+
+	case GET_TREASURE:
+		drawTreasure();
+		break;
+
+	case GET_ITEMS:
+		// This may be called up to three times, for each item
+		drawItem();
+		break;
+
+	case WHO_WILL_TRY: {
+		line = Common::String::format(
+			STRING["dialogs.search.who_will_try"].c_str(),
+			'0' + g_globals->_party.size()
+		);
+		writeString(10, 1, line);
+		break;
+	}
+
+	default:
+		break;
+	}
+}
+
+bool Search::msgKeypress(const KeypressMessage &msg) {
+	if (endDelay())
+		return true;
+
+	switch (_mode) {
+	case INITIAL:
+		endDelay();
+		break;
+
+	case OPTIONS:
+		switch (msg.keycode) {
+		case Common::KEYCODE_1:
+			openContainer();
+			break;
+		case Common::KEYCODE_2:
+			findRemoveTrap();
+			break;
+		case Common::KEYCODE_3:
+			detectMagicTrap();
+			break;
+		default:
+			break;
+		}
+		break;
+
+	case RESPONSE:
+		endDelay();
+		break;
+
+	case WHO_WILL_TRY:
+		if (msg.keycode >= Common::KEYCODE_1 &&
+			msg.keycode <= (Common::KEYCODE_0 + (int)g_globals->_party.size())) {
+			// Character selected
+			g_globals->_currCharacter = &g_globals->_party[
+				msg.keycode - Common::KEYCODE_1];
+			if ((g_globals->_currCharacter->_condition &
+				(BAD_CONDITION | DEAD | STONE | ASLEEP)) != 0) {
+				clearSurface();
+				writeString(3, 2, STRING["dialogs.search.check_condition"]);
+				delaySeconds(4);
+			} else if (_removing) {
+				findRemoveTrap2();
+			} else {
+				openContainer2();
+			}
+		}
+		break;
+
+	case GET_TREASURE:
+		break;
+
+	default:
+		break;
+	}
+
+	return true;
+}
+
+bool Search::msgAction(const ActionMessage &msg) {
+	if (endDelay())
+		return true;
+
+	if (msg._action == KEYBIND_ESCAPE) {
+		switch (_mode) {
+		case OPTIONS:
+			close();
+			break;
+		case WHO_WILL_TRY:
+			_mode = OPTIONS;
+			draw();
+			break;
+		default:
+			break;
+		}
+
+		return true;
+	}
+
+	return true;
+}
+
+void Search::timeout() {
+	switch (_mode) {
+	case INITIAL: {
+		Maps::Map &map = *g_maps->_currentMap;
+		_val1 = MIN(g_globals->_treasure._container * 8 +
+			map[Maps::MAP_TRAP_THRESHOLD], 255);
+
+		if (!g_globals->_treasure._trapType) {
+			g_globals->_treasure._trapType = (getRandomNumber(100) < _val1) ? 1 : 2;
+		}
+
+		// Show the name of the container type in the game view
+		send("View", HeaderMessage(
+			STRING[Common::String::format("dialogs.search.containers.%d",
+				g_globals->_treasure._container)]
+		));
+
+		// Display a graphic for the container type
+		int gfxNum = g_globals->_treasure._container < WOODEN_BOX ? 4 : 2;
+		send("View", DrawGraphicMessage(gfxNum + 65));
+
+		_mode = OPTIONS;
+		draw();
+		break;
+	}
+	case RESPONSE:
+		_mode = OPTIONS;
+		draw();
+		break;
+
+	case WHO_WILL_TRY:
+		draw();
+		break;
+
+	case GET_TREASURE:
+		_mode = GET_ITEMS;
+		draw();
+		break;
+
+	case GET_ITEMS:
+		draw();
+		break;
+
+	case GET_ITEMS_DONE:
+		close();
+		break;
+
+	default:
+		break;
+	}
+}
+
+void Search::openContainer() {
+	_removing = false;
+	if (!whoWillTry())
+		openContainer2();
+}
+
+void Search::openContainer2() {
+	if (g_globals->_treasure._trapType == 1) {
+		Maps::Map &map = *g_maps->_currentMap;
+		int thresold = map[Maps::MAP_TRAP_THRESHOLD] +
+			g_globals->_treasure._container;
+
+		if (getRandomNumber(thresold + 5) < thresold) {
+			// Triggered a trap
+			_mode = FOCUS_GET_TREASURE;
+			g_events->send("Trap", GameMessage("TRAP"));
+			return;
+		}
+	}
+
+	getTreasure();
+}
+
+void Search::findRemoveTrap() {
+	_removing = true;
+	if (!whoWillTry())
+		findRemoveTrap2();
+}
+
+void Search::findRemoveTrap2() {
+	Character &c = *g_globals->_currCharacter;
+
+	if (g_globals->_treasure._trapType == 1) {
+		byte val = c._trapCtr;
+		if (getRandomNumber(val >= 100 ? val + 5 : 100) >= val) {
+			// Triggered a trap
+			g_events->send("Trap", GameMessage("TRAP"));
+			return;
+		}
+	}
+}
+
+void Search::detectMagicTrap() {
+	Character &c = *g_globals->_currCharacter;
+	_mode = RESPONSE;
+
+	if (c._class == PALADIN || c._class == CLERIC) {
+		Sound::sound(SOUND_2);
+		clearSurface();
+		writeString(6, 2, STRING["dialogs.search.bad_class"]);
+		delaySeconds(4);
+
+	} else if (c._sp == 0) {
+		Sound::sound(SOUND_2);
+		clearSurface();
+		writeString(6, 2, STRING["dialogs.search.no_sp"]);
+		delaySeconds(4);
+
+	} else {
+		c._sp._current--;
+		char magic = g_globals->_treasure.hasItems() ||
+			g_globals->_treasure.getGems() ? 'Y' : 'N';
+		char trapped = g_globals->_treasure._trapType == 1 ? 'Y' : 'N';
+
+		clearSurface();
+		writeString(5, 1, Common::String::format(
+			STRING["dialogs.search.magic_trap"].c_str(),
+			magic, trapped));
+
+		delaySeconds(8);
+	}
+}
+
+bool Search::whoWillTry() {
+	if (g_globals->_party.size() == 1) {
+		g_globals->_currCharacter = &g_globals->_party[0];
+		return true;
+	} else {
+		// Switch to mode to ask which character to use
+		_mode = WHO_WILL_TRY;
+		draw();
+		return false;
+	}
+}
+
+void Search::getTreasure() {
+	_mode = GET_TREASURE;
+	_bounds = getLineBounds(17, 24);
+
+	// Display a graphic for the container type
+	int gfxNum = g_globals->_treasure._container < WOODEN_BOX ? 3 : 1;
+	send("View", DrawGraphicMessage(gfxNum + 65));
+
+	redraw();
+}
+
+void Search::drawTreasure() {
+	writeString(15, 0, STRING["dialogs.search.it_opens"]);
+
+	// Split up the gold across the party
+	uint32 goldPerPerson = g_globals->_treasure.getGold() /
+		g_globals->_party.size();
+	g_globals->_treasure.setGold(0);
+
+	for (uint i = 0; i < g_globals->_party.size(); ++i) {
+		Character &c = g_globals->_party[i];
+		uint32 newGold = c._gold + goldPerPerson;
+		if (newGold < c._gold)
+			// As unlikely as it is to overflow 32-bits
+			newGold = 0xffffffff;
+		c._gold = newGold;
+	}
+	
+	writeString(0, 2, Common::String::format(
+		STRING["dialogs.search.each_share"].c_str(),
+		goldPerPerson));
+	g_globals->_treasure.setGold(0);
+
+	// Assign any gems to a random person
+	int gems = g_globals->_treasure.getGems();
+	g_globals->_treasure.setGems(0);
+
+	_lineNum = 3;
+	if (gems) {
+		// Choose a random recipient
+		uint charNum = getRandomNumber(g_globals->_party.size()) - 1;
+		Character &c = g_globals->_party[charNum];
+
+		writeString(0, _lineNum++, Common::String::format(
+			STRING["dialogs.search.found_gems"].c_str(),
+			c._name,
+			gems));
+		c._gems = MIN((int)c._gems + gems, 0xffff);
+	}
+
+	Sound::sound2(SOUND_5);
+	delaySeconds(2);
+}
+
+void Search::drawItem() {
+	Treasure &treasure = g_globals->_treasure;
+	int itemId = treasure.removeItem();
+
+	// Iterate through any treasure items
+	if (itemId != 0) {
+		// Find a person with free backpack space for the item
+		for (uint i = 0; i < g_globals->_party.size(); ++i) {
+			Character &c = g_globals->_party[i];
+
+			// Check if character has backpack space
+			if (c._backpack.full())
+				continue;
+
+			Item *item = g_globals->_items.getItem(itemId);
+			c._backpack.add(itemId, item->_maxCharges);
+
+			// Add line for found item
+			writeString(0, _lineNum++, Common::String::format(
+				STRING["dialogs.search.found_item"].c_str(),
+				c._name,
+				item->_name.c_str()
+			));
+
+			delaySeconds(2);
+			return;
+		}
+	}
+
+	// At this point we've either displayed the up to 3 item
+	// lines (in addition to gold and/or gems), or the party's
+	// backpacks were completely full up. Wait for 7 seconds
+	_mode = GET_ITEMS_DONE;
+	delaySeconds(7);
+}
+
+} // namespace ViewsEnh
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views_enh/search.h b/engines/mm/mm1/views_enh/search.h
new file mode 100644
index 00000000000..d40be42fdbe
--- /dev/null
+++ b/engines/mm/mm1/views_enh/search.h
@@ -0,0 +1,96 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_ENH_SEARCH_H
+#define MM1_VIEWS_ENH_SEARCH_H
+
+#include "mm/mm1/views_enh/scroll_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace ViewsEnh {
+
+class Search : public ScrollView {
+private:
+	enum Mode {
+		INITIAL, OPTIONS, RESPONSE, WHO_WILL_TRY,
+		FOCUS_GET_TREASURE, GET_TREASURE, GET_ITEMS,
+		GET_ITEMS_DONE
+	};
+	Mode _mode = INITIAL;
+	bool _removing = false;
+	byte _val1 = 0;
+	int _lineNum = 0;
+
+	/**
+	 * Open the container
+	 */
+	void openContainer();
+	void openContainer2();
+
+	/**
+	 * Find/remove trap
+	 */
+	void findRemoveTrap();
+	void findRemoveTrap2();
+
+	/**
+	 * Detect magic/trap
+	 */
+	void detectMagicTrap();
+
+	/**
+	 * Select which user to try and remove trap or detect magic
+	 */
+	bool whoWillTry();
+
+	/**
+	 * Finally give the treasure
+	 */
+	void getTreasure();
+
+	/**
+	 * Draw the treasure result
+	 */
+	void drawTreasure();
+
+	/**
+	 * Get any treasure items
+	 */
+	void drawItem();
+
+public:
+	Search();
+	virtual ~Search() {}
+
+	bool msgGame(const GameMessage &msg) override;
+	bool msgFocus(const FocusMessage &msg) override;
+	void draw() override;
+	bool msgKeypress(const KeypressMessage &msg) override;
+	bool msgAction(const ActionMessage &msg) override;
+	void timeout() override;
+};
+
+} // namespace ViewsEnh
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views_enh/spells/cast_spell.cpp b/engines/mm/mm1/views_enh/spells/cast_spell.cpp
index 40dc0aa353c..dd5b384d767 100644
--- a/engines/mm/mm1/views_enh/spells/cast_spell.cpp
+++ b/engines/mm/mm1/views_enh/spells/cast_spell.cpp
@@ -109,8 +109,6 @@ bool CastSpell::msgAction(const ActionMessage &msg) {
 	} else {
 		return PartyView::msgAction(msg);
 	}
-
-	return false;
 }
 
 bool CastSpell::msgGame(const GameMessage &msg) {
diff --git a/engines/mm/mm1/views_enh/trap.cpp b/engines/mm/mm1/views_enh/trap.cpp
new file mode 100644
index 00000000000..62071a1a51d
--- /dev/null
+++ b/engines/mm/mm1/views_enh/trap.cpp
@@ -0,0 +1,92 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views_enh/trap.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace ViewsEnh {
+
+Trap::Trap() : ScrollView("Trap") {
+	setBounds(Common::Rect(0, 144, 234, 200));
+}
+
+bool Trap::msgGame(const GameMessage &msg) {
+	if (msg._name == "TRIGGER") {
+		open();
+		g_globals->_treasure._container =
+			g_maps->_currentMap->dataByte(Maps::MAP_49);
+		g_globals->_currCharacter = &g_globals->_party[0];
+
+		Sound::sound(SOUND_2);
+		return true;
+
+	} else if (msg._name == "TRAP") {
+		open();
+		trap();
+		return true;
+	}
+
+	return false;
+}
+
+void Trap::draw() {
+	ScrollView::draw();
+
+	if (_mode == MODE_TRIGGER) {
+		writeString(0, 0, STRING["dialogs.trap.oops"], ALIGN_MIDDLE);
+	} else {
+		writeString(0, 0, STRING[Common::String::format("dialogs.trap.%d", _trapType)]);
+	}
+}
+
+bool Trap::msgKeypress(const KeypressMessage &msg) {
+	if (_mode == MODE_TRIGGER) {
+		trap();
+	} else {
+		close();
+	}
+
+	return true;
+}
+
+bool Trap::msgAction(const ActionMessage &msg) {
+	if (_mode == MODE_TRIGGER) {
+		trap();
+	} else {
+		close();
+	}
+
+	return true;
+}
+
+void Trap::trap() {
+	TrapData::trap();
+
+	_mode = MODE_TRAP;
+	draw();
+}
+
+} // namespace ViewsEnh
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views_enh/trap.h b/engines/mm/mm1/views_enh/trap.h
new file mode 100644
index 00000000000..40af9129786
--- /dev/null
+++ b/engines/mm/mm1/views_enh/trap.h
@@ -0,0 +1,53 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_ENH_TRAP_H
+#define MM1_VIEWS_ENH_TRAP_H
+
+#include "mm/mm1/views_enh/scroll_view.h"
+#include "mm/mm1/data/trap.h"
+
+namespace MM {
+namespace MM1 {
+namespace ViewsEnh {
+
+class Trap : public ScrollView, public TrapData {
+private:
+	enum Mode { MODE_TRIGGER, MODE_TRAP };
+	Mode _mode = MODE_TRIGGER;
+protected:
+	void trap() override;
+
+public:
+	Trap();
+	virtual ~Trap() {}
+
+	bool msgGame(const GameMessage &msg) override;
+	void draw() override;
+	bool msgKeypress(const KeypressMessage &msg) override;
+	bool msgAction(const ActionMessage &msg) override;
+};
+
+} // namespace ViewsEnh
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views_enh/unlock.cpp b/engines/mm/mm1/views_enh/unlock.cpp
new file mode 100644
index 00000000000..a4f2f177a66
--- /dev/null
+++ b/engines/mm/mm1/views_enh/unlock.cpp
@@ -0,0 +1,128 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views_enh/unlock.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace ViewsEnh {
+
+Unlock::Unlock() : PartyView("Unlock") {
+	_bounds = Common::Rect(234, 144, 320, 200);
+}
+
+bool Unlock::msgGame(const GameMessage &msg) {
+	if (msg._name == "SHOW") {
+		byte walls = g_maps->_currentWalls & g_maps->_forwardMask;
+
+		if (!(g_maps->_currentState & 0x55 & g_maps->_forwardMask) || !walls) {
+			g_globals->_party.checkPartyDead();
+			return true;
+		}
+
+		int offset;
+		if (!(walls & 0x55)) {
+			offset = 1;
+		} else if (!(walls & 0xaa)) {
+			offset = 0;
+		} else {
+			offset = 2;
+		}
+
+		if (g_maps->_currentMap->dataByte(30 + offset) != 1) {
+			g_globals->_party.checkPartyDead();
+			return true;
+		}
+
+		if (g_globals->_party.size() > 1) {
+			// Select the character to use
+			open();
+		} else {
+			// With only one party member, they're automatically used
+			charSelected(0);
+		}
+	} else if (msg._name == "UPDATE") {
+		charSelected(g_globals->_party.indexOf(g_globals->_currCharacter));
+	}
+
+	return true;
+}
+
+void Unlock::draw() {
+	PartyView::draw();
+
+	writeString(Common::String::format(
+		STRING["dialogs.unlock.who_will_try"].c_str(),
+		'0' + g_globals->_party.size()));
+}
+
+
+bool Unlock::msgAction(const ActionMessage &msg) {
+	if (msg._action == KEYBIND_ESCAPE) {
+		close();
+		return true;
+	} else if (msg._action >= KEYBIND_VIEW_PARTY1 &&
+		msg._action <= KEYBIND_VIEW_PARTY6) {
+		charSelected(msg._action - KEYBIND_VIEW_PARTY1);
+		return true;
+	}
+
+	return PartyView::msgAction(msg);
+}
+
+void Unlock::charSelected(uint charIndex) {
+	if (charIndex >= g_globals->_party.size())
+		return;
+
+	Character &c = g_globals->_party[charIndex];
+	g_globals->_currCharacter = &c;
+
+	if (c._condition & (BAD_CONDITION | DEAD | STONE | ASLEEP)) {
+		Sound::sound(SOUND_2);
+		draw();
+
+	} else {
+		if (isFocused())
+			close();
+
+		int val = g_maps->_currentMap->dataByte(Maps::MAP_49) * 4 +
+			getRandomNumber(100);
+
+		if (val < c._trapCtr) {
+			g_maps->_currentMap->unlockDoor();
+			send(InfoMessage(11, 1, STRING["dialogs.unlock.success"]));
+
+		} else if (getRandomNumber(100) <
+				g_maps->_currentMap->dataByte(Maps::MAP_TRAP_THRESHOLD)) {
+			send(InfoMessage(8, 1, STRING["dialogs.unlock.failed"]));
+
+		} else {
+			g_maps->_currentMap->unlockDoor();
+			send("Trap", GameMessage("TRIGGER"));
+		}
+	}
+}
+
+} // namespace ViewsEnh
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views_enh/unlock.h b/engines/mm/mm1/views_enh/unlock.h
new file mode 100644
index 00000000000..5af335a90b8
--- /dev/null
+++ b/engines/mm/mm1/views_enh/unlock.h
@@ -0,0 +1,55 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_ENH_UNLOCK_H
+#define MM1_VIEWS_ENH_UNLOCK_H
+
+#include "mm/mm1/views_enh/party_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace ViewsEnh {
+
+class Unlock : public PartyView {
+private:
+	void charSelected(uint charIndex);
+
+protected:
+	/**
+	 * Return true if a character should be selected by default
+	 */
+	bool selectCharByDefault() const override {
+		return false;
+	}
+public:
+	Unlock();
+	virtual ~Unlock() {}
+
+	bool msgGame(const GameMessage &msg) override;
+	void draw() override;
+	bool msgAction(const ActionMessage &msg) override;
+};
+
+} // namespace ViewsEnh
+} // namespace MM1
+} // namespace MM
+
+#endif


Commit: 55910494544ccf171f6ecb46178fe74837d40f21
    https://github.com/scummvm/scummvm/commit/55910494544ccf171f6ecb46178fe74837d40f21
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-03-09T22:51:38-08:00

Commit Message:
MM: MM1: Implement trap display

Changed paths:
    devtools/create_mm/files/mm1/strings_en.yml
    engines/mm/mm1/globals.cpp


diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 363601e3ef2..1278c51657f 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -563,6 +563,19 @@ enhdialogs:
 		esc: "ESC"
 		needs: "%s\nneeds %d experience for level %d."
 		eligible: "%s\nis eligible for level %d."
+	trap:
+		oops: "Oops a trap!"
+		0: "Darts!! a swarm of poisonous darts fill the air!"
+		1: "Spikes!! Deadly spikes spring forth!"
+		2: "Arrows!! A sudden onslaught of poisonous arrows permeate the party!"
+		3: "Blades!! Razor sharp blades slice through the party!"
+		4: "Boiling oil!! Streams of boiling oil cover the party!"
+		5: "Gas!! A faint hiss can be heard as noxious fumes fill the air!"
+		6: "Fireball!! A fiery explosion engulfs the area!"
+		7: "Lightning bolt!! Electric currents singe the party!"
+		8: "Acid!! A fine mist of volatile acid sprays the party!"
+		9: "Ice storm!! Particles of splintered ice hail through the air!"
+		10: "Death ray!! A blinding light sears through the party!"
 stats:
 	none: "None"
 	inventory: "-----<Equipped>----------<Backpack>----"
diff --git a/engines/mm/mm1/globals.cpp b/engines/mm/mm1/globals.cpp
index a23a56bdea2..44ae7215097 100644
--- a/engines/mm/mm1/globals.cpp
+++ b/engines/mm/mm1/globals.cpp
@@ -98,20 +98,28 @@ bool Globals::load(bool isEnhanced) {
 }
 
 Common::String Globals::operator[](const Common::String &name) const {
-	bool isMapStr = g_engine->isEnhanced() && name.hasPrefix("maps.map");
-
-	if (isMapStr) {
-		// Map strings support having alternate versions in Enhanced version
-		Common::String altName = Common::String::format("maps.emap%s",
-			name.c_str() + 8);
-		if (_strings.contains(altName))
-			return _strings[altName];
+	bool isMapStr = name.hasPrefix("maps.map");
+
+	if (g_engine->isEnhanced()) {
+		if (isMapStr) {
+			// Map strings support having alternate versions in Enhanced version
+			Common::String altName = Common::String::format("maps.emap%s",
+				name.c_str() + 8);
+			if (_strings.contains(altName))
+				return _strings[altName];
+		}
+
+		if (name.hasPrefix("dialogs.")) {
+			Common::String altName = Common::String::format("enh%s", name.c_str());
+			if (_strings.contains(altName))
+				return _strings[altName];
+		}
 	}
 
 	assert(_strings.contains(name));
 	Common::String result = _strings[name];
 
-	if (isMapStr)
+	if (g_engine->isEnhanced() && isMapStr)
 		result = searchAndReplace(result, "\n", " ");
 
 	return result;


Commit: 4bebb71d622218b3c5dd96b2f4b70aafa2e658cf
    https://github.com/scummvm/scummvm/commit/4bebb71d622218b3c5dd96b2f4b70aafa2e658cf
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-03-09T22:51:38-08:00

Commit Message:
MM: MM1: Add a generic WhoWillTry view

Changed paths:
  A engines/mm/mm1/views_enh/who_will_try.cpp
  A engines/mm/mm1/views_enh/who_will_try.h
    devtools/create_mm/files/mm1/strings_en.yml
    engines/mm/mm1/views/search.cpp
    engines/mm/mm1/views/unlock.cpp
    engines/mm/mm1/views_enh/dialogs.h
    engines/mm/mm1/views_enh/search.cpp
    engines/mm/mm1/views_enh/search.h
    engines/mm/mm1/views_enh/unlock.cpp
    engines/mm/mm1/views_enh/unlock.h
    engines/mm/module.mk


diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 1278c51657f..3ef7712368a 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -161,13 +161,13 @@ dialogs:
 			8: "  gold box  "
 			9: " gold chest "
 			10: " black box  "
-		options1: "options:           1) open it"
-		options2: "2) find/remove trap"
-		options3: "3) detect magic/trap"
-		bad_class: "*** bad class ***"
-		no_sp: "*** no spell points ***"
-		magic_trap: "magic (%c)  trap (%c)"
-		who_will_try: "Who will try '1'-'%c'"
+		options: "Options:"
+		options1: "1) Open it"
+		options2: "2) Find/Remove trap"
+		options3: "3) Detect magic/trap"
+		bad_class: "*** Bad class ***"
+		no_sp: "*** No spell points ***"
+		magic_trap: "Magic (%c)  Trap (%c)"
 		check_condition: "*** Check condition ***"
 		it_opens: "It opens!"
 		receives: "receives"
@@ -276,7 +276,6 @@ dialogs:
 		9: "Ice storm!! Particles of splintered ice\n            hail through the air!"
 		10: "Death ray!! A blinding light sears\n            through the party!"
 	unlock:
-		who_will_try: "Who will try '1'-'%c'?"
 		success: "Success!"
 		failed: "Unlock failed!"
 	view_characters:
@@ -314,6 +313,7 @@ dialogs:
 		no_characters: "No available characters"
 		some_characters: "Available characters"
 		full: "*** Backpack full ***"
+		who_will_try: "Who will try '1'-'%c'"
 	spells:
 		detect_charges: "magic (charges)"
 		fly_to_x: "fly to (a-e): "
diff --git a/engines/mm/mm1/views/search.cpp b/engines/mm/mm1/views/search.cpp
index 6f99f8df561..9b19fdff1b0 100644
--- a/engines/mm/mm1/views/search.cpp
+++ b/engines/mm/mm1/views/search.cpp
@@ -82,7 +82,8 @@ void Search::draw() {
 		break;
 
 	case OPTIONS:
-		writeString(1, 1, STRING["dialogs.search.options1"]);
+		writeString(1, 1, STRING["dialogs.search.options"]);
+		writeString(20, 1, STRING["dialogs.search.options1"]);
 		writeString(20, 2, STRING["dialogs.search.options2"]);
 		writeString(20, 3, STRING["dialogs.search.options3"]);
 		escToGoBack(0, 3);
@@ -99,7 +100,7 @@ void Search::draw() {
 
 	case WHO_WILL_TRY: {
 		line = Common::String::format(
-			STRING["dialogs.search.who_will_try"].c_str(),
+			STRING["dialogs.misc.who_will_try"].c_str(),
 			'0' + g_globals->_party.size()
 		);
 		writeString(10, 1, line);
diff --git a/engines/mm/mm1/views/unlock.cpp b/engines/mm/mm1/views/unlock.cpp
index 01f9849b493..d40d10ffd1d 100644
--- a/engines/mm/mm1/views/unlock.cpp
+++ b/engines/mm/mm1/views/unlock.cpp
@@ -74,7 +74,7 @@ void Unlock::draw() {
 	clearSurface();
 
 	writeString(4, 1, Common::String::format(
-		STRING["dialogs.unlock.who_will_try"].c_str(),
+		STRING["dialogs.misc.who_will_try"].c_str(),
 		'0' + g_globals->_party.size()));
 	escToGoBack(0, 3);
 }
diff --git a/engines/mm/mm1/views_enh/dialogs.h b/engines/mm/mm1/views_enh/dialogs.h
index c25481cc6d2..ad09e3e55d7 100644
--- a/engines/mm/mm1/views_enh/dialogs.h
+++ b/engines/mm/mm1/views_enh/dialogs.h
@@ -39,6 +39,7 @@
 #include "mm/mm1/views_enh/title.h"
 #include "mm/mm1/views_enh/trap.h"
 #include "mm/mm1/views_enh/unlock.h"
+#include "mm/mm1/views_enh/who_will_try.h"
 #include "mm/mm1/views_enh/interactions/statue.h"
 #include "mm/mm1/views_enh/locations/inn.h"
 #include "mm/mm1/views_enh/locations/market.h"
@@ -64,6 +65,7 @@ private:
 	ViewsEnh::Search _search;
 	ViewsEnh::Trap _trap;
 	ViewsEnh::Unlock _unlock;
+	ViewsEnh::WhoWillTry _whoWillTry;
 	ViewsEnh::Locations::Tavern _tavern;
 	ViewsEnh::Locations::Temple _temple;
 	ViewsEnh::Locations::Training _training;
diff --git a/engines/mm/mm1/views_enh/search.cpp b/engines/mm/mm1/views_enh/search.cpp
index 7cc66c66eed..d783b79bf28 100644
--- a/engines/mm/mm1/views_enh/search.cpp
+++ b/engines/mm/mm1/views_enh/search.cpp
@@ -29,6 +29,8 @@ namespace ViewsEnh {
 
 Search::Search() : ScrollView("Search") {
 	_bounds = Common::Rect(234, 144, 320, 200);
+	_escSprite.load("esc.icn");
+	addButton(&_escSprite, Common::Point(120, 172), 0, KEYBIND_ESCAPE, true);
 }
 
 bool Search::msgGame(const GameMessage &msg) {
@@ -51,7 +53,6 @@ bool Search::msgGame(const GameMessage &msg) {
 }
 
 bool Search::msgFocus(const FocusMessage &msg) {
-	_bounds = getLineBounds(20, 24);
 	_lineNum = 0;
 
 	if (_mode == FOCUS_GET_TREASURE) {
@@ -69,23 +70,25 @@ bool Search::msgFocus(const FocusMessage &msg) {
 
 void Search::draw() {
 	Common::String line;
-	if (_mode != GET_ITEMS)
-		clearSurface();
+	//if (_mode != GET_ITEMS)
+	setButtonEnabled(0, _mode == OPTIONS);
+	ScrollView::draw();
 
 	switch (_mode) {
 	case INITIAL:
 		Sound::sound(SOUND_2);
 		line = STRING["dialogs.search.search"] +
 			STRING["dialogs.search.you_found"];
-		writeString(0, 1, line);
+		writeString(line);
 		delaySeconds(2);
 		break;
 
 	case OPTIONS:
-		writeString(1, 1, STRING["dialogs.search.options1"]);
-		writeString(20, 2, STRING["dialogs.search.options2"]);
-		writeString(20, 3, STRING["dialogs.search.options3"]);
-		//escToGoBack(0, 3);
+		writeString(0, 0, STRING["dialogs.search.options"]);
+		writeString(160, 0, STRING["dialogs.search.options1"]);
+		writeString(160, 9, STRING["dialogs.search.options2"]);
+		writeString(160, 18, STRING["dialogs.search.options3"]);
+		writeString(140, 30, STRING["enhdialogs.misc.go_back"]);
 		break;
 
 	case GET_TREASURE:
@@ -99,7 +102,7 @@ void Search::draw() {
 
 	case WHO_WILL_TRY: {
 		line = Common::String::format(
-			STRING["dialogs.search.who_will_try"].c_str(),
+			STRING["dialogs.misc.who_will_try"].c_str(),
 			'0' + g_globals->_party.size()
 		);
 		writeString(10, 1, line);
diff --git a/engines/mm/mm1/views_enh/search.h b/engines/mm/mm1/views_enh/search.h
index d40be42fdbe..b02c1d5d198 100644
--- a/engines/mm/mm1/views_enh/search.h
+++ b/engines/mm/mm1/views_enh/search.h
@@ -39,6 +39,7 @@ private:
 	bool _removing = false;
 	byte _val1 = 0;
 	int _lineNum = 0;
+	Shared::Xeen::SpriteResource _escSprite;
 
 	/**
 	 * Open the container
diff --git a/engines/mm/mm1/views_enh/unlock.cpp b/engines/mm/mm1/views_enh/unlock.cpp
index a4f2f177a66..ccd571b3d55 100644
--- a/engines/mm/mm1/views_enh/unlock.cpp
+++ b/engines/mm/mm1/views_enh/unlock.cpp
@@ -20,6 +20,8 @@
  */
 
 #include "mm/mm1/views_enh/unlock.h"
+#include "mm/mm1/views_enh/who_will_try.h"
+#include "mm/mm1/mm1.h"
 #include "mm/mm1/globals.h"
 #include "mm/mm1/sound.h"
 
@@ -32,66 +34,36 @@ Unlock::Unlock() : PartyView("Unlock") {
 }
 
 bool Unlock::msgGame(const GameMessage &msg) {
-	if (msg._name == "SHOW") {
-		byte walls = g_maps->_currentWalls & g_maps->_forwardMask;
+	if (msg._name != "SHOW")
+		return false;
 
-		if (!(g_maps->_currentState & 0x55 & g_maps->_forwardMask) || !walls) {
-			g_globals->_party.checkPartyDead();
-			return true;
-		}
-
-		int offset;
-		if (!(walls & 0x55)) {
-			offset = 1;
-		} else if (!(walls & 0xaa)) {
-			offset = 0;
-		} else {
-			offset = 2;
-		}
-
-		if (g_maps->_currentMap->dataByte(30 + offset) != 1) {
-			g_globals->_party.checkPartyDead();
-			return true;
-		}
+	byte walls = g_maps->_currentWalls & g_maps->_forwardMask;
 
-		if (g_globals->_party.size() > 1) {
-			// Select the character to use
-			open();
-		} else {
-			// With only one party member, they're automatically used
-			charSelected(0);
-		}
-	} else if (msg._name == "UPDATE") {
-		charSelected(g_globals->_party.indexOf(g_globals->_currCharacter));
+	if (!(g_maps->_currentState & 0x55 & g_maps->_forwardMask) || !walls) {
+		g_globals->_party.checkPartyDead();
+		return true;
 	}
 
-	return true;
-}
-
-void Unlock::draw() {
-	PartyView::draw();
-
-	writeString(Common::String::format(
-		STRING["dialogs.unlock.who_will_try"].c_str(),
-		'0' + g_globals->_party.size()));
-}
-
+	int offset;
+	if (!(walls & 0x55)) {
+		offset = 1;
+	} else if (!(walls & 0xaa)) {
+		offset = 0;
+	} else {
+		offset = 2;
+	}
 
-bool Unlock::msgAction(const ActionMessage &msg) {
-	if (msg._action == KEYBIND_ESCAPE) {
-		close();
-		return true;
-	} else if (msg._action >= KEYBIND_VIEW_PARTY1 &&
-		msg._action <= KEYBIND_VIEW_PARTY6) {
-		charSelected(msg._action - KEYBIND_VIEW_PARTY1);
+	if (g_maps->_currentMap->dataByte(30 + offset) != 1) {
+		g_globals->_party.checkPartyDead();
 		return true;
 	}
 
-	return PartyView::msgAction(msg);
+	WhoWillTry::display(charSelected);
+	return true;
 }
 
-void Unlock::charSelected(uint charIndex) {
-	if (charIndex >= g_globals->_party.size())
+void Unlock::charSelected(int charIndex) {
+	if (charIndex == -1 || charIndex >= (int)g_globals->_party.size())
 		return;
 
 	Character &c = g_globals->_party[charIndex];
@@ -99,26 +71,22 @@ void Unlock::charSelected(uint charIndex) {
 
 	if (c._condition & (BAD_CONDITION | DEAD | STONE | ASLEEP)) {
 		Sound::sound(SOUND_2);
-		draw();
 
 	} else {
-		if (isFocused())
-			close();
-
 		int val = g_maps->_currentMap->dataByte(Maps::MAP_49) * 4 +
-			getRandomNumber(100);
+			g_engine->getRandomNumber(100);
 
 		if (val < c._trapCtr) {
 			g_maps->_currentMap->unlockDoor();
-			send(InfoMessage(11, 1, STRING["dialogs.unlock.success"]));
+			g_engine->send(InfoMessage(11, 1, STRING["dialogs.unlock.success"]));
 
-		} else if (getRandomNumber(100) <
+		} else if (g_engine->getRandomNumber(100) <
 				g_maps->_currentMap->dataByte(Maps::MAP_TRAP_THRESHOLD)) {
-			send(InfoMessage(8, 1, STRING["dialogs.unlock.failed"]));
+			g_engine->send(InfoMessage(8, 1, STRING["dialogs.unlock.failed"]));
 
 		} else {
 			g_maps->_currentMap->unlockDoor();
-			send("Trap", GameMessage("TRIGGER"));
+			g_engine->send("Trap", GameMessage("TRIGGER"));
 		}
 	}
 }
diff --git a/engines/mm/mm1/views_enh/unlock.h b/engines/mm/mm1/views_enh/unlock.h
index 5af335a90b8..69e7838abcb 100644
--- a/engines/mm/mm1/views_enh/unlock.h
+++ b/engines/mm/mm1/views_enh/unlock.h
@@ -30,22 +30,14 @@ namespace ViewsEnh {
 
 class Unlock : public PartyView {
 private:
-	void charSelected(uint charIndex);
-
-protected:
-	/**
-	 * Return true if a character should be selected by default
-	 */
-	bool selectCharByDefault() const override {
-		return false;
-	}
+	static void charSelected(int charIndex);
+
 public:
 	Unlock();
 	virtual ~Unlock() {}
 
 	bool msgGame(const GameMessage &msg) override;
-	void draw() override;
-	bool msgAction(const ActionMessage &msg) override;
+	void draw() override {}		// View no direct display
 };
 
 } // namespace ViewsEnh
diff --git a/engines/mm/mm1/views_enh/who_will_try.cpp b/engines/mm/mm1/views_enh/who_will_try.cpp
new file mode 100644
index 00000000000..113975ad7bb
--- /dev/null
+++ b/engines/mm/mm1/views_enh/who_will_try.cpp
@@ -0,0 +1,90 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "mm/mm1/views_enh/who_will_try.h"
+#include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
+
+namespace MM {
+namespace MM1 {
+namespace ViewsEnh {
+
+WhoWillTry::WhoWillTry() : PartyView("WhoWillTry") {
+	_bounds = Common::Rect(234, 144, 320, 200);
+}
+
+void WhoWillTry::display(WhoWillProc callback) {
+	WhoWillTry *view = static_cast<WhoWillTry *>(g_events->findView("WhoWillTry"));
+	view->open(callback);
+}
+
+void WhoWillTry::open(WhoWillProc callback) {
+	_callback = callback;
+
+	if (g_globals->_party.size() > 1) {
+		// Select the character to use
+		addView();
+
+	} else {
+		// With only one party member, they're automatically used
+		callback(0);
+	}
+}
+
+bool WhoWillTry::msgGame(const GameMessage &msg) {
+	if (msg._name == "UPDATE") {
+		close();
+		_callback(g_globals->_party.indexOf(g_globals->_currCharacter));
+	}
+
+	return true;
+}
+
+void WhoWillTry::draw() {
+	PartyView::draw();
+
+	writeString(0, 0, Common::String::format(
+		STRING["dialogs.misc.who_will_try"].c_str(),
+		'0' + g_globals->_party.size()));
+}
+
+bool WhoWillTry::msgAction(const ActionMessage &msg) {
+	if (msg._action == KEYBIND_ESCAPE) {
+		close();
+		return true;
+	} else if (msg._action >= KEYBIND_VIEW_PARTY1 &&
+		msg._action <= KEYBIND_VIEW_PARTY6) {
+		int charNum = msg._action - KEYBIND_VIEW_PARTY1;
+
+		if (charNum < (int)g_globals->_party.size()) {
+			close();
+			_callback(charNum);
+		}
+
+		return true;
+	}
+
+	return PartyView::msgAction(msg);
+}
+
+} // namespace ViewsEnh
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views_enh/who_will_try.h b/engines/mm/mm1/views_enh/who_will_try.h
new file mode 100644
index 00000000000..706f8754cdc
--- /dev/null
+++ b/engines/mm/mm1/views_enh/who_will_try.h
@@ -0,0 +1,60 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MM1_VIEWS_ENH_WHO_WILL_TRY_H
+#define MM1_VIEWS_ENH_WHO_WILL_TRY_H
+
+#include "mm/mm1/views_enh/party_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace ViewsEnh {
+
+typedef void (*WhoWillProc)(int charNum);
+
+class WhoWillTry : public PartyView {
+private:
+	WhoWillProc _callback = nullptr;
+
+protected:
+	/**
+	 * Return true if a character should be selected by default
+	 */
+	bool selectCharByDefault() const override {
+		return false;
+	}
+public:
+	WhoWillTry();
+	virtual ~WhoWillTry() {}
+
+	static void display(WhoWillProc callback);
+	void open(WhoWillProc callback);
+
+	bool msgGame(const GameMessage &msg) override;
+	void draw() override;
+	bool msgAction(const ActionMessage &msg) override;
+};
+
+} // namespace ViewsEnh
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 9874b0e619c..259a0cc27f7 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -149,6 +149,7 @@ MODULE_OBJS += \
 	mm1/views_enh/text_entry.o \
 	mm1/views_enh/text_view.o \
 	mm1/views_enh/title.o \
+	mm1/views_enh/who_will_try.o \
 	mm1/views_enh/interactions/interaction.o \
 	mm1/views_enh/interactions/statue.o \
 	mm1/views_enh/locations/inn.o \




More information about the Scummvm-git-logs mailing list