[Scummvm-git-logs] scummvm master -> 5e39b24240d3be7b17ea109fea384c168fad6535

dreammaster noreply at scummvm.org
Tue Mar 21 03:14:46 UTC 2023


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

Summary:
c1c863de78 MM: MM1: Show items characters can't use in grey
a37a9fbc24 MM: MM1: Beginnings of character inventory screen
40cfc422b4 MM: MM1: In progress adding a Which Item view
9a7b3abb36 MM: MM1: Discarding items now working
462d002393 MM: MM1: Refactor equip/remove logic into it's own class
5e39b24240 MM: MM1: Added equip/remove to enhanced character items view


Commit: c1c863de78c542a4b115f04e9992b7ba22e7c6ba
    https://github.com/scummvm/scummvm/commit/c1c863de78c542a4b115f04e9992b7ba22e7c6ba
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-03-20T20:14:21-07:00

Commit Message:
MM: MM1: Show items characters can't use in grey

Changed paths:
    engines/mm/mm1/views_enh/items_view.cpp
    engines/mm/mm1/views_enh/items_view.h
    engines/mm/mm1/views_enh/locations/blacksmith_items.cpp
    engines/mm/mm1/views_enh/locations/blacksmith_items.h


diff --git a/engines/mm/mm1/views_enh/items_view.cpp b/engines/mm/mm1/views_enh/items_view.cpp
index 3ddc53a1320..3dd0ae88708 100644
--- a/engines/mm/mm1/views_enh/items_view.cpp
+++ b/engines/mm/mm1/views_enh/items_view.cpp
@@ -88,7 +88,7 @@ void ItemsView::draw() {
 			item._name.c_str()
 		);
 
-		setTextColor(i == _selectedItem ? 15 : 0);
+		setTextColor(i == _selectedItem ? 15 : getLineColor());
 		writeLine(2 + i, line, ALIGN_LEFT, 10);
 
 		if (_costMode != NO_COST) {
diff --git a/engines/mm/mm1/views_enh/items_view.h b/engines/mm/mm1/views_enh/items_view.h
index d4e0292439d..905721b2b56 100644
--- a/engines/mm/mm1/views_enh/items_view.h
+++ b/engines/mm/mm1/views_enh/items_view.h
@@ -59,6 +59,13 @@ protected:
 	 */
 	void displayMessage(const Common::String &msg);
 
+	/**
+	 * Get the text color for a line
+	 */
+	virtual int getLineColor() const {
+		return 0;
+	}
+
 	/**
 	 * Called when an item is selected
 	 */
diff --git a/engines/mm/mm1/views_enh/locations/blacksmith_items.cpp b/engines/mm/mm1/views_enh/locations/blacksmith_items.cpp
index 1077bcd04a4..1109559c507 100644
--- a/engines/mm/mm1/views_enh/locations/blacksmith_items.cpp
+++ b/engines/mm/mm1/views_enh/locations/blacksmith_items.cpp
@@ -215,6 +215,22 @@ void BlacksmithItems::itemConfirmed() {
 	}
 }
 
+int BlacksmithItems::getLineColor() const {
+	const Character &c = *g_globals->_currCharacter;
+	const Item &item = g_globals->_currItem;
+
+	if (_mode == SELL_MODE) {
+		return 0;
+	} else {
+		if (c._class != NONE && c._class <= ROBBER) {
+			if (!(BLACKSMITH_CLASS_USAGE[c._class - 1] & item._disablements))
+				return 0;
+		}
+
+		return 1;
+	}
+}
+
 } // namespace Locations
 } // namespace ViewsEnh
 } // namespace MM1
