[Scummvm-git-logs] scummvm master -> 41caa6897ff1da4773f71b4dc6931d7610f72538
dreammaster
noreply at scummvm.org
Sat May 2 11:21:46 UTC 2026
This automated email contains information about 5 new commits which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .
Summary:
92564f58d8 MM: MM1: Improve enhanced menu mouse controls
9c97218760 MM: MM1: UI enhancements and improved mouse support for enhanced views
35a7d0d78d MM: MM1: Character game generation and UI enhancement
287c7811d8 MM: MM1: Added 'Roster is full' string, fixing the crash
41caa6897f MM: MM1: Fix text cases in multiple text and bump version to 1.1
Commit: 92564f58d8619cf1f5345f8d6fd7ba719822eaef
https://github.com/scummvm/scummvm/commit/92564f58d8619cf1f5345f8d6fd7ba719822eaef
Author: Scorp (scorp at mrs.mn)
Date: 2026-05-02T21:01:46+10:00
Commit Message:
MM: MM1: Improve enhanced menu mouse controls
Add mouse move dispatch and raw Y/N key passthrough so enhanced views can share keyboard and mouse handling for hover and confirmation controls.
Make the title screen mouse-aware: clicking the start/scenes labels triggers the matching key actions, scene clicks and Space advance the slideshow, right click returns to the initial screen, and text-scene delays are lengthened.
Add enhanced main-menu hover and click handling for create/view/town choices. Introduce a town selection popup using the same numbered button style as the leprechaun town selector, with keyboard, hover, outside-click, right-click, and Escape close behavior.
Add hover support and exact text hitboxes for create-character class, race, alignment, and sex choices while leaving icon-only controls as icons. Show Neutral instead of Neut in the enhanced create-character flow.
Add clickable and hoverable delete confirmation icons in View Character and reset delete state when switching characters.
Fix the Inn party toggle code so unselecting the last character disables only the exit/start button and does not hide the go-back icon.
Changed paths:
A engines/mm/mm1/views_enh/town_select.cpp
A engines/mm/mm1/views_enh/town_select.h
engines/mm/mm1/events.cpp
engines/mm/mm1/events.h
engines/mm/mm1/messages.h
engines/mm/mm1/metaengine.cpp
engines/mm/mm1/metaengine.h
engines/mm/mm1/views/title.cpp
engines/mm/mm1/views/title.h
engines/mm/mm1/views_enh/character_manage.cpp
engines/mm/mm1/views_enh/character_manage.h
engines/mm/mm1/views_enh/create_characters.cpp
engines/mm/mm1/views_enh/create_characters.h
engines/mm/mm1/views_enh/dialogs.h
engines/mm/mm1/views_enh/locations/inn.cpp
engines/mm/mm1/views_enh/main_menu.cpp
engines/mm/mm1/views_enh/main_menu.h
engines/mm/mm1/views_enh/scroll_view.h
engines/mm/module.mk
diff --git a/engines/mm/mm1/events.cpp b/engines/mm/mm1/events.cpp
index 8ff20da9bee..6f5499f112f 100644
--- a/engines/mm/mm1/events.cpp
+++ b/engines/mm/mm1/events.cpp
@@ -92,7 +92,14 @@ void Events::processEvent(Common::Event &ev) {
msgKeypress(KeypressMessage(ev.kbd));
break;
case Common::EVENT_CUSTOM_ENGINE_ACTION_START:
- msgAction(ActionMessage((KeybindingAction)ev.customType));
+ if (MetaEngine::getActionKeyState((KeybindingAction)ev.customType).keycode != Common::KEYCODE_INVALID) {
+ msgKeypress(KeypressMessage(MetaEngine::getActionKeyState((KeybindingAction)ev.customType)));
+ } else {
+ msgAction(ActionMessage((KeybindingAction)ev.customType));
+ }
+ break;
+ case Common::EVENT_MOUSEMOVE:
+ msgMouseMove(MouseMoveMessage(ev.mouse));
break;
case Common::EVENT_LBUTTONDOWN:
case Common::EVENT_RBUTTONDOWN:
diff --git a/engines/mm/mm1/events.h b/engines/mm/mm1/events.h
index 6383e173414..c9b963214af 100644
--- a/engines/mm/mm1/events.h
+++ b/engines/mm/mm1/events.h
@@ -247,6 +247,7 @@ public:
MESSAGE(Keypress);
MESSAGE(MouseDown);
MESSAGE(MouseUp);
+ MESSAGE(MouseMove);
MESSAGE(Action);
MESSAGE(Game);
MESSAGE(Header);
@@ -293,6 +294,7 @@ protected:
MESSAGE(Keypress);
MESSAGE(MouseDown);
MESSAGE(MouseUp);
+ MESSAGE(MouseMove);
MESSAGE(DrawGraphic);
#undef MESSAGE
public:
diff --git a/engines/mm/mm1/messages.h b/engines/mm/mm1/messages.h
index 5ccf6b950c3..3524c4287b8 100644
--- a/engines/mm/mm1/messages.h
+++ b/engines/mm/mm1/messages.h
@@ -83,6 +83,11 @@ struct MouseUpMessage : public MouseMessage {
MouseUpMessage(Common::EventType type, const Common::Point &pos) :
MouseMessage(type, pos) {}
};
+struct MouseMoveMessage : public MouseMessage {
+ MouseMoveMessage() : MouseMessage() {}
+ MouseMoveMessage(const Common::Point &pos) :
+ MouseMessage(MB_LEFT, pos) {}
+};
struct GameMessage : public Message {
Common::String _name;
diff --git a/engines/mm/mm1/metaengine.cpp b/engines/mm/mm1/metaengine.cpp
index fdda610cdc8..068cea36b8c 100644
--- a/engines/mm/mm1/metaengine.cpp
+++ b/engines/mm/mm1/metaengine.cpp
@@ -48,6 +48,8 @@ static const KeybindingRecord MENU_KEYS[] = {
{ KEYBIND_ESCAPE, "ESCAPE", _s("Escape"), "ESCAPE", nullptr },
// I18N: Return key
{ KEYBIND_SELECT, "SELECT", _s("Select"), "RETURN", nullptr },
+ { KEYBIND_KEY_N, "KEY_N", _s("N"), "n", nullptr },
+ { KEYBIND_KEY_Y, "KEY_Y", _s("Y"), "y", nullptr },
{ KEYBIND_NONE, nullptr, nullptr, nullptr, nullptr }
};
@@ -244,5 +246,16 @@ void MetaEngine::executeAction(KeybindingAction keyAction) {
g_engine->send(ActionMessage(keyAction));
}
+Common::KeyState MetaEngine::getActionKeyState(KeybindingAction keyAction) {
+ switch (keyAction) {
+ case KEYBIND_KEY_N:
+ return Common::KeyState(Common::KEYCODE_n, 'n');
+ case KEYBIND_KEY_Y:
+ return Common::KeyState(Common::KEYCODE_y, 'y');
+ default:
+ return Common::KeyState(Common::KEYCODE_INVALID, 0);
+ }
+}
+
} // End of namespace MM1
} // End of namespace MM
diff --git a/engines/mm/mm1/metaengine.h b/engines/mm/mm1/metaengine.h
index 7a1bfb08aa9..d5c758f152d 100644
--- a/engines/mm/mm1/metaengine.h
+++ b/engines/mm/mm1/metaengine.h
@@ -30,6 +30,8 @@ namespace MM1 {
enum KeybindingAction {
KEYBIND_ESCAPE,
KEYBIND_SELECT,
+ KEYBIND_KEY_N,
+ KEYBIND_KEY_Y,
KEYBIND_FORWARDS,
KEYBIND_BACKWARDS,
@@ -106,6 +108,11 @@ public:
*/
static void executeAction(KeybindingAction keyAction);
+ /**
+ * Return the keypress represented by a keymap action, if any
+ */
+ static Common::KeyState getActionKeyState(KeybindingAction keyAction);
+
/**
* Sets the current set of actions which are active
*/
diff --git a/engines/mm/mm1/views/title.cpp b/engines/mm/mm1/views/title.cpp
index 98392fd9f65..40b602afc19 100644
--- a/engines/mm/mm1/views/title.cpp
+++ b/engines/mm/mm1/views/title.cpp
@@ -31,8 +31,16 @@ namespace Views {
#define FADE_SEGMENTS 20
#define FADE_SEGMENT_X (SCREEN_W / 2 / FADE_SEGMENTS)
#define FADE_SEGMENT_Y (SCREEN_H / 2 / FADE_SEGMENTS)
+#define FIRST_SCENE_SCREEN 2
+#define FIRST_TEXT_SCENE_SCREEN 5
+#define SCENE_SECONDS 5
+#define TEXT_SCENE_SECONDS 12
+
+static const Common::Rect START_GAME_BOUNDS(23, 164, 157, 173);
+static const Common::Rect SCENES_BOUNDS(162, 164, 292, 173);
Title::Title() : UIElement("Title", g_engine) {
+ _bounds = Common::Rect(0, 0, SCREEN_W, SCREEN_H);
}
bool Title::msgFocus(const FocusMessage &msg) {
@@ -109,22 +117,18 @@ void Title::draw() {
const Graphics::ManagedSurface &src = _screens[_screenNum];
surf.blitFrom(src);
- delaySeconds(5);
+ delaySeconds(_screenNum >= FIRST_TEXT_SCENE_SCREEN ? TEXT_SCENE_SECONDS : SCENE_SECONDS);
}
}
void Title::timeout() {
- if (_screenNum < 2) {
+ if (_screenNum < FIRST_SCENE_SCREEN) {
if (_fadeIndex++ == FADE_SEGMENTS) {
_screenNum = (_screenNum == 0) ? 1 : 0;
_fadeIndex = 0;
}
} else {
- if (++_screenNum >= SCREENS_COUNT) {
- // Go back to alternating first two screens
- _screenNum = -1;
- _fadeIndex = 0;
- }
+ advanceSlideshow();
}
redraw();
@@ -132,7 +136,7 @@ void Title::timeout() {
bool Title::msgKeypress(const KeypressMessage &msg) {
if (msg.keycode == Common::KEYCODE_SPACE)
- startSlideshow();
+ msgAction(ActionMessage(KEYBIND_SELECT));
return true;
}
@@ -143,20 +147,59 @@ bool Title::msgAction(const ActionMessage &msg) {
"MainMenu" : "AreYouReady");
return true;
} else if (msg._action == KEYBIND_SELECT) {
- startSlideshow();
+ if (_screenNum >= FIRST_SCENE_SCREEN) {
+ cancelDelay();
+ advanceSlideshow();
+ redraw();
+ } else {
+ startSlideshow();
+ }
return true;
}
return false;
}
+bool Title::msgMouseUp(const MouseUpMessage &msg) {
+ if (msg._button == MouseMessage::MB_RIGHT) {
+ _screenNum = -1;
+ _fadeIndex = 0;
+ cancelDelay();
+ redraw();
+ return true;
+ }
+
+ if (msg._button != MouseMessage::MB_LEFT)
+ return false;
+
+ Common::Point pos = msg._pos;
+ pos -= Common::Point(_bounds.left, _bounds.top);
+
+ if (_screenNum >= FIRST_SCENE_SCREEN) {
+ msgAction(ActionMessage(KEYBIND_SELECT));
+ } else if (START_GAME_BOUNDS.contains(pos)) {
+ msgAction(ActionMessage(KEYBIND_ESCAPE));
+ } else if (SCENES_BOUNDS.contains(pos)) {
+ msgAction(ActionMessage(KEYBIND_SELECT));
+ }
+
+ return true;
+}
+
void Title::startSlideshow() {
cancelDelay();
- _screenNum = 2;
+ _screenNum = FIRST_SCENE_SCREEN;
_fadeIndex = 0;
redraw();
}
+void Title::advanceSlideshow() {
+ if (++_screenNum >= SCREENS_COUNT) {
+ _screenNum = -1;
+ _fadeIndex = 0;
+ }
+}
+
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views/title.h b/engines/mm/mm1/views/title.h
index 881bd102667..0ca5d9005fe 100644
--- a/engines/mm/mm1/views/title.h
+++ b/engines/mm/mm1/views/title.h
@@ -37,6 +37,11 @@ private:
*/
void startSlideshow();
+ /**
+ * Advances to the next scene screen
+ */
+ void advanceSlideshow();
+
protected:
Graphics::ManagedSurface _screens[SCREENS_COUNT];
int _screenNum = -1;
@@ -75,6 +80,11 @@ public:
* Handle actions
*/
bool msgAction(const ActionMessage &msg) override;
+
+ /**
+ * Mouse up handler
+ */
+ bool msgMouseUp(const MouseUpMessage &msg) override;
};
} // namespace Views
diff --git a/engines/mm/mm1/views_enh/character_manage.cpp b/engines/mm/mm1/views_enh/character_manage.cpp
index 81e9a800b9b..b9f376ef498 100644
--- a/engines/mm/mm1/views_enh/character_manage.cpp
+++ b/engines/mm/mm1/views_enh/character_manage.cpp
@@ -32,10 +32,18 @@ CharacterManage::CharacterManage() : CharacterBase("CharacterManage") {
addButton(&_escSprite, Common::Point(90, 172), 0, Common::KEYCODE_r, true);
addButton(&_escSprite, Common::Point(160, 172), 0, Common::KEYCODE_d, true);
addButton(&_escSprite, Common::Point(230, 172), 0, KEYBIND_ESCAPE, true);
+ addButton(&g_globals->_confirmIcons, Common::Point(240, 163), 0,
+ Common::KeyState(Common::KEYCODE_y, 'y'));
+ addButton(&g_globals->_confirmIcons, Common::Point(270, 163), 2,
+ Common::KeyState(Common::KEYCODE_n, 'n'));
+
+ setButtonEnabled(4, false);
+ setButtonEnabled(5, false);
}
bool CharacterManage::msgFocus(const FocusMessage &msg) {
CharacterBase::msgFocus(msg);
+ setMode(DISPLAY);
_changed = false;
return true;
}
@@ -79,7 +87,7 @@ void CharacterManage::draw() {
break;
case DELETE:
- writeString(120, 174, STRING["enhdialogs.character.are_you_sure"]);
+ writeString(110, 171, STRING["enhdialogs.character.are_you_sure"]);
break;
}
}
@@ -150,6 +158,7 @@ bool CharacterManage::msgAction(const ActionMessage &msg) {
// Removes the character and returns to View All Characters
g_globals->_roster.remove(g_globals->_currCharacter);
_changed = true;
+ setMode(DISPLAY);
close();
}
}
@@ -159,12 +168,25 @@ bool CharacterManage::msgAction(const ActionMessage &msg) {
void CharacterManage::setMode(ViewState state) {
_state = state;
+ resetSelectedButton();
for (int i = 0; i < 4; ++i)
setButtonEnabled(i, state == DISPLAY);
+ setButtonEnabled(4, state == DELETE);
+ setButtonEnabled(5, state == DELETE);
redraw();
}
+bool CharacterManage::msgMouseMove(const MouseMoveMessage &msg) {
+ int selectedButton = _state == DELETE ? getButtonAt(msg._pos) : -1;
+ if (selectedButton != _selectedButton) {
+ _selectedButton = selectedButton;
+ redraw();
+ }
+
+ return true;
+}
+
void CharacterManage::setName(const Common::String &newName) {
Character &c = *g_globals->_currCharacter;
Common::strcpy_s(c._name, newName.c_str());
diff --git a/engines/mm/mm1/views_enh/character_manage.h b/engines/mm/mm1/views_enh/character_manage.h
index 1087341c8ac..344a55ffdb6 100644
--- a/engines/mm/mm1/views_enh/character_manage.h
+++ b/engines/mm/mm1/views_enh/character_manage.h
@@ -61,6 +61,7 @@ public:
void draw() override;
bool msgKeypress(const KeypressMessage &msg) override;
bool msgAction(const ActionMessage &msg) override;
+ bool msgMouseMove(const MouseMoveMessage &msg) override;
};
diff --git a/engines/mm/mm1/views_enh/create_characters.cpp b/engines/mm/mm1/views_enh/create_characters.cpp
index a2d90efe8b9..d320769fd26 100644
--- a/engines/mm/mm1/views_enh/create_characters.cpp
+++ b/engines/mm/mm1/views_enh/create_characters.cpp
@@ -29,6 +29,13 @@ namespace ViewsEnh {
#define RIGHT_X 200
+static Common::String getAlignmentString(Alignment alignment) {
+ if (alignment == NEUTRAL)
+ return "Neutral";
+
+ return STRING[Common::String::format("stats.alignments.%d", alignment)];
+}
+
void CreateCharacters::NewCharacter::clear() {
Common::fill(_attribs1, _attribs1 + 7, 0);
Common::fill(_attribs2, _attribs2 + 7, 0);
@@ -211,6 +218,10 @@ bool CreateCharacters::msgFocus(const FocusMessage &msg) {
}
void CreateCharacters::draw() {
+ if (_state == SELECT_CLASS || _state == SELECT_RACE ||
+ _state == SELECT_ALIGNMENT || _state == SELECT_SEX)
+ removeButtons(5, -1);
+
ScrollView::draw();
printAttributes();
@@ -276,30 +287,34 @@ void CreateCharacters::printAttributes() {
}
}
-void CreateCharacters::addSelection(int yStart, int num) {
- Common::Rect r(170, 0, 320, 9);
+int CreateCharacters::addSelection(int yStart, int num, const Common::String &text) {
+ Common::Rect r(170, 0, 170 + getStringWidth(text),
+ g_globals->_fontNormal.getFontHeight());
r.translate(0, (yStart + num) * 9);
- addButton(r, Common::KeyState((Common::KeyCode)(Common::KEYCODE_0 + num), '0' + num));
+ return addButton(r, Common::KeyState((Common::KeyCode)(Common::KEYCODE_0 + num), '0' + num));
}
void CreateCharacters::printClasses() {
+ bool rosterFull = g_globals->_roster.full();
for (int classNum = KNIGHT; classNum <= SORCERER; ++classNum) {
- setTextColor(_newChar._classesAllowed[classNum] ? 0 : 1);
- writeLine(4 + classNum, Common::String::format("%d) %s",
+ Common::String text = Common::String::format("%d) %s",
classNum,
STRING[Common::String::format("stats.classes.%d", classNum)].c_str()
- ), ALIGN_LEFT, 170);
+ );
+ bool enabled = _newChar._classesAllowed[classNum] && !rosterFull;
+ int buttonNum = enabled ? addSelection(4, classNum, text) : -1;
+ setTextColor(enabled ? (_selectedButton == buttonNum ? 15 : 0) : 1);
+ writeLine(4 + classNum, text, ALIGN_LEFT, 170);
- if (_newChar._classesAllowed[classNum])
- addSelection(4, classNum);
}
- setTextColor(0);
- writeLine(10, Common::String::format("6) %s", STRING["stats.classes.6"].c_str()),
- ALIGN_LEFT, 170);
- addSelection(4, ROBBER);
+ Common::String text = Common::String::format("6) %s", STRING["stats.classes.6"].c_str());
+ int buttonNum = rosterFull ? -1 : addSelection(4, ROBBER, text);
+ setTextColor(rosterFull ? 1 : (_selectedButton == buttonNum ? 15 : 0));
+ writeLine(10, text, ALIGN_LEFT, 170);
+ setTextColor(0);
writeLine(13, STRING["dialogs.create_characters.select_class"], ALIGN_MIDDLE, RIGHT_X);
writeLine(14, "(1-6)", ALIGN_MIDDLE, RIGHT_X);
}
@@ -309,10 +324,12 @@ void CreateCharacters::printRaces() {
writeString(STRING[Common::String::format("stats.classes.%d", _newChar._class)]);
for (int i = 1; i <= 5; ++i) {
- writeLine(6 + i, Common::String::format("%d) %s", i,
- STRING[Common::String::format("stats.races.%d", i)].c_str()),
- ALIGN_LEFT, 170);
- addSelection(6, i);
+ Common::String text = Common::String::format("%d) %s", i,
+ STRING[Common::String::format("stats.races.%d", i)].c_str());
+ int buttonNum = addSelection(6, i, text);
+ byte oldColor = setTextColor(_selectedButton == buttonNum ? 15 : 0);
+ writeLine(6 + i, text, ALIGN_LEFT, 170);
+ setTextColor(oldColor);
}
writeLine(13, STRING["dialogs.create_characters.select_race"], ALIGN_MIDDLE, RIGHT_X);
@@ -326,10 +343,12 @@ void CreateCharacters::printAlignments() {
writeString(STRING[Common::String::format("stats.races.%d", _newChar._race)]);
for (int i = 1; i <= 3; ++i) {
- writeLine(7 + i, Common::String::format("%d) %s", i,
- STRING[Common::String::format("stats.alignments.%d", i)].c_str()),
- ALIGN_LEFT, 170);
- addSelection(7, i);
+ Common::String text = Common::String::format("%d) %s", i,
+ getAlignmentString((Alignment)i).c_str());
+ int buttonNum = addSelection(7, i, text);
+ byte oldColor = setTextColor(_selectedButton == buttonNum ? 15 : 0);
+ writeLine(7 + i, text, ALIGN_LEFT, 170);
+ setTextColor(oldColor);
}
writeLine(13, STRING["dialogs.create_characters.select_alignment"], ALIGN_MIDDLE, RIGHT_X);
@@ -342,14 +361,18 @@ void CreateCharacters::printSexes() {
writeLine(6, STRING["enhdialogs.create_characters.race"], ALIGN_RIGHT, RIGHT_X);
writeString(STRING[Common::String::format("stats.races.%d", _newChar._race)]);
writeLine(7, STRING["enhdialogs.create_characters.alignment"], ALIGN_RIGHT, RIGHT_X);
- writeString(STRING[Common::String::format("stats.alignments.%d", _newChar._alignment)]);
-
- writeLine(9, "1) ", ALIGN_LEFT, 170);
- writeString(STRING["stats.sex.1"]);
- addSelection(8, 1);
- writeLine(10, "2) ", ALIGN_LEFT, 170);
- writeString(STRING["stats.sex.2"]);
- addSelection(8, 2);
+ writeString(getAlignmentString(_newChar._alignment));
+
+ Common::String male = Common::String::format("1) %s", STRING["stats.sex.1"].c_str());
+ Common::String female = Common::String::format("2) %s", STRING["stats.sex.2"].c_str());
+ int maleButton = addSelection(8, 1, male);
+ byte oldColor = setTextColor(_selectedButton == maleButton ? 15 : 0);
+ writeLine(9, male, ALIGN_LEFT, 170);
+ setTextColor(oldColor);
+ int femaleButton = addSelection(8, 2, female);
+ oldColor = setTextColor(_selectedButton == femaleButton ? 15 : 0);
+ writeLine(10, female, ALIGN_LEFT, 170);
+ setTextColor(oldColor);
writeLine(14, STRING["dialogs.create_characters.select_sex"], ALIGN_MIDDLE, RIGHT_X);
writeLine(15, "(1-2)", ALIGN_MIDDLE, RIGHT_X);
@@ -361,7 +384,7 @@ void CreateCharacters::printSelections() {
writeLine(6, STRING["enhdialogs.create_characters.race"], ALIGN_RIGHT, RIGHT_X);
writeString(STRING[Common::String::format("stats.races.%d", _newChar._race)]);
writeLine(7, STRING["enhdialogs.create_characters.alignment"], ALIGN_RIGHT, RIGHT_X);
- writeString(STRING[Common::String::format("stats.alignments.%d", _newChar._alignment)]);
+ writeString(getAlignmentString(_newChar._alignment));
writeLine(8, STRING["enhdialogs.create_characters.sex"], ALIGN_RIGHT, RIGHT_X);
writeString(STRING[Common::String::format("stats.sex.%d", _newChar._sex)]);
}
@@ -550,6 +573,16 @@ bool CreateCharacters::msgAction(const ActionMessage &msg) {
return false;
}
+bool CreateCharacters::msgMouseMove(const MouseMoveMessage &msg) {
+ int selectedButton = getButtonAt(msg._pos);
+ if (selectedButton != _selectedButton) {
+ _selectedButton = selectedButton;
+ redraw();
+ }
+
+ return true;
+}
+
void CreateCharacters::abortFunc() {
CreateCharacters *view = static_cast<CreateCharacters *>(g_events->focusedView());
view->setState(SELECT_CLASS);
@@ -564,6 +597,7 @@ void CreateCharacters::enterFunc(const Common::String &name) {
void CreateCharacters::setState(State state) {
_state = state;
+ resetSelectedButton();
setButtonEnabled(2, _state == SELECT_PORTRAIT);
setButtonEnabled(3, _state == SELECT_PORTRAIT);
diff --git a/engines/mm/mm1/views_enh/create_characters.h b/engines/mm/mm1/views_enh/create_characters.h
index e0ec2700a92..696b720b896 100644
--- a/engines/mm/mm1/views_enh/create_characters.h
+++ b/engines/mm/mm1/views_enh/create_characters.h
@@ -80,7 +80,7 @@ private:
/**
* Add a selection entry
*/
- void addSelection(int yStart, int num);
+ int addSelection(int yStart, int num, const Common::String &text);
/**
* Display the available classes
@@ -135,6 +135,7 @@ public:
void draw() override;
bool msgKeypress(const KeypressMessage &msg) override;
bool msgAction(const ActionMessage &msg) override;
+ bool msgMouseMove(const MouseMoveMessage &msg) override;
};
} // namespace ViewsEnh
diff --git a/engines/mm/mm1/views_enh/dialogs.h b/engines/mm/mm1/views_enh/dialogs.h
index b1d0105815a..3d1107a4f81 100644
--- a/engines/mm/mm1/views_enh/dialogs.h
+++ b/engines/mm/mm1/views_enh/dialogs.h
@@ -44,6 +44,7 @@
#include "mm/mm1/views_enh/rest.h"
#include "mm/mm1/views_enh/search.h"
#include "mm/mm1/views_enh/title.h"
+#include "mm/mm1/views_enh/town_select.h"
#include "mm/mm1/views_enh/trade.h"
#include "mm/mm1/views_enh/trap.h"
#include "mm/mm1/views_enh/unlock.h"
@@ -170,6 +171,7 @@ private:
ViewsEnh::Rest _rest;
ViewsEnh::Search _search;
ViewsEnh::Title _title;
+ ViewsEnh::TownSelect _townSelect;
ViewsEnh::Trade _trade;
ViewsEnh::Trap _trap;
ViewsEnh::Unlock _unlock;
diff --git a/engines/mm/mm1/views_enh/locations/inn.cpp b/engines/mm/mm1/views_enh/locations/inn.cpp
index 0e7efd3b8b5..34a73e359b5 100644
--- a/engines/mm/mm1/views_enh/locations/inn.cpp
+++ b/engines/mm/mm1/views_enh/locations/inn.cpp
@@ -70,6 +70,7 @@ bool Inn::msgFocus(const FocusMessage &msg) {
}
void Inn::draw() {
+ setButtonEnabled(0, true);
setButtonEnabled(1, !_partyChars.empty());
if (!_partyChars.empty()) {
setButtonPos(0, Common::Point(155, 166));
@@ -149,7 +150,7 @@ bool Inn::msgMouseDown(const MouseDownMessage &msg) {
else
_partyChars.push_back(charNum);
- setButtonEnabled(0, !_partyChars.empty());
+ setButtonEnabled(1, !_partyChars.empty());
redraw();
} else {
g_globals->_currCharacter = &g_globals->_roster[charNum];
@@ -174,7 +175,7 @@ bool Inn::msgKeypress(const KeypressMessage &msg) {
else
_partyChars.push_back(charNum);
- setButtonEnabled(0, !_partyChars.empty());
+ setButtonEnabled(1, !_partyChars.empty());
redraw();
} else {
diff --git a/engines/mm/mm1/views_enh/main_menu.cpp b/engines/mm/mm1/views_enh/main_menu.cpp
index c55d672e8d1..c8b6f5d9fc6 100644
--- a/engines/mm/mm1/views_enh/main_menu.cpp
+++ b/engines/mm/mm1/views_enh/main_menu.cpp
@@ -122,14 +122,51 @@ void MainMenu::draw() {
writeString(80, 120, Common::String(line1.c_str(), line1.c_str() + 3));
writeString(80, 130, Common::String(line2.c_str(), line2.c_str() + 3));
writeString(43, 140, line31);
+
+ byte oldColor = setTextColor(_hoverChoice == CHOICE_CREATE ? 15 : 0);
writeString(110, 120, Common::String(line1.c_str() + line1.findLastOf('.') + 1));
+ setTextColor(oldColor);
+ oldColor = setTextColor(_hoverChoice == CHOICE_VIEW ? 15 : 0);
writeString(110, 130, Common::String(line2.c_str() + line2.findLastOf('.') + 1));
+ setTextColor(oldColor);
+ oldColor = setTextColor(_hoverChoice == CHOICE_TOWN ? 15 : 0);
writeString(110, 140, line32);
+ setTextColor(oldColor);
writeString(0, 165, STRING["dialogs.main_menu.copyright1"], ALIGN_MIDDLE);
writeString(0, 175, STRING["dialogs.main_menu.scummvm"], ALIGN_MIDDLE);
}
+MainMenu::Choice MainMenu::getChoiceAt(const Common::Point &pos) {
+ const int height = g_globals->_fontNormal.getFontHeight();
+ const Common::String line1 = STRING["dialogs.main_menu.option1"];
+ const Common::String line2 = STRING["dialogs.main_menu.option2"];
+ const Common::String line32 = STRING["dialogs.main_menu.option3e2"];
+ const Common::String create = Common::String(line1.c_str() + line1.findLastOf('.') + 1);
+ const Common::String view = Common::String(line2.c_str() + line2.findLastOf('.') + 1);
+
+ Common::Rect createBounds(110, 120, 110 + getStringWidth(create), 120 + height);
+ Common::Rect viewBounds(110, 130, 110 + getStringWidth(view), 130 + height);
+ Common::Rect townBounds(110, 140, 110 + getStringWidth(line32), 140 + height);
+ createBounds.translate(_innerBounds.left, _innerBounds.top);
+ viewBounds.translate(_innerBounds.left, _innerBounds.top);
+ townBounds.translate(_innerBounds.left, _innerBounds.top);
+
+ if (createBounds.contains(pos))
+ return CHOICE_CREATE;
+ if (viewBounds.contains(pos))
+ return CHOICE_VIEW;
+ if (townBounds.contains(pos))
+ return CHOICE_TOWN;
+
+ return CHOICE_NONE;
+}
+
+bool MainMenu::msgFocus(const FocusMessage &msg) {
+ _hoverChoice = CHOICE_NONE;
+ return ScrollView::msgFocus(msg);
+}
+
bool MainMenu::msgKeypress(const KeypressMessage &msg) {
switch (msg.keycode) {
case Common::KEYCODE_c:
@@ -158,11 +195,52 @@ bool MainMenu::msgKeypress(const KeypressMessage &msg) {
}
-bool msgAction(const ActionMessage &msg) {
- if (msg._action == KEYBIND_SELECT) {
+bool MainMenu::msgMouseMove(const MouseMoveMessage &msg) {
+ Choice choice = getChoiceAt(msg._pos);
+ if (choice != _hoverChoice) {
+ _hoverChoice = choice;
+ redraw();
+ }
+
+ return true;
+}
+
+bool MainMenu::msgMouseDown(const MouseDownMessage &msg) {
+ return msg._button == MouseMessage::MB_LEFT && getChoiceAt(msg._pos) != CHOICE_NONE;
+}
+
+bool MainMenu::msgMouseUp(const MouseUpMessage &msg) {
+ if (msg._button != MouseMessage::MB_LEFT)
+ return false;
+
+ Choice choice = getChoiceAt(msg._pos);
+ _hoverChoice = CHOICE_NONE;
+
+ switch (choice) {
+ case CHOICE_CREATE:
+ addView("CreateCharacters");
+ break;
+ case CHOICE_VIEW:
+ addView("Characters");
+ break;
+ case CHOICE_TOWN:
+ addView("TownSelect");
+ break;
+ default:
+ break;
+ }
+
+ return choice != CHOICE_NONE;
+}
+
+bool MainMenu::msgGame(const GameMessage &msg) {
+ if (msg._name == "START_TOWN") {
+ g_globals->_startingTown = (Maps::TownId)msg._value;
+ replaceView("Inn");
+ return true;
}
- return false;
+ return ScrollView::msgGame(msg);
}
} // namespace ViewsEnh
diff --git a/engines/mm/mm1/views_enh/main_menu.h b/engines/mm/mm1/views_enh/main_menu.h
index 1e17e7e84d3..7ed776e85b6 100644
--- a/engines/mm/mm1/views_enh/main_menu.h
+++ b/engines/mm/mm1/views_enh/main_menu.h
@@ -29,8 +29,15 @@ namespace MM1 {
namespace ViewsEnh {
class MainMenu : public ScrollView {
+ enum Choice {
+ CHOICE_NONE,
+ CHOICE_CREATE,
+ CHOICE_VIEW,
+ CHOICE_TOWN
+ };
private:
Graphics::ManagedSurface _circles[2];
+ Choice _hoverChoice = CHOICE_NONE;
/**
* Draws the two circles from the original game screens
@@ -48,11 +55,21 @@ private:
void drawCircleLine(const Graphics::Surface *src,
Graphics::ManagedSurface *dest, int x, int y);
+ /**
+ * Gets the choice at the given mouse position
+ */
+ Choice getChoiceAt(const Common::Point &pos);
+
public:
MainMenu() : ScrollView("MainMenu") {}
virtual ~MainMenu() {}
+ bool msgFocus(const FocusMessage &msg) override;
bool msgKeypress(const KeypressMessage &msg) override;
+ bool msgMouseMove(const MouseMoveMessage &msg) override;
+ bool msgMouseDown(const MouseDownMessage &msg) override;
+ bool msgMouseUp(const MouseUpMessage &msg) override;
+ bool msgGame(const GameMessage &msg) override;
void draw() override;
};
diff --git a/engines/mm/mm1/views_enh/scroll_view.h b/engines/mm/mm1/views_enh/scroll_view.h
index ec1aaf4748f..c8d6f09e03d 100644
--- a/engines/mm/mm1/views_enh/scroll_view.h
+++ b/engines/mm/mm1/views_enh/scroll_view.h
@@ -75,8 +75,8 @@ class ScrollView : public TextView {
};
private:
Common::Array<Button> _buttons;
- int _selectedButton = -1;
protected:
+ int _selectedButton = -1;
Common::Point _symbolPos;
protected:
/**
diff --git a/engines/mm/mm1/views_enh/town_select.cpp b/engines/mm/mm1/views_enh/town_select.cpp
new file mode 100644
index 00000000000..828e709cd0d
--- /dev/null
+++ b/engines/mm/mm1/views_enh/town_select.cpp
@@ -0,0 +1,112 @@
+/* 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/town_select.h"
+#include "mm/mm1/globals.h"
+
+namespace MM {
+namespace MM1 {
+namespace ViewsEnh {
+
+static const int BTN_SIZE = 10;
+static const int BTN_X = 14;
+static const int TEXT_X = BTN_X + BTN_SIZE + 5;
+
+TownSelect::TownSelect() : ScrollView("TownSelect") {
+ _bounds = Common::Rect(87, 49, 233, 155);
+ _bounds.setBorderSize(10);
+
+ for (int i = 1; i <= 5; ++i) {
+ int row = i - 1;
+ int y = 22 + row * 12;
+ Common::String text = STRING[Common::String::format("stats.towns.%d", i)];
+ addButton(Common::Rect(BTN_X, y, TEXT_X + (int)getStringWidth(text),
+ y + BTN_SIZE),
+ (Common::KeyCode)(Common::KEYCODE_0 + i));
+ }
+}
+
+void TownSelect::draw() {
+ ScrollView::draw();
+ Graphics::ManagedSurface s = getSurface();
+ setReduced(false);
+ writeString(0, 0, STRING["spells.which_town"], ALIGN_MIDDLE);
+
+ Graphics::ManagedSurface btnSmall(BTN_SIZE, BTN_SIZE);
+ btnSmall.blitFrom(g_globals->_blankButton, Common::Rect(0, 0, 20, 20),
+ Common::Rect(0, 0, BTN_SIZE, BTN_SIZE));
+
+ for (int i = 1; i <= 5; ++i) {
+ int y = 22 + (i - 1) * 12;
+ s.blitFrom(btnSmall, Common::Point(BTN_X + _bounds.borderSize() + 1,
+ y + _bounds.borderSize() - 1));
+
+ writeString(BTN_X + (BTN_SIZE / 2) + 1, y,
+ Common::String::format("%d", i), ALIGN_MIDDLE);
+
+ byte oldColor = setTextColor(i == _selectedButton + 1 ? 15 : 0);
+ writeString(TEXT_X, y, STRING[Common::String::format("stats.towns.%d", i)]);
+ setTextColor(oldColor);
+ }
+}
+
+bool TownSelect::msgKeypress(const KeypressMessage &msg) {
+ if (msg.keycode >= Common::KEYCODE_1 && msg.keycode <= Common::KEYCODE_5) {
+ g_globals->_startingTown = (Maps::TownId)(msg.keycode - Common::KEYCODE_0);
+ close();
+ send("MainMenu", GameMessage("START_TOWN", (int)g_globals->_startingTown));
+ return true;
+ }
+
+ return ScrollView::msgKeypress(msg);
+}
+
+bool TownSelect::msgMouseMove(const MouseMoveMessage &msg) {
+ int selectedButton = getButtonAt(msg._pos);
+ if (selectedButton != _selectedButton) {
+ _selectedButton = selectedButton;
+ redraw();
+ }
+
+ return true;
+}
+
+bool TownSelect::msgMouseDown(const MouseDownMessage &msg) {
+ if (msg._button == MouseMessage::MB_RIGHT || !getBounds().contains(msg._pos)) {
+ msgAction(ActionMessage(KEYBIND_ESCAPE));
+ return true;
+ }
+
+ return ScrollView::msgMouseDown(msg);
+}
+
+bool TownSelect::msgAction(const ActionMessage &msg) {
+ if (msg._action == KEYBIND_ESCAPE) {
+ close();
+ return true;
+ }
+
+ return ScrollView::msgAction(msg);
+}
+
+} // namespace ViewsEnh
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views_enh/town_select.h b/engines/mm/mm1/views_enh/town_select.h
new file mode 100644
index 00000000000..571e57ccd5c
--- /dev/null
+++ b/engines/mm/mm1/views_enh/town_select.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_VIEWS_ENH_TOWN_SELECT_H
+#define MM1_VIEWS_ENH_TOWN_SELECT_H
+
+#include "mm/mm1/views_enh/scroll_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace ViewsEnh {
+
+class TownSelect : public ScrollView {
+public:
+ TownSelect();
+ virtual ~TownSelect() {}
+
+ void draw() override;
+ bool msgAction(const ActionMessage &msg) override;
+ bool msgKeypress(const KeypressMessage &msg) override;
+ bool msgMouseMove(const MouseMoveMessage &msg) override;
+ bool msgMouseDown(const MouseDownMessage &msg) override;
+};
+
+} // namespace ViewsEnh
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index b2b87fbf723..5f69cbaaaf4 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -182,6 +182,7 @@ MODULE_OBJS += \
mm1/views_enh/text_entry.o \
mm1/views_enh/text_view.o \
mm1/views_enh/title.o \
+ mm1/views_enh/town_select.o \
mm1/views_enh/trade.o \
mm1/views_enh/trap.o \
mm1/views_enh/unlock.o \
Commit: 9c97218760d04dc54eb81e94a4985fde41ba8d01
https://github.com/scummvm/scummvm/commit/9c97218760d04dc54eb81e94a4985fde41ba8d01
Author: Scorp (scorp at mrs.mn)
Date: 2026-05-02T21:01:57+10:00
Commit Message:
MM: MM1: UI enhancements and improved mouse support for enhanced views
Implement string truncation for character names across various enhanced views to prevent overflow. Improve camelCase utility to correctly handle Roman numerals (Zenon III is not Zenon Iii anymore).
Add right-click support to many views (Title, ScrollView, CharacterView, etc.) to act as an Escape/Back action.
Enhance location views:
- Blacksmith: Add graphical Browse button.
- Tavern: Add graphical buttons for all actions and improve layout.
- Temple: Add interactive numbered buttons for services and display costs.
Refine mouse interaction in Combat, GameMessages, and Dead views. Dynamically calculate TextEntry bounds for better fit.
Changed paths:
engines/mm/mm1/views_enh/character_base.cpp
engines/mm/mm1/views_enh/character_info.cpp
engines/mm/mm1/views_enh/character_manage.cpp
engines/mm/mm1/views_enh/character_manage.h
engines/mm/mm1/views_enh/character_view.cpp
engines/mm/mm1/views_enh/character_view.h
engines/mm/mm1/views_enh/characters.cpp
engines/mm/mm1/views_enh/combat.cpp
engines/mm/mm1/views_enh/create_characters.cpp
engines/mm/mm1/views_enh/dead.cpp
engines/mm/mm1/views_enh/dead.h
engines/mm/mm1/views_enh/game_messages.cpp
engines/mm/mm1/views_enh/locations/blacksmith.cpp
engines/mm/mm1/views_enh/locations/blacksmith.h
engines/mm/mm1/views_enh/locations/inn.cpp
engines/mm/mm1/views_enh/locations/tavern.cpp
engines/mm/mm1/views_enh/locations/tavern.h
engines/mm/mm1/views_enh/locations/temple.cpp
engines/mm/mm1/views_enh/locations/temple.h
engines/mm/mm1/views_enh/quick_ref.cpp
engines/mm/mm1/views_enh/scroll_view.cpp
engines/mm/mm1/views_enh/spells/cast_spell.cpp
engines/mm/mm1/views_enh/spells/spellbook.cpp
engines/mm/mm1/views_enh/text_entry.cpp
engines/mm/mm1/views_enh/text_view.cpp
engines/mm/mm1/views_enh/text_view.h
engines/mm/mm1/views_enh/title.cpp
engines/mm/mm1/views_enh/title.h
engines/mm/mm1/views_enh/wheel_spin.cpp
engines/mm/shared/utils/strings.cpp
diff --git a/engines/mm/mm1/views_enh/character_base.cpp b/engines/mm/mm1/views_enh/character_base.cpp
index aef1ab0d744..eed6178533a 100644
--- a/engines/mm/mm1/views_enh/character_base.cpp
+++ b/engines/mm/mm1/views_enh/character_base.cpp
@@ -87,28 +87,27 @@ void CharacterBase::printStats() {
void CharacterBase::printSummary() {
const Character &c = *g_globals->_currCharacter;
- writeString(35, LINE1_Y, c._name);
-
- writeString(120, LINE1_Y, ": ");
-
- writeString((c._sex == MALE) ? "M " : (c._sex == FEMALE ? "F " : "O "));
-
- writeString((c._alignment >= GOOD && c._alignment <= EVIL) ?
+ Common::String suffix = Common::String::format(": %s %s ",
+ STRING[Common::String::format("stats.sex.%d", c._sex)].c_str(),
+ ((c._alignment >= GOOD && c._alignment <= EVIL) ?
STRING[Common::String::format("stats.alignments.%d", c._alignment)] :
- STRING["stats.none"]
+ STRING["stats.none"]).c_str()
);
- writeChar(' ');
if (c._race >= HUMAN && c._race <= HALF_ORC)
- writeString(STRING[Common::String::format("stats.races.%d", c._race)]);
+ suffix += STRING[Common::String::format("stats.races.%d", c._race)];
else
- writeString(STRING["stats.none"]);
- writeChar(' ');
+ suffix += STRING["stats.none"];
+ suffix += ' ';
if (c._class >= KNIGHT && c._class <= ROBBER)
- writeString(STRING[Common::String::format("stats.classes.%d", c._class)]);
+ suffix += STRING[Common::String::format("stats.classes.%d", c._class)];
else
- writeString(STRING["stats.none"]);
+ suffix += STRING["stats.none"];
+
+ writeString(35, LINE1_Y, truncateString(c._name,
+ _innerBounds.width() - 35 - (int)getStringWidth(suffix)));
+ writeString(suffix);
}
void CharacterBase::printCondition() {
diff --git a/engines/mm/mm1/views_enh/character_info.cpp b/engines/mm/mm1/views_enh/character_info.cpp
index 6722afb0023..59ce2792a35 100644
--- a/engines/mm/mm1/views_enh/character_info.cpp
+++ b/engines/mm/mm1/views_enh/character_info.cpp
@@ -179,6 +179,12 @@ bool CharacterInfo::msgAction(const ActionMessage &msg) {
}
bool CharacterInfo::msgMouseUp(const MouseUpMessage &msg) {
+ if (msg._button == MouseMessage::MB_RIGHT)
+ return true;
+
+ if (msg._button != MouseMessage::MB_LEFT)
+ return PartyView::msgMouseUp(msg);
+
// Check if a stat icon was clicked
Common::Rect r(25, 22);
for (int i = 0; i < CHAR_ICONS_COUNT; ++i) {
@@ -220,14 +226,21 @@ void CharacterInfo::draw() {
void CharacterInfo::drawTitle() {
const Character &c = *g_globals->_currCharacter;
- Common::String msg = Common::String::format(
- "%s : %s %s %s %s",
- camelCase(c._name).c_str(),
- STRING[Common::String::format("stats.sex.%d", (int)c._sex)].c_str(),
+ const char *sex = (c._sex == MALE) ? "M" : (c._sex == FEMALE ? "F" : "O");
+ Common::String suffix = Common::String::format(
+ " : %s %s %s %s",
+ sex,
STRING[Common::String::format("stats.alignments.%d", (int)c._alignment)].c_str(),
STRING[Common::String::format("stats.races.%d", (int)c._race)].c_str(),
STRING[Common::String::format("stats.classes.%d", (int)c._class)].c_str()
);
+ Common::String name = truncateString(camelCase(c._name),
+ 269 - (int)getStringWidth(suffix));
+ Common::String msg = Common::String::format(
+ "%s%s",
+ name.c_str(),
+ suffix.c_str()
+ );
writeString(0, 0, msg);
}
diff --git a/engines/mm/mm1/views_enh/character_manage.cpp b/engines/mm/mm1/views_enh/character_manage.cpp
index b9f376ef498..b5849dec6e5 100644
--- a/engines/mm/mm1/views_enh/character_manage.cpp
+++ b/engines/mm/mm1/views_enh/character_manage.cpp
@@ -20,6 +20,7 @@
*/
#include "mm/mm1/views_enh/character_manage.h"
+#include "mm/shared/utils/strings.h"
#include "mm/mm1/utils/strings.h"
#include "mm/mm1/globals.h"
@@ -62,7 +63,7 @@ void CharacterManage::abortFunc() {
void CharacterManage::enterFunc(const Common::String &name) {
CharacterManage *view = static_cast<CharacterManage *>(g_events->focusedView());
- view->setName(name);
+ view->setName(camelCase(name));
}
void CharacterManage::draw() {
@@ -187,6 +188,18 @@ bool CharacterManage::msgMouseMove(const MouseMoveMessage &msg) {
return true;
}
+bool CharacterManage::msgMouseUp(const MouseUpMessage &msg) {
+ if (msg._button == MouseMessage::MB_RIGHT && _state == DISPLAY) {
+ const Common::Rect portrait(_innerBounds.left, _innerBounds.top,
+ _innerBounds.left + 30, _innerBounds.top + 30);
+
+ if (portrait.contains(msg._pos) || getButtonAt(msg._pos) == 0)
+ return true;
+ }
+
+ return CharacterBase::msgMouseUp(msg);
+}
+
void CharacterManage::setName(const Common::String &newName) {
Character &c = *g_globals->_currCharacter;
Common::strcpy_s(c._name, newName.c_str());
diff --git a/engines/mm/mm1/views_enh/character_manage.h b/engines/mm/mm1/views_enh/character_manage.h
index 344a55ffdb6..d7b4ea70328 100644
--- a/engines/mm/mm1/views_enh/character_manage.h
+++ b/engines/mm/mm1/views_enh/character_manage.h
@@ -62,6 +62,7 @@ public:
bool msgKeypress(const KeypressMessage &msg) override;
bool msgAction(const ActionMessage &msg) override;
bool msgMouseMove(const MouseMoveMessage &msg) override;
+ bool msgMouseUp(const MouseUpMessage &msg) override;
};
diff --git a/engines/mm/mm1/views_enh/character_view.cpp b/engines/mm/mm1/views_enh/character_view.cpp
index d8fa83dd338..396aa1399b4 100644
--- a/engines/mm/mm1/views_enh/character_view.cpp
+++ b/engines/mm/mm1/views_enh/character_view.cpp
@@ -36,6 +36,13 @@ void CharacterView::draw() {
writeString(120, 174, STRING["dialogs.misc.go_back"]);
}
+bool CharacterView::msgMouseUp(const MouseUpMessage &msg) {
+ if (msg._button == MouseMessage::MB_RIGHT)
+ return true;
+
+ return CharacterBase::msgMouseUp(msg);
+}
+
} // namespace ViewsEnh
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views_enh/character_view.h b/engines/mm/mm1/views_enh/character_view.h
index ecb920980f3..61666322f46 100644
--- a/engines/mm/mm1/views_enh/character_view.h
+++ b/engines/mm/mm1/views_enh/character_view.h
@@ -41,6 +41,7 @@ public:
* Draw the view
*/
void draw() override;
+ bool msgMouseUp(const MouseUpMessage &msg) override;
};
} // namespace Views
diff --git a/engines/mm/mm1/views_enh/characters.cpp b/engines/mm/mm1/views_enh/characters.cpp
index 7b80659a819..6b16dc4e085 100644
--- a/engines/mm/mm1/views_enh/characters.cpp
+++ b/engines/mm/mm1/views_enh/characters.cpp
@@ -67,7 +67,9 @@ void Characters::draw() {
s.blitFrom(portrait, Common::Rect(0, 0, 30, 30),
Common::Rect(pt.x + 2, pt.y + 2, pt.x + 17, pt.y + 17));
- writeString(pt.x - _innerBounds.left + 22, pt.y - _innerBounds.top + 5, c._name);
+ Common::String name = truncateString(c._name, _innerBounds.width() / 3 - 22);
+
+ writeString(pt.x - _innerBounds.left + 22, pt.y - _innerBounds.top + 5, name);
}
setReduced(false);
diff --git a/engines/mm/mm1/views_enh/combat.cpp b/engines/mm/mm1/views_enh/combat.cpp
index 0282a696369..c877e5b1970 100644
--- a/engines/mm/mm1/views_enh/combat.cpp
+++ b/engines/mm/mm1/views_enh/combat.cpp
@@ -374,6 +374,9 @@ bool Combat::msgAction(const ActionMessage &msg) {
}
bool Combat::msgMouseUp(const MouseUpMessage &msg) {
+ if (msg._button != MouseMessage::MB_LEFT)
+ return ScrollView::msgMouseUp(msg);
+
const KeybindingAction BTN_ACTIONS[8] = {
KEYBIND_COMBAT_ATTACK, KEYBIND_COMBAT_FIGHT,
KEYBIND_COMBAT_RETREAT, KEYBIND_COMBAT_EXCHANGE,
diff --git a/engines/mm/mm1/views_enh/create_characters.cpp b/engines/mm/mm1/views_enh/create_characters.cpp
index d320769fd26..73c8656c087 100644
--- a/engines/mm/mm1/views_enh/create_characters.cpp
+++ b/engines/mm/mm1/views_enh/create_characters.cpp
@@ -20,6 +20,7 @@
*/
#include "mm/mm1/views_enh/create_characters.h"
+#include "mm/shared/utils/strings.h"
#include "mm/mm1/globals.h"
#include "mm/mm1/mm1.h"
@@ -591,7 +592,7 @@ void CreateCharacters::abortFunc() {
void CreateCharacters::enterFunc(const Common::String &name) {
CreateCharacters *view = static_cast<CreateCharacters *>(g_events->focusedView());
- view->_newChar._name = name;
+ view->_newChar._name = camelCase(name);
view->setState(SAVE_PROMPT);
}
diff --git a/engines/mm/mm1/views_enh/dead.cpp b/engines/mm/mm1/views_enh/dead.cpp
index f910805eecd..68bbd2a96b3 100644
--- a/engines/mm/mm1/views_enh/dead.cpp
+++ b/engines/mm/mm1/views_enh/dead.cpp
@@ -63,6 +63,15 @@ bool Dead::msgAction(const ActionMessage &msg) {
return false;
}
+bool Dead::msgMouseUp(const MouseUpMessage &msg) {
+ if (msg._button == MouseMessage::MB_LEFT || msg._button == MouseMessage::MB_RIGHT) {
+ msgAction(ActionMessage(KEYBIND_SELECT));
+ return true;
+ }
+
+ return false;
+}
+
} // namespace Views
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views_enh/dead.h b/engines/mm/mm1/views_enh/dead.h
index f322ace2a6e..139f27e7c13 100644
--- a/engines/mm/mm1/views_enh/dead.h
+++ b/engines/mm/mm1/views_enh/dead.h
@@ -36,6 +36,7 @@ public:
bool msgFocus(const FocusMessage &msg) override;
void draw() override;
bool msgAction(const ActionMessage &msg) override;
+ bool msgMouseUp(const MouseUpMessage &msg) override;
};
} // namespace ViewsEnh
diff --git a/engines/mm/mm1/views_enh/game_messages.cpp b/engines/mm/mm1/views_enh/game_messages.cpp
index 6edf40366ae..5a65789acd1 100644
--- a/engines/mm/mm1/views_enh/game_messages.cpp
+++ b/engines/mm/mm1/views_enh/game_messages.cpp
@@ -157,7 +157,8 @@ bool GameMessages::msgMouseDown(const MouseDownMessage &msg) {
if (_callback)
return send("MessagesYesNo", msg);
- return msgAction(KeybindingAction(KEYBIND_SELECT));
+ return msgAction(ActionMessage(msg._button == MouseMessage::MB_RIGHT ?
+ KEYBIND_ESCAPE : KEYBIND_SELECT));
}
bool GameMessages::msgMouseUp(const MouseUpMessage &msg) {
diff --git a/engines/mm/mm1/views_enh/locations/blacksmith.cpp b/engines/mm/mm1/views_enh/locations/blacksmith.cpp
index 7006c26f420..c638016c079 100644
--- a/engines/mm/mm1/views_enh/locations/blacksmith.cpp
+++ b/engines/mm/mm1/views_enh/locations/blacksmith.cpp
@@ -30,6 +30,8 @@ namespace ViewsEnh {
namespace Locations {
Blacksmith::Blacksmith() : Location("Blacksmith", LOC_BLACKSMITH) {
+ _browseSprite.load("buy.icn");
+ addButton(&_browseSprite, Common::Point(7, 52), 0, Common::KEYCODE_b, true);
addButton(&g_globals->_escSprites, Common::Point(24, 100), 0, KEYBIND_ESCAPE);
}
@@ -43,7 +45,7 @@ void Blacksmith::draw() {
writeLine(1, STRING["enhdialogs.location.options_for"], ALIGN_MIDDLE);
writeLine(3, c._name, ALIGN_MIDDLE);
- writeLine(5, STRING["enhdialogs.blacksmith.browse"], ALIGN_LEFT, 10);
+ writeLine(6, STRING["enhdialogs.blacksmith.browse"], ALIGN_LEFT, 23);
writeLine(10, STRING["enhdialogs.location.gold"]);
writeLine(10, Common::String::format("%d",
diff --git a/engines/mm/mm1/views_enh/locations/blacksmith.h b/engines/mm/mm1/views_enh/locations/blacksmith.h
index 940ed520b27..99e0d8a087c 100644
--- a/engines/mm/mm1/views_enh/locations/blacksmith.h
+++ b/engines/mm/mm1/views_enh/locations/blacksmith.h
@@ -31,6 +31,8 @@ namespace ViewsEnh {
namespace Locations {
class Blacksmith : public Location {
+private:
+ Shared::Xeen::SpriteResource _browseSprite;
public:
Blacksmith();
diff --git a/engines/mm/mm1/views_enh/locations/inn.cpp b/engines/mm/mm1/views_enh/locations/inn.cpp
index 34a73e359b5..7a77f5cc9b4 100644
--- a/engines/mm/mm1/views_enh/locations/inn.cpp
+++ b/engines/mm/mm1/views_enh/locations/inn.cpp
@@ -115,7 +115,9 @@ void Inn::draw() {
if (isInParty)
s.frameRect(Common::Rect(pt.x, pt.y, pt.x + 19, pt.y + 19), 37);
- writeString(pt.x - _innerBounds.left + 22, pt.y - _innerBounds.top + 5, c._name);
+ Common::String name = truncateString(c._name, _innerBounds.width() / 3 - 22);
+
+ writeString(pt.x - _innerBounds.left + 22, pt.y - _innerBounds.top + 5, name);
}
setReduced(false);
diff --git a/engines/mm/mm1/views_enh/locations/tavern.cpp b/engines/mm/mm1/views_enh/locations/tavern.cpp
index b501263865f..b4690de12c8 100644
--- a/engines/mm/mm1/views_enh/locations/tavern.cpp
+++ b/engines/mm/mm1/views_enh/locations/tavern.cpp
@@ -30,6 +30,11 @@ namespace ViewsEnh {
namespace Locations {
Tavern::Tavern() : Location("Tavern", LOC_TAVERN) {
+ _btnSprites.load("buy.icn");
+ addButton(&_btnSprites, Common::Point(2, 45), 0, Common::KEYCODE_d, true);
+ addButton(&_btnSprites, Common::Point(2, 56), 2, Common::KEYCODE_g, true);
+ addButton(&_btnSprites, Common::Point(2, 67), 6, Common::KEYCODE_t, true);
+ addButton(&_btnSprites, Common::Point(2, 78), 10, Common::KEYCODE_r, true);
addButton(&_escSprite, Common::Point(24, 100), 0, KEYBIND_ESCAPE);
}
@@ -40,12 +45,12 @@ void Tavern::draw() {
setReduced(false);
writeLine(0, STRING["enhdialogs.tavern.title"], ALIGN_MIDDLE);
writeLine(1, STRING["enhdialogs.location.options_for"], ALIGN_MIDDLE);
- writeLine(3, c._name, ALIGN_MIDDLE);
+ writeString(0, 23, c._name, ALIGN_MIDDLE);
- writeLine(5, STRING["enhdialogs.tavern.drink"], ALIGN_LEFT, 10);
- writeLine(6, STRING["enhdialogs.tavern.gather"], ALIGN_LEFT, 10);
- writeLine(7, STRING["enhdialogs.tavern.tip"], ALIGN_LEFT, 10);
- writeLine(8, STRING["enhdialogs.tavern.rumor"], ALIGN_LEFT, 10);
+ writeString(18, 46, STRING["enhdialogs.tavern.drink"]);
+ writeString(18, 57, STRING["enhdialogs.tavern.gather"]);
+ writeString(18, 68, STRING["enhdialogs.tavern.tip"]);
+ writeString(18, 79, STRING["enhdialogs.tavern.rumor"]);
writeLine(10, STRING["enhdialogs.location.gold"]);
writeLine(10, Common::String::format("%d",
diff --git a/engines/mm/mm1/views_enh/locations/tavern.h b/engines/mm/mm1/views_enh/locations/tavern.h
index 8525a2c18a0..6ae82b9e2df 100644
--- a/engines/mm/mm1/views_enh/locations/tavern.h
+++ b/engines/mm/mm1/views_enh/locations/tavern.h
@@ -32,6 +32,7 @@ namespace Locations {
class Tavern : public Location {
private:
+ Shared::Xeen::SpriteResource _btnSprites;
/**
* Have a drink
*/
diff --git a/engines/mm/mm1/views_enh/locations/temple.cpp b/engines/mm/mm1/views_enh/locations/temple.cpp
index 28ddce5d336..1bf067e08e3 100644
--- a/engines/mm/mm1/views_enh/locations/temple.cpp
+++ b/engines/mm/mm1/views_enh/locations/temple.cpp
@@ -30,7 +30,34 @@ namespace MM1 {
namespace ViewsEnh {
namespace Locations {
+static const int BTN_SIZE = 10;
+static const int OPTION_X = 0;
+static const int OPTION_Y = 45;
+static const int OPTION_SPACING = 11;
+static const int OPTION_TEXT_X = OPTION_X + BTN_SIZE;
+
+static Common::Rect getOptionButtonRect(int row) {
+ const int y = OPTION_Y + OPTION_SPACING * row;
+ return Common::Rect(OPTION_X, y, OPTION_X + BTN_SIZE, y + BTN_SIZE);
+}
+
+static Common::String getOptionText(const Common::String &text) {
+ const char *s = text.c_str();
+
+ // Option strings highlight their hotkey as "\x01NNx".
+ if (*s == '\x01' && s[1] && s[2] && s[3])
+ return Common::String(s + 4);
+ if (*s)
+ return Common::String(s + 1);
+
+ return text;
+}
+
Temple::Temple() : Location("Temple", LOC_TEMPLE) {
+ addButton(getOptionButtonRect(0), Common::KEYCODE_h);
+ addButton(getOptionButtonRect(1), Common::KEYCODE_u);
+ addButton(getOptionButtonRect(2), Common::KEYCODE_r);
+ addButton(getOptionButtonRect(3), Common::KEYCODE_d);
addButton(&_escSprite, Common::Point(24, 100), 0, KEYBIND_ESCAPE);
}
@@ -47,25 +74,17 @@ void Temple::draw() {
setReduced(false);
writeLine(0, STRING["enhdialogs.temple.title"], ALIGN_MIDDLE);
writeLine(1, STRING["enhdialogs.location.options_for"], ALIGN_MIDDLE);
- writeLine(3, camelCase(g_globals->_currCharacter->_name), ALIGN_MIDDLE);
+ writeString(0, 23, camelCase(g_globals->_currCharacter->_name), ALIGN_MIDDLE);
setReduced(true);
- writeLine(5, STRING["enhdialogs.temple.heal"]);
- writeLine(6, STRING["enhdialogs.temple.uncurse"]);
- writeLine(7, STRING["enhdialogs.temple.realign"]);
- writeLine(8, STRING["enhdialogs.temple.donate"]);
-
- writeLine(5, _healCost ?
- Common::String::format("%d", _healCost).c_str() : "----",
- ALIGN_RIGHT);
- writeLine(6, _uncurseCost ?
- Common::String::format("%d", _uncurseCost).c_str() : "----",
- ALIGN_RIGHT);
- writeLine(7, _alignmentCost ?
- Common::String::format("%d", _alignmentCost).c_str() : "----",
- ALIGN_RIGHT);
- writeLine(8, Common::String::format("%d", _donateCost).c_str(),
- ALIGN_RIGHT);
+ writeOption(0, 'H', STRING["enhdialogs.temple.heal"],
+ _healCost ? Common::String::format("%d", _healCost) : "----");
+ writeOption(1, 'U', STRING["enhdialogs.temple.uncurse"],
+ _uncurseCost ? Common::String::format("%d", _uncurseCost) : "----");
+ writeOption(2, 'R', STRING["enhdialogs.temple.realign"],
+ _alignmentCost ? Common::String::format("%d", _alignmentCost) : "----");
+ writeOption(3, 'D', STRING["enhdialogs.temple.donate"],
+ Common::String::format("%d", _donateCost));
setReduced(false);
writeLine(10, STRING["enhdialogs.location.gold"]);
@@ -76,6 +95,25 @@ void Temple::draw() {
writeString(27, 122, STRING["enhdialogs.location.esc"]);
}
+void Temple::writeOption(int row, char c, const Common::String &text,
+ const Common::String &cost) {
+ const int y = OPTION_Y + OPTION_SPACING * row;
+ const int textY = y + (BTN_SIZE - 8) / 2 + 1;
+
+ Graphics::ManagedSurface btnSmall(BTN_SIZE, BTN_SIZE);
+ btnSmall.blitFrom(g_globals->_blankButton, Common::Rect(0, 0, 20, 20),
+ Common::Rect(0, 0, BTN_SIZE, BTN_SIZE));
+
+ Graphics::ManagedSurface s = getSurface();
+ s.blitFrom(btnSmall, Common::Point(OPTION_X + _bounds.borderSize(),
+ y + _bounds.borderSize()));
+
+ writeString(OPTION_X + (BTN_SIZE / 2) + 1, textY,
+ Common::String::format("%c", c), ALIGN_MIDDLE);
+ writeString(OPTION_TEXT_X, textY, getOptionText(text));
+ writeString(0, textY, cost, ALIGN_RIGHT);
+}
+
bool Temple::msgKeypress(const KeypressMessage &msg) {
switch (msg.keycode) {
case Common::KEYCODE_h:
diff --git a/engines/mm/mm1/views_enh/locations/temple.h b/engines/mm/mm1/views_enh/locations/temple.h
index 62799ae8c08..3f1e9bf60ee 100644
--- a/engines/mm/mm1/views_enh/locations/temple.h
+++ b/engines/mm/mm1/views_enh/locations/temple.h
@@ -38,6 +38,7 @@ private:
int _alignmentCost = 0, _donateCost = 0;
private:
void updateCosts();
+ void writeOption(int row, char c, const Common::String &text, const Common::String &cost);
void restoreHealth();
void uncurseItems();
void restoreAlignment();
diff --git a/engines/mm/mm1/views_enh/quick_ref.cpp b/engines/mm/mm1/views_enh/quick_ref.cpp
index 03e6f4d0eb2..a2f40202fce 100644
--- a/engines/mm/mm1/views_enh/quick_ref.cpp
+++ b/engines/mm/mm1/views_enh/quick_ref.cpp
@@ -29,9 +29,9 @@ namespace MM1 {
namespace ViewsEnh {
#define COLUMN_NUM 5
-#define COLUMN_NAME 30
-#define COLUMN_CLASS 113
-#define COLUMN_LEVEL 157
+#define COLUMN_NAME 22
+#define COLUMN_CLASS 117
+#define COLUMN_LEVEL 162
#define COLUMN_HP 175
#define COLUMN_SP 211
#define COLUMN_AC 245
@@ -81,7 +81,7 @@ void QuickRef::writeCharacterLine(int charNum) {
writeChar(COLUMN_NUM, yp, '1' + charNum);
writeChar(')');
- writeString(COLUMN_NAME, yp, c._name);
+ writeString(COLUMN_NAME, yp, truncateString(c._name, COLUMN_CLASS - COLUMN_NAME - 3));
Common::String classStr = STRING[Common::String::format(
"stats.classes.%d", c._class)];
diff --git a/engines/mm/mm1/views_enh/scroll_view.cpp b/engines/mm/mm1/views_enh/scroll_view.cpp
index 1788e2518b9..2349e4480bc 100644
--- a/engines/mm/mm1/views_enh/scroll_view.cpp
+++ b/engines/mm/mm1/views_enh/scroll_view.cpp
@@ -182,6 +182,11 @@ bool ScrollView::msgFocus(const FocusMessage &msg) {
}
bool ScrollView::msgMouseDown(const MouseDownMessage &msg) {
+ if (msg._button == MouseMessage::MB_RIGHT) {
+ _selectedButton = -1;
+ return true;
+ }
+
_selectedButton = getButtonAt(msg._pos);
if (_selectedButton != -1) {
draw();
@@ -192,6 +197,15 @@ bool ScrollView::msgMouseDown(const MouseDownMessage &msg) {
}
bool ScrollView::msgMouseUp(const MouseUpMessage &msg) {
+ if (msg._button == MouseMessage::MB_RIGHT) {
+ int oldSelection = _selectedButton;
+ _selectedButton = -1;
+ if (oldSelection != -1)
+ draw();
+
+ return msgAction(ActionMessage(KEYBIND_ESCAPE));
+ }
+
int oldSelection = _selectedButton;
_selectedButton = -1;
if (oldSelection != -1)
diff --git a/engines/mm/mm1/views_enh/spells/cast_spell.cpp b/engines/mm/mm1/views_enh/spells/cast_spell.cpp
index 18d23fe97dd..a99e8ccee2c 100644
--- a/engines/mm/mm1/views_enh/spells/cast_spell.cpp
+++ b/engines/mm/mm1/views_enh/spells/cast_spell.cpp
@@ -64,7 +64,7 @@ void CastSpell::draw() {
const Character &c = *g_globals->_currCharacter;
writeString(0, 0, STRING["enhdialogs.cast_spell.title"], ALIGN_MIDDLE);
- writeString(0, 20, c._name, ALIGN_MIDDLE);
+ writeString(0, 16, c._name, ALIGN_MIDDLE);
writeString(0, 40, STRING["enhdialogs.cast_spell.spell_ready"]);
setTextColor(37);
diff --git a/engines/mm/mm1/views_enh/spells/spellbook.cpp b/engines/mm/mm1/views_enh/spells/spellbook.cpp
index 6ec28a75ea9..84e518272eb 100644
--- a/engines/mm/mm1/views_enh/spells/spellbook.cpp
+++ b/engines/mm/mm1/views_enh/spells/spellbook.cpp
@@ -97,6 +97,7 @@ void Spellbook::draw() {
STRING["enhdialogs.spellbook.title"].c_str(),
c._name
);
+ title = truncateString(title, _innerBounds.width());
writeString(0, 0, title, ALIGN_MIDDLE);
// Write current spell points
diff --git a/engines/mm/mm1/views_enh/text_entry.cpp b/engines/mm/mm1/views_enh/text_entry.cpp
index 88b4d816b54..9a8364b52b8 100644
--- a/engines/mm/mm1/views_enh/text_entry.cpp
+++ b/engines/mm/mm1/views_enh/text_entry.cpp
@@ -32,7 +32,13 @@ void TextEntry::display(int x, int y, int maxLen,
_enterFn = enterFn;
_isNumeric = isNumeric;
_text = "";
- _bounds = Common::Rect(x, y, x + maxLen * 8, y + 9);
+
+ Common::String maxText;
+ for (int i = 0; i < maxLen; ++i)
+ maxText += isNumeric ? '8' : 'W';
+
+ _bounds = Common::Rect(x, y, x + getStringWidth(maxText) +
+ getStringWidth("_") + 1, y + 9);
addView(this);
}
diff --git a/engines/mm/mm1/views_enh/text_view.cpp b/engines/mm/mm1/views_enh/text_view.cpp
index 72337fcea68..2b9fe0226f4 100644
--- a/engines/mm/mm1/views_enh/text_view.cpp
+++ b/engines/mm/mm1/views_enh/text_view.cpp
@@ -180,6 +180,21 @@ size_t TextView::getStringWidth(const Common::String &str) {
return getFont()->getStringWidth(str);
}
+Common::String TextView::truncateString(const Common::String &str, int maxWidth) {
+ Common::String result = str;
+ const Common::String ellipsis = "...";
+
+ if ((int)getStringWidth(result) <= maxWidth)
+ return result;
+
+ const int ellipsisWidth = (int)getStringWidth(ellipsis);
+ while (!result.empty() && (int)getStringWidth(result) + ellipsisWidth > maxWidth)
+ result.deleteLastChar();
+
+ return result.empty() && ellipsisWidth > maxWidth ? Common::String() :
+ result + ellipsis;
+}
+
void TextView::newLine() {
_textPos.x = 0;
_textPos.y += ROW_HEIGHT;
@@ -202,13 +217,15 @@ Common::StringArray TextView::splitLines(const Common::String &str,
return lines;
do {
+ bool forceSplit = false;
endP = strchr(startP, '\n');
+ const char *lineEndP = endP;
int strWidth = font.getStringWidth(endP ?
Common::String(startP, endP) : Common::String(startP));
if (strWidth > lineWidth) {
// Find the last space before a full line
- endP = startP + strlen(startP) - 1;
+ endP = startP + (lineEndP ? lineEndP - startP : (int)strlen(startP)) - 1;
while (strWidth > lineWidth) {
// Move back to a prior space
for (--endP; endP > startP && *endP != ' '; --endP) {
@@ -225,8 +242,17 @@ Common::StringArray TextView::splitLines(const Common::String &str,
if (endP <= startP) {
// No place to word wrap, and it's longer than the width.
- // So just use the entirety of the remainder
- endP = startP + strlen(startP) - 1;
+ // Split an unbroken word near the visual center.
+ const char *wordEndP = lineEndP ? lineEndP : startP + strlen(startP);
+ endP = startP + (wordEndP - startP) / 2;
+
+ while (endP > startP + 1 &&
+ font.getStringWidth(Common::String(startP, endP)) > lineWidth)
+ --endP;
+ if (endP <= startP)
+ endP = startP + 1;
+
+ forceSplit = true;
break;
}
@@ -241,7 +267,7 @@ Common::StringArray TextView::splitLines(const Common::String &str,
break;
// Start next line after space or carriage return
- startP = endP + 1;
+ startP = forceSplit ? endP : endP + 1;
} while (*startP);
diff --git a/engines/mm/mm1/views_enh/text_view.h b/engines/mm/mm1/views_enh/text_view.h
index 96eccd7459f..8f3711b2a3f 100644
--- a/engines/mm/mm1/views_enh/text_view.h
+++ b/engines/mm/mm1/views_enh/text_view.h
@@ -89,6 +89,11 @@ protected:
*/
size_t getStringWidth(const Common::String &str);
+ /**
+ * Truncates a string to fit in the given pixel width
+ */
+ Common::String truncateString(const Common::String &str, int maxWidth);
+
/**
* Move the text position to the next line
*/
diff --git a/engines/mm/mm1/views_enh/title.cpp b/engines/mm/mm1/views_enh/title.cpp
index bbf9bef8f55..989cc4e1ae1 100644
--- a/engines/mm/mm1/views_enh/title.cpp
+++ b/engines/mm/mm1/views_enh/title.cpp
@@ -26,6 +26,8 @@ namespace MM {
namespace MM1 {
namespace ViewsEnh {
+#define FIRST_SCENE_SCREEN 2
+
bool Title::msgFocus(const FocusMessage &msg) {
Views::Title::msgFocus(msg);
g_engine->_sound->playSong("inn.m");
@@ -37,6 +39,21 @@ bool Title::msgUnfocus(const UnfocusMessage &msg) {
return Views::Title::msgUnfocus(msg);
}
+bool Title::msgMouseUp(const MouseUpMessage &msg) {
+ if (msg._button == MouseMessage::MB_RIGHT) {
+ if (_screenNum >= FIRST_SCENE_SCREEN) {
+ _screenNum = -1;
+ _fadeIndex = 0;
+ cancelDelay();
+ redraw();
+ }
+
+ return true;
+ }
+
+ return Views::Title::msgMouseUp(msg);
+}
+
} // namespace ViewsEnh
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views_enh/title.h b/engines/mm/mm1/views_enh/title.h
index c724945e576..ea3cd20ed74 100644
--- a/engines/mm/mm1/views_enh/title.h
+++ b/engines/mm/mm1/views_enh/title.h
@@ -35,6 +35,7 @@ public:
bool msgFocus(const FocusMessage &msg) override;
bool msgUnfocus(const UnfocusMessage &msg) override;
+ bool msgMouseUp(const MouseUpMessage &msg) override;
};
} // namespace ViewsEnh
diff --git a/engines/mm/mm1/views_enh/wheel_spin.cpp b/engines/mm/mm1/views_enh/wheel_spin.cpp
index 120ba54509f..536b3158b41 100644
--- a/engines/mm/mm1/views_enh/wheel_spin.cpp
+++ b/engines/mm/mm1/views_enh/wheel_spin.cpp
@@ -41,8 +41,8 @@ void WheelSpin::draw() {
for (uint i = 0; i < g_globals->_party.size(); ++i) {
const Character &c = g_globals->_party[i];
- writeLine(i, c._name, ALIGN_LEFT, 0);
- writeLine(i, _results[i], ALIGN_LEFT, 100);
+ writeLine(i, truncateString(c._name, 130), ALIGN_LEFT, 0);
+ writeLine(i, _results[i], ALIGN_LEFT, 130);
}
}
diff --git a/engines/mm/shared/utils/strings.cpp b/engines/mm/shared/utils/strings.cpp
index ddfc7420e72..64921a21b93 100644
--- a/engines/mm/shared/utils/strings.cpp
+++ b/engines/mm/shared/utils/strings.cpp
@@ -24,6 +24,28 @@
namespace MM {
+static bool isRomanNumeral(const Common::String &str, uint start, uint end) {
+ if (start == end)
+ return false;
+
+ for (uint i = start; i < end; ++i) {
+ switch (toupper(str[i])) {
+ case 'I':
+ case 'V':
+ case 'X':
+ case 'L':
+ case 'C':
+ case 'D':
+ case 'M':
+ break;
+ default:
+ return false;
+ }
+ }
+
+ return true;
+}
+
Common::String capitalize(const Common::String &str) {
Common::String result = str;
bool capitalize = true;
@@ -52,6 +74,20 @@ Common::String camelCase(const Common::String &str) {
bool capitalize = true;
for (uint i = 0; i < str.size(); ++i) {
+ if (capitalize) {
+ uint end = i;
+ while (end < str.size() && str[end] != ' ')
+ ++end;
+
+ if (isRomanNumeral(str, i, end)) {
+ for (; i < end; ++i)
+ result.setChar(toupper(result[i]), i);
+ --i;
+ capitalize = false;
+ continue;
+ }
+ }
+
if (capitalize) {
result.setChar(toupper(result[i]), i);
capitalize = false;
Commit: 35a7d0d78d351fe0e53878912b574f803b1cc811
https://github.com/scummvm/scummvm/commit/35a7d0d78d351fe0e53878912b574f803b1cc811
Author: Scorp (scorp at mrs.mn)
Date: 2026-05-02T21:13:24+10:00
Commit Message:
MM: MM1: Character game generation and UI enhancement
Generate character name in create view from the pool of pre-build names from HoMM depending on class and sex, also add Y/N icons to confirm name with mouse.
Changed paths:
A devtools/create_mm/files/mm1/mm1_names.txt
engines/mm/mm1/views_enh/create_characters.cpp
engines/mm/mm1/views_enh/create_characters.h
engines/mm/mm1/views_enh/text_entry.cpp
engines/mm/mm1/views_enh/text_entry.h
diff --git a/devtools/create_mm/files/mm1/mm1_names.txt b/devtools/create_mm/files/mm1/mm1_names.txt
new file mode 100644
index 00000000000..670415c0ede
--- /dev/null
+++ b/devtools/create_mm/files/mm1/mm1_names.txt
@@ -0,0 +1,199 @@
+2 1 Orrin
+2 2 Valeska
+2 1 Edric
+2 2 Sylvia
+2 2 Beatrice
+2 1 Lord Haart
+2 2 Sorsha
+2 1 Christian
+2 2 Tyris
+2 1 Sir Mullich
+4 2 Adela
+4 1 Cuthbert
+4 2 Adelaide
+4 1 Ingham
+4 2 Sanya
+4 1 Loynis
+4 2 Caitlin
+4 1 Rion
+3 2 Mephala
+3 1 Ufretin
+3 2 Jenova
+3 1 Ryland
+3 1 Thorgrim
+3 2 Giselle
+3 1 Ivor
+3 1 Clancy
+3 2 Kyrre
+4 1 Coronius
+4 1 Uland
+4 1 Elleshar
+4 2 Gem
+4 1 Malcom
+4 2 Melodia
+4 1 Alagar
+4 1 Aeris
+5 1 Piquedram
+5 1 Thane
+5 2 Josephine
+5 2 Neela
+5 1 Torosar
+5 1 Fafner
+5 2 Rissa
+5 2 Iona
+5 1 Astral
+5 1 Halon
+5 2 Serena
+5 2 Daremyth
+5 1 Theodorus
+5 1 Solmyr
+5 2 Aine
+5 2 Cyra
+1 2 Fiona
+1 1 Rashka
+1 2 Marius
+1 1 Ignatius
+1 2 Octavia
+1 1 Calh
+1 2 Pyre
+1 2 Nymus
+5 1 Ayden
+5 1 Xyron
+5 1 Axsis
+5 2 Olema
+5 2 Calid
+5 2 Ash
+5 1 Zydar
+5 1 Xarfax
+1 1 Straker
+1 1 Vokial
+1 1 Moandor
+1 2 Charna
+1 2 Tamika
+1 2 Isra
+1 1 Clavius
+1 1 Galthran
+1 1 Ranloo
+5 2 Septienna
+5 2 Aislinn
+5 1 Sandro
+5 1 Nimbus
+5 1 Thant
+5 2 Xsi
+5 2 Vidomina
+5 1 Nagash
+1 2 Lorelei
+1 1 Arlach
+1 1 Dace
+1 1 Ajit
+1 1 Damacon
+1 1 Gunnar
+1 2 Synca
+1 1 Shakti
+5 1 Alamar
+5 1 Jaegar
+5 1 Malekith
+5 1 Jeddite
+5 1 Geon
+5 1 Deemer
+5 2 Sephinroth
+5 1 Darkstorn
+1 1 Yog
+1 1 Gurnisson
+1 1 Jabarkas
+1 2 Shiva
+1 2 Gretchin
+1 1 Krellion
+1 1 Crag Hack
+1 1 Tyraxor
+5 2 Gird
+5 1 Vey
+5 1 Dessa
+5 1 Terek
+5 1 Zubin
+5 2 Gundula
+5 2 Oris
+5 1 Saurug
+1 1 Bron
+1 1 Drakon
+1 1 Wystan
+1 1 Tazar
+1 1 Alkin
+1 1 Korbac
+1 1 Gerwulf
+1 1 Broghild
+4 2 Mirlanda
+4 2 Rosic
+4 2 Voy
+4 2 Kinkeria
+4 2 Verdish
+4 2 Merist
+4 2 Styg
+4 2 Andra
+4 2 Tiva
+5 2 Pasis
+5 2 Thunar
+5 2 Ignissa
+5 2 Lacus
+5 1 Monere
+5 1 Erdamon
+5 1 Fiur
+5 1 Kalt
+5 2 Luna
+5 2 Brissa
+5 2 Ciele
+5 2 Labetha
+5 1 Inteus
+5 1 Aenain
+5 1 Gelare
+5 1 Grindan
+6 1 Corkes
+6 1 Jeremy
+6 1 Illor
+6 1 Derek
+6 1 Elmore
+6 2 Leena
+6 2 Anabel
+6 2 Cassiopeia
+6 2 Miriam
+5 2 Casmetra
+5 1 Eovacius
+5 1 Spint
+5 1 Andal
+5 1 Manfred
+5 1 Zilare
+5 2 Astra
+5 1 Dargem
+6 2 Henrietta
+6 2 Sam
+6 1 Tancred
+6 1 Melchior
+6 1 Floribert
+6 2 Wynona
+6 2 Dury
+6 1 Morton
+5 2 Celestine
+5 1 Todd
+5 1 Agar
+5 1 Bertram
+5 1 Wrathmont
+5 2 Ziph
+5 2 Victoria
+5 2 Eanswythe
+1 1 Dhuin
+1 2 Oidana
+1 2 Neia
+1 1 Eikthurn
+1 2 Creyle
+1 1 Spadum
+1 1 Kynr
+1 1 Ergon
+4 1 Kriv
+4 1 Glacius
+4 2 Sial
+4 1 Dalton
+4 2 Biarma
+4 1 Haugir
+4 2 Akka
+4 2 Vehr
+4 2 Allora
diff --git a/engines/mm/mm1/views_enh/create_characters.cpp b/engines/mm/mm1/views_enh/create_characters.cpp
index 73c8656c087..c4d61445529 100644
--- a/engines/mm/mm1/views_enh/create_characters.cpp
+++ b/engines/mm/mm1/views_enh/create_characters.cpp
@@ -19,6 +19,8 @@
*
*/
+#include "common/file.h"
+#include "common/textconsole.h"
#include "mm/mm1/views_enh/create_characters.h"
#include "mm/shared/utils/strings.h"
#include "mm/mm1/globals.h"
@@ -29,6 +31,79 @@ namespace MM1 {
namespace ViewsEnh {
#define RIGHT_X 200
+#define NAMES_FILENAME "mm1_names.txt"
+#define NAME_X 160
+#define NAME_Y 110
+#define NAME_MAX_LEN 15
+#define NAME_CONFIRM_X 21
+#define NAME_CANCEL_X 51
+#define NAME_CONFIRM_Y 15
+
+struct SuggestedName {
+ CharacterClass _class;
+ Sex _sex;
+ Common::String _name;
+};
+
+static Common::Array<SuggestedName> g_suggestedNames;
+static bool g_suggestedNamesLoaded = false;
+
+static bool openSuggestedNamesFile(Common::File &f, Common::Path &filename) {
+ filename = Common::Path(NAMES_FILENAME);
+ if (f.open(filename))
+ return true;
+
+ filename = Common::Path("mm1").appendComponent(NAMES_FILENAME);
+ if (f.open(filename))
+ return true;
+
+ filename = Common::Path("files/mm1").appendComponent(NAMES_FILENAME);
+ return f.open(filename);
+}
+
+static void addSuggestedName(CharacterClass classId, Sex sexId,
+ const Common::String &name) {
+ SuggestedName entry;
+ entry._class = classId;
+ entry._sex = sexId;
+ entry._name = name;
+ g_suggestedNames.push_back(entry);
+}
+
+static void loadSuggestedNames() {
+ if (g_suggestedNamesLoaded)
+ return;
+
+ Common::File f;
+ Common::Path filename;
+ if (!openSuggestedNamesFile(f, filename)) {
+ warning("MM1: Could not open suggested names file");
+ g_suggestedNamesLoaded = true;
+ return;
+ }
+ g_suggestedNamesLoaded = true;
+
+ int invalidLines = 0;
+ while (!f.eos()) {
+ Common::String line = f.readLine();
+ line.trim();
+ if (line.empty() || line.hasPrefix("#"))
+ continue;
+
+ size_t p1 = line.findFirstOf('\t');
+ size_t p2 = p1 == Common::String::npos ? Common::String::npos :
+ line.findFirstOf('\t', p1 + 1);
+ if (p1 == Common::String::npos || p2 == Common::String::npos) {
+ ++invalidLines;
+ continue;
+ }
+
+ int classId = atoi(Common::String(line.c_str(), line.c_str() + p1).c_str());
+ int sexId = atoi(Common::String(line.c_str() + p1 + 1, line.c_str() + p2).c_str());
+ Common::String name(line.c_str() + p2 + 1);
+ addSuggestedName((CharacterClass)classId, (Sex)sexId, name);
+ }
+}
static Common::String getAlignmentString(Alignment alignment) {
if (alignment == NEUTRAL)
@@ -144,6 +219,7 @@ void CreateCharacters::NewCharacter::save() {
const int ALIGNMENT_VALS[3] = { 0, 0x10, 0x20 };
re._alignmentCtr = ALIGNMENT_VALS[re._alignmentInitial];
re._portrait = _portrait;
+ re.loadFaceSprites();
g_globals->_roster.save();
}
@@ -198,7 +274,63 @@ void CreateCharacters::NewCharacter::setSP(int amount) {
/*------------------------------------------------------------------------*/
-CreateCharacters::CreateCharacters() : ScrollView("CreateCharacters") {
+void CreateCharacters::NameEntry::addConfirmIcons() {
+ _confirmBounds = Common::Rect(NAME_CONFIRM_X, NAME_CONFIRM_Y,
+ NAME_CONFIRM_X + GLYPH_W, NAME_CONFIRM_Y + GLYPH_H);
+ _cancelBounds = Common::Rect(NAME_CANCEL_X, NAME_CONFIRM_Y,
+ NAME_CANCEL_X + GLYPH_W, NAME_CONFIRM_Y + GLYPH_H);
+ int right = MAX((int)_bounds.right, _bounds.left + _cancelBounds.right);
+ _bounds = Common::Rect(_bounds.left, _bounds.top,
+ right, _bounds.top + _confirmBounds.bottom);
+}
+
+void CreateCharacters::NameEntry::draw() {
+ TextEntry::draw();
+
+ Graphics::ManagedSurface s = getSurface();
+ g_globals->_confirmIcons.draw(&s, _confirmHover ? 1 : 0,
+ Common::Point(_confirmBounds.left, _confirmBounds.top));
+ g_globals->_confirmIcons.draw(&s, 2 + (_cancelHover ? 1 : 0),
+ Common::Point(_cancelBounds.left, _cancelBounds.top));
+}
+
+bool CreateCharacters::NameEntry::msgMouseDown(const MouseDownMessage &msg) {
+ Common::Point pt(msg._pos.x - _bounds.left, msg._pos.y - _bounds.top);
+ return msg._button == MouseMessage::MB_LEFT &&
+ (_confirmBounds.contains(pt) || _cancelBounds.contains(pt));
+}
+
+bool CreateCharacters::NameEntry::msgMouseUp(const MouseUpMessage &msg) {
+ Common::Point pt(msg._pos.x - _bounds.left, msg._pos.y - _bounds.top);
+ if (msg._button == MouseMessage::MB_LEFT && _confirmBounds.contains(pt)) {
+ _owner->acceptName();
+ return true;
+ }
+ if (msg._button == MouseMessage::MB_LEFT && _cancelBounds.contains(pt)) {
+ _owner->abortName();
+ return true;
+ }
+
+ return false;
+}
+
+bool CreateCharacters::NameEntry::msgMouseMove(const MouseMoveMessage &msg) {
+ Common::Point pt(msg._pos.x - _bounds.left, msg._pos.y - _bounds.top);
+ bool confirmHover = _confirmBounds.contains(pt);
+ bool cancelHover = _cancelBounds.contains(pt);
+ if (confirmHover != _confirmHover || cancelHover != _cancelHover) {
+ _confirmHover = confirmHover;
+ _cancelHover = cancelHover;
+ redraw();
+ }
+
+ return true;
+}
+
+/*------------------------------------------------------------------------*/
+
+CreateCharacters::CreateCharacters() : ScrollView("CreateCharacters"),
+ _textEntry(this) {
_icons.load("create.icn");
addButton(&_icons, Common::Point(120, 172), 4, KEYBIND_ESCAPE, true);
@@ -555,6 +687,9 @@ bool CreateCharacters::msgAction(const ActionMessage &msg) {
case SELECT_PORTRAIT:
setState(SELECT_NAME);
break;
+ case SELECT_NAME:
+ acceptName();
+ break;
case SAVE_PROMPT:
_newChar.save();
@@ -596,6 +731,53 @@ void CreateCharacters::enterFunc(const Common::String &name) {
view->setState(SAVE_PROMPT);
}
+Common::String CreateCharacters::getSuggestedName() {
+ loadSuggestedNames();
+ if (g_suggestedNames.empty()) {
+ return "";
+ }
+
+ Common::Array<uint> matches;
+ for (uint i = 0; i < g_suggestedNames.size(); ++i) {
+ if (g_suggestedNames[i]._class == _newChar._class &&
+ g_suggestedNames[i]._sex == _newChar._sex)
+ matches.push_back(i);
+ }
+
+ if (matches.empty()) {
+ for (uint i = 0; i < g_suggestedNames.size(); ++i) {
+ if (g_suggestedNames[i]._class == _newChar._class)
+ matches.push_back(i);
+ }
+ }
+
+ if (matches.empty()) {
+ return "";
+ }
+
+ uint idx = matches.size() == 1 ? matches[0] : matches[g_engine->getRandomNumber(matches.size()) - 1];
+ return g_suggestedNames[idx]._name;
+}
+
+void CreateCharacters::acceptName() {
+ if (_textEntry._text.empty())
+ return;
+
+ Common::String name = _textEntry._text;
+ if (g_events->focusedView() == &_textEntry)
+ _textEntry.close();
+
+ _newChar._name = camelCase(name);
+ setState(SAVE_PROMPT);
+}
+
+void CreateCharacters::abortName() {
+ if (g_events->focusedView() == &_textEntry)
+ _textEntry.close();
+
+ setState(SELECT_CLASS);
+}
+
void CreateCharacters::setState(State state) {
_state = state;
resetSelectedButton();
@@ -615,13 +797,25 @@ void CreateCharacters::setState(State state) {
}
if (_state == SELECT_NAME) {
+ _newChar._name = getSuggestedName();
draw();
- _textEntry.display(160, 110, 15, false, abortFunc, enterFunc);
+ _textEntry.display(NAME_X, NAME_Y, NAME_MAX_LEN, false, abortFunc, enterFunc,
+ _newChar._name);
+ _textEntry.addConfirmIcons();
+ _textEntry.draw();
} else {
redraw();
}
}
+#undef NAME_CONFIRM_Y
+#undef NAME_CANCEL_X
+#undef NAME_CONFIRM_X
+#undef NAME_X
+#undef NAME_Y
+#undef NAME_MAX_LEN
+#undef NAMES_FILENAME
+
} // namespace ViewsEnh
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/views_enh/create_characters.h b/engines/mm/mm1/views_enh/create_characters.h
index 696b720b896..e54a03a71e1 100644
--- a/engines/mm/mm1/views_enh/create_characters.h
+++ b/engines/mm/mm1/views_enh/create_characters.h
@@ -63,8 +63,26 @@ class CreateCharacters : public ScrollView {
void loadPortrait();
};
+ class NameEntry : public TextEntry {
+ private:
+ CreateCharacters *_owner;
+ Common::Rect _confirmBounds;
+ Common::Rect _cancelBounds;
+ bool _confirmHover = false;
+ bool _cancelHover = false;
+ public:
+ NameEntry(CreateCharacters *owner) : _owner(owner) {}
+
+ void addConfirmIcons();
+
+ void draw() override;
+ bool msgMouseDown(const MouseDownMessage &msg) override;
+ bool msgMouseUp(const MouseUpMessage &msg) override;
+ bool msgMouseMove(const MouseMoveMessage &msg) override;
+ };
+
private:
- TextEntry _textEntry;
+ NameEntry _textEntry;
static void abortFunc();
static void enterFunc(const Common::String &name);
Shared::Xeen::SpriteResource _icons;
@@ -122,6 +140,21 @@ private:
*/
void printSummary();
+ /**
+ * Gets a random suggested name for the selected class and sex
+ */
+ Common::String getSuggestedName();
+
+ /**
+ * Accepts the name currently in the text entry
+ */
+ void acceptName();
+
+ /**
+ * Cancels the current name entry
+ */
+ void abortName();
+
/**
* Sets a new state
*/
diff --git a/engines/mm/mm1/views_enh/text_entry.cpp b/engines/mm/mm1/views_enh/text_entry.cpp
index 9a8364b52b8..0302f090a48 100644
--- a/engines/mm/mm1/views_enh/text_entry.cpp
+++ b/engines/mm/mm1/views_enh/text_entry.cpp
@@ -26,12 +26,13 @@ namespace MM1 {
namespace ViewsEnh {
void TextEntry::display(int x, int y, int maxLen,
- bool isNumeric, Abort abortFn, Enter enterFn) {
+ bool isNumeric, Abort abortFn, Enter enterFn,
+ const Common::String &initialText) {
_maxLen = maxLen;
_abortFn = abortFn;
_enterFn = enterFn;
_isNumeric = isNumeric;
- _text = "";
+ _text = initialText;
Common::String maxText;
for (int i = 0; i < maxLen; ++i)
diff --git a/engines/mm/mm1/views_enh/text_entry.h b/engines/mm/mm1/views_enh/text_entry.h
index df04086f037..c6e78fc7a57 100644
--- a/engines/mm/mm1/views_enh/text_entry.h
+++ b/engines/mm/mm1/views_enh/text_entry.h
@@ -56,7 +56,8 @@ public:
bool msgAction(const ActionMessage &msg) override;
void display(int x, int y, int maxLen, bool isNumeric,
- Abort abortFn, Enter enterFn);
+ Abort abortFn, Enter enterFn,
+ const Common::String &initialText = Common::String());
};
} // namespace ViewsEnh
Commit: 287c7811d841c1a3d5914ffb0961623ff1a810d8
https://github.com/scummvm/scummvm/commit/287c7811d841c1a3d5914ffb0961623ff1a810d8
Author: Scorp (scorp at mrs.mn)
Date: 2026-05-02T21:14:19+10:00
Commit Message:
MM: MM1: Added 'Roster is full' string, fixing the crash
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 753e1d4972c..20c873af87e 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -82,6 +82,7 @@ dialogs:
select_alignment: "Select alignment"
select_sex: "Select a sex"
save_character: "Save character"
+ full: "*** Roster is full ***"
reroll: "'ent' to re-roll"
start_over: "'esc' start over"
name: "name:"
Commit: 41caa6897ff1da4773f71b4dc6931d7610f72538
https://github.com/scummvm/scummvm/commit/41caa6897ff1da4773f71b4dc6931d7610f72538
Author: Scorp (scorp at mrs.mn)
Date: 2026-05-02T21:14:19+10:00
Commit Message:
MM: MM1: Fix text cases in multiple text and bump version to 1.1
Changed paths:
devtools/create_mm/files/mm1/strings_en.yml
devtools/create_mm/files/mm1/version.txt
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 20c873af87e..ab9017b8eb2 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -49,8 +49,8 @@ dialogs:
use_what: "use which 'a'-'f','1'-'6'?"
gems: "1) gems"
gold: "2) gold"
- food: "3) food"
- item: "4) item"
+ food: "3) Food"
+ item: "4) Item"
how_much: "how much:"
cast_spell: "cast spell: level="
number: "number="
@@ -82,7 +82,7 @@ dialogs:
select_alignment: "Select alignment"
select_sex: "Select a sex"
save_character: "Save character"
- full: "*** Roster is full ***"
+ full: "*** Roster is Full ***"
reroll: "'ent' to re-roll"
start_over: "'esc' start over"
name: "name:"
@@ -126,23 +126,23 @@ dialogs:
title: "Protect: Spells currently active"
protection: "Protection from"
to_attacks: "to attacks"
- 1: "fear"
- 2: "cold"
- 3: "fire"
- 4: "poison"
- 5: "acid"
- 6: "elec"
- 7: "magic"
+ 1: "Fear"
+ 2: "Cold"
+ 3: "Fire"
+ 4: "Poison"
+ 5: "Acid"
+ 6: "Elec"
+ 7: "Magic"
8: "Light ("
- 9: "Leather skin"
+ 9: "Leather Skin"
10: "Levitate"
- 11: "Walk on water"
- 12: "Guard dog"
- 13: "Psychic protection"
+ 11: "Walk on Water"
+ 12: "Guard Dog"
+ 13: "Psychic Protection"
14: "Bless"
15: "Invisibility"
16: "Shield"
- 17: "Power shield"
+ 17: "Power Shield"
18: "*** Cursed -"
quick_ref:
title: "# name hit pts spell pts ac"
@@ -156,21 +156,21 @@ dialogs:
you_found: "You found..."
nothing: "nothing"
containers:
- 0: " cloth sack "
- 1: "leather sack"
- 2: " wooden box "
- 3: "wooden chest"
- 4: " iron box "
- 5: " iron chest "
- 6: " silver box "
- 7: "silver chest"
- 8: " gold box "
- 9: " gold chest "
- 10: " black box "
+ 0: " Cloth Sack "
+ 1: "Leather Sack"
+ 2: " Wooden Box "
+ 3: "Wooden Chest"
+ 4: " Iron Box "
+ 5: " Iron Chest "
+ 6: " Silver Box "
+ 7: "Silver Chest"
+ 8: " Gold Box "
+ 9: " Gold Chest "
+ 10: " Black Box "
options: "Options:"
- options1: "1) Open it"
- options2: "2) Find/Remove trap"
- options3: "3) Detect magic/trap"
+ 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)"
@@ -349,7 +349,7 @@ dialogs:
surprise: "You surprised a group of monsters,"
approach: "Approach (Y/N)?"
options1: "Options: 'A' Attack 'R' Retreat"
- options2: "'B' bribe 'S' surrender"
+ options2: "'B' Bribe 'S' Surrender"
surrender_failed: "The monsters don't take prisoners!"
nowhere_to_run: "Nowhere to run"
surround: "The monsters surround you!"
@@ -1018,7 +1018,7 @@ maps:
leprechaun_title: "Leprechaun"
map01:
- blacksmith: "\"B. Smith's workshop\""
+ blacksmith: "\"B. Smith's Workshop\""
inn: "\"Inn of Portsmith\""
market: "\"Maid Marion's Market\""
tavern: "\"Zorelda's Watering Hole\""
@@ -1045,7 +1045,7 @@ maps:
inn: "\"The Inn of Algary\""
market: "\"Arcon's Slop\""
tavern: "\"Jolly Jester Tavern\""
- temple: "\"Temple Half-dead\""
+ temple: "\"Temple Half-Dead\""
training: "\"Dragons Claw Training\""
docks: "\"Ye Old Docks\""
@@ -1060,8 +1060,8 @@ maps:
resistances2: "Magic Fire Cold Elec\nAcid Fear Poison Sleep"
pit: "Swaze pit! jump in (Y/N)?"
portal: "A magic portal! enter (Y/N)?"
- zom0: "Note: zom 1,1"
- zom1: "\"I am zom, astral brother of zam.\n"
+ zom0: "Note: Zom 1,1"
+ zom1: "\"I am Zom, astral brother of Zam.\n"
zom2: "My clue is 1-15.\""
zom3: "You're not the couriers!\""
emap02:
@@ -1092,7 +1092,7 @@ maps:
training_inside: "Several empty suits of armor approach\nasking, \"Need training (Y/N)?\""
telgoran1: "An elf dressed in robes approaches...\n\n"
- telgoran2: "\"Friends, I am telgoran. This scroll you\nhave brought me will be very helpful\n(+2500 exp) Here's 1500 gold for your\nservices. I'll tell you a secret, if\ntreasure is what you want...\""
+ telgoran2: "\"Friends, I am Telgoran. This scroll you\nhave brought me will be very helpful\n(+2500 exp) Here's 1500 gold for your\nservices. I'll tell you a secret, if\ntreasure is what you want...\""
telgoran3: "\"The brothers you must find...\nPortsmith and Algary are combined.\""
telgoran4: "\"You're not the couriers!\""
emap03:
@@ -1190,13 +1190,13 @@ maps:
poof: "Poof! you've been teleported..."
ranalou1: "\"I'm the wizard Ranalou. Are you here to\nuse the portals (Y/N)?\""
# FIXME: Spelling incorrect. judgement should be judgment. Fixing changes game data and thus may cause issues
- ranalou2: "\"Good! inside this room are 6 portals,\neach of which leads to a castle. The\nstatue of judgement requires you to find\none prisoner from each of these castles\nbefore you may be found worthy.\""
+ ranalou2: "\"Good! Inside this room are 6 portals,\neach of which leads to a castle. The\nStatue of Judgement requires you to find\none prisoner from each of these castles\nbefore you may be found worthy.\""
ranalou3: "\"Then begone!\""
sign1: "A sign:\n\nExperiment in progress, do not enter!"
sign2: "A sign:\n\nAuthorized personnel only! Keep out."
map11:
- volcano_god: "The volcano god bellows,\n\"What do you seek here?\"\na) A challenge b) A riddle c) A clue"
+ volcano_god: "The Volcano God bellows,\n\"What do you seek here?\"\na) A challenge b) A riddle c) A clue"
question: "Who was brave yet failed?\n\nanswer:> .........."
sign: "Painted in a black and white pattern,\na sign reads: The second part is the\nmost valuable."
pit: "Pit of bubbling lava!"
@@ -1216,7 +1216,7 @@ maps:
god_b: "A Riddle"
god_c: "A Clue"
volcano_god: "Volcano God"
- god_text: "The volcano god bellows,\n\"What do you seek here?\""
+ god_text: "The Volcano God bellows,\n\"What do you seek here?\""
question: "Who was brave yet failed?""
map12:
@@ -1248,7 +1248,7 @@ maps:
castle: "The fabeled Castle Doom!\nWill you enter (Y/N)?"
map15:
- lava: "Lava fills the valley of fire!"
+ lava: "Lava fills the Valley of Fire!"
body: "The dragons body disappears, except\nfor a shiny tooth!"
cove: "A pirates secret cove, search (Y/N)?"
percella1: "I am Percella the druid and i have what\nyou need. But promise me that you won't\nhelp that demonic menace. Accept (Y/N)?"
@@ -1266,7 +1266,7 @@ maps:
wheel: "Embedded in the side of the mountain is\na large wheel covered in strange and\narchaic symbols. Spin the wheel (Y/N)?"
map17:
- options: "1) Red thorac 2) Blue ogram\n3) Green bagar 4) Yellow limra\n5) Purple sagran 6) Orange oolak\n7) Black dresidion 8) White dilithium"
+ options: "1) Red Thorac 2) Blue Ogram\n3) Green Bagar 4) Yellow Limra\n5) Purple Sagran 6) Orange Oolak\n7) Black Dresidion 8) White Dilithium"
bridge: "A wooden bridge extendes across the\nocean into the mist. A hooded figure\nmaterializes, \"To cross you must each\nanswer a question, Accept (Y/N)?\""
color: "What is your color (1-8)?"
wrong: "Wrong!"
@@ -1310,7 +1310,7 @@ maps:
whistle: "Your ruby whistle begins to glow,\nblow it (0-9 times)?"
stairs_down: "Stairs going down, enter (Y/N)?"
temple: "An ancient temple converted to a\nstronghold has no apparent entrance."
- peak: "Atop this peak looking:\n\nN= A cave beyond white wolf.\nE= Large beasts above wyvern peaks!\nS= Distant uncharted isles.\nW= A pirate ship beyond korin bluffs."
+ peak: "Atop this peak looking:\n\nN= A cave beyond White Wolf.\nE= Large beasts above Wyvern Peaks!\nS= Distant uncharted isles.\nW= A pirate ship beyond Korin Bluffs."
sign1: "A sign pointing N. reads: White Wolf"
sign2: "A sign pointing S. reads: Portsmith"
emap20:
@@ -1319,7 +1319,7 @@ maps:
map21:
trivia_island: "Trivia Island! 500 gold, enter (Y/N)?"
not_enough_gold: "Not enough gold!"
- ghostship: "Pirate ghostship anarchist!"
+ ghostship: "Pirate Ghostship Anarchist!"
who_be_ye: "Who be ye?"
free_trivia: "Free trivia chance, pull branch (Y/N)?"
questions:
@@ -1329,11 +1329,11 @@ maps:
3: "Where's the very latest?"
4: "Who be ye?"
answers:
- 0: "Lord ironfist"
+ 0: "Lord Ironfist"
1: "Laura"
2: "Og"
- 3: "erliquin"
- 4: "i be me"
+ 3: "Erliquin"
+ 4: "I be me"
correct: "Correct! +50 gems"
incorrect: "Wrong!"
answer: "Answer:> .............."
@@ -1399,7 +1399,7 @@ maps:
map27:
pool: "The pool of wisdom grants those who are\nworthy +4 personality."
- retreat: "Clerical retreat"
+ retreat: "Clerical Retreat"
clerics: "We are the clerics of the"
cured: "Your party is cured!"
alignment: "Your alignment is restored!"
@@ -1474,12 +1474,12 @@ maps:
option_c: "Friendly"
map32:
- castle: "King alamar's castle, enter (Y/N)?"
+ castle: "King Alamar's castle, enter (Y/N)?"
door: "A diamond door!"
key: "Use your key (Y/N)?"
statue: "Statue of a lion growls, \"Password?\"\nResponse:> .........."
password: "is the password for today,\nleave the area and change it i may!\""
- heratio: "Heratio harper sings:"
+ heratio: "Heratio Harper sings:"
music: "Distant harp music..."
passwords:
0: "Musical"
@@ -1515,7 +1515,7 @@ maps:
box: "A metalic box echoes:\n\"Intruder alert!\""
message1: "Scratched on the wall:\nSearch after the canine rewards you!"
message2: "Scrawled on the wall:\nFor the world is hollow and i have\ntouched the sky!"
- message3: "Etched in silver, message d reads:\n//sv/21;-22r,;du1rs0"
+ message3: "Etched in silver, message D reads:\n//sv/21;-22r,;du1rs0"
message4: "Written in blue blood:\nThe canine has the key!"
message5: "Etched in silver:\nMessage interleave 'fedbac'"
message6: "Etched in gold:\nMessage interleave '8,5,3,9,1,4,6,2,7'"
@@ -1523,7 +1523,7 @@ maps:
door: "A golden door repels you!"
alamar: "Suspended in a forcefield is the body\nof a man enclosed in an iron suit.\nTelepathic communication: \"I am the true\nKing Alamar, imprisoned by a demonic\nalien being! Confront him with this Eye\nof Goros and you shall see his true\nself. The fate of the realm is at stake\""
emap34:
- alamar1: "Suspended in a forcefield is the body\nof a man enclosed in an iron suit. Telepathic communication: \"I am the true King Alamar, imprisoned by a demonic alien being! Confront him with this eye of goros and you shall see his true self."
+ alamar1: "Suspended in a forcefield is the body\nof a man enclosed in an iron suit. Telepathic communication: \"I am the true King Alamar, imprisoned by a demonic alien being! Confront him with this Eye of Goros and you shall see his true self."
map35:
exit: "Exit castle (Y/N)?"
@@ -1532,11 +1532,11 @@ maps:
0: "Find the ancient ruins in the\nQuivering Forest"
1: "Visit Blithes Peak, and report"
2: "The people of the desert have much to\ntrade,bring me a sample of their goods"
- 3: "Find the Shrine of Okzar in the\ncaves below dusk"
+ 3: "Find the Shrine of Okzar in the\ncaves below Dusk"
4: "Find the Fabled Fountain in Dragadune"
5: "Solve the Riddle of the Ruby"
6: "Defeat the stronghold\nin the Enchanted Forest"
- inspectron1: "Lord inspectron speaks:\n"
+ inspectron1: "Lord Inspectron speaks:\n"
inspectron2: "\"Your services are needed!\"Accept (Y/N)?"
inspectron3: "\"Return not until thy quest is complete\""
inspectron4: "\"Sorry, but since you are currently\nquested, i can't engage your services.\""
@@ -1561,8 +1561,8 @@ maps:
3: "the head of a medusa"
4: "an eye of a wyvern"
5: "a dragons tooth"
- 6: "the ring of okirm"
- hacker1: "Lord hacker speaks:\n"
+ 6: "the ring of Okrim"
+ hacker1: "Lord Hacker speaks:\n"
hacker2: "\"Your services are needed!\"Accept (Y/N)?"
hacker3: "Bring me"
hacker4: "\"Sorry, you're already quested.\""
@@ -1589,7 +1589,7 @@ maps:
map38:
message4: "Etched in gold, message 4 reads:'\nof-be-has-true-knowledge-plane-a-level-'\nto-reality-it"
- banner: "A banner reads:\nthe labyrinth of lazzeruth...\nfew have entered, none have returned!"
+ banner: "A banner reads:\nthe Labyrinth of Lazzeruth...\nFew have entered, none have returned!"
face1: "Inset in the wall, a stone face\nyells: \"My brain hurts!\""
face2: "Inset in the wall, a stone face\nspeaks: \"I would pay highly for a green\nhandled, pearl encrusted abelnuski.\""
face3: "Inset in the wall, a stone face\nspeaks: \"I see all, hear all,\nknow nothing...\""
@@ -1612,15 +1612,15 @@ maps:
map40:
message2: "Etched in gold, message 2 reads:\nOne,-riddles-value-you-you-5-card-must-\nclaimed.-dreams,-..."
- archer: "\"I am lord archer, the raven,\nI take from those who have and give to\nthose who have not! submit (Y/N)?\""
+ archer: "\"I am Lord Archer, the Raven,\nI take from those who have and give to\nthose who have not! Submit (Y/N)?\""
giants: "Giants hurl boulders!"
button: "A button on the wall, push it (Y/N)?"
squish: "Squish! The party is impaled on a wall\nof spears!"
boulder: "A boulder says:\"There should be 5 tests\""
- test1: "The first test"
- test2: "The second test"
- test3: "The third test"
- test4: "The fourth test"
+ test1: "The First Test"
+ test2: "The Second Test"
+ test3: "The Third Test"
+ test4: "The Fourth Test"
conveyor_belt: "Conveyor belt..."
emap40:
message2: "Etched in gold, message 2 reads:\nOne,-riddles-value-you-you-\n5-card-must-claimed.-Dreams,-..."
@@ -1631,11 +1631,11 @@ maps:
map41:
message3: "Etched in gold, message 3 reads:\nFor-tasks-and-rating.-be-from-6th-\nfrustrations!-the-to-in"
dung: "Minotaur dung slushes beneath you!"
- sign1: "The enchanted chamber"
- sign2: "Cleptomian guild, do not disturb!"
+ sign1: "The Enchanted Chamber"
+ sign2: "Cleptomian Guild, do not disturb!"
sign3: "The Council of Strength is in session"
sign4: "The Uglies Club - Members only!"
- sign5: "Specimen tank - keep closed"
+ sign5: "Specimen Tank - keep closed"
stairs_up: "Spiralling stairs go up,take them (Y/N)?"
tapestry1: "A tapestry on the wall depicts a gray\nminotaur stomping on a group of knights."
tapestry2: "A tapestry on the wall depicts\na kingdom ruled by minotaurs"
@@ -1646,7 +1646,7 @@ maps:
map42:
message9: "Etched in gold, message 9 reads:\nSuccessful-that-training,-the-worthy-\nthe-visit-yet-inner-reality,-order,"
defeated: "The master of this stronghold\nhas been defeated!"
- sign1: "Enter the maze of the minotaur...\nif you dare!"
+ sign1: "Enter the Maze of the Minotaur...\nIf you dare!"
statue1: "Standing atop a pedestal in the center\nof the room is a statue of a small sable\nand white dog. "
statue2: "It comes to life and\nspeaks,\"Congratulations, you've\ncompleted a major quest (+10000 exp)\nRemember B.J.!\""
statue3: "Desecrate it (Y/N)?"
@@ -1657,8 +1657,8 @@ maps:
map43:
exit: "Exit castle, (Y/N)?"
button: "Button on the wall, push it (Y/N)?"
- tower: "The tower"
- throne_room: "Throne room"
+ tower: "The Tower"
+ throne_room: "Throne Room"
ironfist1: "Lord Ironfist speaks:\n"
ironfist2: "\"Your services are needed!\" Accept(Y/N)?"
ironfist3: "\"Return not until thy quest is complete\""
@@ -1667,13 +1667,14 @@ maps:
message_b: "Etched in silver, message B reads:\nrstia-,e1,;/11rn;/m-"
guards: "Castle guards exclaim,\n\"No merchants pass! Begone peasants.\""
quests:
- 1: "Find the stronghold in ravens wood"
- 2: "Find lord kilburn"
- 3: "Discover the secret of portsmith"
+ 1: "Find the stronghold in Ravens Wood"
+ 2: "Find Lord Kilburn"
+ 3: "Discover the secret of Portsmith"
4: "Find the pirates secret cove"
- 5: "Find the shipwreck of the jolly raven"
- 6: "Defeat the pirate ghost ship anarchist"
- 7: "Defeat the stronghold in ravens wood"
+ 5: "Find the shipwreck of the Jolly Raven"
+ 6: "Defeat the Pirate Ghost Ship Anarchist"
+ 7: "Defeat the stronghold in Ravens Wood"
+
emap43:
title: "Lord Ironfist"
ironfist2: "\"Your services are needed!\" Accept (Y/N)?"
@@ -1709,7 +1710,7 @@ maps:
1: "A loud tone resounds\nthroughout the room!"
2: "A sharp tone assaults your senses!"
3: "A mellow tone relaxes you."
- clerics1: "The clerics of the south speak:\n"
+ clerics1: "The Clerics of the South speak:\n"
clerics2: "\"Hear the 3 tones and return!\""
clerics3: "\"We deem you worthy of advancement!\""
poof: "Poof!"
@@ -1722,7 +1723,7 @@ maps:
map48:
orango1: "A strange alien being in a shimmering\nsilver jumpsuit proclaims, \"This is a\nsoul maze and you are its prisoner!\nTo escape, you must find your captor's\nname hidden within these walls.\"\n\nanswer:>"
orango2: "Keep looking!"
- orango3: "Agent Orango seventeen reporting:\nImposter xx21a7-3 voided!\nStarphase 5281.6 at 120-varn-161 pod #41\nYou are now rank 1 and eligible for\ntransfer. Find inner sanctum for new\nassignment. The walls begin to fade...\n(press space)"
+ orango3: "Agent Orango Seventeen reporting:\nImposter xx21a7-3 voided!\nStarphase 5281.6 at 120-varn-161 pod #41\nYou are now rank 1 and eligible for\ntransfer. Find Inner Sanctum for new\nassignment. The walls begin to fade...\n(press space)"
emap48:
title: "Strange Alien"
orango1: "A strange alien being in a silver jumpsuit proclaims, \"This is a soul maze and you are its prisoner!\nTo escape, you must find your captor's name hidden within these walls.\""
@@ -1733,14 +1734,14 @@ maps:
message_e: "Etched in silver, message E reads:\noei/:1-33-1ek5;d-et,"
alamar1: "The omnipotent King Alamar speaks,\n\n"
alamar2: "\"Varnlings, I quest thee to find the\nCrypt of Carmenca. Away with you...\""
- alamar3: "\"My saviors, you're always welcome here!\nYou should find the inner sanctum...\nLive long and prosper.\""
+ alamar3: "\"My saviors, you're always welcome here!\nYou should find the Inner Sanctum...\nLive long and prosper.\""
alamar4: "\"You've discovered my true identity!\nInto the soul maze you go...\""
guards1: "Castle guards exclaim,\n\"No Merchants Pass! begone peasants.\""
guards2: "Kings guards approach.\n\"No King's Pass, no admittance!\""
scream: "A loud scream from behind the door!"
trap: "Singe! Acid trap."
explosion: "Boom! A fiery explosion."
- throne_room: "Throne room"
+ throne_room: "Throne Room"
emap49:
king_alamar: "King Alamar"
sheltem: "Imposter King Alamar"
@@ -1749,10 +1750,10 @@ maps:
message7: "Etched in gold, message 7 reads:\nThese-and-that-must-can-different-\nshall-have-from-a-jvc"
sign1: "Club Dead...\nThe antidote to humanization!"
sign2: "Temple of the Old Order"
- sign3: "Glass room"
- sign4: "Ruby room"
- sign5: "Twinkle room"
- sign6: "Rainbow room"
+ sign3: "Glass Room"
+ sign4: "Ruby Room"
+ sign5: "Twinkle Room"
+ sign6: "Rainbow Room"
grate: "The crystal grate repels you!"
emap50:
message7: "Etched in gold, message 7 reads:\nThese-and-that-must-can-\ndifferent-shall-have-from-a-jvc"
@@ -1772,7 +1773,7 @@ maps:
ladder: "A ladder going up, climb it (Y/N)?"
map54:
- projector: "Astral projector # %c, zap!"
+ projector: "Astral Projector # %c, zap!"
slot1: "There's a small slot in the door.\n"
slot2: "No admittance!"
slot3: "Key card is rejected!"
@@ -1782,7 +1783,7 @@ maps:
keeper2: ":::Inner Sanctum:::"
keeper3: "In a serene voice, the data keeper says,\n\"Welcome to your inner sanctum\nVarnlings! I am very pleased that you've\nmade it this far. You are to be\ncommended. I've been monitoring your\nprogress.\" Turning to the strange\nmechanical device, he inserts a flat\nobject into a slot. Your party's current\nperformance total=%u"
keeper4: "\"You are not yet worthy for transfer. Return after defeating the imposter.\""
- keeper5: "Excellent rating! this is a rare occasion, for only a privileged few are given the opportunity for transfer to\nanother V.A.R.N. (Vehicular Astropod\nResearch Nacelle). Return now to the\nInn of Sorpigal for rest and celebration\nthen continue on to your new assignment at the Gates To Another World...\" (+50000 exp for your accomplishment!)\n----------------------------------------\nPlease send your performance total to\nNew World Computing, Inc.\n P. O. Box 2068 Van Nuys, CA 91404"
+ keeper5: "Excellent rating! This is a rare occasion, for only a privileged few are given the opportunity for transfer to\nanother V.A.R.N. (Vehicular Astropod\nResearch Nacelle). Return now to the\nInn of Sorpigal for rest and celebration\nthen continue on to your new assignment at the Gates To Another World...\" (+50000 exp for your accomplishment!)\n----------------------------------------\nPlease send your performance total to\nNew World Computing, Inc.\n P. O. Box 2068 Van Nuys, CA 91404"
emap54:
keeper: "Keeper"
keeper2: "In a serene voice, the data keeper says, \"Welcome to your inner sanctum Varnlings! I am very pleased that you've made it this far. You are to be commended. I've been monitoring your\nprogress.\""
diff --git a/devtools/create_mm/files/mm1/version.txt b/devtools/create_mm/files/mm1/version.txt
index d3827e75a5c..9459d4ba2a0 100644
--- a/devtools/create_mm/files/mm1/version.txt
+++ b/devtools/create_mm/files/mm1/version.txt
@@ -1 +1 @@
-1.0
+1.1
diff --git a/engines/mm/mm1/globals.cpp b/engines/mm/mm1/globals.cpp
index 9dc2f167b9a..3ed1332759f 100644
--- a/engines/mm/mm1/globals.cpp
+++ b/engines/mm/mm1/globals.cpp
@@ -57,7 +57,7 @@ void Globals::createBlankButton() {
bool Globals::load(bool isEnhanced) {
// Initialise engine data for the game
Common::U32String errMsg;
- if (!Common::load_engine_data("mm.dat", "mm1", 1, 0, errMsg)) {
+ if (!Common::load_engine_data("mm.dat", "mm1", 1, 1, errMsg)) {
GUIErrorMessage(errMsg);
return false;
}
More information about the Scummvm-git-logs
mailing list