diff --git a/devtools/create_mm/files/mm1/strings_en.yml b/devtools/create_mm/files/mm1/strings_en.yml
index 8e023f56e69..44588866149 100644
--- a/devtools/create_mm/files/mm1/strings_en.yml
+++ b/devtools/create_mm/files/mm1/strings_en.yml
@@ -1301,3 +1301,23 @@ maps:
door: "A GOLDEN DOOR REPELS YOU!"
alamar1: "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."
alamar2: "THE FATE OF THE REALM IS AT STAKE."""
+
+ map35:
+ exit: "EXIT CASTLE, (Y/N)?"
+ guards: "CASTLE GUARDS EXCLAIM\n""NO MERCHANTS PASS! BEGONE PEASANTS."""
+ quests:
+ 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"
+ 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"
+ 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."""
+ inspectron5: "WELL DONE, QUEST COMPLETE! +%d EXP"
+ message: "ETCHED IN SILVER, MESSAGE A READS:\nATIS-19-31UD54AEUPI1"
+ slide: "A SLIDE!"
+ vault: "EMPTY VAULT, ALARM!"
diff --git a/engines/mm/mm1/data/character.h b/engines/mm/mm1/data/character.h
index 3602c402da4..1b918957399 100644
--- a/engines/mm/mm1/data/character.h
+++ b/engines/mm/mm1/data/character.h
@@ -107,7 +107,11 @@ enum CharFlags5 {
CHARFLAG5_1 = 1,
CHARFLAG5_2 = 2,
CHARFLAG5_4 = 4,
- CHARFLAG5_8 = 8
+ CHARFLAG5_8 = 8,
+ CHARFLAG5_10 = 0x10,
+ CHARFLAG5_20 = 0x20,
+ CHARFLAG5_40 = 0x40,
+ CHARFLAG5_80 = 0x80
};
enum CharFlags7 {
diff --git a/engines/mm/mm1/data/items.h b/engines/mm/mm1/data/items.h
index 92fabf97d45..cac89e6e726 100644
--- a/engines/mm/mm1/data/items.h
+++ b/engines/mm/mm1/data/items.h
@@ -34,6 +34,7 @@ namespace MM1 {
enum ItemId {
VELLUM_SCROLL_ID = 231,
RUBY_WHISTLE_ID = 232,
+ MERCHANTS_PASS_ID = 234,
CORAL_KEY_ID = 236,
BRONZE_KEY_ID = 237,
SILVER_KEY_ID = 238,
diff --git a/engines/mm/mm1/maps/map.cpp b/engines/mm/mm1/maps/map.cpp
index 29c5580dca0..b7404b70f9b 100644
--- a/engines/mm/mm1/maps/map.cpp
+++ b/engines/mm/mm1/maps/map.cpp
@@ -108,6 +108,10 @@ void Map::updateGame() {
g_events->send("Game", GameMessage("UPDATE"));
}
+void Map::redrawGame() {
+ g_events->findView("Game")->redraw();
+}
+
} // namespace Maps
} // namespace MM1
} // namespace MM
diff --git a/engines/mm/mm1/maps/map.h b/engines/mm/mm1/maps/map.h
index 91d7599e0d2..725f9af4f1b 100644
--- a/engines/mm/mm1/maps/map.h
+++ b/engines/mm/mm1/maps/map.h
@@ -187,6 +187,11 @@ public:
* Updates the game display
*/
static void updateGame();
+
+ /**
+ * Redraw the game display
+ */
+ static void redrawGame();
};
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map18.cpp b/engines/mm/mm1/maps/map18.cpp
index e9458c6415d..4f45f5742f0 100644
--- a/engines/mm/mm1/maps/map18.cpp
+++ b/engines/mm/mm1/maps/map18.cpp
@@ -71,7 +71,7 @@ void Map18::special01() {
_data[VAL1] = 0;
} else {
- g_events->findView("Game")->redraw();
+ redrawGame();
send(SoundMessage(
STRING["maps.map18.blackridge_south"],
[](const Common::KeyState &ks) {
@@ -97,7 +97,7 @@ void Map18::special02() {
_data[VAL2] = 0;
} else {
- g_events->findView("Game")->redraw();
+ redrawGame();
send(SoundMessage(
STRING["maps.map18.blackridge_north"],
[](const Common::KeyState &ks) {
diff --git a/engines/mm/mm1/maps/map35.cpp b/engines/mm/mm1/maps/map35.cpp
index f246850eb2f..06443cd9b73 100644
--- a/engines/mm/mm1/maps/map35.cpp
+++ b/engines/mm/mm1/maps/map35.cpp
@@ -29,6 +29,17 @@ namespace MM {
namespace MM1 {
namespace Maps {
+#define VAL1 29
+#define VAL2 47
+
+static const byte MATCH_ITEMS[7] = {
+ 0, 0,241, 0, 0, 0, 0
+};
+static const byte MATCH_FLAGS[7] = {
+ CHARFLAG5_1, CHARFLAG5_2, CHARFLAG5_4, CHARFLAG5_8,
+ CHARFLAG5_10, CHARFLAG5_20, CHARFLAG5_40
+};
+
void Map35::special() {
// Scan for special actions on the map cell
for (uint i = 0; i < 11; ++i) {
@@ -55,27 +66,109 @@ void Map35::special00() {
}
void Map35::special01() {
+ send(SoundMessage(
+ STRING["maps.map35.exit"],
+ []() {
+ g_maps->_mapPos = Common::Point(14, 10);
+ g_maps->changeMap(0xa00, 2);
+ }
+ ));
}
void Map35::special02() {
+ send(SoundMessage(STRING["maps.map35.slide"]));
+ g_maps->_mapPos = Common::Point(14, 9);
+ g_maps->changeMap(0xa00, 2);
}
void Map35::special03() {
+ send(SoundMessage(STRING["maps.map35.message"]));
}
void Map35::special04() {
+ if (!g_globals->_party.hasItem(MERCHANTS_PASS_ID)) {
+ send(SoundMessage(STRING["maps.map35.merchants"]));
+ g_maps->_mapPos.y++;
+ updateGame();
+ }
}
void Map35::special05() {
+ updateFlags();
+ warning("TODO: drawMonster");
+ g_events->addView("Inspectron");
}
void Map35::special06() {
+ g_maps->clearSpecial();
+ g_globals->_treasure[8] = 30;
+ g_events->addAction(KEYBIND_SEARCH);
}
void Map35::special07() {
+ send(SoundMessage(STRING["maps.map35.vault"]));
+ _data[VAL1] = 30;
+ _data[VAL2] = 7;
}
void Map35::special09() {
+ g_maps->clearSpecial();
+ g_globals->_treasure[8] = 50;
+ special07();
+}
+
+void Map35::updateFlags() {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ int counte = c._equipped.size();
+ int count = counte + c._backpack.size();
+ for (int itemIdx = 0; itemIdx < count; ++itemIdx) {
+ byte itemId = (itemIdx < counte) ?
+ c._equipped[itemIdx]._id : c._backpack[itemIdx - counte]._id;
+
+ // Scan list of items to match against
+ for (int arrIdx = 0; arrIdx < 7; ++arrIdx) {
+ if (itemId == MATCH_ITEMS[arrIdx]) {
+ c._flags[5] |= MATCH_FLAGS[arrIdx];
+ break;
+ }
+ }
+ }
+ }
+}
+
+void Map35::acceptQuest() {
+ Character &leader = g_globals->_party[0];
+ byte flags = leader._flags[8];
+
+ // Find quest that hasn't been done yet
+ int questNum;
+ for (questNum = 8; flags && questNum < 15; ++questNum, flags >>= 1) {
+ if (!(flags & 1))
+ break;
+ }
+ if (questNum == 15) {
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ c._flags[8] = CHARFLAG8_80;
+ c._flags[5] = CHARFLAG5_80;
+ }
+ }
+
+ // Assign the quest to all party characters
+ for (uint i = 0; i < g_globals->_party.size(); ++i) {
+ Character &c = g_globals->_party[i];
+ c._quest = questNum;
+ }
+
+ // Draw the scene
+ g_maps->_mapPos.y++;
+ redrawGame();
+}
+
+bool Map35::matchQuest(Common::String &line) {
+ // TODO
+ return false;
}
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map35.h b/engines/mm/mm1/maps/map35.h
index 1064706fe39..8eeb634d80c 100644
--- a/engines/mm/mm1/maps/map35.h
+++ b/engines/mm/mm1/maps/map35.h
@@ -40,6 +40,7 @@ private:
void special06();
void special07();
void special09();
+ void updateFlags();
const SpecialFn SPECIAL_FN[11] = {
&Map35::special00,
@@ -61,6 +62,17 @@ public:
* Handles all special stuff that happens on the map
*/
void special() override;
+
+ /**
+ * Accepts a quest from Inspectron
+ */
+ void acceptQuest();
+
+ /**
+ * Does a check for the party's current quest is one
+ * of Inspectron's, and if it's complete
+ */
+ bool matchQuest(Common::String &line);
};
} // namespace Maps
diff --git a/engines/mm/mm1/maps/map_desert.cpp b/engines/mm/mm1/maps/map_desert.cpp
index 7ec410cfc35..91e4c83d7d8 100644
--- a/engines/mm/mm1/maps/map_desert.cpp
+++ b/engines/mm/mm1/maps/map_desert.cpp
@@ -29,8 +29,6 @@ namespace MM1 {
namespace Maps {
void MapDesert::desert() {
- Game::Encounter &enc = g_globals->_encounters;
-
SoundMessage msg;
msg._lines.push_back(Line(0, 1, STRING["maps.desert.its_hot"]));
diff --git a/engines/mm/mm1/views/dialogs.h b/engines/mm/mm1/views/dialogs.h
index fda980c2dcf..11b38948ef2 100644
--- a/engines/mm/mm1/views/dialogs.h
+++ b/engines/mm/mm1/views/dialogs.h
@@ -47,6 +47,7 @@
#include "mm/mm1/views/maps/arrested.h"
#include "mm/mm1/views/maps/chess.h"
#include "mm/mm1/views/maps/ice_princess.h"
+#include "mm/mm1/views/maps/inspectron.h"
#include "mm/mm1/views/maps/lion.h"
#include "mm/mm1/views/maps/prisoners.h"
#include "mm/mm1/views/maps/resistances.h"
@@ -96,6 +97,7 @@ private:
Views::Maps::DemonPrisoner _demonPrisoner;
Views::Maps::ManPrisoner _manPrisoner;
Views::Maps::IcePrincess _icePrincess;
+ Views::Maps::Inspectron _inspectron;
Views::Maps::Lion _lion;
Views::Maps::Resistances _resistances;
Views::Maps::Trivia _trivia;
diff --git a/engines/mm/mm1/views/maps/inspectron.cpp b/engines/mm/mm1/views/maps/inspectron.cpp
new file mode 100644
index 00000000000..40e4416f717
--- /dev/null
+++ b/engines/mm/mm1/views/maps/inspectron.cpp
@@ -0,0 +1,97 @@
+/* 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 .
+ *
+ */
+
+#include "mm/mm1/views/maps/inspectron.h"
+#include "mm/mm1/maps/map35.h"
+#include "mm/mm1/globals.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Maps {
+
+#define VAL1 123
+#define ANSWER_OFFSET 167
+
+Inspectron::Inspectron() : TextView("Inspectron") {
+ _bounds = getLineBounds(20, 24);
+}
+
+bool Inspectron::msgFocus(const FocusMessage &msg) {
+ _canAccept = !g_globals->_party[0]._quest;
+ return TextView::msgFocus(msg);
+}
+
+void Inspectron::draw() {
+ MM1::Maps::Map35 &map = *static_cast(g_maps->_currentMap);
+ clearSurface();
+
+ if (_canAccept) {
+ send(SoundMessage(
+ 0, 1, STRING["maps.map35.inspectron1"],
+ 0, 2, STRING["maps.map35.inspectron2"]
+ ));
+ } else {
+ int questNum = g_globals->_party[0]._quest;
+ Common::String line;
+
+ if (questNum < 8 || questNum > 14 || !map.matchQuest(line))
+ line = STRING["maps.map35.inspectron4"];
+
+ g_maps->_mapPos.y++;
+ map.redrawGame();
+
+ clearSurface();
+ send(SoundMessage(
+ 0, 1, STRING["maps.map35.inspectron1"],
+ 0, 2, line
+ ));
+ close();
+ }
+}
+
+bool Inspectron::msgKeypress(const KeypressMessage &msg) {
+ MM1::Maps::Map35 &map = *static_cast(g_maps->_currentMap);
+
+ if (_canAccept) {
+ if (msg.keycode == Common::KEYCODE_y) {
+ map.acceptQuest();
+
+ clearSurface();
+ writeString(0, 1, STRING["maps.map35.inspectron1"]);
+ writeString(0, 2, STRING[Common::String::format(
+ "maps.map35.quests.%d",
+ g_globals->_party[0]._quest)]);
+ close();
+
+ } else if (msg.keycode == Common::KEYCODE_n) {
+ close();
+ map.redrawGame();
+ }
+ }
+
+ return true;
+}
+
+} // namespace Maps
+} // namespace Views
+} // namespace MM1
+} // namespace MM
diff --git a/engines/mm/mm1/views/maps/inspectron.h b/engines/mm/mm1/views/maps/inspectron.h
new file mode 100644
index 00000000000..257d863e691
--- /dev/null
+++ b/engines/mm/mm1/views/maps/inspectron.h
@@ -0,0 +1,49 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+#ifndef MM1_VIEWS_MAPS_INSPECTRON_H
+#define MM1_VIEWS_MAPS_INSPECTRON_H
+
+#include "mm/mm1/views/text_view.h"
+
+namespace MM {
+namespace MM1 {
+namespace Views {
+namespace Maps {
+
+class Inspectron : public TextView {
+private:
+ bool _canAccept;
+public:
+ Inspectron();
+ virtual ~Inspectron() {}
+
+ bool msgFocus(const FocusMessage &msg) override;
+ void draw() override;
+ bool msgKeypress(const KeypressMessage &msg) override;
+};
+
+} // namespace Maps
+} // namespace Views
+} // namespace MM1
+} // namespace MM
+
+#endif
diff --git a/engines/mm/module.mk b/engines/mm/module.mk
index a4d003f0ae4..f173c5e38cd 100644
--- a/engines/mm/module.mk
+++ b/engines/mm/module.mk
@@ -58,6 +58,7 @@ MODULE_OBJS := \
mm1/views/maps/giant.o \
mm1/views/maps/gypsy.o \
mm1/views/maps/ice_princess.o \
+ mm1/views/maps/inspectron.o \
mm1/views/maps/lion.o \
mm1/views/maps/prisoners.o \
mm1/views/maps/resistances.o \