diff --git a/engines/mm/mm1/views_enh/locations/blacksmith_items.h b/engines/mm/mm1/views_enh/locations/blacksmith_items.h
index b63f505064e..1f6d06b2e39 100644
--- a/engines/mm/mm1/views_enh/locations/blacksmith_items.h
+++ b/engines/mm/mm1/views_enh/locations/blacksmith_items.h
@@ -31,8 +31,8 @@ namespace ViewsEnh {
 namespace Locations {
 
 class BlacksmithItems : public ItemsView,
-	public BuyWeaponData, public BuyArmorData,
-	public BuyMiscData {
+	public BlacksmithData, public BuyWeaponData,
+	public BuyArmorData, public BuyMiscData {
 private:
 	enum BlacksmithMode {
 		WEAPONS_MODE = 0, ARMOR_MODE = 1, MISC_MODE = 2,
@@ -57,6 +57,11 @@ private:
 	void itemConfirmed();
 
 protected:
+	/**
+	 * Get the text color for a line
+	 */
+	int getLineColor() const override;
+
 	/**
 	 * Called when an item is selected
 	 */


Commit: a37a9fbc2450d08f9fa0b444cf5a6b30b803049f
    https://github.com/scummvm/scummvm/commit/a37a9fbc2450d08f9fa0b444cf5a6b30b803049f
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-03-20T20:14:21-07:00

Commit Message:
MM: MM1: Beginnings of character inventory screen

Changed paths:
  A engines/mm/mm1/views_enh/character_inventory.cpp
  A engines/mm/mm1/views_enh/character_inventory.h
    devtools/create_mm/files/mm1/strings_en.yml
    engines/mm/mm1/views_enh/character_info.cpp
    engines/mm/mm1/views_enh/dialogs.h
    engines/mm/mm1/views_enh/locations/blacksmith_items.cpp
    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 26c774b5588..794f2b2437d 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -430,6 +430,7 @@ dialogs:
 enhdialogs:
 	blacksmith:
 		browse: "\x01""37Browse"
+		arms_for: "Equipment for %s the %s"
 		backpack_for: "Backpack for %s the %s"
 		cost: "Cost"
 		gold: "Gold"
@@ -438,7 +439,7 @@ enhdialogs:
 		sell: "Sell"
 		for_gold: "for %d gold"
 		areas:
-			weapons: "Weapons"
+			weapons: "Weapons"	
 			armor: "Armor"
 			misc: "Misc"
 		buttons:
@@ -449,6 +450,13 @@ enhdialogs:
 			sell: "\x01""37Sell"
 			buy: "\x01""37Buy"
 			sell: "\x01""37Sell"
+			arms: "\x01""37Arms"
+			backpack: "\x01""37BkPack"
+			equip: "\x01""37Equip"
+			remove: "\x01""37Rem"
+			discard: "\x01""37Disc"
+			gather: "\x01""37Gath"		
+			use: "\x01""37Use"
 			exit: "Exit"
 	cast_spell:
 		title: "Cast Spell"
diff --git a/engines/mm/mm1/views_enh/character_info.cpp b/engines/mm/mm1/views_enh/character_info.cpp
index f2a9b65e0df..8e91cd2eb0f 100644
--- a/engines/mm/mm1/views_enh/character_info.cpp
+++ b/engines/mm/mm1/views_enh/character_info.cpp
@@ -130,6 +130,9 @@ bool CharacterInfo::msgKeypress(const KeypressMessage &msg) {
 		_cursorCell = EXPANDED_TO_REDUCED(idx);
 		showCursor(true);
 		break;
+	case Common::KEYCODE_i:
+		addView("CharacterInventory");
+		break;
 	case Common::KEYCODE_e:
 		addView("Exchange");
 		break;
diff --git a/engines/mm/mm1/views_enh/character_inventory.cpp b/engines/mm/mm1/views_enh/character_inventory.cpp
new file mode 100644
index 00000000000..f4aaf3cf54b
--- /dev/null
+++ b/engines/mm/mm1/views_enh/character_inventory.cpp
@@ -0,0 +1,138 @@
+/* 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/character_inventory.h"
+#include "mm/mm1/globals.h"
+
+namespace MM {
+namespace MM1 {
+namespace ViewsEnh {
+
+CharacterInventory::CharacterInventory() : ItemsView("CharacterInventory") {
+	_btnSprites.load("items.icn");
+	addButton(2, STRING["enhdialogs.blacksmith.buttons.arms"], Common::KEYCODE_a);
+	addButton(6, STRING["enhdialogs.blacksmith.buttons.backpack"], Common::KEYCODE_b);
+	addButton(8, STRING["enhdialogs.blacksmith.buttons.equip"], Common::KEYCODE_e);
+	addButton(10, STRING["enhdialogs.blacksmith.buttons.remove"], Common::KEYCODE_r);
+	addButton(12, STRING["enhdialogs.blacksmith.buttons.discard"], Common::KEYCODE_d);
+	addButton(6, STRING["enhdialogs.blacksmith.buttons.gather"], Common::KEYCODE_g);
+	addButton(14, STRING["enhdialogs.blacksmith.buttons.use"], Common::KEYCODE_u);
+	addButton(16, STRING["enhdialogs.blacksmith.buttons.exit"], Common::KEYCODE_ESCAPE);
+}
+
+bool CharacterInventory::msgFocus(const FocusMessage &msg) {
+	ItemsView::msgFocus(msg);
+
+	_mode = ARMS_MODE;
+	populateItems();
+
+	return true;
+}
+
+void CharacterInventory::draw() {
+	ItemsView::draw();
+	drawTitle();
+}
+
+void CharacterInventory::drawTitle() {
+	const Character &c = *g_globals->_currCharacter;
+	const Common::String fmt = STRING[(_mode == ARMS_MODE) ?
+		"enhdialogs.blacksmith.arms_for" :
+		"enhdialogs.blacksmith.backpack_for"];
+
+	const Common::String title = Common::String::format(fmt.c_str(),
+		c._name,
+		STRING[Common::String::format("stats.classes.%d", c._class)].c_str()
+	);
+
+	setReduced(false);
+	writeLine(0, title, ALIGN_MIDDLE);
+}
+
+bool CharacterInventory::msgKeypress(const KeypressMessage &msg) {
+	if (endDelay())
+		return true;
+
+	switch (msg.keycode) {
+	case Common::KEYCODE_a:
+		_mode = ARMS_MODE;
+		populateItems();
+		redraw();
+		break;
+	case Common::KEYCODE_b:
+		_mode = BACKPACK_MODE;
+		populateItems();
+		redraw();
+		break;
+		/*
+	case Common::KEYCODE_w:
+		_mode = WEAPONS_MODE;
+		populateItems();
+		redraw();
+		break;
+	case Common::KEYCODE_a:
+		_mode = ARMOR_MODE;
+		populateItems();
+		redraw();
+		break;
+	case Common::KEYCODE_m:
+		_mode = MISC_MODE;
+		populateItems();
+		redraw();
+		break;
+	case Common::KEYCODE_s:
+		_mode = SELL_MODE;
+		populateItems();
+		redraw();
+		break;
+*/
+	default:
+		return ItemsView::msgKeypress(msg);
+	}
+
+	return true;
+}
+
+bool CharacterInventory::msgAction(const ActionMessage &msg) {
+	if (endDelay())
+		return true;
+
+	return ItemsView::msgAction(msg);
+}
+
+void CharacterInventory::populateItems() {
+	_items.clear();
+	_selectedItem = -1;
+
+	const Character &c = *g_globals->_currCharacter;
+	const Inventory &inv = (_mode == ARMS_MODE) ? c._equipped : c._backpack;
+
+	for (uint i = 0; i < inv.size(); ++i)
+		_items.push_back(inv[i]._id);
+}
+
+void CharacterInventory::itemSelected() {
+	// No implementation
+}
+
+} // namespace ViewsEnh
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views_enh/character_inventory.h b/engines/mm/mm1/views_enh/character_inventory.h
new file mode 100644
index 00000000000..2c20ee7eb4b
--- /dev/null
+++ b/engines/mm/mm1/views_enh/character_inventory.h
@@ -0,0 +1,68 @@
+/* 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_CHARACTER_INVENTORY_H
+#define MM1_VIEWS_ENH_CHARACTER_INVENTORY_H
+
+#include "mm/mm1/views_enh/items_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace ViewsEnh {
+
+class CharacterInventory : public ItemsView {
+private:
+	enum DisplayMode {
+		ARMS_MODE, BACKPACK_MODE
+	};
+	DisplayMode _mode = ARMS_MODE;
+
+	/**
+	 * Populates the list of items
+	 */
+	void populateItems();
+
+	/**
+	 * Displays the title row
+	 */
+	void drawTitle();
+
+protected:
+	/**
+	 * Called when an item is selected
+	 */
+	void itemSelected() override;
+
+public:
+	CharacterInventory();
+	virtual ~CharacterInventory() {}
+
+	bool msgFocus(const FocusMessage &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/dialogs.h b/engines/mm/mm1/views_enh/dialogs.h
index 48e2cb8f451..1b3adde0ee7 100644
--- a/engines/mm/mm1/views_enh/dialogs.h
+++ b/engines/mm/mm1/views_enh/dialogs.h
@@ -26,6 +26,7 @@
 #include "mm/mm1/views/bash.h"
 #include "mm/mm1/views/title.h"
 #include "mm/mm1/views_enh/character_info.h"
+#include "mm/mm1/views_enh/character_inventory.h"
 #include "mm/mm1/views_enh/character_select.h"
 #include "mm/mm1/views_enh/characters.h"
 #include "mm/mm1/views_enh/confirm.h"
@@ -71,6 +72,7 @@ private:
 	ViewsEnh::Spells::CastSpell _castSpell;
 	ViewsEnh::Spells::Spellbook _spellbook;
 	ViewsEnh::CharacterInfo _characterInfo;
+	ViewsEnh::CharacterInventory _characterInventory;
 	ViewsEnh::CharacterSelect _characterSelect;
 	ViewsEnh::Characters _characters;
 	ViewsEnh::Confirm _confirm;
diff --git a/engines/mm/mm1/views_enh/locations/blacksmith_items.cpp b/engines/mm/mm1/views_enh/locations/blacksmith_items.cpp
index 1109559c507..45d86c090ba 100644
--- a/engines/mm/mm1/views_enh/locations/blacksmith_items.cpp
+++ b/engines/mm/mm1/views_enh/locations/blacksmith_items.cpp
@@ -40,8 +40,7 @@ BlacksmithItems::BlacksmithItems() : ItemsView("BlacksmithItems") {
 bool BlacksmithItems::msgFocus(const FocusMessage &msg) {
 	ItemsView::msgFocus(msg);
 
-	if (dynamic_cast<Confirm *>(msg._priorView) == nullptr)
-		_mode = WEAPONS_MODE;
+	_mode = WEAPONS_MODE;
 	populateItems();
 
 	return true;
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index c7169bbc231..cbe38acac61 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -127,6 +127,7 @@ MODULE_OBJS += \
 	mm1/views_enh/button_container.o \
 	mm1/views_enh/character_base.o \
 	mm1/views_enh/character_info.o \
+	mm1/views_enh/character_inventory.o \
 	mm1/views_enh/character_manage.o \
 	mm1/views_enh/character_select.o \
 	mm1/views_enh/character_view.o \


Commit: 40cfc422b461004b56915f867257836d9d82b6d3
    https://github.com/scummvm/scummvm/commit/40cfc422b461004b56915f867257836d9d82b6d3
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-03-20T20:14:21-07:00

Commit Message:
MM: MM1: In progress adding a Which Item view

Changed paths:
  A engines/mm/mm1/views_enh/which_item.cpp
  A engines/mm/mm1/views_enh/which_item.h
    devtools/create_mm/files/mm1/strings_en.yml
    engines/mm/mm1/views_enh/character_inventory.cpp
    engines/mm/mm1/views_enh/dialogs.h
    engines/mm/mm1/views_enh/locations/blacksmith_items.cpp
    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 794f2b2437d..b1820b42bbc 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -430,8 +430,6 @@ dialogs:
 enhdialogs:
 	blacksmith:
 		browse: "\x01""37Browse"
-		arms_for: "Equipment for %s the %s"
-		backpack_for: "Backpack for %s the %s"
 		cost: "Cost"
 		gold: "Gold"
 		available: "Available"
@@ -450,14 +448,6 @@ enhdialogs:
 			sell: "\x01""37Sell"
 			buy: "\x01""37Buy"
 			sell: "\x01""37Sell"
-			arms: "\x01""37Arms"
-			backpack: "\x01""37BkPack"
-			equip: "\x01""37Equip"
-			remove: "\x01""37Rem"
-			discard: "\x01""37Disc"
-			gather: "\x01""37Gath"		
-			use: "\x01""37Use"
-			exit: "Exit"
 	cast_spell:
 		title: "Cast Spell"
 		spell_ready: "Spell Ready:"
@@ -545,6 +535,30 @@ enhdialogs:
 		right_click: "Right click to view"
 		exit: "Exit Inn"
 		esc: "ESC to go back"
+	items:
+		arms_for: "Equipment for %s the %s"
+		backpack_for: "Backpack for %s the %s"
+		which_item: "which item?"
+		equip: "Equip"
+		remove: "Remove"
+		discard: "Discard"
+		use: "Use"
+		buttons:
+		buttons:
+			weapons: "\x01""37Weap"
+			armor: "\x01""37Armor"
+			misc: "\x01""37Misc"
+			buy: "\x01""37Buy"
+			sell: "\x01""37Sell"
+			buy: "\x01""37Buy"
+			sell: "\x01""37Sell"
+			arms: "\x01""37Arms"
+			backpack: "\x01""37BkPack"
+			equip: "\x01""37Equip"
+			remove: "\x01""37Rem"
+			discard: "\x01""37Disc"
+			trade: "\x01""37Trade"		
+			use: "\x01""37Use"
 	location:
 		store: "Store"
 		options: "options"
diff --git a/engines/mm/mm1/views_enh/character_inventory.cpp b/engines/mm/mm1/views_enh/character_inventory.cpp
index f4aaf3cf54b..ba47b04f8f6 100644
--- a/engines/mm/mm1/views_enh/character_inventory.cpp
+++ b/engines/mm/mm1/views_enh/character_inventory.cpp
@@ -20,6 +20,7 @@
  */
 
 #include "mm/mm1/views_enh/character_inventory.h"
+#include "mm/mm1/views_enh/which_item.h"
 #include "mm/mm1/globals.h"
 
 namespace MM {
@@ -28,20 +29,21 @@ namespace ViewsEnh {
 
 CharacterInventory::CharacterInventory() : ItemsView("CharacterInventory") {
 	_btnSprites.load("items.icn");
-	addButton(2, STRING["enhdialogs.blacksmith.buttons.arms"], Common::KEYCODE_a);
-	addButton(6, STRING["enhdialogs.blacksmith.buttons.backpack"], Common::KEYCODE_b);
-	addButton(8, STRING["enhdialogs.blacksmith.buttons.equip"], Common::KEYCODE_e);
-	addButton(10, STRING["enhdialogs.blacksmith.buttons.remove"], Common::KEYCODE_r);
-	addButton(12, STRING["enhdialogs.blacksmith.buttons.discard"], Common::KEYCODE_d);
-	addButton(6, STRING["enhdialogs.blacksmith.buttons.gather"], Common::KEYCODE_g);
-	addButton(14, STRING["enhdialogs.blacksmith.buttons.use"], Common::KEYCODE_u);
-	addButton(16, STRING["enhdialogs.blacksmith.buttons.exit"], Common::KEYCODE_ESCAPE);
+	addButton(2, STRING["enhdialogs.items.buttons.arms"], Common::KEYCODE_a);
+	addButton(6, STRING["enhdialogs.items.buttons.backpack"], Common::KEYCODE_b);
+	addButton(8, STRING["enhdialogs.items.buttons.equip"], Common::KEYCODE_e);
+	addButton(10, STRING["enhdialogs.items.buttons.remove"], Common::KEYCODE_r);
+	addButton(12, STRING["enhdialogs.items.buttons.discard"], Common::KEYCODE_d);
+	addButton(6, STRING["enhdialogs.items.buttons.trade"], Common::KEYCODE_t);
+	addButton(14, STRING["enhdialogs.items.buttons.use"], Common::KEYCODE_u);
+	addButton(16, STRING["enhdialogs.misc.exit"], Common::KEYCODE_ESCAPE);
 }
 
 bool CharacterInventory::msgFocus(const FocusMessage &msg) {
 	ItemsView::msgFocus(msg);
 
-	_mode = ARMS_MODE;
+	if (dynamic_cast<WhichItem *>(msg._priorView) == nullptr)
+		_mode = ARMS_MODE;
 	populateItems();
 
 	return true;
@@ -55,8 +57,8 @@ void CharacterInventory::draw() {
 void CharacterInventory::drawTitle() {
 	const Character &c = *g_globals->_currCharacter;
 	const Common::String fmt = STRING[(_mode == ARMS_MODE) ?
-		"enhdialogs.blacksmith.arms_for" :
-		"enhdialogs.blacksmith.backpack_for"];
+		"enhdialogs.items.arms_for" :
+		"enhdialogs.items.backpack_for"];
 
 	const Common::String title = Common::String::format(fmt.c_str(),
 		c._name,
@@ -82,28 +84,6 @@ bool CharacterInventory::msgKeypress(const KeypressMessage &msg) {
 		populateItems();
 		redraw();
 		break;
-		/*
-	case Common::KEYCODE_w:
-		_mode = WEAPONS_MODE;
-		populateItems();
-		redraw();
-		break;
-	case Common::KEYCODE_a:
-		_mode = ARMOR_MODE;
-		populateItems();
-		redraw();
-		break;
-	case Common::KEYCODE_m:
-		_mode = MISC_MODE;
-		populateItems();
-		redraw();
-		break;
-	case Common::KEYCODE_s:
-		_mode = SELL_MODE;
-		populateItems();
-		redraw();
-		break;
-*/
 	default:
 		return ItemsView::msgKeypress(msg);
 	}
diff --git a/engines/mm/mm1/views_enh/dialogs.h b/engines/mm/mm1/views_enh/dialogs.h
index 1b3adde0ee7..0fabe4b6f6b 100644
--- a/engines/mm/mm1/views_enh/dialogs.h
+++ b/engines/mm/mm1/views_enh/dialogs.h
@@ -43,6 +43,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/which_item.h"
 #include "mm/mm1/views_enh/who_will_try.h"
 #include "mm/mm1/views_enh/interactions/statue.h"
 #include "mm/mm1/views_enh/locations/blacksmith_items.h"
@@ -89,6 +90,7 @@ private:
 	ViewsEnh::Title _title;
 	ViewsEnh::Trap _trap;
 	ViewsEnh::Unlock _unlock;
+	ViewsEnh::WhichItem _whichItem;
 	ViewsEnh::WhoWillTry _whoWillTry;
 	Views::Bash _bash;
 public:
diff --git a/engines/mm/mm1/views_enh/locations/blacksmith_items.cpp b/engines/mm/mm1/views_enh/locations/blacksmith_items.cpp
index 45d86c090ba..0ecf291ee84 100644
--- a/engines/mm/mm1/views_enh/locations/blacksmith_items.cpp
+++ b/engines/mm/mm1/views_enh/locations/blacksmith_items.cpp
@@ -34,7 +34,7 @@ BlacksmithItems::BlacksmithItems() : ItemsView("BlacksmithItems") {
 	addButton(2, STRING["enhdialogs.blacksmith.buttons.armor"], Common::KEYCODE_a);
 	addButton(6, STRING["enhdialogs.blacksmith.buttons.misc"], Common::KEYCODE_m);
 	addButton(10, STRING["enhdialogs.blacksmith.buttons.sell"], Common::KEYCODE_s);
-	addButton(12, STRING["enhdialogs.blacksmith.buttons.exit"], Common::KEYCODE_ESCAPE);
+	addButton(12, STRING["enhdialogs.misc.exit"], Common::KEYCODE_ESCAPE);
 }
 
 bool BlacksmithItems::msgFocus(const FocusMessage &msg) {
diff --git a/engines/mm/mm1/views_enh/which_item.cpp b/engines/mm/mm1/views_enh/which_item.cpp
new file mode 100644
index 00000000000..5204e93cd15
--- /dev/null
+++ b/engines/mm/mm1/views_enh/which_item.cpp
@@ -0,0 +1,69 @@
+/* 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/which_item.h"
+#include "mm/mm1/globals.h"
+
+namespace MM {
+namespace MM1 {
+namespace ViewsEnh {
+
+WhichItem::WhichItem() : ScrollView("WhichItem") {
+	_bounds = Common::Rect(50, 103, 266, 139);
+	addButton(&g_globals->_escSprites, Common::Point(70, 0), 0, KEYBIND_ESCAPE);
+}
+
+void WhichItem::show(const Common::String &msg, KeyCallback callback) {
+	WhichItem *view = static_cast<WhichItem *>(g_events->findView("WhichItem"));
+	view->_msg = msg;
+	view->_callback = callback;
+	view->addView();
+}
+
+void WhichItem::draw() {
+	ScrollView::draw();
+	writeString(0, 0, _msg);
+}
+
+bool WhichItem::msgKeypress(const KeypressMessage &msg) {
+	if (msg.keycode >= Common::KEYCODE_1 &&
+			msg.keycode <= Common::KEYCODE_6) {
+		close();
+		_callback(Common::KeyState(msg.keycode));
+		return true;
+	} else {
+		return false;
+	}
+}
+
+bool WhichItem::msgAction(const ActionMessage &msg) {
+	if (msg._action == KEYBIND_ESCAPE) {
+		close();
+		_callback(Common::KeyState(Common::KEYCODE_ESCAPE));
+		return true;
+	} else {
+		return false;
+	}
+}
+
+} // namespace ViewsEnh
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views_enh/which_item.h b/engines/mm/mm1/views_enh/which_item.h
new file mode 100644
index 00000000000..18c6a1fb3f2
--- /dev/null
+++ b/engines/mm/mm1/views_enh/which_item.h
@@ -0,0 +1,49 @@
+/* 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_WHICH_ITEM_H
+#define MM1_VIEWS_ENH_WHICH_ITEM_H
+
+#include "mm/mm1/views_enh/scroll_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace ViewsEnh {
+
+class WhichItem : public ScrollView {
+private:
+	Common::String _msg;
+	KeyCallback _callback = nullptr;
+public:
+	WhichItem();
+	virtual ~WhichItem() {}
+
+	static void show(const Common::String &msg, KeyCallback callback);
+	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/module.mk b/engines/mm/module.mk
index cbe38acac61..fa7f885bd5a 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -159,6 +159,7 @@ MODULE_OBJS += \
 	mm1/views_enh/title.o \
 	mm1/views_enh/trap.o \
 	mm1/views_enh/unlock.o \
+	mm1/views_enh/which_item.o \
 	mm1/views_enh/who_will_try.o \
 	mm1/views_enh/yes_no.o \
 	mm1/views_enh/interactions/interaction.o \


Commit: 9a7b3abb36353495532943507ca2fb57b3f47a86
    https://github.com/scummvm/scummvm/commit/9a7b3abb36353495532943507ca2fb57b3f47a86
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-03-20T20:14:21-07:00

Commit Message:
MM: MM1: Discarding items now working

Changed paths:
    engines/mm/mm1/views_enh/character_inventory.cpp
    engines/mm/mm1/views_enh/character_inventory.h
    engines/mm/mm1/views_enh/which_item.cpp
    engines/mm/mm1/views_enh/which_item.h


diff --git a/engines/mm/mm1/views_enh/character_inventory.cpp b/engines/mm/mm1/views_enh/character_inventory.cpp
index ba47b04f8f6..014cbb1da49 100644
--- a/engines/mm/mm1/views_enh/character_inventory.cpp
+++ b/engines/mm/mm1/views_enh/character_inventory.cpp
@@ -49,6 +49,17 @@ bool CharacterInventory::msgFocus(const FocusMessage &msg) {
 	return true;
 }
 
+bool CharacterInventory::msgGame(const GameMessage &msg) {
+	if (msg._name == "ITEM" && msg._value >= 0 &&
+			msg._value <= (int)_items.size()) {
+		_selectedItem = msg._value;
+		performAction();
+		return true;
+	}
+
+	return false;
+}
+
 void CharacterInventory::draw() {
 	ItemsView::draw();
 	drawTitle();
@@ -84,6 +95,16 @@ bool CharacterInventory::msgKeypress(const KeypressMessage &msg) {
 		populateItems();
 		redraw();
 		break;
+	case Common::KEYCODE_e:
+		selectButton(BTN_EQUIP);
+		break;
+	case Common::KEYCODE_r:
+		selectButton(BTN_REMOVE);
+		break;
+	case Common::KEYCODE_d:
+		selectButton(BTN_DISCARD);
+		break;
+
 	default:
 		return ItemsView::msgKeypress(msg);
 	}
@@ -101,6 +122,7 @@ bool CharacterInventory::msgAction(const ActionMessage &msg) {
 void CharacterInventory::populateItems() {
 	_items.clear();
 	_selectedItem = -1;
+	_selectedButton = BTN_NONE;
 
 	const Character &c = *g_globals->_currCharacter;
 	const Inventory &inv = (_mode == ARMS_MODE) ? c._equipped : c._backpack;
@@ -113,6 +135,62 @@ void CharacterInventory::itemSelected() {
 	// No implementation
 }
 
+void CharacterInventory::selectButton(SelectedButton btnMode) {
+	_selectedButton = btnMode;
+
+	if (_selectedItem != -1) {
+		performAction();
+	} else {
+		Common::String btn = STRING["enhdialogs.items.equip"];
+		if (btnMode == BTN_REMOVE)
+			btn = STRING["enhdialogs.items.remove"];
+		else if (btnMode == BTN_DISCARD)
+			btn = STRING["enhdialogs.items.discard"];
+
+		send("WhichItem", GameMessage("DISPLAY",
+			Common::String::format("%s %s", btn.c_str(),
+				STRING["enhdialogs.items.which_item"].c_str())
+		));
+	}
+}
+
+void CharacterInventory::performAction() {
+	switch (_selectedButton) {
+	case BTN_EQUIP:
+		equipItem();
+		break;
+	case BTN_REMOVE:
+		removeItem();
+		break;
+
+	case BTN_DISCARD:
+		discardItem();
+		break;
+
+	default:
+		error("No button selected");
+		break;
+	}
+}
+
+
+void CharacterInventory::equipItem() {
+	// TODO
+}
+
+void CharacterInventory::removeItem() {
+	// TODO
+}
+
+void CharacterInventory::discardItem() {
+	Character &c = *g_globals->_currCharacter;
+	Inventory &inv = (_mode == ARMS_MODE) ? c._equipped : c._backpack;
+
+	inv.removeAt(_selectedItem);
+	populateItems();
+	redraw();
+}
+
 } // namespace ViewsEnh
 } // namespace MM1
 } // namespace MM
diff --git a/engines/mm/mm1/views_enh/character_inventory.h b/engines/mm/mm1/views_enh/character_inventory.h
index 2c20ee7eb4b..cc1270b1c4d 100644
--- a/engines/mm/mm1/views_enh/character_inventory.h
+++ b/engines/mm/mm1/views_enh/character_inventory.h
@@ -34,6 +34,10 @@ private:
 		ARMS_MODE, BACKPACK_MODE
 	};
 	DisplayMode _mode = ARMS_MODE;
+	enum SelectedButton {
+		BTN_NONE, BTN_EQUIP, BTN_REMOVE, BTN_DISCARD
+	};
+	SelectedButton _selectedButton = BTN_NONE;
 
 	/**
 	 * Populates the list of items
@@ -45,6 +49,31 @@ private:
 	 */
 	void drawTitle();
 
+	/**
+	 * Selects a button mode
+	 */
+	void selectButton(SelectedButton btnMode);
+
+	/**
+	 * Handle action with selected button mode and selected item
+	 */
+	void performAction();
+
+	/**
+	 * Equip an item
+	 */
+	void equipItem();
+
+	/**
+	 * Unequip an item
+	 */
+	void removeItem();
+
+	/**
+	 * Discard an item
+	 */
+	void discardItem();
+
 protected:
 	/**
 	 * Called when an item is selected
@@ -56,6 +85,7 @@ public:
 	virtual ~CharacterInventory() {}
 
 	bool msgFocus(const FocusMessage &msg) override;
+	bool msgGame(const GameMessage &msg) override;
 	void draw() override;
 	bool msgKeypress(const KeypressMessage &msg) override;
 	bool msgAction(const ActionMessage &msg) override;
diff --git a/engines/mm/mm1/views_enh/which_item.cpp b/engines/mm/mm1/views_enh/which_item.cpp
index 5204e93cd15..9b8d821c6a5 100644
--- a/engines/mm/mm1/views_enh/which_item.cpp
+++ b/engines/mm/mm1/views_enh/which_item.cpp
@@ -31,11 +31,14 @@ WhichItem::WhichItem() : ScrollView("WhichItem") {
 	addButton(&g_globals->_escSprites, Common::Point(70, 0), 0, KEYBIND_ESCAPE);
 }
 
-void WhichItem::show(const Common::String &msg, KeyCallback callback) {
-	WhichItem *view = static_cast<WhichItem *>(g_events->findView("WhichItem"));
-	view->_msg = msg;
-	view->_callback = callback;
-	view->addView();
+bool WhichItem::msgGame(const GameMessage &msg) {
+	if (msg._name == "DISPLAY") {
+		_msg = msg._stringValue;
+		addView();
+		return true;
+	}
+
+	return ScrollView::msgGame(msg);
 }
 
 void WhichItem::draw() {
@@ -47,7 +50,8 @@ bool WhichItem::msgKeypress(const KeypressMessage &msg) {
 	if (msg.keycode >= Common::KEYCODE_1 &&
 			msg.keycode <= Common::KEYCODE_6) {
 		close();
-		_callback(Common::KeyState(msg.keycode));
+		send("CharacterInventory", GameMessage("ITEM",
+			msg.keycode - Common::KEYCODE_1));
 		return true;
 	} else {
 		return false;
@@ -57,7 +61,7 @@ bool WhichItem::msgKeypress(const KeypressMessage &msg) {
 bool WhichItem::msgAction(const ActionMessage &msg) {
 	if (msg._action == KEYBIND_ESCAPE) {
 		close();
-		_callback(Common::KeyState(Common::KEYCODE_ESCAPE));
+		send("CharacterInventory", GameMessage("ITEM", -1));
 		return true;
 	} else {
 		return false;
diff --git a/engines/mm/mm1/views_enh/which_item.h b/engines/mm/mm1/views_enh/which_item.h
index 18c6a1fb3f2..f08db4c23a4 100644
--- a/engines/mm/mm1/views_enh/which_item.h
+++ b/engines/mm/mm1/views_enh/which_item.h
@@ -31,12 +31,11 @@ namespace ViewsEnh {
 class WhichItem : public ScrollView {
 private:
 	Common::String _msg;
-	KeyCallback _callback = nullptr;
 public:
 	WhichItem();
 	virtual ~WhichItem() {}
 
-	static void show(const Common::String &msg, KeyCallback callback);
+	bool msgGame(const GameMessage &msg) override;
 	void draw() override;
 	bool msgKeypress(const KeypressMessage &msg) override;
 	bool msgAction(const ActionMessage &msg) override;


Commit: 462d002393dbf8a5b2340e5efa1684366d1aa652
    https://github.com/scummvm/scummvm/commit/462d002393dbf8a5b2340e5efa1684366d1aa652
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-03-20T20:14:22-07:00

Commit Message:
MM: MM1: Refactor equip/remove logic into it's own class

Changed paths:
  A engines/mm/mm1/game/equip_remove.cpp
  A engines/mm/mm1/game/equip_remove.h
    engines/mm/mm1/views/character_info.cpp
    engines/mm/mm1/views/character_info.h
    engines/mm/module.mk


diff --git a/engines/mm/mm1/game/equip_remove.cpp b/engines/mm/mm1/game/equip_remove.cpp
new file mode 100644
index 00000000000..42891174785
--- /dev/null
+++ b/engines/mm/mm1/game/equip_remove.cpp
@@ -0,0 +1,226 @@
+/* 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/game/equip_remove.h"
+#include "mm/mm1/globals.h"
+
+namespace MM {
+namespace MM1 {
+namespace Game {
+
+bool EquipRemove::equipItem(int index, Common::Point &textPos, Common::String &equipError) {
+	Character &c = *g_globals->_currCharacter;
+	uint itemId = c._backpack[index]._id;
+	uint item14 = c._backpack[index]._charges;
+
+	int classBit = 0;
+	textPos.x = 0;
+
+	switch (c._class) {
+	case KNIGHT:
+		classBit = KNIGHT_BIT;
+		break;
+	case PALADIN:
+		classBit = PALADIN_BIT;
+		break;
+	case ARCHER:
+		classBit = ARCHER_BIT;
+		break;
+	case CLERIC:
+		classBit = CLERIC_BIT;
+		break;
+	case SORCERER:
+		classBit = SORCERER_BIT;
+		break;
+	case ROBBER:
+		classBit = ROBBER_BIT;
+		break;
+	default:
+		equipError = STRING["dialogs.character.wrong_class"];
+		break;
+	}
+
+	g_globals->_items.getItem(itemId);
+	const Item &item = g_globals->_currItem;
+
+	if (equipError.empty() && (item._disablements & classBit))
+		equipError = STRING["dialogs.character.wrong_class"];
+	if (equipError.empty()) {
+		int alignBit = 0;
+		switch (c._alignment) {
+		case GOOD:
+			alignBit = GOOD_BIT;
+			break;
+		case NEUTRAL:
+			alignBit = NEUTRAL_BIT;
+			break;
+		case EVIL:
+			alignBit = EVIL_BIT;
+			break;
+		default:
+			equipError = STRING["dialogs.character.wrong_alignment"];
+			break;
+		}
+
+		if ((item._disablements & alignBit) && alignBit != NEUTRAL_BIT)
+			equipError = STRING["dialogs.character.wrong_alignment"];
+	}
+
+	if (equipError.empty()) {
+		if (item._equipMode == IS_EQUIPPABLE) {
+			equipError = STRING["dialogs.character.not_equipped"];
+			textPos.x = 10;
+		}
+	}
+
+	if (equipError.empty()) {
+		if (isWeapon(itemId)) {
+			if (c._equipped.hasWeapon() || c._equipped.hasTwoHanded())
+				equipError = STRING["dialogs.character.have_weapon"];
+		} else if (isMissile(itemId)) {
+			if (c._equipped.hasMissile()) {
+				equipError = STRING["dialogs.character.have_missile"];
+				textPos.x = 3;
+			}
+		} else if (isTwoHanded(itemId)) {
+			if (c._equipped.hasShield()) {
+				equipError = STRING["dialogs.character.cannot_with_shield"];
+				textPos.x = 7;
+			} else if (c._equipped.hasWeapon()) {
+				equipError = STRING["dialogs.character.have_weapon"];
+
+			}
+		} else if (isArmor(itemId)) {
+			if (c._equipped.hasArmor()) {
+				equipError = STRING["dialogs.character.have_armor"];
+				textPos.x = 5;
+			}
+		} else if (isShield(itemId)) {
+			if (c._equipped.hasTwoHanded()) {
+				equipError = STRING["dialogs.character.cannot_two_handed"];
+				textPos.x = 1;
+			}
+		} else if (itemId == 255) {
+			equipError = STRING["dialogs.character.not_equipped"];
+			textPos.x = 10;
+		}
+	}
+
+	if (equipError.empty() && c._equipped.full()) {
+		equipError = STRING["dialogs.character.full"];
+		textPos.x = 14;
+	}
+
+	if (equipError.empty()) {
+		// All checks passed, can equip item
+		c._backpack.removeAt(index);
+		uint freeIndex = c._equipped.add(itemId, item14);
+
+		if (item._equipMode != EQUIPMODE_0) {
+			if (item._equipMode == IS_EQUIPPABLE) {
+				equipError = STRING["dialogs.character.not_equipped"];
+				textPos.x = 10;
+			} else if (item._equipMode == EQUIP_CURSED) {
+				c._equipped[freeIndex]._charges += item._val10;
+			}
+		}
+	}
+
+	if (equipError.empty()) {
+		switch (getItemCategory(itemId)) {
+		case ITEMCAT_WEAPON:
+		case ITEMCAT_TWO_HANDED:
+			c._physicalAttr._base = item._val16;
+			c._physicalAttr._current = item._val17;
+			break;
+		case ITEMCAT_MISSILE:
+			c._missileAttr._base = item._val16;
+			c._missileAttr._current = item._val17;
+			break;
+		case ITEMCAT_ARMOR:
+		case ITEMCAT_SHIELD:
+			c._ac._base += item._val17;
+			break;
+		default:
+			break;
+		}
+
+		c.updateResistances();
+		c.updateAttributes();
+		c.updateAC();
+		return false;
+	}
+
+	return false;
+}
+
+bool EquipRemove::removeItem(int index, Common::Point &textPos, Common::String &removeError) {
+	Character &c = *g_globals->_currCharacter;
+	uint itemId = c._equipped[index]._id;
+	uint item14 = c._equipped[index]._charges;
+
+	g_globals->_items.getItem(itemId);
+	const Item &item = g_globals->_currItem;
+	if (item._equipMode == EQUIP_CURSED) {
+		removeError = STRING["dialogs.character.cursed"];
+		textPos.x = 13;
+	} else if (c._backpack.full()) {
+		removeError = STRING["dialogs.character.full"];
+		textPos.x = 14;
+	}
+
+	if (!removeError.empty())
+		return false;
+
+	// Shift item to backpack
+	c._equipped.removeAt(index);
+	c._backpack.add(itemId, item14);
+
+	if (item._val10) {
+		// TODO: _equipMode is used as a character offset. Need to
+		// find an example that calls it so I know what area of
+		// the character updates are being done to
+		error("TODO: item flag in remove item");
+	}
+
+	switch (getItemCategory(itemId)) {
+	case ITEMCAT_WEAPON:
+	case ITEMCAT_TWO_HANDED:
+		c._physicalAttr.clear();
+		break;
+	case ITEMCAT_MISSILE:
+		c._missileAttr.clear();
+		break;
+	case ITEMCAT_ARMOR:
+	case ITEMCAT_SHIELD:
+		c._ac._base = MAX((int)c._ac._base - (int)item._val17, 0);
+		break;
+	default:
+		break;
+	}
+
+	return true;
+}
+
+
+} // namespace Game
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/game/equip_remove.h b/engines/mm/mm1/game/equip_remove.h
new file mode 100644
index 00000000000..dd3dfb4957e
--- /dev/null
+++ b/engines/mm/mm1/game/equip_remove.h
@@ -0,0 +1,47 @@
+/* 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_GAME_EQUIP_REMOVE_H
+#define MM1_GAME_EQUIP_REMOVE_H
+
+#include "common/rect.h"
+
+namespace MM {
+namespace MM1 {
+namespace Game {
+
+struct EquipRemove {
+	/**
+	 * Equip an item
+	 */
+	bool equipItem(int index, Common::Point &textPos, Common::String &equipError);
+
+	/**
+	 * Remove an item
+	 */
+	bool removeItem(int index, Common::Point &textPos, Common::String &removeError);
+};
+
+} // namespace Game
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/mm1/views/character_info.cpp b/engines/mm/mm1/views/character_info.cpp
index 2bea5c454ab..d7f320d51e7 100644
--- a/engines/mm/mm1/views/character_info.cpp
+++ b/engines/mm/mm1/views/character_info.cpp
@@ -299,213 +299,30 @@ bool CharacterInfo::msgGame(const GameMessage &msg) {
 }
 
 void CharacterInfo::equipItem(uint index) {
-	Character &c = *g_globals->_currCharacter;
-	uint itemId = c._backpack[index]._id;
-	uint item14 = c._backpack[index]._charges;
-
-	int classBit = 0;
-	Common::String equipError;
-	_textPos.x = 0;
-
-	switch (c._class) {
-	case KNIGHT:
-		classBit = KNIGHT_BIT;
-		break;
-	case PALADIN:
-		classBit = PALADIN_BIT;
-		break;
-	case ARCHER:
-		classBit = ARCHER_BIT;
-		break;
-	case CLERIC:
-		classBit = CLERIC_BIT;
-		break;
-	case SORCERER:
-		classBit = SORCERER_BIT;
-		break;
-	case ROBBER:
-		classBit = ROBBER_BIT;
-		break;
-	default:
-		equipError = STRING["dialogs.character.wrong_class"];
-		break;
-	}
-
-	g_globals->_items.getItem(itemId);
-	const Item &item = g_globals->_currItem;
-
-	if (equipError.empty() && (item._disablements & classBit))
-		equipError = STRING["dialogs.character.wrong_class"];
-	if (equipError.empty()) {
-		int alignBit = 0;
-		switch (c._alignment) {
-		case GOOD:
-			alignBit = GOOD_BIT;
-			break;
-		case NEUTRAL:
-			alignBit = NEUTRAL_BIT;
-			break;
-		case EVIL:
-			alignBit = EVIL_BIT;
-			break;
-		default:
-			equipError = STRING["dialogs.character.wrong_alignment"];
-			break;
-		}
-
-		if ((item._disablements & alignBit) && alignBit != NEUTRAL_BIT)
-			equipError = STRING["dialogs.character.wrong_alignment"];
-	}
-
-	if (equipError.empty()) {
-		if (item._equipMode == IS_EQUIPPABLE) {
-			equipError = STRING["dialogs.character.not_equipped"];
-			_textPos.x = 10;
-		}
-	}
-
-	if (equipError.empty()) {
-		if (isWeapon(itemId)) {
-			if (c._equipped.hasWeapon() || c._equipped.hasTwoHanded())
-				equipError = STRING["dialogs.character.have_weapon"];
-		} else if (isMissile(itemId)) {
-			if (c._equipped.hasMissile()) {
-				equipError = STRING["dialogs.character.have_missile"];
-				_textPos.x = 3;
-			}
-		} else if (isTwoHanded(itemId)) {
-			if (c._equipped.hasShield()) {
-				equipError = STRING["dialogs.character.cannot_with_shield"];
-				_textPos.x = 7;
-			} else if (c._equipped.hasWeapon()) {
-				equipError = STRING["dialogs.character.have_weapon"];
-
-			}
-		} else if (isArmor(itemId)) {
-			if (c._equipped.hasArmor()) {
-				equipError = STRING["dialogs.character.have_armor"];
-				_textPos.x = 5;
-			}
-		} else if (isShield(itemId)) {
-			if (c._equipped.hasTwoHanded()) {
-				equipError = STRING["dialogs.character.cannot_two_handed"];
-				_textPos.x = 1;
-			}
-		} else if (itemId == 255) {
-			equipError = STRING["dialogs.character.not_equipped"];
-			_textPos.x = 10;
-		}
-	}
-
-	if (equipError.empty() && c._equipped.full()) {
-		equipError = STRING["dialogs.character.full"];
-		_textPos.x = 14;
-	}
-
-	if (equipError.empty()) {
-		// All checks passed, can equip item
-		c._backpack.removeAt(index);
-		uint freeIndex = c._equipped.add(itemId, item14);
-
-		if (item._equipMode != EQUIPMODE_0) {
-			if (item._equipMode == IS_EQUIPPABLE) {
-				equipError = STRING["dialogs.character.not_equipped"];
-				_textPos.x = 10;
-			} else if (item._equipMode == EQUIP_CURSED) {
-				c._equipped[freeIndex]._charges += item._val10;
-			}
-		}
-	}
-
-	if (equipError.empty()) {
-		switch (getItemCategory(itemId)) {
-		case ITEMCAT_WEAPON:
-		case ITEMCAT_TWO_HANDED:
-			c._physicalAttr._base = item._val16;
-			c._physicalAttr._current = item._val17;
-			break;
-		case ITEMCAT_MISSILE:
-			c._missileAttr._base = item._val16;
-			c._missileAttr._current = item._val17;
-			break;
-		case ITEMCAT_ARMOR:
-		case ITEMCAT_SHIELD:
-			c._ac._base += item._val17;
-			break;
-		default:
-			break;
-		}
-
-		c.updateResistances();
-		c.updateAttributes();
-		c.updateAC();
+	Common::String errMsg;
+	_state = DISPLAY;
 
-	} else {
+	if (!EquipRemove::equipItem(index, _textPos, errMsg)) {
 		clearLines(20, 24);
 		_textPos.y = 21;
-		writeString(equipError);
+		writeString(errMsg);
 
 		Sound::sound(SOUND_2);
 		delaySeconds(3);
 	}
-
-	_state = DISPLAY;
 }
 
 void CharacterInfo::removeItem(uint index) {
-	Character &c = *g_globals->_currCharacter;
-	uint itemId = c._equipped[index]._id;
-	uint item14 = c._equipped[index]._charges;
-
-	Common::String removeError;
-
-	g_globals->_items.getItem(itemId);
-	const Item &item = g_globals->_currItem;
-	if (item._equipMode == EQUIP_CURSED) {
-		removeError = STRING["dialogs.character.cursed"];
-		_textPos.x = 13;
-	} else if (c._backpack.full()) {
-		removeError = STRING["dialogs.character.full"];
-		_textPos.x = 14;
-	}
-
+	Common::String errMsg;
 	_state = DISPLAY;
 
-	if (!removeError.empty()) {
+	if (!EquipRemove::removeItem(index, _textPos, errMsg)) {
 		clearLines(20, 24);
 		_textPos.y = 21;
-		writeString(removeError);
+		writeString(errMsg);
 
 		Sound::sound(SOUND_2);
 		delaySeconds(3);
-		return;
-	}
-
-	// Shift item to backpack
-	c._equipped.removeAt(index);
-	c._backpack.add(itemId, item14);
-
-	if (item._val10) {
-		// TODO: _equipMode is used as a character offset. Need to
-		// find an example that calls it so I know what area of
-		// the character updates are being done to
-		error("TODO: item flag in remove item");
-	}
-
-	switch (getItemCategory(itemId)) {
-	case ITEMCAT_WEAPON:
-	case ITEMCAT_TWO_HANDED:
-		c._physicalAttr.clear();
-		break;
-	case ITEMCAT_MISSILE:
-		c._missileAttr.clear();
-		break;
-	case ITEMCAT_ARMOR:
-	case ITEMCAT_SHIELD:
-		c._ac._base = MAX((int)c._ac._base - (int)item._val17, 0);
-		break;
-	default:
-		break;
 	}
 }
 
diff --git a/engines/mm/mm1/views/character_info.h b/engines/mm/mm1/views/character_info.h
index c888d7781db..1cedc926bf9 100644
--- a/engines/mm/mm1/views/character_info.h
+++ b/engines/mm/mm1/views/character_info.h
@@ -27,6 +27,7 @@
 #include "mm/mm1/data/character.h"
 #include "mm/mm1/data/items.h"
 #include "mm/mm1/game/spell_casting.h"
+#include "mm/mm1/game/equip_remove.h"
 #include "mm/mm1/views/text_entry.h"
 
 namespace MM {
@@ -36,7 +37,8 @@ namespace Views {
 /**
  * In-game character dialog
  */
-class CharacterInfo : public CharacterBase, MM1::Game::SpellCasting {
+class CharacterInfo : public CharacterBase, MM1::Game::SpellCasting,
+		MM1::Game::EquipRemove {
 private:
 	enum ViewState {
 		DISPLAY, EQUIP, GATHER, REMOVE, SHARE,
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index fa7f885bd5a..ff147fc22b1 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -39,6 +39,7 @@ MODULE_OBJS += \
 	mm1/game/game_logic.o \
 	mm1/game/combat.o \
 	mm1/game/encounter.o \
+	mm1/game/equip_remove.o \
 	mm1/game/monster_touch.o \
 	mm1/game/rest.o \
 	mm1/game/spell_casting.o \


Commit: 5e39b24240d3be7b17ea109fea384c168fad6535
    https://github.com/scummvm/scummvm/commit/5e39b24240d3be7b17ea109fea384c168fad6535
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-03-20T20:14:22-07:00

Commit Message:
MM: MM1: Added equip/remove to enhanced character items view

Changed paths:
    engines/mm/mm1/game/equip_remove.cpp
    engines/mm/mm1/views_enh/character_inventory.cpp
    engines/mm/mm1/views_enh/character_inventory.h


diff --git a/engines/mm/mm1/game/equip_remove.cpp b/engines/mm/mm1/game/equip_remove.cpp
index 42891174785..7bbb51607c8 100644
--- a/engines/mm/mm1/game/equip_remove.cpp
+++ b/engines/mm/mm1/game/equip_remove.cpp
@@ -29,7 +29,7 @@ namespace Game {
 bool EquipRemove::equipItem(int index, Common::Point &textPos, Common::String &equipError) {
 	Character &c = *g_globals->_currCharacter;
 	uint itemId = c._backpack[index]._id;
-	uint item14 = c._backpack[index]._charges;
+	uint charges = c._backpack[index]._charges;
 
 	int classBit = 0;
 	textPos.x = 0;
@@ -132,7 +132,7 @@ bool EquipRemove::equipItem(int index, Common::Point &textPos, Common::String &e
 	if (equipError.empty()) {
 		// All checks passed, can equip item
 		c._backpack.removeAt(index);
-		uint freeIndex = c._equipped.add(itemId, item14);
+		uint freeIndex = c._equipped.add(itemId, charges);
 
 		if (item._equipMode != EQUIPMODE_0) {
 			if (item._equipMode == IS_EQUIPPABLE) {
@@ -144,38 +144,37 @@ bool EquipRemove::equipItem(int index, Common::Point &textPos, Common::String &e
 		}
 	}
 
-	if (equipError.empty()) {
-		switch (getItemCategory(itemId)) {
-		case ITEMCAT_WEAPON:
-		case ITEMCAT_TWO_HANDED:
-			c._physicalAttr._base = item._val16;
-			c._physicalAttr._current = item._val17;
-			break;
-		case ITEMCAT_MISSILE:
-			c._missileAttr._base = item._val16;
-			c._missileAttr._current = item._val17;
-			break;
-		case ITEMCAT_ARMOR:
-		case ITEMCAT_SHIELD:
-			c._ac._base += item._val17;
-			break;
-		default:
-			break;
-		}
-
-		c.updateResistances();
-		c.updateAttributes();
-		c.updateAC();
+	if (!equipError.empty())
 		return false;
+
+	switch (getItemCategory(itemId)) {
+	case ITEMCAT_WEAPON:
+	case ITEMCAT_TWO_HANDED:
+		c._physicalAttr._base = item._val16;
+		c._physicalAttr._current = item._val17;
+		break;
+	case ITEMCAT_MISSILE:
+		c._missileAttr._base = item._val16;
+		c._missileAttr._current = item._val17;
+		break;
+	case ITEMCAT_ARMOR:
+	case ITEMCAT_SHIELD:
+		c._ac._base += item._val17;
+		break;
+	default:
+		break;
 	}
 
-	return false;
+	c.updateResistances();
+	c.updateAttributes();
+	c.updateAC();
+	return true;
 }
 
 bool EquipRemove::removeItem(int index, Common::Point &textPos, Common::String &removeError) {
 	Character &c = *g_globals->_currCharacter;
 	uint itemId = c._equipped[index]._id;
-	uint item14 = c._equipped[index]._charges;
+	uint charges = c._equipped[index]._charges;
 
 	g_globals->_items.getItem(itemId);
 	const Item &item = g_globals->_currItem;
@@ -192,7 +191,7 @@ bool EquipRemove::removeItem(int index, Common::Point &textPos, Common::String &
 
 	// Shift item to backpack
 	c._equipped.removeAt(index);
-	c._backpack.add(itemId, item14);
+	c._backpack.add(itemId, charges);
 
 	if (item._val10) {
 		// TODO: _equipMode is used as a character offset. Need to
diff --git a/engines/mm/mm1/views_enh/character_inventory.cpp b/engines/mm/mm1/views_enh/character_inventory.cpp
index 014cbb1da49..87105be7851 100644
--- a/engines/mm/mm1/views_enh/character_inventory.cpp
+++ b/engines/mm/mm1/views_enh/character_inventory.cpp
@@ -43,7 +43,7 @@ bool CharacterInventory::msgFocus(const FocusMessage &msg) {
 	ItemsView::msgFocus(msg);
 
 	if (dynamic_cast<WhichItem *>(msg._priorView) == nullptr)
-		_mode = ARMS_MODE;
+		_mode = BACKPACK_MODE;
 	populateItems();
 
 	return true;
@@ -175,11 +175,29 @@ void CharacterInventory::performAction() {
 
 
 void CharacterInventory::equipItem() {
-	// TODO
+	Common::String errMsg;
+	Common::Point textPos;
+
+	if (EquipRemove::equipItem(_selectedItem, textPos, errMsg)) {
+		_mode = ARMS_MODE;
+		populateItems();
+		redraw();
+	} else {
+		displayMessage(errMsg);
+	}
 }
 
 void CharacterInventory::removeItem() {
-	// TODO
+	Common::String errMsg;
+	Common::Point textPos;
+
+	if (EquipRemove::removeItem(_selectedItem, textPos, errMsg)) {
+		_mode = BACKPACK_MODE;
+		populateItems();
+		redraw();
+	} else {
+		displayMessage(errMsg);
+	}
 }
 
 void CharacterInventory::discardItem() {
diff --git a/engines/mm/mm1/views_enh/character_inventory.h b/engines/mm/mm1/views_enh/character_inventory.h
index cc1270b1c4d..f9a74dd2953 100644
--- a/engines/mm/mm1/views_enh/character_inventory.h
+++ b/engines/mm/mm1/views_enh/character_inventory.h
@@ -23,12 +23,13 @@
 #define MM1_VIEWS_ENH_CHARACTER_INVENTORY_H
 
 #include "mm/mm1/views_enh/items_view.h"
+#include "mm/mm1/game/equip_remove.h"
 
 namespace MM {
 namespace MM1 {
 namespace ViewsEnh {
 
-class CharacterInventory : public ItemsView {
+class CharacterInventory : public ItemsView, Game::EquipRemove {
 private:
 	enum DisplayMode {
 		ARMS_MODE, BACKPACK_MODE




More information about the Scummvm-git-logs mailing list