[Scummvm-git-logs] scummvm master -> f9bbbf9595582c844f425b6df06e5dbb72343bf9

dreammaster noreply at scummvm.org
Sun Mar 19 05:28:58 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:
ef8f5648c9 MM: MM1: Blacksmith item selection
033f1f66db MM: MM1: Added Buy/Sell confirmation dialog
f9bbbf9595 MM: MM1: Added blacksmith buy/sell logic


Commit: ef8f5648c94c8b1e3d2be05c0027ca23f87e3baf
    https://github.com/scummvm/scummvm/commit/ef8f5648c94c8b1e3d2be05c0027ca23f87e3baf
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-03-18T22:28:35-07:00

Commit Message:
MM: MM1: Blacksmith item selection

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 01a171c84a6..bc2c7f03373 100644
--- a/engines/mm/mm1/views_enh/items_view.cpp
+++ b/engines/mm/mm1/views_enh/items_view.cpp
@@ -49,6 +49,11 @@ void ItemsView::addButton(int frame, const Common::String &text,
 
 bool ItemsView::msgFocus(const FocusMessage &msg) {
 	ScrollView::msgFocus(msg);
+
+	// Disable the normal '1' to '6' character selection keybindings,
+	// since we're using them in this dialog for item selection
+	MetaEngine::setKeybindingMode(KeybindingMode::KBMODE_MENUS);
+
 	_selectedItem = -1;
 	return true;
 }
@@ -74,13 +79,15 @@ void ItemsView::draw() {
 	}
 
 	// List the items
-	for (uint i = 0; i < _items.size(); ++i) {
+	for (int i = 0; i < (int)_items.size(); ++i) {
 		g_globals->_items.getItem(_items[i]);
 		const Item &item = g_globals->_currItem;
 		const Common::String line = Common::String::format(
 			"%d) %s", i + 1,
 			item._name.c_str()
 		);
+
+		setTextColor(i == _selectedItem ? 15 : 0);
 		writeLine(2 + i, line, ALIGN_LEFT, 10);
 
 		if (_costMode != NO_COST) {
@@ -91,12 +98,22 @@ void ItemsView::draw() {
 	}
 	if (_items.size() == 0)
 		writeLine(2, STRING["enhdialogs.misc.no_items"], ALIGN_LEFT, 10);
+	setTextColor(0);
 }
 
 bool ItemsView::msgKeypress(const KeypressMessage &msg) {
 	if (endDelay())
 		return true;
 
+	if (msg.keycode >= Common::KEYCODE_1 &&
+			msg.keycode <= (int)(Common::KEYCODE_0 + _items.size())) {
+		_selectedItem = msg.keycode - Common::KEYCODE_1;
+		draw();
+
+		itemSelected();
+		return true;
+	}
+
 	return PartyView::msgKeypress(msg);
 }
 
diff --git a/engines/mm/mm1/views_enh/items_view.h b/engines/mm/mm1/views_enh/items_view.h
index bc394aed241..b0d5dd54cae 100644
--- a/engines/mm/mm1/views_enh/items_view.h
+++ b/engines/mm/mm1/views_enh/items_view.h
@@ -43,6 +43,12 @@ protected:
 	 */
 	void addButton(int frame, const Common::String &text,
 		Common::KeyCode keycode);
+
+	/**
+	 * Called when an item is selected
+	 */
+	virtual void itemSelected() = 0;
+
 public:
 	ItemsView(const Common::String &name);
 	virtual ~ItemsView() {}
diff --git a/engines/mm/mm1/views_enh/locations/blacksmith_items.cpp b/engines/mm/mm1/views_enh/locations/blacksmith_items.cpp
index 7c4490141f9..15dad66021d 100644
--- a/engines/mm/mm1/views_enh/locations/blacksmith_items.cpp
+++ b/engines/mm/mm1/views_enh/locations/blacksmith_items.cpp
@@ -32,7 +32,6 @@ BlacksmithItems::BlacksmithItems() : ItemsView("BlacksmithItems") {
 	addButton(0, STRING["enhdialogs.blacksmith.buttons.weapons"], Common::KEYCODE_w);
 	addButton(2, STRING["enhdialogs.blacksmith.buttons.armor"], Common::KEYCODE_a);
 	addButton(6, STRING["enhdialogs.blacksmith.buttons.misc"], Common::KEYCODE_m);
-	addButton(8, STRING["enhdialogs.blacksmith.buttons.buy"], Common::KEYCODE_b);
 	addButton(10, STRING["enhdialogs.blacksmith.buttons.sell"], Common::KEYCODE_s);
 	addButton(12, STRING["enhdialogs.blacksmith.buttons.exit"], Common::KEYCODE_ESCAPE);
 }
@@ -156,6 +155,10 @@ void BlacksmithItems::populateItems() {
 	}
 }
 
+void BlacksmithItems::itemSelected() {
+	// TODO: buy/sell items
+}
+
 } // 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 201dd0197ee..411fe6522b2 100644
--- a/engines/mm/mm1/views_enh/locations/blacksmith_items.h
+++ b/engines/mm/mm1/views_enh/locations/blacksmith_items.h
@@ -50,6 +50,12 @@ private:
 	 */
 	void drawTitle();
 
+protected:
+	/**
+	 * Called when an item is selected
+	 */
+	void itemSelected() override;
+
 public:
 	BlacksmithItems();
 	virtual ~BlacksmithItems() {}


Commit: 033f1f66db908693772f21448b3e955cca45c451
    https://github.com/scummvm/scummvm/commit/033f1f66db908693772f21448b3e955cca45c451
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-03-18T22:28:35-07:00

Commit Message:
MM: MM1: Added Buy/Sell confirmation dialog

Changed paths:
  A engines/mm/mm1/views_enh/confirm.cpp
  A engines/mm/mm1/views_enh/confirm.h
    engines/mm/mm1/data/items.cpp
    engines/mm/mm1/views_enh/dialogs.h
    engines/mm/mm1/views_enh/locations/blacksmith_items.cpp
    engines/mm/mm1/views_enh/locations/blacksmith_items.h
    engines/mm/mm1/views_enh/quick_ref.cpp
    engines/mm/mm1/views_enh/quick_ref.h
    engines/mm/mm1/views_enh/text_view.cpp
    engines/mm/module.mk
    engines/mm/shared/utils/xeen_font.cpp


diff --git a/engines/mm/mm1/data/items.cpp b/engines/mm/mm1/data/items.cpp
index 835cc8ad127..117f5b3ba02 100644
--- a/engines/mm/mm1/data/items.cpp
+++ b/engines/mm/mm1/data/items.cpp
@@ -47,6 +47,8 @@ bool ItemsArray::load() {
 
 		item._name = Common::String(line.c_str() + 1, line.c_str() + 15);
 		line = Common::String(line.c_str() + 16);
+		while (item._name.lastChar() == ' ')
+			item._name.deleteLastChar();
 
 		item._disablements = getNextValue(line);
 		item._equipMode = (EquipMode)getNextValue(line);
diff --git a/engines/mm/mm1/views_enh/confirm.cpp b/engines/mm/mm1/views_enh/confirm.cpp
new file mode 100644
index 00000000000..f9c2118f141
--- /dev/null
+++ b/engines/mm/mm1/views_enh/confirm.cpp
@@ -0,0 +1,83 @@
+/* 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/confirm.h"
+#include "mm/mm1/globals.h"
+
+namespace MM {
+namespace MM1 {
+namespace ViewsEnh {
+
+Confirm::Confirm() : ScrollView("Confirm") {
+	_bounds = Common::Rect(99, 59, 237, 141);
+	_bounds.setBorderSize(10);
+	addButton(&g_globals->_confirmIcons, Common::Point(20, 44), 0, Common::KEYCODE_y);
+	addButton(&g_globals->_confirmIcons, Common::Point(70, 44), 2, Common::KEYCODE_n);
+}
+
+void Confirm::show(const Common::String &msg,
+		YNCallback callback) {
+	Confirm *view = static_cast<Confirm *>(g_events->findView("Confirm"));
+	view->_msg = msg;
+	view->_callback = callback;
+
+	view->addView();
+}
+
+
+void Confirm::draw() {
+	ScrollView::draw();
+	writeString(0, 0, _msg);
+}
+
+bool Confirm::msgKeypress(const KeypressMessage &msg) {
+	switch (msg.keycode) {
+	case Common::KEYCODE_y:
+		return msgAction(ActionMessage(KEYBIND_SELECT));
+		break;
+	case Common::KEYCODE_n:
+		return msgAction(ActionMessage(KEYBIND_ESCAPE));
+		break;
+	default:
+		return true;
+	}
+}
+
+bool Confirm::msgAction(const ActionMessage &msg) {
+	switch (msg._action) {
+	case KEYBIND_SELECT:
+		close();
+		_callback();
+		break;
+	case KEYBIND_ESCAPE:
+		close();
+		break;
+
+	default:
+		break;
+	}
+
+	return true;
+}
+
+} // namespace ViewsEnh
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views_enh/confirm.h b/engines/mm/mm1/views_enh/confirm.h
new file mode 100644
index 00000000000..20984a7e47a
--- /dev/null
+++ b/engines/mm/mm1/views_enh/confirm.h
@@ -0,0 +1,51 @@
+/* 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_CONFIRM_H
+#define MM1_VIEWS_ENH_CONFIRM_H
+
+#include "mm/mm1/views_enh/scroll_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace ViewsEnh {
+
+class Confirm : public ScrollView {
+private:
+	Common::String _msg;
+	YNCallback _callback = nullptr;
+public:
+	Confirm();
+	virtual ~Confirm() {}
+
+	static void show(const Common::String &msg,
+		YNCallback callback);
+
+	bool msgKeypress(const KeypressMessage &msg) override;
+	bool msgAction(const ActionMessage &msg) override;
+	void draw() 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 0e121c2c95d..48e2cb8f451 100644
--- a/engines/mm/mm1/views_enh/dialogs.h
+++ b/engines/mm/mm1/views_enh/dialogs.h
@@ -28,6 +28,7 @@
 #include "mm/mm1/views_enh/character_info.h"
 #include "mm/mm1/views_enh/character_select.h"
 #include "mm/mm1/views_enh/characters.h"
+#include "mm/mm1/views_enh/confirm.h"
 #include "mm/mm1/views_enh/create_characters.h"
 #include "mm/mm1/views_enh/exchange.h"
 #include "mm/mm1/views_enh/game.h"
@@ -72,6 +73,7 @@ private:
 	ViewsEnh::CharacterInfo _characterInfo;
 	ViewsEnh::CharacterSelect _characterSelect;
 	ViewsEnh::Characters _characters;
+	ViewsEnh::Confirm _confirm;
 	ViewsEnh::CreateCharacters _createCharacters;
 	ViewsEnh::Exchange _exchange;
 	ViewsEnh::Game _game;
diff --git a/engines/mm/mm1/views_enh/locations/blacksmith_items.cpp b/engines/mm/mm1/views_enh/locations/blacksmith_items.cpp
index 15dad66021d..cb83b42668c 100644
--- a/engines/mm/mm1/views_enh/locations/blacksmith_items.cpp
+++ b/engines/mm/mm1/views_enh/locations/blacksmith_items.cpp
@@ -20,6 +20,7 @@
  */
 
 #include "mm/mm1/views_enh/locations/blacksmith_items.h"
+#include "mm/mm1/views_enh/confirm.h"
 #include "mm/mm1/globals.h"
 
 namespace MM {
@@ -39,7 +40,8 @@ BlacksmithItems::BlacksmithItems() : ItemsView("BlacksmithItems") {
 bool BlacksmithItems::msgFocus(const FocusMessage &msg) {
 	ItemsView::msgFocus(msg);
 
-	_mode = WEAPONS_MODE;
+	if (dynamic_cast<Confirm *>(msg._priorView) == nullptr)
+		_mode = WEAPONS_MODE;
 	populateItems();
 
 	return true;
@@ -156,7 +158,34 @@ void BlacksmithItems::populateItems() {
 }
 
 void BlacksmithItems::itemSelected() {
-	// TODO: buy/sell items
+	Common::String buySell, gold;
+	g_globals->_items.getItem(_items[_selectedItem]);
+	const Item &item = g_globals->_currItem;
+
+	if (_mode != SELL_MODE) {
+		buySell = STRING["enhdialogs.blacksmith.buy"];
+		gold = Common::String::format(
+			STRING["enhdialogs.blacksmith.for_gold"].c_str(),
+			item._cost);
+	} else {
+		buySell = STRING["enhdialogs.blacksmith.sell"];
+		gold = Common::String::format(
+			STRING["enhdialogs.blacksmith.for_gold"].c_str(),
+			item.getSellCost());
+	}
+
+	Common::String msg = Common::String::format(
+		"%s \x02""15%s\x02""00 %s?",
+		buySell.c_str(), item._name.c_str(), gold.c_str());
+	Confirm::show(msg, []() {
+		BlacksmithItems *view = static_cast<BlacksmithItems *>(
+			g_events->focusedView());
+		view->itemConfirmed();
+	});
+}
+
+void BlacksmithItems::itemConfirmed() {
+	// TODO: Actual buy/sell logic
 }
 
 } // namespace Locations
diff --git a/engines/mm/mm1/views_enh/locations/blacksmith_items.h b/engines/mm/mm1/views_enh/locations/blacksmith_items.h
index 411fe6522b2..b45dc39ae2f 100644
--- a/engines/mm/mm1/views_enh/locations/blacksmith_items.h
+++ b/engines/mm/mm1/views_enh/locations/blacksmith_items.h
@@ -50,6 +50,11 @@ private:
 	 */
 	void drawTitle();
 
+	/**
+	 * Called if the buy/sell action has been confirmed
+	 */
+	void itemConfirmed();
+
 protected:
 	/**
 	 * Called when an item is selected
diff --git a/engines/mm/mm1/views_enh/quick_ref.cpp b/engines/mm/mm1/views_enh/quick_ref.cpp
index 7ef30940990..03e6f4d0eb2 100644
--- a/engines/mm/mm1/views_enh/quick_ref.cpp
+++ b/engines/mm/mm1/views_enh/quick_ref.cpp
@@ -145,6 +145,6 @@ bool QuickRef::isInCombat() const {
 	return g_events->isPresent("Combat");
 }
 
-} // namespace Views
+} // namespace ViewsEnh
 } // namespace MM1
 } // namespace MM
diff --git a/engines/mm/mm1/views_enh/quick_ref.h b/engines/mm/mm1/views_enh/quick_ref.h
index 95eccdd3be8..09c09f06c82 100644
--- a/engines/mm/mm1/views_enh/quick_ref.h
+++ b/engines/mm/mm1/views_enh/quick_ref.h
@@ -47,7 +47,7 @@ public:
 	void draw() override;
 };
 
-} // namespace Views
+} // namespace ViewsEnh
 } // namespace MM1
 } // namespace MM
 
diff --git a/engines/mm/mm1/views_enh/text_view.cpp b/engines/mm/mm1/views_enh/text_view.cpp
index 3ae732d4e87..bd898f8b0e9 100644
--- a/engines/mm/mm1/views_enh/text_view.cpp
+++ b/engines/mm/mm1/views_enh/text_view.cpp
@@ -94,6 +94,11 @@ void TextView::rawWriteString(const Common::String &str) {
 			writeChar(*s);
 			setTextColor(oldCol);
 
+		} else if (c == '\x02') {
+			int colNum = atoi(Common::String(s + 1, s + 3).c_str());
+			setTextColor(colNum);
+			s += 2;
+
 		} else {
 			writeChar(c);
 		}
@@ -184,6 +189,7 @@ Common::StringArray TextView::splitLines(const Common::String &str,
 		int lineWidth) {
 	XeenFont &font = _fontReduced ?
 		g_globals->_fontReduced : g_globals->_fontNormal;
+	const Common::String CONTROL_CHARS = "\x01\x02";
 	const char *startP = str.c_str();
 	const char *endP;
 
@@ -205,6 +211,13 @@ Common::StringArray TextView::splitLines(const Common::String &str,
 			while (strWidth > lineWidth) {
 				// Move back to a prior space
 				for (--endP; endP > startP && *endP != ' '; --endP) {
+					// Strings can have a byte value of 1 or 2 (for changing the
+					// color of the next character/all text), followed by 2 characters
+					// for the color. So in such cases, skip over the digits
+					size_t p = Common::String(startP).findLastOf(CONTROL_CHARS);
+					if (p != Common::String::npos && endP >= (startP + p) &&
+						endP < (startP + p + 3))
+						endP = startP + p;
 				}
 				assert(endP > startP);
 
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index 8c37830ed2b..c7169bbc231 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -131,6 +131,7 @@ MODULE_OBJS += \
 	mm1/views_enh/character_select.o \
 	mm1/views_enh/character_view.o \
 	mm1/views_enh/characters.o \
+	mm1/views_enh/confirm.o \
 	mm1/views_enh/create_characters.o \
 	mm1/views_enh/dialogs.o \
 	mm1/views_enh/exchange.o \
diff --git a/engines/mm/shared/utils/xeen_font.cpp b/engines/mm/shared/utils/xeen_font.cpp
index 8c7b16d19dd..fd8e449ff53 100644
--- a/engines/mm/shared/utils/xeen_font.cpp
+++ b/engines/mm/shared/utils/xeen_font.cpp
@@ -84,13 +84,22 @@ void XeenFont::drawChar(Graphics::Surface *dst, uint32 chr, int x, int y, uint32
 int XeenFont::getStringWidth(const Common::String &str) const {
 	// Handle not counting character highlighting sequences
 	// as part of the string width
-	size_t p = str.findFirstOf('\x01');
-	if (p == Common::String::npos) {
+	static const char *const CONTROL_CHARS = "\x01\x02";
+	size_t p = str.findFirstOf(CONTROL_CHARS);
+	if (p == Common::String::npos)
 		return Graphics::Font::getStringWidth(str);
-	} else {
-		return Graphics::Font::getStringWidth(
-			Common::String(str.c_str() + p + 3));
-	}
+
+	size_t totalWidth = 0;
+	Common::String strCopy = str;
+	do {
+		totalWidth += Graphics::Font::getStringWidth(
+			Common::String(strCopy.c_str(), strCopy.c_str() + p));
+		strCopy = Common::String(strCopy.c_str() + p + 3);
+		p = strCopy.findFirstOf(CONTROL_CHARS);
+	} while (p != Common::String::npos);
+
+	totalWidth += Graphics::Font::getStringWidth(strCopy);
+	return totalWidth;
 }
 
 } // namespace MM


Commit: f9bbbf9595582c844f425b6df06e5dbb72343bf9
    https://github.com/scummvm/scummvm/commit/f9bbbf9595582c844f425b6df06e5dbb72343bf9
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2023-03-18T22:28:35-07:00

Commit Message:
MM: MM1: Added blacksmith buy/sell logic

Changed paths:
    devtools/create_mm/files/mm1/strings_en.yml
    engines/mm/mm1/game/spell_casting.cpp
    engines/mm/mm1/views/locations/blacksmith_subview.cpp
    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
    engines/mm/mm1/views_enh/text_view.cpp


diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 60272be0f4d..26c774b5588 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -314,6 +314,10 @@ dialogs:
 		full: "*** Backpack full ***"
 		who_will_try: "Who will try '1'-'%c'"
 		check_condition: "*** Check condition ***"
+		not_enough_gold: "Not enough gold"
+		not_enough_gems: "Not enough gems"
+		not_enough_sp: "Not enough spell points"
+		backpack_full: "Backpack is full"
 	spells:
 		detect_charges: "magic (charges)"
 		fly_to_x: "fly to (a-e): "
@@ -675,9 +679,6 @@ movement:
 view:
 	darkness: "  darkness"
 spells:
-	not_enough_gold: "Not enough gold"
-	not_enough_gems: "Not enough gems"
-	not_enough_sp: "Not enough spell points"
 	done: "Done"
 	combat_only: "Combat only"
 	noncombat_only: "Non combat only"
diff --git a/engines/mm/mm1/game/spell_casting.cpp b/engines/mm/mm1/game/spell_casting.cpp
index 457212037bc..bfa59661af3 100644
--- a/engines/mm/mm1/game/spell_casting.cpp
+++ b/engines/mm/mm1/game/spell_casting.cpp
@@ -161,10 +161,10 @@ Common::String SpellCasting::getSpellError() const {
 	Common::String msg;
 	switch (_spellState) {
 	case SS_NOT_ENOUGH_SP:
-		msg = STRING["spells.not_enough_sp"];
+		msg = STRING["dialogs.misc.not_enough_sp"];
 		break;
 	case SS_NOT_ENOUGH_GEMS:
-		msg = STRING["spells.not_enough_gems"];
+		msg = STRING["dialogs.misc.not_enough_gems"];
 		break;
 	case SS_COMBAT_ONLY:
 		msg = STRING["spells.combat_only"];
diff --git a/engines/mm/mm1/views/locations/blacksmith_subview.cpp b/engines/mm/mm1/views/locations/blacksmith_subview.cpp
index 3e6db4516d3..903b933d570 100644
--- a/engines/mm/mm1/views/locations/blacksmith_subview.cpp
+++ b/engines/mm/mm1/views/locations/blacksmith_subview.cpp
@@ -94,7 +94,6 @@ void BlacksmithSubview::selectItem(uint index) {
 		break;
 	default:
 		// Purchased successfully
-		clearSurface();
 		displayMessage(15, STRING["dialogs.blacksmith.thankyou"]);
 		break;
 	}
diff --git a/engines/mm/mm1/views_enh/items_view.cpp b/engines/mm/mm1/views_enh/items_view.cpp
index bc2c7f03373..3ddc53a1320 100644
--- a/engines/mm/mm1/views_enh/items_view.cpp
+++ b/engines/mm/mm1/views_enh/items_view.cpp
@@ -21,6 +21,7 @@
 
 #include "mm/mm1/views_enh/items_view.h"
 #include "mm/mm1/globals.h"
+#include "mm/mm1/sound.h"
 
 namespace MM {
 namespace MM1 {
@@ -130,7 +131,26 @@ bool ItemsView::msgAction(const ActionMessage &msg) {
 }
 
 void ItemsView::timeout() {
-	close();
+	redraw();
+}
+
+void ItemsView::backpackFull() {
+	displayMessage(STRING["dialogs.misc.backpack_full"]);
+}
+
+void ItemsView::notEnoughGold() {
+	displayMessage(STRING["dialogs.misc.not_enough_gold"]);
+}
+
+void ItemsView::displayMessage(const Common::String &msg) {
+	SoundMessage infoMsg(msg, ALIGN_MIDDLE);
+	infoMsg._delaySeconds = 3;
+	infoMsg._timeoutCallback = []() {
+		ItemsView *view = static_cast<ItemsView *>(g_events->focusedView());
+		view->timeout();
+	};
+
+	send(infoMsg);
 }
 
 } // namespace ViewsEnh
diff --git a/engines/mm/mm1/views_enh/items_view.h b/engines/mm/mm1/views_enh/items_view.h
index b0d5dd54cae..d4e0292439d 100644
--- a/engines/mm/mm1/views_enh/items_view.h
+++ b/engines/mm/mm1/views_enh/items_view.h
@@ -44,6 +44,21 @@ protected:
 	void addButton(int frame, const Common::String &text,
 		Common::KeyCode keycode);
 
+	/**
+	 * Display a message that the inventory is full
+	 */
+	void backpackFull();
+
+	/**
+	 * Display a message the character doesn't have enough gold
+	 */
+	void notEnoughGold();
+
+	/**
+	 * Display an arbitrary message
+	 */
+	void displayMessage(const Common::String &msg);
+
 	/**
 	 * 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 cb83b42668c..1077bcd04a4 100644
--- a/engines/mm/mm1/views_enh/locations/blacksmith_items.cpp
+++ b/engines/mm/mm1/views_enh/locations/blacksmith_items.cpp
@@ -161,6 +161,7 @@ void BlacksmithItems::itemSelected() {
 	Common::String buySell, gold;
 	g_globals->_items.getItem(_items[_selectedItem]);
 	const Item &item = g_globals->_currItem;
+	_buySellItem = _selectedItem;
 
 	if (_mode != SELL_MODE) {
 		buySell = STRING["enhdialogs.blacksmith.buy"];
@@ -185,7 +186,33 @@ void BlacksmithItems::itemSelected() {
 }
 
 void BlacksmithItems::itemConfirmed() {
-	// TODO: Actual buy/sell logic
+	Character &c = *g_globals->_currCharacter;
+	Inventory &inv = c._backpack;
+
+	if (_mode == SELL_MODE) {
+		// Give the character the item value, and remove from inventory
+		c._gold += g_globals->_currItem.getSellCost();
+		inv.removeAt(_buySellItem);
+		populateItems();
+
+	} else {
+		auto buyResult = c.buyItem(_items[_buySellItem]);
+		if (buyResult == Character::BUY_SUCCESS)
+			_items.remove_at(_buySellItem);
+		draw();
+
+		switch (buyResult) {
+		case Character::BUY_BACKPACK_FULL:
+			backpackFull();
+			break;
+		case Character::BUY_NOT_ENOUGH_GOLD:
+			notEnoughGold();
+			break;
+		default:
+			displayMessage(STRING["dialogs.blacksmith.thankyou"]);
+			break;
+		}
+	}
 }
 
 } // namespace Locations
diff --git a/engines/mm/mm1/views_enh/locations/blacksmith_items.h b/engines/mm/mm1/views_enh/locations/blacksmith_items.h
index b45dc39ae2f..b63f505064e 100644
--- a/engines/mm/mm1/views_enh/locations/blacksmith_items.h
+++ b/engines/mm/mm1/views_enh/locations/blacksmith_items.h
@@ -39,6 +39,7 @@ private:
 		SELL_MODE = 3
 	};
 	BlacksmithMode _mode = WEAPONS_MODE;
+	int _buySellItem = -1;
 
 	/**
 	 * Populates the list of items
diff --git a/engines/mm/mm1/views_enh/text_view.cpp b/engines/mm/mm1/views_enh/text_view.cpp
index bd898f8b0e9..d48f0df3e6b 100644
--- a/engines/mm/mm1/views_enh/text_view.cpp
+++ b/engines/mm/mm1/views_enh/text_view.cpp
@@ -190,6 +190,7 @@ Common::StringArray TextView::splitLines(const Common::String &str,
 	XeenFont &font = _fontReduced ?
 		g_globals->_fontReduced : g_globals->_fontNormal;
 	const Common::String CONTROL_CHARS = "\x01\x02";
+	bool hasControlChars = str.findFirstOf(CONTROL_CHARS) != Common::String::npos;
 	const char *startP = str.c_str();
 	const char *endP;
 
@@ -211,13 +212,15 @@ Common::StringArray TextView::splitLines(const Common::String &str,
 			while (strWidth > lineWidth) {
 				// Move back to a prior space
 				for (--endP; endP > startP && *endP != ' '; --endP) {
-					// Strings can have a byte value of 1 or 2 (for changing the
-					// color of the next character/all text), followed by 2 characters
-					// for the color. So in such cases, skip over the digits
-					size_t p = Common::String(startP).findLastOf(CONTROL_CHARS);
-					if (p != Common::String::npos && endP >= (startP + p) &&
-						endP < (startP + p + 3))
-						endP = startP + p;
+					if (hasControlChars) {
+						// Strings can have a byte value of 1 or 2 (for changing the
+						// color of the next character/all text), followed by 2 characters
+						// for the color. So in such cases, skip over the digits
+						size_t p = Common::String(startP).findLastOf(CONTROL_CHARS);
+						if (p != Common::String::npos && endP >= (startP + p) &&
+							endP < (startP + p + 3))
+							endP = startP + p;
+					}
 				}
 				assert(endP > startP);
 




More information about the Scummvm-git-logs mailing list